oracle / truffleruby

A high performance implementation of the Ruby programming language, built on GraalVM.
https://www.graalvm.org/ruby/
Other
2.98k stars 179 forks source link

dead handle with mongoid #3577

Open gillesbergerp opened 1 month ago

gillesbergerp commented 1 month ago

We previously started experimenting with moving a large Rails application to Truffleruby but hit several walls so far. We are on truffleruby-jvm-24.0.01. Please find the stacktrace below

dead handle 0xbad0000006df518 (com.oracle.truffle.api.CompilerDirectives.ShouldNotReachHere)
    from com.oracle.truffle.api.CompilerDirectives.shouldNotReachHere(CompilerDirectives.java:574)
    from com.oracle.truffle.api.CompilerDirectives.shouldNotReachHere(CompilerDirectives.java:520)
    from org.truffleruby.cext.UnwrapNode$UnwrapNativeNode.raiseError(UnwrapNode.java:107)
    from org.truffleruby.cext.UnwrapNode$UnwrapNativeNode.unwrapTaggedObject(UnwrapNode.java:92)
    from org.truffleruby.cext.UnwrapNodeGen$UnwrapNativeNodeGen$Inlined.executeAndSpecialize(UnwrapNodeGen.java:421)
    from org.truffleruby.cext.UnwrapNodeGen$UnwrapNativeNodeGen$Inlined.execute(UnwrapNodeGen.java:387)
    from org.truffleruby.cext.UnwrapNode.longToWrapper(UnwrapNode.java:270)
    from org.truffleruby.cext.UnwrapNodeGen$Inlined.execute(UnwrapNodeGen.java:143)
    from org.truffleruby.core.array.library.NativeArrayStorage.read(NativeArrayStorage.java:98)
    from org.truffleruby.core.array.library.NativeArrayStorageGen$ArrayStoreLibraryExports$Cached.read(NativeArrayStorageGen.java:249)
    from org.truffleruby.core.array.library.DelegatedArrayStorage.read(DelegatedArrayStorage.java:54)
    from org.truffleruby.core.array.library.DelegatedArrayStorageGen$ArrayStoreLibraryExports$Cached.read(DelegatedArrayStorageGen.java:111)
    from org.truffleruby.core.array.library.SharedArrayStorage.read(SharedArrayStorage.java:74)
    from org.truffleruby.core.array.library.SharedArrayStorageGen$ArrayStoreLibraryExports$Cached.read(SharedArrayStorageGen.java:326)
    from org.truffleruby.core.array.ArrayEachIteratorNode.iterateMany(ArrayEachIteratorNode.java:66)
    from org.truffleruby.core.array.ArrayEachIteratorNodeGen$Inlined.executeAndSpecialize(ArrayEachIteratorNodeGen.java:497)
    from org.truffleruby.core.array.ArrayEachIteratorNodeGen$Inlined.execute(ArrayEachIteratorNodeGen.java:447)
    from org.truffleruby.core.array.ArrayNodes$MapNode.map(ArrayNodes.java:1455)
    from org.truffleruby.core.array.ArrayNodesFactory$MapNodeFactory$MapNodeGen.executeAndSpecialize(ArrayNodesFactory.java:10161)
    from org.truffleruby.core.array.ArrayNodesFactory$MapNodeFactory$MapNodeGen.execute(ArrayNodesFactory.java:10150)
    from org.truffleruby.builtins.EnumeratorSizeNode.execute(EnumeratorSizeNode.java:56)
    from org.truffleruby.language.RubyCoreMethodRootNode.execute(RubyCoreMethodRootNode.java:58)
/usr/local/bundle/gems/mongoid-7.4.0/lib/mongoid/criteria/queryable/extensions/array.rb:39:in `map'
    from /usr/local/bundle/gems/mongoid-7.4.0/lib/mongoid/criteria/queryable/extensions/array.rb:39:in `__deep_copy__'
    from /usr/local/bundle/gems/mongoid-7.4.0/lib/mongoid/changeable.rb:198:in `attribute_will_change!'
    from /usr/local/bundle/gems/mongoid-7.4.0/lib/mongoid/fields.rb:483:in `foo'

