From: Eric Wong Date: 2011-06-18T08:55:19+09:00 Subject: [ruby-core:37211] Re: [Request for Comment] avoid timer thread Eric Wong wrote: > I'm testing the following fix on my server: > http://bogomips.org/ruby.git/commit/?h=sleepy-timer-thread&id=9154363119 One more patch below: http://bogomips.org/ruby.git/commit/?h=sleepy-timer-thread&id=853275cb9ec From 853275cb9ecdee021c0426f0e009f69b0999256a Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 17 Jun 2011 16:20:48 -0700 Subject: [PATCH] thread_pthread: prevent deadlock from signal spam I managed to get the following code snippet to deadlock on a dual-core machine due to blocked write() call in rb_thread_wakeup_timer_thread(): ------------------------- 8< ---------------------------- n = 0 parent = $$ trap(:USR1) { n += 1 } fork do Process.kill(:USR1, parent) while true end p(Process.waitpid(fork { exit!(0) })) while true ------------------------- 8< ---------------------------- --- thread_pthread.c | 20 +++++++++++++++++++- 1 files changed, 19 insertions(+), 1 deletions(-) diff --git a/thread_pthread.c b/thread_pthread.c index 3d99974..c2771ac 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -20,6 +20,12 @@ #include #endif +#if defined(HAVE_FCNTL_H) +#include +#elif defined(HAVE_SYS_FCNTL_H) +#include +#endif + static void native_mutex_lock(pthread_mutex_t *lock); static void native_mutex_unlock(pthread_mutex_t *lock); static int native_mutex_trylock(pthread_mutex_t *lock); @@ -1006,7 +1012,8 @@ rb_thread_wakeup_timer_thread(void) const char *buff = "!"; int err; if ((err = write(timer_thread_pipe[1], buff, 1)) <= 0) { - rb_bug_errno("rb_thread_wakeup_timer_thread - write", errno); + if (errno != EAGAIN) + rb_bug_errno("rb_thread_wakeup_timer_thread - write", errno); } } } @@ -1107,6 +1114,17 @@ rb_thread_create_timer_thread(void) exit(EXIT_FAILURE); } timer_thread_pid = getpid(); + err = fcntl(timer_thread_pipe[1], F_GETFL); + if (err == -1) { + fprintf(stderr, "[FATAL] Failed to get flags for timer thread pipe (errno: %d)\n", errno); + exit(EXIT_FAILURE); + } + err = fcntl(timer_thread_pipe[1], F_SETFL, err | O_NONBLOCK); + if (err == -1) { + fprintf(stderr, "[FATAL] Failed to set flags for timer thread pipe (errno: %d)\n", errno); + exit(EXIT_FAILURE); + } + timer_thread_pid = getpid(); } rb_disable_interrupt(); /* only timer thread recieve signal */ } -- Eric Wong