merge revision(s) df6b72b8ff: [Backport #19348]

Avoid checking interrupt when loading iseq
	MIME-Version: 1.0
	Content-Type: text/plain; charset=UTF-8
	Content-Transfer-Encoding: 8bit

	The interrupt check will unintentionally release the VM lock when loading an iseq.
	And this will cause issues with the `debug` gem's
	[`ObjectSpace.each_iseq` method](0fcfc28aca/ext/debug/iseq_collector.c (L61-L67)),
	which wraps iseqs with a wrapper and exposes their internal states when they're actually not ready to be used.

	And when that happens, errors like this would occur and kill the `debug` gem's thread:

	```
	 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'",
	...
	```

	A way to reproduce the issue is to satisfy these conditions at the same time:

	1. `debug` gem calling `ObjectSpace.each_iseq` (e.g. [activating a `LineBreakpoint`](0fcfc28aca/lib/debug/breakpoint.rb (L246))).
	2. A large amount of iseq being loaded from another thread (possibly through the `bootsnap` gem).
	3. 1 and 2 iterating through the same iseq(s) at the same time.

	Because this issue requires external dependencies and a rather complicated timing setup to reproduce, I wasn't able to write a test case for it.
	But here's some pseudo code to help reproduce it:

	```rb
	require "debug/session"

	Thread.new do
	  100.times do
	    ObjectSpace.each_iseq do |iseq|
	      iseq.absolute_path
	    end
	  end
	end

	sleep 0.1

	load_a_bunch_of_iseq
	possibly_through_bootsnap
	```

	[Bug #19348]

	Co-authored-by: Peter Zhu <peter@peterzhu.ca>
	---
	 compile.c       |  2 +-
	 vm_core.h       |  1 +
	 vm_insnhelper.c | 11 +++++++++++
	 3 files changed, 13 insertions(+), 1 deletion(-)
This commit is contained in:
NARUSE, Yui 2023-01-25 10:23:38 +09:00
parent a20061cb1a
commit 0090cb82b0
4 changed files with 14 additions and 2 deletions

View file

@ -1747,6 +1747,7 @@ const VALUE *rb_binding_add_dynavars(VALUE bindval, rb_binding_t *bind, int dync
void rb_vm_inc_const_missing_count(void);
VALUE rb_vm_call_kw(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc,
const VALUE *argv, const rb_callable_method_entry_t *me, int kw_splat);
void rb_vm_pop_frame_no_int(rb_execution_context_t *ec);
MJIT_STATIC void rb_vm_pop_frame(rb_execution_context_t *ec);
void rb_thread_start_timer_thread(void);