From 78d9fe69479d32214a52ad7291c3973f1b6b7f6f Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Thu, 22 Feb 2024 00:32:59 +1300 Subject: Ensure that exiting thread invokes end-of-life behaviour. (#10039) --- thread.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'thread.c') diff --git a/thread.c b/thread.c index 7be2a5f9f5..5dd26543ff 100644 --- a/thread.c +++ b/thread.c @@ -601,14 +601,12 @@ thread_do_start_proc(rb_thread_t *th) } } -static void +static VALUE thread_do_start(rb_thread_t *th) { native_set_thread_name(th); VALUE result = Qundef; - EXEC_EVENT_HOOK(th->ec, RUBY_EVENT_THREAD_BEGIN, th->self, 0, 0, 0, Qundef); - switch (th->invoke_type) { case thread_invoke_type_proc: result = thread_do_start_proc(th); @@ -627,11 +625,7 @@ thread_do_start(rb_thread_t *th) rb_bug("unreachable"); } - rb_fiber_scheduler_set(Qnil); - - th->value = result; - - EXEC_EVENT_HOOK(th->ec, RUBY_EVENT_THREAD_END, th->self, 0, 0, 0, Qundef); + return result; } void rb_ec_clear_current_thread_trace_func(const rb_execution_context_t *ec); @@ -662,12 +656,31 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start) // Ensure that we are not joinable. VM_ASSERT(UNDEF_P(th->value)); + int fiber_scheduler_closed = 0, event_thread_end_hooked = 0; + VALUE result = Qundef; + EC_PUSH_TAG(th->ec); if ((state = EC_EXEC_TAG()) == TAG_NONE) { - SAVE_ROOT_JMPBUF(th, thread_do_start(th)); + EXEC_EVENT_HOOK(th->ec, RUBY_EVENT_THREAD_BEGIN, th->self, 0, 0, 0, Qundef); + + SAVE_ROOT_JMPBUF(th, result = thread_do_start(th)); } - else { + + if (!fiber_scheduler_closed) { + fiber_scheduler_closed = 1; + rb_fiber_scheduler_set(Qnil); + } + + if (!event_thread_end_hooked) { + event_thread_end_hooked = 1; + EXEC_EVENT_HOOK(th->ec, RUBY_EVENT_THREAD_END, th->self, 0, 0, 0, Qundef); + } + + if (state == TAG_NONE) { + // This must be set AFTER doing all user-level code. At this point, the thread is effectively finished and calls to `Thread#join` will succeed. + th->value = result; + } else { errinfo = th->ec->errinfo; VALUE exc = rb_vm_make_jump_tag_but_local_jump(state, Qundef); -- cgit v1.2.3