Eric Wong <normalperson / yhbt.net> 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 <normalperson / yhbt.net>
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 <thread.h>
 #endif
 
+#if defined(HAVE_FCNTL_H)
+#include <fcntl.h>
+#elif defined(HAVE_SYS_FCNTL_H)
+#include <sys/fcntl.h>
+#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