Unfortunately, I was not able to come up with a minimal example that reproduces the error.


Ruby version: truffleruby-jvm-24.0.01 Rails version: rails-6.1.7.7 Mongoid version: mongoid-7.4.0

gillesbergerp commented 1 month ago

I completely overlooked that Mongoid is only officially compatible with ruby 3.2 from version 8.1. I'll give that a try

https://www.mongodb.com/docs/mongoid/current/reference/compatibility/#ruby-compatibility

gillesbergerp commented 1 month ago

mongoid-8.1 with truffleruby-jvm-24.0.1 results in the same behavior

gillesbergerp commented 1 month ago

I was able to produce an example of a (maybe?) related issue:

class Foo
  include(Mongoid::Document)

  field(:bar, type: Array)
end

foo = Foo.create!
foo.set(bar: [DateTime.now]) # works
foo.set(bar: foo.bar + [DateTime.now]) # works
foo.set(bar: (foo.bar << DateTime.now)) # throws

The last line results in

Cannot invoke "org.truffleruby.cext.ValueWrapperManager$ValueWrapperWeakReferenc
e.get()" because "this.wrappers[offset]" is null (java.lang.NullPointerException
)
        from org.truffleruby.cext.ValueWrapperManager$HandleBlock.getWrapper(Val
ueWrapperManager.java:234)
        from org.truffleruby.cext.ValueWrapperManager.getWrapperFromHandleMap(Va
lueWrapperManager.java:109)
        from org.truffleruby.cext.UnwrapNode$UnwrapNativeNode.unwrapTaggedObject
(UnwrapNode.java:89)
        from org.truffleruby.cext.UnwrapNodeGen$UnwrapNativeNodeGen$Inlined.exec
uteAndSpecialize(UnwrapNodeGen.java:421)
        from org.truffleruby.cext.UnwrapNodeGen$UnwrapNativeNodeGen$Inlined.exec
ute(UnwrapNodeGen.java:387)
        from org.truffleruby.cext.UnwrapNode.longToWrapper(UnwrapNode.java:270)
        from org.truffleruby.cext.UnwrapNodeGen$Inlined.executeAndSpecialize(Unw
rapNodeGen.java:183)
        from org.truffleruby.cext.UnwrapNodeGen$Inlined.execute(UnwrapNodeGen.ja
va:158)
        from org.truffleruby.core.array.library.NativeArrayStorage.read(NativeAr
rayStorage.java:98)
        from org.truffleruby.core.array.library.NativeArrayStorageGen$ArrayStore
LibraryExports$Cached.read(NativeArrayStorageGen.java:249)
        from org.truffleruby.core.array.ArrayEachIteratorNode.iterateMany(ArrayE
achIteratorNode.java:66)
        from org.truffleruby.core.array.ArrayEachIteratorNodeGen$Inlined.execute
AndSpecialize(ArrayEachIteratorNodeGen.java:497)
        from org.truffleruby.core.array.ArrayEachIteratorNodeGen$Inlined.execute
(ArrayEachIteratorNodeGen.java:447)
        from org.truffleruby.core.array.ArrayNodes$MapNode.map(ArrayNodes.java:1
455)
        from org.truffleruby.core.array.ArrayNodesFactory$MapNodeFactory$MapNode
Gen.executeAndSpecialize(ArrayNodesFactory.java:10161)
        from org.truffleruby.core.array.ArrayNodesFactory$MapNodeFactory$MapNode
Gen.execute(ArrayNodesFactory.java:10150)
        from org.truffleruby.builtins.EnumeratorSizeNode.execute(EnumeratorSizeN
ode.java:56)
        from org.truffleruby.language.RubyCoreMethodRootNode.execute(RubyCoreMet
hodRootNode.java:58)
/usr/local/bundle/gems/mongoid-8.1.5/lib/mongoid/extensions/array.rb:152:in `map
'
        from /usr/local/bundle/gems/mongoid-8.1.5/lib/mongoid/extensions/array.r
b:152:in `mongoize'
        from /usr/local/lib/mri/forwardable.rb:240:in `mongoize'
        from /usr/local/bundle/gems/mongoid-8.1.5/lib/mongoid/attributes.rb:285:
in `typed_value_for'
        from /usr/local/bundle/gems/mongoid-8.1.5/lib/mongoid/attributes.rb:175:
