Environment Information
- JRuby version: jruby 10.1.0.0 (4.0.0) 2026-04-20 32f988b OpenJDK 64-Bit Server VM 25.0.2+10-LTS on 25.0.2+10-LTS +indy +jit [x86_64-linux]
- Operating system and platform: Linux 6.12.94+deb13-amd64 # 1 SMP PREEMPT_DYNAMIC Debian 6.12.94-1 (2026-06-20) x86_64 GNU/Linux
- JRUBY_OPTS=
-Xparser.prism=true -J-XX:+UseParallelGC
The Bug
When calling transfer() inside the fiber() method of a Fiber::Scheduler implementation on a JVM with support for Virtual Threads, the VM stalls after several seconds, failing to enter the fiber in question.
Relevant code snippets are reproduced below:
Fiber::Scheduler#fiber( &block )
def fiber( &block )
current = Fiber.current
@nested.append( current ) if current != @primary
# spawn it
fiber = Fiber.new( blocking: false, &block )
fiber.transfer # <-- Stalls here
return fiber
end
The offending fiber:
INTERVAL = 1.0 / 60.0
@scheduler = Scheduler.new
Fiber.set_scheduler( @scheduler )
# ... more setup performed here ...
# clock (cube updater)
@clock = Fiber.schedule do
ptr = FFI::MemoryPointer.new( :char, @matrices.size )
loop do
break if ctx.window.closing?
# track time, update camera matrix
head = Process.clock_gettime( Process::CLOCK_MONOTONIC )
@state.memory.write( @camera.matrix.pack )
# update matrices
@transforms.each_with_index {|tf, i| # Line 216
tf.rotation.y += 0.02
ptr.put_array_of_float( i * 64, tf.affine.cells ) # Line 218; various matrix.rb calls here
}
@matrices.memory.write( ptr )
# compute sleep
tail = Process.clock_gettime( Process::CLOCK_MONOTONIC ) - head
delta = INTERVAL - tail
sleep( delta ) if delta > 0
end
ensure
ptr.free
end
# report -- bug: THIS IS NEVER REACHED!
time = Process.clock_gettime( Process::CLOCK_MONOTONIC ) - head
puts sprintf('[!] Bootstrapping took: %.6f seconds', time )
Expected Behavior
Note: interestingly enough, when replacing the fiber with a thread, this works without error in JRuby.
The fiber @clock is instantiated in a non-blocking manner and the code immediately proceeds to the report block below, after calling transfer() within Fiber::Scheduler#fiber( &block ).
Meanwhile, the @clock ticks at 60 Hz, updating the relevant values by writing into device memory.
This was tested in Ruby 4.0.5.
Actual Behavior
As stated, the JRuby VM stalls upon the call to transfer(), failing to print anything after that point nor indicate whether it has entered the fiber in question.
Running JavaFlightRecorder was able to capture the error, as far as I have been able to trace it. It appears to stem from transfer() in ThreadFiber.java:315.
At this point, the "main" fiber reports that it has become parked and is waiting on a condition:
"main" #3 [47670] prio=5 os_prio=0 cpu=3414.14ms elapsed=9.51s tid=0x00007f0a0c02cf60 nid=47670 waiting on condition [0x00007f0a135fc000]
java.lang.Thread.State: WAITING (parking)
at jdk.internal.misc.Unsafe.park([email protected]/Native Method)
- parking to wait for <0x0000000708378638> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park([email protected]/Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block([email protected]/Unknown Source)
at java.util.concurrent.ForkJoinPool.unmanagedBlock([email protected]/Unknown Source)
at java.util.concurrent.ForkJoinPool.managedBlock([email protected]/Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await([email protected]/Unknown Source)
at java.util.concurrent.ArrayBlockingQueue.take([email protected]/Unknown Source)
at org.jruby.ext.fiber.FiberQueue$1.run(org.jruby.dist/FiberQueue.java:56)
at org.jruby.ext.fiber.FiberQueue$1.run(org.jruby.dist/FiberQueue.java:53)
at org.jruby.RubyThread.executeTask(org.jruby.dist/RubyThread.java:1924)
at org.jruby.RubyThread.executeTaskBlocking(org.jruby.dist/RubyThread.java:1898)
at org.jruby.ext.fiber.FiberQueue.pop(org.jruby.dist/FiberQueue.java:92)
at org.jruby.ext.fiber.ThreadFiber.exchangeWithFiber(org.jruby.dist/ThreadFiber.java:265)
at org.jruby.ext.fiber.ThreadFiber.transfer(org.jruby.dist/ThreadFiber.java:372)
at org.jruby.ext.fiber.ThreadFiber$INVOKER$i$0$0$transfer.call(org.jruby.dist/ThreadFiber$INVOKER$i$0$0$transfer.gen)
at org.jruby.internal.runtime.methods.JavaMethod$JavaMethodN.call(org.jruby.dist/JavaMethod.java:709)
at org.jruby.internal.runtime.methods.DynamicMethod.call(org.jruby.dist/DynamicMethod.java:217)
at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(org.jruby.dist/CachingCallSite.java:442)
at org.jruby.runtime.callsite.CachingCallSite.call(org.jruby.dist/CachingCallSite.java:193)
at org.jruby.ir.interpreter.InterpreterEngine.processCall(org.jruby.dist/InterpreterEngine.java:352)
at org.jruby.ir.interpreter.StartupInterpreterEngine.interpret(org.jruby.dist/StartupInterpreterEngine.java:66)
at org.jruby.internal.runtime.methods.MixedModeIRMethod.INTERPRET_METHOD(org.jruby.dist/MixedModeIRMethod.java:133)
at org.jruby.internal.runtime.methods.MixedModeIRMethod.call(org.jruby.dist/MixedModeIRMethod.java:120)
at org.jruby.RubyClass.finvokeWithRefinements(org.jruby.dist/RubyClass.java:644)
at org.jruby.RubyClass.finvoke(org.jruby.dist/RubyClass.java:632)
at org.jruby.runtime.Helpers.invoke(org.jruby.dist/Helpers.java:784)
at org.jruby.RubyBasicObject.callMethod(org.jruby.dist/RubyBasicObject.java:410)
at org.jruby.ext.fiber.ThreadFiber$FiberSchedulerSupport.schedule(org.jruby.dist/ThreadFiber.java:832)
at org.jruby.ext.fiber.ThreadFiber$FiberSchedulerSupport$INVOKER$s$0$0$schedule.call(org.jruby.dist/ThreadFiber$FiberSchedulerSupport$INVOKER$s$0$0$schedule.gen)
at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(org.jruby.dist/CachingCallSite.java:432)
at org.jruby.runtime.callsite.CachingCallSite.call(org.jruby.dist/CachingCallSite.java:90)
at org.jruby.runtime.callsite.CachingCallSite.callIter(org.jruby.dist/CachingCallSite.java:101)
at org.jruby.ir.instructions.CallBase.interpret(org.jruby.dist/CallBase.java:548)
at org.jruby.ir.interpreter.InterpreterEngine.processCall(org.jruby.dist/InterpreterEngine.java:372)
at org.jruby.ir.interpreter.StartupInterpreterEngine.interpret(org.jruby.dist/StartupInterpreterEngine.java:66)
at org.jruby.ir.interpreter.Interpreter.INTERPRET_BLOCK(org.jruby.dist/Interpreter.java:120)
at org.jruby.runtime.MixedModeIRBlockBody.commonYieldPath(org.jruby.dist/MixedModeIRBlockBody.java:138)
at org.jruby.runtime.IRBlockBody.doYield(org.jruby.dist/IRBlockBody.java:170)
at org.jruby.runtime.BlockBody.yield(org.jruby.dist/BlockBody.java:108)
at org.jruby.runtime.Block.yield(org.jruby.dist/Block.java:191)
at org.jruby.ir.runtime.IRRuntimeHelpers.yield(org.jruby.dist/IRRuntimeHelpers.java:498)
at org.jruby.ir.instructions.YieldInstr.interpret(org.jruby.dist/YieldInstr.java:97)
at org.jruby.ir.interpreter.StartupInterpreterEngine.processOtherOp(org.jruby.dist/StartupInterpreterEngine.java:155)
at org.jruby.ir.interpreter.StartupInterpreterEngine.interpret(org.jruby.dist/StartupInterpreterEngine.java:98)
at org.jruby.internal.runtime.methods.MixedModeIRMethod.INTERPRET_METHOD(org.jruby.dist/MixedModeIRMethod.java:133)
at org.jruby.internal.runtime.methods.MixedModeIRMethod.call(org.jruby.dist/MixedModeIRMethod.java:120)
at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(org.jruby.dist/CachingCallSite.java:432)
at org.jruby.runtime.callsite.CachingCallSite.call(org.jruby.dist/CachingCallSite.java:90)
at org.jruby.runtime.callsite.CachingCallSite.callIter(org.jruby.dist/CachingCallSite.java:101)
at org.jruby.ir.instructions.CallBase.interpret(org.jruby.dist/CallBase.java:548)
at org.jruby.ir.interpreter.InterpreterEngine.processCall(org.jruby.dist/InterpreterEngine.java:372)
at org.jruby.ir.interpreter.StartupInterpreterEngine.interpret(org.jruby.dist/StartupInterpreterEngine.java:66)
at org.jruby.ir.interpreter.Interpreter.INTERPRET_ROOT(org.jruby.dist/Interpreter.java:100)
at org.jruby.ir.interpreter.Interpreter.execute(org.jruby.dist/Interpreter.java:85)
at org.jruby.ir.interpreter.Interpreter.execute(org.jruby.dist/Interpreter.java:35)
at org.jruby.ir.IRTranslator.execute(org.jruby.dist/IRTranslator.java:42)
at org.jruby.Ruby.runInterpreter(org.jruby.dist/Ruby.java:1238)
at org.jruby.Ruby.runInterpreter(org.jruby.dist/Ruby.java:1268)
at org.jruby.Ruby.runNormally(org.jruby.dist/Ruby.java:1142)
at org.jruby.Ruby.runFromMain(org.jruby.dist/Ruby.java:982)
at org.jruby.main.Main.internalRun(org.jruby.dist/Main.java:289)
at org.jruby.main.Main.run(org.jruby.dist/Main.java:239)
at org.jruby.main.Main.main(org.jruby.dist/Main.java:211)
Shortly afterward, "ForkJoinPool-1-worker-2" reports that it is carrying virtual thread No. 50 and attempts to run the continuation, after cycling through java.lang.invoke.DelegatingMethodHandle$Holder.delegate and java.lang.invoke.LambdaForm$MH/xyz.guard and java.lang.invoke.LambdaForm$MH/xyz.invoke (where xyz is the hex identifier of the object).
"ForkJoinPool-1-worker-2" #49 [47716] daemon prio=5 os_prio=0 cpu=5657.33ms elapsed=5.96s tid=0x00007f08c17a2730 [0x00007f08e3e17000]
Carrying virtual thread #50
at jdk.internal.vm.Continuation.run([email protected]/Unknown Source)
at java.lang.VirtualThread.runContinuation([email protected]/Unknown Source)
at java.lang.VirtualThread$$Lambda/0x00000000550f3af8.run([email protected]/Unknown Source)
at java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec([email protected]/Unknown Source)
at java.util.concurrent.ForkJoinTask.doExec([email protected]/Unknown Source)
at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec([email protected]/Unknown Source)
at java.util.concurrent.ForkJoinPool.runWorker([email protected]/Unknown Source)
at java.util.concurrent.ForkJoinWorkerThread.run([email protected]/Unknown Source)
Mounted virtual thread #50
at java.lang.invoke.LambdaForm$DMH/0x0000000055041800.invokeStatic([email protected]/LambdaForm$DMH)
at java.lang.invoke.LambdaForm$MH/0x00000000555ad800.invoke([email protected]/LambdaForm$MH)
at java.lang.invoke.LambdaForm$MH/0x00000000555b0c00.invoke([email protected]/LambdaForm$MH)
at java.lang.invoke.DelegatingMethodHandle$Holder.delegate([email protected]/DelegatingMethodHandle$Holder)
at java.lang.invoke.LambdaForm$MH/0x00000000555af000.guard([email protected]/LambdaForm$MH)
at java.lang.invoke.DelegatingMethodHandle$Holder.delegate([email protected]/DelegatingMethodHandle$Holder)
at java.lang.invoke.LambdaForm$MH/0x00000000555af000.guard([email protected]/LambdaForm$MH)
at java.lang.invoke.DelegatingMethodHandle$Holder.delegate([email protected]/DelegatingMethodHandle$Holder)
at java.lang.invoke.LambdaForm$MH/0x00000000555af000.guard([email protected]/LambdaForm$MH)
at java.lang.invoke.DelegatingMethodHandle$Holder.delegate([email protected]/DelegatingMethodHandle$Holder)
at java.lang.invoke.LambdaForm$MH/0x00000000555af000.guard([email protected]/LambdaForm$MH)
at java.lang.invoke.Invokers$Holder.linkToCallSite([email protected]/Invokers$Holder)
at home.rien.code.vulkanize.lib.data.matrix.️❤ def multiply #0(/home/rien/code/vulkanize/lib/data/matrix.rb:111)
at java.lang.invoke.DirectMethodHandle$Holder.invokeStatic([email protected]/DirectMethodHandle$Holder)
at java.lang.invoke.LambdaForm$MH/0x000000005562a000.invoke([email protected]/LambdaForm$MH)
at java.lang.invoke.DelegatingMethodHandle$Holder.delegate([email protected]/DelegatingMethodHandle$Holder)
at java.lang.invoke.LambdaForm$MH/0x00000000555b9c00.guard([email protected]/LambdaForm$MH)
at java.lang.invoke.DelegatingMethodHandle$Holder.delegate([email protected]/DelegatingMethodHandle$Holder)
at java.lang.invoke.LambdaForm$MH/0x00000000555b9c00.guard([email protected]/LambdaForm$MH)
at java.lang.invoke.Invokers$Holder.linkToCallSite([email protected]/Invokers$Holder)
at home.rien.code.vulkanize.lib.data.matrix.️❤ def mul! #0(/home/rien/code/vulkanize/lib/data/matrix.rb:149)
at java.lang.invoke.LambdaForm$DMH/0x0000000055684000.invokeStatic([email protected]/LambdaForm$DMH)
at java.lang.invoke.LambdaForm$MH/0x000000005560e800.invoke([email protected]/LambdaForm$MH)
at java.lang.invoke.DelegatingMethodHandle$Holder.delegate([email protected]/DelegatingMethodHandle$Holder)
at java.lang.invoke.LambdaForm$MH/0x00000000555af000.guard([email protected]/LambdaForm$MH)
at java.lang.invoke.DelegatingMethodHandle$Holder.delegate([email protected]/DelegatingMethodHandle$Holder)
at java.lang.invoke.LambdaForm$MH/0x00000000555af000.guard([email protected]/LambdaForm$MH)
at java.lang.invoke.Invokers$Holder.linkToCallSite([email protected]/Invokers$Holder)
at home.rien.code.vulkanize.lib.data.transform.️❤ def affine #0(/home/rien/code/vulkanize/lib/data/transform.rb:49)
at java.lang.invoke.DirectMethodHandle$Holder.invokeStatic([email protected]/DirectMethodHandle$Holder)
at java.lang.invoke.LambdaForm$MH/0x00000000555eb800.invoke([email protected]/LambdaForm$MH)
at java.lang.invoke.DelegatingMethodHandle$Holder.delegate([email protected]/DelegatingMethodHandle$Holder)
at java.lang.invoke.LambdaForm$MH/0x00000000555b9c00.guard([email protected]/LambdaForm$MH)
at java.lang.invoke.DelegatingMethodHandle$Holder.delegate([email protected]/DelegatingMethodHandle$Holder)
at java.lang.invoke.LambdaForm$MH/0x00000000555b9c00.guard([email protected]/LambdaForm$MH)
at java.lang.invoke.Invokers$Holder.linkToCallSite([email protected]/Invokers$Holder)
at test.clock.️❤ {} \=\^main\_ #1(test/clock.rb:218)
at java.lang.invoke.DirectMethodHandle$Holder.invokeStatic([email protected]/DirectMethodHandle$Holder)
at java.lang.invoke.LambdaForm$MH/0x0000000055696c00.invoke([email protected]/LambdaForm$MH)
at java.lang.invoke.LambdaForm$MH/0x00000000555b1400.invokeExact_MT([email protected]/LambdaForm$MH)
at org.jruby.runtime.CompiledIRBlockBody.callDirect(org.jruby.dist/CompiledIRBlockBody.java:141)
at org.jruby.runtime.IRBlockBody.call(org.jruby.dist/IRBlockBody.java:66)
at org.jruby.runtime.IRBlockBody.call(org.jruby.dist/IRBlockBody.java:50)
at org.jruby.runtime.Block.call(org.jruby.dist/Block.java:172)
at org.jruby.RubyEnumerable$EachWithIndex.call(org.jruby.dist/RubyEnumerable.java:1106)
at org.jruby.runtime.CallBlock.doYield(org.jruby.dist/CallBlock.java:91)
at org.jruby.runtime.BlockBody.yield(org.jruby.dist/BlockBody.java:108)
at org.jruby.runtime.Block.yield(org.jruby.dist/Block.java:191)
at org.jruby.RubyArrayNative.each(org.jruby.dist/RubyArrayNative.java:1729)
at org.jruby.RubyArray$INVOKER$i$0$0$each.call(org.jruby.dist/RubyArray$INVOKER$i$0$0$each.gen)
at org.jruby.internal.runtime.methods.JavaMethod$JavaMethodZeroBlock.call(org.jruby.dist/JavaMethod.java:498)
at org.jruby.runtime.callsite.CachingCallSite.call(org.jruby.dist/CachingCallSite.java:88)
at org.jruby.RubyEnumerable.callEach(org.jruby.dist/RubyEnumerable.java:111)
at org.jruby.RubyEnumerable.each_with_indexCommon(org.jruby.dist/RubyEnumerable.java:1123)
at org.jruby.RubyEnumerable.each_with_index(org.jruby.dist/RubyEnumerable.java:1157)
at org.jruby.RubyEnumerable.each_with_index(org.jruby.dist/RubyEnumerable.java:1147)
at java.lang.invoke.DirectMethodHandle$Holder.invokeStatic([email protected]/DirectMethodHandle$Holder)
at java.lang.invoke.LambdaForm$MH/0x00000000555ad400.invoke([email protected]/LambdaForm$MH)
at java.lang.invoke.LambdaForm$MH/0x000000005561c800.invoke([email protected]/LambdaForm$MH)
at java.lang.invoke.DelegatingMethodHandle$Holder.delegate([email protected]/DelegatingMethodHandle$Holder)
at java.lang.invoke.LambdaForm$MH/0x00000000555af000.guard([email protected]/LambdaForm$MH)
at java.lang.invoke.DelegatingMethodHandle$Holder.delegate([email protected]/DelegatingMethodHandle$Holder)
at java.lang.invoke.LambdaForm$MH/0x00000000555af000.guard([email protected]/LambdaForm$MH)
at java.lang.invoke.Invokers$Holder.linkToCallSite([email protected]/Invokers$Holder)
at test.clock.️❤ {} \=\^main\_ #0(test/clock.rb:216)
at java.lang.invoke.DirectMethodHandle$Holder.invokeStatic([email protected]/DirectMethodHandle$Holder)
at java.lang.invoke.LambdaForm$MH/0x0000000055699000.invoke([email protected]/LambdaForm$MH)
at java.lang.invoke.LambdaForm$MH/0x00000000555b1400.invokeExact_MT([email protected]/LambdaForm$MH)
at org.jruby.runtime.CompiledIRBlockBody.yieldDirect(org.jruby.dist/CompiledIRBlockBody.java:151)
at org.jruby.runtime.MixedModeIRBlockBody.yieldDirect(org.jruby.dist/MixedModeIRBlockBody.java:113)
at org.jruby.runtime.IRBlockBody.yieldSpecific(org.jruby.dist/IRBlockBody.java:74)
at org.jruby.runtime.Block.yieldSpecific(org.jruby.dist/Block.java:160)
at org.jruby.RubyKernel.loop(org.jruby.dist/RubyKernel.java:1680)
at org.jruby.RubyKernel$INVOKER$s$0$0$loop.call(org.jruby.dist/RubyKernel$INVOKER$s$0$0$loop.gen)
at org.jruby.internal.runtime.methods.JavaMethod$JavaMethodZeroBlock.call(org.jruby.dist/JavaMethod.java:498)
at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(org.jruby.dist/CachingCallSite.java:432)
at org.jruby.runtime.callsite.CachingCallSite.call(org.jruby.dist/CachingCallSite.java:90)
at org.jruby.runtime.callsite.CachingCallSite.callIter(org.jruby.dist/CachingCallSite.java:101)
at org.jruby.ir.instructions.CallBase.interpret(org.jruby.dist/CallBase.java:548)
at org.jruby.ir.interpreter.InterpreterEngine.processCall(org.jruby.dist/InterpreterEngine.java:372)
at org.jruby.ir.interpreter.StartupInterpreterEngine.interpret(org.jruby.dist/StartupInterpreterEngine.java:66)
at org.jruby.ir.interpreter.Interpreter.INTERPRET_BLOCK(org.jruby.dist/Interpreter.java:120)
at org.jruby.runtime.MixedModeIRBlockBody.commonYieldPath(org.jruby.dist/MixedModeIRBlockBody.java:138)
at org.jruby.runtime.IRBlockBody.yieldSpecific(org.jruby.dist/IRBlockBody.java:78)
at org.jruby.runtime.Block.yieldSpecific(org.jruby.dist/Block.java:160)
at org.jruby.ext.fiber.ThreadFiber.lambda$createThread$0(org.jruby.dist/ThreadFiber.java:534)
at org.jruby.ext.fiber.ThreadFiber$$Lambda/0x000000005565dbe0.run(org.jruby.dist/Unknown Source)
at java.lang.Thread.runWith([email protected]/Unknown Source)
at java.lang.VirtualThread.run([email protected]/Unknown Source)
at java.lang.VirtualThread$VThreadContinuation$1.run([email protected]/Unknown Source)
at jdk.internal.vm.Continuation.enter0([email protected]/Unknown Source)
at jdk.internal.vm.Continuation.enter([email protected]/Unknown Source)
Other potentially relevant state information:
"VirtualThread-unblocker" #45 [47714] daemon prio=5 os_prio=0 cpu=0.36ms elapsed=5.96s tid=0x00007f08c179ea60 nid=47714 runnable [0x00007f08e421d000]
java.lang.Thread.State: RUNNABLE
at java.lang.VirtualThread.takeVirtualThreadListToUnblock([email protected]/Native Method)
at java.lang.VirtualThread.unblockVirtualThreads([email protected]/Unknown Source)
at java.lang.VirtualThread$$Lambda/0x00000000550f3428.run([email protected]/Unknown Source)
at java.lang.Thread.runWith([email protected]/Unknown Source)
at java.lang.Thread.run([email protected]/Unknown Source)
at jdk.internal.misc.InnocuousThread.run([email protected]/Unknown Source)
"ForkJoinPool-1-worker-1" #47 [47715] daemon prio=5 os_prio=0 cpu=0.77ms elapsed=5.96s tid=0x00007f08c17a0de0 nid=47715 waiting on condition [0x00007f08e401b000]
java.lang.Thread.State: WAITING (parking)
at jdk.internal.misc.Unsafe.park([email protected]/Native Method)
- parking to wait for <0x00000007bba853c0> (a java.util.concurrent.ForkJoinPool)
at java.util.concurrent.ForkJoinPool.awaitWork([email protected]/Unknown Source)
at java.util.concurrent.ForkJoinPool.deactivate([email protected]/Unknown Source)
at java.util.concurrent.ForkJoinPool.runWorker([email protected]/Unknown Source)
at java.util.concurrent.ForkJoinWorkerThread.run([email protected]/Unknown Source)
"ForkJoinPool-1-delayScheduler" #51 [47719] daemon prio=5 os_prio=0 cpu=13.04ms elapsed=4.75s tid=0x00007f08bc0f3db0 nid=47719 waiting on condition [0x00007f08e3a16000]
java.lang.Thread.State: WAITING (parking)
at jdk.internal.misc.Unsafe.park([email protected]/Native Method)
at java.util.concurrent.DelayScheduler.loop([email protected]/Unknown Source)
at java.util.concurrent.DelayScheduler.run([email protected]/Unknown Source)
Environment Information
-Xparser.prism=true -J-XX:+UseParallelGCThe Bug
When calling
transfer()inside thefiber()method of aFiber::Schedulerimplementation on a JVM with support for Virtual Threads, the VM stalls after several seconds, failing to enter the fiber in question.Relevant code snippets are reproduced below:
Fiber::Scheduler#fiber( &block )
The offending fiber:
Expected Behavior
The fiber
@clockis instantiated in a non-blocking manner and the code immediately proceeds to the report block below, after callingtransfer()withinFiber::Scheduler#fiber( &block ).Meanwhile, the
@clockticks at 60 Hz, updating the relevant values by writing into device memory.This was tested in Ruby 4.0.5.
Actual Behavior
As stated, the JRuby VM stalls upon the call to
transfer(), failing to print anything after that point nor indicate whether it has entered the fiber in question.Running JavaFlightRecorder was able to capture the error, as far as I have been able to trace it. It appears to stem from
transfer()in ThreadFiber.java:315.At this point, the "main" fiber reports that it has become parked and is waiting on a condition:
Shortly afterward, "ForkJoinPool-1-worker-2" reports that it is carrying virtual thread No. 50 and attempts to run the continuation, after cycling through
java.lang.invoke.DelegatingMethodHandle$Holder.delegateandjava.lang.invoke.LambdaForm$MH/xyz.guardandjava.lang.invoke.LambdaForm$MH/xyz.invoke(wherexyzis the hex identifier of the object).Other potentially relevant state information: