summaryrefslogtreecommitdiff
path: root/thread.c
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2024-05-29 10:02:15 -0700
committerTakashi Kokubun <takashikkbn@gmail.com>2024-05-29 10:02:15 -0700
commita8b2317d16fa172edd3cd7e6fcb3bc694287d109 (patch)
tree322eaa670f8c69e51e303001780da1d8ee146651 /thread.c
parent6aaf673e4d3fa1f8a90e6006aadefddcb87fe1de (diff)
merge revision(s) 78d9fe69479d32214a52ad7291c3973f1b6b7f6f: [Backport #20286]
Ensure that exiting thread invokes end-of-life behaviour. (#10039)
Diffstat (limited to 'thread.c')
-rw-r--r--thread.c33
1 files changed, 23 insertions, 10 deletions
diff --git a/thread.c b/thread.c
index 756e98414c..74f0d13109 100644
--- a/thread.c
+++ b/thread.c
@@ -602,14 +602,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);
@@ -628,11 +626,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);
@@ -665,12 +659,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);