in `block in write_attribute'
        from /usr/local/bundle/gems/mongoid-8.1.5/lib/mongoid/threaded/lifecycle
.rb:30:in `_assigning'
        from /usr/local/bundle/gems/mongoid-8.1.5/lib/mongoid/attributes.rb:172:
in `write_attribute'
        from /usr/local/bundle/gems/mongoid-8.1.5/lib/mongoid/fields.rb:691:in `
bar='
        from /usr/local/bundle/gems/mongoid-8.1.5/lib/mongoid/attributes/process
ing.rb:122:in `process_attribute'
        from /usr/local/bundle/gems/mongoid-8.1.5/lib/mongoid/persistable/settab
le.rb:82:in `block (2 levels) in set'
        from /usr/local/bundle/gems/mongoid-8.1.5/lib/mongoid/persistable.rb:208
:in `block in process_atomic_operations'
        from /usr/local/bundle/gems/mongoid-8.1.5/lib/mongoid/persistable.rb:206
:in `each'
        from /usr/local/bundle/gems/mongoid-8.1.5/lib/mongoid/persistable.rb:206
:in `process_atomic_operations'
        from /usr/local/bundle/gems/mongoid-8.1.5/lib/mongoid/persistable/settab
le.rb:49:in `block in set'
        from /usr/local/bundle/gems/mongoid-8.1.5/lib/mongoid/persistable.rb:186
:in `prepare_atomic_operation'
        from /usr/local/bundle/gems/mongoid-8.1.5/lib/mongoid/persistable/settab
le.rb:48:in `set'
        from (irb):10:in `<top (required)>'
        from /usr/local/lib/mri/irb/workspace.rb:119:in `evaluate'
        from /usr/local/lib/mri/irb/context.rb:502:in `evaluate'
        from /usr/local/lib/mri/irb.rb:588:in `block (2 levels) in eval_input'
        from /usr/local/lib/mri/irb.rb:777:in `signal_status'
        from /usr/local/lib/mri/irb.rb:567:in `block in eval_input'
        from /usr/local/lib/mri/irb/ruby-lex.rb:267:in `block (2 levels) in each
_top_level_statement'
        from <internal:core> core/kernel.rb:409:in `loop'
        from /usr/local/lib/mri/irb/ruby-lex.rb:249:in `block in each_top_level_
statement'
        from <internal:core> core/throw_catch.rb:36:in `catch'
        from /usr/local/lib/mri/irb/ruby-lex.rb:248:in `each_top_level_statement
'
        from /usr/local/lib/mri/irb.rb:566:in `eval_input'
        from /usr/local/lib/mri/irb.rb:500:in `block in run'
        from <internal:core> core/throw_catch.rb:36:in `catch'
        from /usr/local/lib/mri/irb.rb:499:in `run'
        from /usr/local/lib/mri/irb.rb:421:in `start'
        from /usr/local/bundle/gems/railties-6.1.7.7/lib/rails/commands/console/
console_command.rb:70:in `start'
        from /usr/local/bundle/gems/railties-6.1.7.7/lib/rails/commands/console/
console_command.rb:19:in `start'
        from /usr/local/bundle/gems/railties-6.1.7.7/lib/rails/commands/console/
console_command.rb:102:in `perform'
        from /usr/local/bundle/gems/thor-1.3.1/lib/thor/command.rb:28:in `run'
        from /usr/local/bundle/gems/thor-1.3.1/lib/thor/invocation.rb:127:in `in
voke_command'
        from /usr/local/bundle/gems/thor-1.3.1/lib/thor.rb:527:in `dispatch'
        from /usr/local/bundle/gems/railties-6.1.7.7/lib/rails/command/base.rb:6
