From: Eric Wong Date: 2012-02-03T07:19:53+09:00 Subject: [ruby-core:42329] [RFC/PATCH] reinit signal_thread_list_lock atfork This issue was found under Ruby 1.9.3 (-p0 presumably), but probably also applies to trunk. I cannot reproduce the original issue since I don't have access to a FreeBSD machine, so this patch is a stab-in-the-dark for me. I've only ensured this patch doesn't break existing behavior under Linux/NPTL, not that it fixes a real problem under FreeBSD. Original reports (for unicorn) are linked below. Gmane threading didn't work because some messages were too big for the ML. http://mid.gmane.org/CB4DE1F5.7D9%25philipp.bruell@skrill.com http://mid.gmane.org/20120201181445.GA31624@dcvr.yhbt.net http://mid.gmane.org/20120202193136.GA1478@dcvr.yhbt.net This change is also pullable from the "sig-th-list-atfork" branch on git://bogomips.org/ruby.git From 95ab472c90c27e6e964be3ebc156d618a435b0df Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 2 Feb 2012 21:40:58 +0000 Subject: [PATCH] thread_pthread.c (gvl_atfork): reinitialize signal_thread_list_lock signal_thread_list_lock may be held in the timer thread during fork(), causing the lock to be held in the child process by a non-existent thread. Reinitializing this should allow Ruby signal handlers to continue working after fork() This change may fix a problem exhibited with the following script under a FreeBSD jail, running FreeBSD 8.2-STABLE on amd64. When SIGQUIT is sent to the parent, the child will spin constantly instead of running it's signal handler: -------------------------- 8< ---------------------------- pid = fork do r, w = IO.pipe trap(:QUIT) do puts "SIGQUIT received in child, exiting" w.close end r.read end trap(:QUIT) do puts "SIGQUIT received in parent, killing child" Process.kill(:QUIT, pid) p Process.waitpid2(pid) exit end sleep 1 # wait for child to setup sig handler puts "Child ready on #{pid}, parent on #$$" sleep -------------------------- 8< ---------------------------- --- thread_pthread.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/thread_pthread.c b/thread_pthread.c index 52997ec..51c4a20 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -157,6 +157,9 @@ gvl_destroy(rb_vm_t *vm) static void gvl_atfork(rb_vm_t *vm) { +#ifdef USE_SIGNAL_THREAD_LIST + native_mutex_initialize(&signal_thread_list_lock); +#endif gvl_init(vm); gvl_acquire(vm, GET_THREAD()); } -- Eric Wong