From 91f0a5a11006d7d6ba72c4d9128ae909c3adaaf8 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Wed, 4 Feb 2026 13:12:42 +0100 Subject: [3.3] Fix deadlock on th->interrupt_lock after fork [Bug #21860] If a thread was holding this lock before fork, it will not exist in the child process. We should re-initialize these locks as we do with the VM locks when forking. Co-Authored-By: John Hawthorn Co-authored-by: Aaron Patterson --- bootstraptest/test_fork.rb | 9 +++++++-- thread.c | 1 + thread_pthread.c | 5 +++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/bootstraptest/test_fork.rb b/bootstraptest/test_fork.rb index 0cdfb5ab24..7a613026ad 100644 --- a/bootstraptest/test_fork.rb +++ b/bootstraptest/test_fork.rb @@ -88,14 +88,19 @@ assert_equal 'ok', %q{ 10.times do pid = fork{ exit!(0) } - deadline = now + 1 - until Process.waitpid(pid, Process::WNOHANG) + deadline = now + 10 + while true + _, status = Process.waitpid2(pid, Process::WNOHANG) + break if status if now > deadline Process.kill(:KILL, pid) raise "failed" end sleep 0.001 end + unless status.success? + raise "child exited with status #{status}" + end rescue NotImplementedError end :ok diff --git a/thread.c b/thread.c index 1fe1e01595..b2b5177d4e 100644 --- a/thread.c +++ b/thread.c @@ -4698,6 +4698,7 @@ static void terminate_atfork_i(rb_thread_t *th, const rb_thread_t *current_th) { if (th != current_th) { + rb_native_mutex_initialize(&th->interrupt_lock); rb_mutex_abandon_keeping_mutexes(th); rb_mutex_abandon_locking_mutex(th); thread_cleanup_func(th, TRUE); diff --git a/thread_pthread.c b/thread_pthread.c index ed624416aa..77994796f1 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -1531,6 +1531,11 @@ thread_sched_atfork(struct rb_thread_sched *sched) vm->ractor.sched.running_cnt = 0; rb_native_mutex_initialize(&vm->ractor.sched.lock); +#if VM_CHECK_MODE > 0 + vm->ractor.sched.lock_owner = NULL; + vm->ractor.sched.locked = false; +#endif + // rb_native_cond_destroy(&vm->ractor.sched.cond); rb_native_cond_initialize(&vm->ractor.sched.cond); rb_native_cond_initialize(&vm->ractor.sched.barrier_complete_cond); -- cgit v1.2.3