From ff96f9dc1cd7074f0ff26d7955ec201bc298297c Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Thu, 2 Jul 2026 20:47:37 +0000 Subject: [PATCH] thread: build a new Ractor's interrupt queue on its own main thread Defer creating a Ractor main thread's pending-interrupt queue and mask stack from thread_create_core (the creating thread) to thread_start_func_2 (the new Ractor's own main thread). The mask stack starts empty rather than duplicating the creating thread's, so a new Ractor does not inherit its Thread.handle_interrupt state. Co-Authored-By: Claude Opus 4.8 (1M context) --- thread.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/thread.c b/thread.c index 0d58e75760..22f0fe8e0f 100644 --- a/thread.c +++ b/thread.c @@ -680,6 +680,13 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start) r->r_stdin = rb_io_prep_stdin(); r->r_stdout = rb_io_prep_stdout(); r->r_stderr = rb_io_prep_stderr(); + + /* Build the interrupt queue and mask stack here, on the new Ractor's + * own main thread, instead of carrying over the ones the creating + * thread made. The mask stack starts empty so a new Ractor does not + * inherit the creating thread's Thread.handle_interrupt state. */ + th->pending_interrupt_queue = rb_ary_hidden_new(0); + th->pending_interrupt_mask_stack = rb_ary_hidden_new(0); } RB_VM_UNLOCK(); } @@ -887,10 +894,19 @@ thread_create_core(VALUE thval, struct thread_create_params *params) th->priority = current_th->priority; th->thgroup = current_th->thgroup; - th->pending_interrupt_queue = rb_ary_hidden_new(0); - th->pending_interrupt_queue_checked = 0; - th->pending_interrupt_mask_stack = rb_ary_dup(current_th->pending_interrupt_mask_stack); - RBASIC_CLEAR_CLASS(th->pending_interrupt_mask_stack); + if (th->invoke_type == thread_invoke_type_ractor_proc) { + /* A new Ractor's main thread builds these on start + * (thread_start_func_2); leave them unset until then. */ + th->pending_interrupt_queue = 0; + th->pending_interrupt_mask_stack = 0; + th->pending_interrupt_queue_checked = 0; + } + else { + th->pending_interrupt_queue = rb_ary_hidden_new(0); + th->pending_interrupt_queue_checked = 0; + th->pending_interrupt_mask_stack = rb_ary_dup(current_th->pending_interrupt_mask_stack); + RBASIC_CLEAR_CLASS(th->pending_interrupt_mask_stack); + } rb_native_mutex_initialize(&th->interrupt_lock);