From: Eric Wong Date: 2011-06-18T10:05:24+09:00 Subject: [ruby-core:37215] Re: [Request for Comment] avoid timer thread SASADA Koichi wrote: > (2011/06/14 3:37), Eric Wong wrote: > > I'll just wait on the 1.9.3 version for now based on ko1's response \o/ > > Here is my current patch. This is only tested on Linux on VirtualBox. > I'm happy if you test on the other environment. > > http://www.atdot.net/sp/view/yonwml/readonly > http://www.atdot.net/sp/raw/yonwml In case there are C extensions or FFI wrappers that fork() directly without using Ruby, I prefer pthread_atfork() to close the pipe: http://bogomips.org/ruby.git/commit/?h=sleepy-timer-thread&id=b8bb000953b From b8bb000953b0c9d892bd9314054b80a3fe2eec48 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 17 Jun 2011 17:50:32 -0700 Subject: [PATCH] thread_pthread.c: avoid pipe leak to extensions that fork() internally Some extensions (or FFI wrapper) may call fork() directly and bypass Ruby-specific hooks for fork(). --- thread_pthread.c | 25 +++++++++++++++++++------ 1 files changed, 19 insertions(+), 6 deletions(-) diff --git a/thread_pthread.c b/thread_pthread.c index c2771ac..5f61df4 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -1085,14 +1085,32 @@ thread_timer(void *p) return NULL; } +static void close_timer_thread_pipe(void) +{ + if (timer_thread_pipe[0] && close(timer_thread_pipe[0]) < 0) { rb_bug_errno("native_stop_timer_thread - close(ttp[0])", errno); } + if (timer_thread_pipe[1] && close(timer_thread_pipe[1]) < 0) { rb_bug_errno("native_stop_timer_thread - close(ttp[1])", errno); } + timer_thread_pipe[0] = timer_thread_pipe[1] = 0; +} + static void rb_thread_create_timer_thread(void) { + static int atfork_installed; + int err; + + if (!atfork_installed) { + err = pthread_atfork(NULL, NULL, close_timer_thread_pipe); + if (err != 0) { + fprintf(stderr, "[FATAL] Failed to install atfork hook for timer thread pipe (errno: %d)\n", err); + exit(EXIT_FAILURE); + } + atfork_installed = 1; + } + rb_enable_interrupt(); if (!timer_thread_id) { pthread_attr_t attr; - int err; pthread_attr_init(&attr); #ifdef PTHREAD_STACK_MIN @@ -1151,11 +1169,6 @@ native_reset_timer_thread(void) if (TT_DEBUG) fprintf(stderr, "reset timer thread\n"); timer_thread_id = 0; timer_thread_pid = 0; - - /* close */ - if (timer_thread_pipe[0] && close(timer_thread_pipe[0]) < 0) { rb_bug_errno("native_stop_timer_thread - close(ttp[0])", errno); } - if (timer_thread_pipe[1] && close(timer_thread_pipe[1]) < 0) { rb_bug_errno("native_stop_timer_thread - close(ttp[1])", errno); } - timer_thread_pipe[0] = timer_thread_pipe[1] = 0; } #ifdef HAVE_SIGALTSTACK -- Eric Wong