9:in `perform'
        from /usr/local/bundle/gems/railties-6.1.7.7/lib/rails/command.rb:48:in
`invoke'
        from /usr/local/bundle/gems/railties-6.1.7.7/lib/rails/commands.rb:18:in
 `<top (required)>'
        from <internal:core> core/kernel.rb:229:in `gem_original_require'
        from <internal:/usr/local/lib/mri/rubygems/core_ext/kernel_require.rb>:3
7:in `require'
        from /workspace/bin/rails:4:in `<main>'
eregon commented 1 month ago

Thank you for the report, could you try with truffleruby+graalvm-dev (e.g. available in ruby-build or here)? There have been some C extension fixes on master but not yet in a release related to dead handles errors like the ones above.

gillesbergerp commented 4 weeks ago

Using the latest dev version yields the same result

flavorjones commented 6 days ago

I recently had a similar error in Nokogiri's test suite:

log snippet ``` dead handle 0xbad000000159ea0 (com.oracle.truffle.api.CompilerDirectives.ShouldNotReachHere) from com.oracle.truffle.api.CompilerDirectives.shouldNotReachHere(CompilerDirectives.java:603) from com.oracle.truffle.api.CompilerDirectives.shouldNotReachHere(CompilerDirectives.java:549) from org.truffleruby.cext.UnwrapNode$UnwrapNativeNode.raiseError(UnwrapNode.java:107) from org.truffleruby.cext.UnwrapNode$UnwrapNativeNode.unwrapTaggedObject(UnwrapNode.java:92) from org.truffleruby.cext.UnwrapNodeGen$UnwrapNativeNodeGen$Inlined.execute(UnwrapNodeGen.java:367) from org.truffleruby.cext.UnwrapNode.unwrapGeneric(UnwrapNode.java:286) from org.truffleruby.cext.UnwrapNodeGen$Inlined.execute(UnwrapNodeGen.java:156) from org.truffleruby.cext.CExtNodes$CallWithCExtLockAndFrameAndUnwrapNode.callWithCExtLockAndFrame(CExtNodes.java:262) from org.truffleruby.cext.CExtNodesFactory$CallWithCExtLockAndFrameAndUnwrapNodeFactory$CallWithCExtLockAndFrameAndUnwrapNodeGen.execute(CExtNodesFactory.java:5[54](https://github.com/sparklemotion/nokogiri/actions/runs/9709463631/job/26798206017#step:6:55)) from org.truffleruby.language.locals.WriteLocalVariableNode.execute(WriteLocalVariableNode.java:28) from org.truffleruby.language.RubyContextSourceNode.executeVoid(RubyContextSourceNode.java:23) from org.truffleruby.language.control.SequenceNode.execute(SequenceNode.java:32) from org.truffleruby.core.module.ModuleNodes$DefineMethodNode$CallMethodWithLambdaBody.execute(ModuleNodes.java:1373) from org.truffleruby.language.RubyLambdaRootNode.execute(RubyLambdaRootNode.java:84) /home/runner/.rubies/truffleruby-head/lib/truffle/truffle/cext_ruby.rb:24:in `parent' from /home/runner/work/nokogiri/nokogiri/test/xml/test_node_set.rb:602:in `block (4 levels) in ' from /home/runner/work/nokogiri/nokogiri/lib/nokogiri/xml/node_set.rb:237:in `block in each' from /home/runner/work/nokogiri/nokogiri/lib/nokogiri/xml/node_set.rb:236:in `upto' from /home/runner/work/nokogiri/nokogiri/lib/nokogiri/xml/node_set.rb:236:in `each' from /home/runner/work/nokogiri/nokogiri/test/xml/test_node_set.rb:[60](https://github.com/sparklemotion/nokogiri/actions/runs/9709463631/job/26798206017#step:6:61)1:in `test_0002_wraps each node within a dup of the Node argument' ```

This was on truffleruby 24.2.0-dev-954bfcf3, like ruby 3.2.4, GraalVM CE Native

eregon commented 6 days ago

@flavorjones That seems the same as https://github.com/oracle/truffleruby/issues/3503

flavorjones commented 6 days ago

Yikes, apologies for the noise, I forgot I had opened that one.