From: "st0012 (Stan Lo) via ruby-core" Date: 2023-01-17T11:30:36+00:00 Subject: [ruby-core:111849] [Ruby master Bug#19348] GVL being released earlier than expected when loading iseqs Issue #19348 has been reported by st0012 (Stan Lo). ---------------------------------------- Bug #19348: GVL being released earlier than expected when loading iseqs https://bugs.ruby-lang.org/issues/19348 * Author: st0012 (Stan Lo) * Status: Open * Priority: Normal * ruby -v: 3.2.0 * Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- 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, we found that it's because: 1. During the Rails app's boot time, it uses `bootsnap` to load iseqs, which uses the [`ibf_load_iseq_each `](https://github.com/ruby/ruby/blob/9399352a43253e2905d76d21774fb0301069197b/compile.c#L12125) function underneath. 2. After commit [e35c528d721d209ed8531b10b46c2ac725ea7bf5](https://github.com/ruby/ruby/commit/e35c528d721d209ed8531b10b46c2ac725ea7bf5) (added in 3.2), that function starts calling `rb_vm_pop_frame` at the end of execution. 3. 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. 4. Now, if the `debug` gem calls [`ObjectSpace.each_iseq`](https://github.com/ruby/debug/blob/0fcfc28acae33ec1c08068fb7c33703cfa681fa7/ext/debug/iseq_collector.c#L61-L67) to [activate a `LineBreakpoint`](https://github.com/ruby/debug/blob/0fcfc28acae33ec1c08068fb7c33703cfa681fa7/lib/debug/breakpoint.rb#L246) from its own thread, it'd gain access to those unready iseqs and try to read their state, which would then cause the [`uninitialized InstructionSequence` error](https://github.com/ruby/ruby/blob/40a9964b893fee5680b455d0e905155be3360685/iseq.c#L1540). -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/