Ruby-1.8.6系のSIGVTALRMバグ

1.8.7系では修正されているのですが、1.8.6系ではp420を含めてバックポートされていないようです。

こんなの

Virtual timer expired

以下は1.8.7系での修正を1.8.6系へ移植したものです。

diff -Naur ruby-1.8.6-p420//eval.c ruby-1.8.6-p420-SIGVTALRM//eval.c
--- ruby-1.8.6-p420//eval.c	2010-06-22 05:32:00.000000000 +0900
+++ ruby-1.8.6-p420-SIGVTALRM//eval.c	2010-10-26 10:48:20.658203999 +0900
@@ -11953,6 +11953,12 @@
 
 static int thread_init;
 
+#if defined(POSIX_SIGNAL)
+#define CATCH_VTALRM() posix_signal(SIGVTALRM, catch_timer)
+#else
+#define CATCH_VTALRM() signal(SIGVTALRM, catch_timer)
+#endif
+
 #if defined(_THREAD_SAFE)
 static void
 catch_timer(sig)
@@ -12036,6 +12042,8 @@
     static pthread_cond_t start = PTHREAD_COND_INITIALIZER;
 
     if (!thread_init) return;
+    if (rb_thread_alone()) return;
+    CATCH_VTALRM();
     args[0] = &time_thread;
     args[1] = &start;
     safe_mutex_lock(&time_thread.lock);
@@ -12078,6 +12086,8 @@
     struct itimerval tval;
 
     if (thread_init) return;
+    if (rb_thread_alone()) return;
+    CATCH_VTALRM();
     tval.it_interval.tv_sec = 0;
     tval.it_interval.tv_usec = 10000;
     tval.it_value = tval.it_interval;
@@ -12117,17 +12127,11 @@
 		 "can't start a new thread (frozen ThreadGroup)");
     }
 
-    if (!thread_init) {
 #if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE)
-#if defined(POSIX_SIGNAL)
-	posix_signal(SIGVTALRM, catch_timer);
-#else
-	signal(SIGVTALRM, catch_timer);
-#endif
-
+    if (!thread_init) {
 	rb_thread_start_timer();
-#endif
     }
+#endif
 
     if (THREAD_SAVE_CONTEXT(curr_thread)) {
 	return thread;
@@ -12876,6 +12880,9 @@
     main_thread = curr_thread;
     curr_thread->next = curr_thread;
     curr_thread->prev = curr_thread;
+#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE)
+    rb_thread_stop_timer();
+#endif
 }

バージョンコードが同じだと色々困るので、version.h にも手をいれて使っています。

diff -Naur ruby-1.8.6-p420//version.h ruby-1.8.6-p420-SIGVTALRM//version.h
--- ruby-1.8.6-p420//version.h	2010-09-02 00:14:52.000000000 +0900
+++ ruby-1.8.6-p420-SIGVTALRM//version.h	2010-10-26 10:53:51.608203999 +0900
@@ -1,7 +1,7 @@
 #define RUBY_VERSION "1.8.6"
-#define RUBY_RELEASE_DATE "2010-09-02"
+#define RUBY_RELEASE_DATE "2010-10-26"
 #define RUBY_VERSION_CODE 186
-#define RUBY_RELEASE_CODE 20100902
+#define RUBY_RELEASE_CODE 20101026
 #define RUBY_PATCHLEVEL 420
 
 #define RUBY_VERSION_MAJOR 1