Environment Information
$ jruby -v
jruby 10.0.4.0 (3.4.5) 2026-03-03 9af05b916f Java HotSpot(TM) 64-Bit Server VM 24.0.1+9-30 on 24.0.1+9-30 +indy +jit [arm64-darwin]
$ uname -a
Darwin meowputer-m3.local 25.3.0 Darwin Kernel Version 25.3.0: Wed Jan 28 20:47:03 PST 2026; root:xnu-12377.81.4~5/RELEASE_ARM64_T6031 arm64
Description
Process.detach raises ArrayIndexOutOfBoundsException if called from a thread that is not the main thread.
It works as expected if called from the main thread:
pid = Process.spawn("sleep 2")
puts "Spawned #{pid}"
proc_thread = Process.detach(pid)
puts "Final status #{proc_thread.join.value.inspect}"
Output:
Spawned 485
Final status #<Process::Status: pid 485 exit 0>
If I create a new thread and call Process.detach from that thread, it raises:
pid = Process.spawn("sleep 2")
puts "Spawned #{pid}"
my_thread = Thread.new do
proc_thread = Process.detach(pid)
puts "Final status #{proc_thread.join.value.inspect}"
end
my_thread.join
Output:
Spawned 780
warning: thread "Ruby-0-Thread-1: foo2.rb:3" terminated with exception (report_on_exception is true):java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 10
at org.jruby.dist/org.jruby.runtime.ThreadContext.getCurrentFrame(ThreadContext.java:580)
at org.jruby.dist/org.jruby.runtime.ThreadContext.currentBinding(ThreadContext.java:1262)
at org.jruby.dist/org.jruby.runtime.CallBlock.newCallClosure(CallBlock.java:49)
at org.jruby.dist/org.jruby.RubyProcess.detach(RubyProcess.java:1751)
at org.jruby.dist/org.jruby.RubyProcess$INVOKER$s$1$0$detach.call(RubyProcess$INVOKER$s$1$0$detach.gen)
at org.jruby.dist/org.jruby.internal.runtime.methods.JavaMethod$JavaMethodN.call(JavaMethod.java:841)
at org.jruby.dist/org.jruby.ir.targets.indy.InvokeSite.performIndirectCall(InvokeSite.java:885)
at org.jruby.dist/org.jruby.ir.targets.indy.InvokeSite.invoke(InvokeSite.java:789)
at foo2.️❤ {} \=\^main\_ #0(foo2.rb:4)
at org.jruby.dist/org.jruby.runtime.CompiledIRBlockBody.callDirect(CompiledIRBlockBody.java:141)
at org.jruby.dist/org.jruby.runtime.IRBlockBody.call(IRBlockBody.java:66)
at org.jruby.dist/org.jruby.runtime.IRBlockBody.call(IRBlockBody.java:60)
at org.jruby.dist/org.jruby.runtime.Block.call(Block.java:146)
at org.jruby.dist/org.jruby.RubyProc.call(RubyProc.java:394)
at org.jruby.dist/org.jruby.internal.runtime.RubyRunnable.run(RubyRunnable.java:122)
at java.base/java.lang.Thread.run(Thread.java:1447)
Unhandled Java exception: java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 10
java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 10
getCurrentFrame at org/jruby/runtime/ThreadContext.java:580
currentBinding at org/jruby/runtime/ThreadContext.java:1262
newCallClosure at org/jruby/runtime/CallBlock.java:49
detach at org/jruby/RubyProcess.java:1751
call at org/jruby/RubyProcess$INVOKER$s$1$0$detach.gen:-1
call at org/jruby/internal/runtime/methods/JavaMethod.java:841
performIndirectCall at org/jruby/ir/targets/indy/InvokeSite.java:885
invoke at org/jruby/ir/targets/indy/InvokeSite.java:789
️❤ {} \=\^main\_ #0 at foo2.rb:4
callDirect at org/jruby/runtime/CompiledIRBlockBody.java:141
call at org/jruby/runtime/IRBlockBody.java:66
call at org/jruby/runtime/IRBlockBody.java:60
call at org/jruby/runtime/Block.java:146
call at org/jruby/RubyProc.java:394
run at org/jruby/internal/runtime/RubyRunnable.java:122
run at java/lang/Thread.java:1447
It also fails if I spawn the process from the same separate thread, so it's not a matter of the detach needing to happen from the same thread as the spawn. The difference seems to be main thread vs any other thread.
my_thread = Thread.new do
pid = Process.spawn("sleep 2")
puts "Spawned #{pid}"
proc_thread = Process.detach(pid)
puts "Final status #{proc_thread.join.value.inspect}"
end
my_thread.join
Similar output:
Spawned 882
warning: thread "Ruby-0-Thread-1: foo3.rb:3" terminated with exception (report_on_exception is true):java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 10
at org.jruby.dist/org.jruby.runtime.ThreadContext.getCurrentFrame(ThreadContext.java:580)
at org.jruby.dist/org.jruby.runtime.ThreadContext.currentBinding(ThreadContext.java:1262)
at org.jruby.dist/org.jruby.runtime.CallBlock.newCallClosure(CallBlock.java:49)
at org.jruby.dist/org.jruby.RubyProcess.detach(RubyProcess.java:1751)
at org.jruby.dist/org.jruby.RubyProcess$INVOKER$s$1$0$detach.call(RubyProcess$INVOKER$s$1$0$detach.gen)
at org.jruby.dist/org.jruby.internal.runtime.methods.JavaMethod$JavaMethodN.call(JavaMethod.java:841)
at org.jruby.dist/org.jruby.ir.targets.indy.InvokeSite.performIndirectCall(InvokeSite.java:885)
at org.jruby.dist/org.jruby.ir.targets.indy.InvokeSite.invoke(InvokeSite.java:789)
at foo3.️❤ {} \=\^main\_ #0(foo3.rb:4)
at org.jruby.dist/org.jruby.runtime.CompiledIRBlockBody.callDirect(CompiledIRBlockBody.java:141)
at org.jruby.dist/org.jruby.runtime.IRBlockBody.call(IRBlockBody.java:66)
at org.jruby.dist/org.jruby.runtime.IRBlockBody.call(IRBlockBody.java:60)
at org.jruby.dist/org.jruby.runtime.Block.call(Block.java:146)
at org.jruby.dist/org.jruby.RubyProc.call(RubyProc.java:394)
at org.jruby.dist/org.jruby.internal.runtime.RubyRunnable.run(RubyRunnable.java:122)
at java.base/java.lang.Thread.run(Thread.java:1447)
Unhandled Java exception: java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 10
java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 10
getCurrentFrame at org/jruby/runtime/ThreadContext.java:580
currentBinding at org/jruby/runtime/ThreadContext.java:1262
newCallClosure at org/jruby/runtime/CallBlock.java:49
detach at org/jruby/RubyProcess.java:1751
call at org/jruby/RubyProcess$INVOKER$s$1$0$detach.gen:-1
call at org/jruby/internal/runtime/methods/JavaMethod.java:841
performIndirectCall at org/jruby/ir/targets/indy/InvokeSite.java:885
invoke at org/jruby/ir/targets/indy/InvokeSite.java:789
️❤ {} \=\^main\_ #0 at foo3.rb:4
callDirect at org/jruby/runtime/CompiledIRBlockBody.java:141
call at org/jruby/runtime/IRBlockBody.java:66
call at org/jruby/runtime/IRBlockBody.java:60
call at org/jruby/runtime/Block.java:146
call at org/jruby/RubyProc.java:394
run at org/jruby/internal/runtime/RubyRunnable.java:122
run at java/lang/Thread.java:1447
CRuby/MRI works correctly in all three cases.
Environment Information
Description
Process.detachraises ArrayIndexOutOfBoundsException if called from a thread that is not the main thread.It works as expected if called from the main thread:
Output:
If I create a new thread and call Process.detach from that thread, it raises:
Output:
It also fails if I spawn the process from the same separate thread, so it's not a matter of the detach needing to happen from the same thread as the spawn. The difference seems to be main thread vs any other thread.
Similar output:
CRuby/MRI works correctly in all three cases.