Actions
Bug #19348
closedGVL being released earlier than expected when loading iseqs
Bug #19348:
GVL being released earlier than expected when loading iseqs
Description
When using the debug
gem in a Rails app with Ruby 3.2, I noticed that if the VS Code editor connects to the debugger during the app boot, this error could occur:
DEBUGGER: ReaderThreadError: uninitialized InstructionSequence
┃ DEBUGGER: Disconnected.
┃ ["/opt/rubies/ruby-3.2.0/lib/ruby/gems/3.2.0/gems/debug-1.7.1/lib/debug/breakpoint.rb:247:in `absolute_path'",
┃ "/opt/rubies/ruby-3.2.0/lib/ruby/gems/3.2.0/gems/debug-1.7.1/lib/debug/breakpoint.rb:247:in `block in iterate_iseq'",
┃ "/opt/rubies/ruby-3.2.0/lib/ruby/gems/3.2.0/gems/debug-1.7.1/lib/debug/breakpoint.rb:246:in `each_iseq'",
...
After investigating it with @peterzhu2118 (Peter Zhu), we found that it's because:
- During the Rails app's boot time, it uses
bootsnap
to load iseqs, which uses theibf_load_iseq_each
function underneath. - After commit e35c528d721d209ed8531b10b46c2ac725ea7bf5 (added in 3.2), that function starts calling
rb_vm_pop_frame
at the end of execution. - Because
rb_vm_pop_frame
triggers the release of GVL, iseqs that just being loaded now become accessible by other threads, even though they're not ready to be used. - Now, if the
debug
gem callsObjectSpace.each_iseq
to activate aLineBreakpoint
from its own thread, it'd gain access to those unready iseqs and try to read their state, which would then cause theuninitialized InstructionSequence
error.
Actions