Tue Nov 17 16:22:22 2009  Nobuyoshi Nakada  <nobu@ruby-lang.org>

	* eval.c (rb_thread_start_0, rb_thread_start_1): should call star
	  timer after added new thread to thread list.  [ruby-core:25613]

Tue Nov 17 16:22:22 2009  Nobuyoshi Nakada  <nobu@ruby-lang.org>

	* eval.c (rb_thread_start_timer): start to catch SIGVTALRM together
	  with timer thread.   [ruby-core:25606]

	* eval.c (rb_thread_atfork): stop timer thread.

Index: test/ruby/test_signal.rb
===================================================================
--- test/ruby/test_signal.rb.orig	2007-02-13 00:01:19.000000000 +0100
+++ test/ruby/test_signal.rb	2011-05-31 23:50:24.190777320 +0200
@@ -65,4 +65,11 @@ class TestSignal < Test::Unit::TestCase
       w0.close
     end
   end
+
+  def test_child_vtalrm
+    return unless have_fork?	# snip this test
+    pid = fork {100_000.times{ 1+1 }}
+    pid, status = Process.wait2(pid)
+    assert_equal(false, status.signaled?, '[ruby-core:25606]')
+  end
 end
Index: eval.c
===================================================================
--- eval.c.orig	2011-05-31 23:50:22.000000000 +0200
+++ eval.c	2011-06-01 00:04:07.744777223 +0200
@@ -5599,6 +5599,17 @@ stack_check()
     }
 }
 
+static void
+eval_check_tick()
+{
+    static int tick;
+    if ((++tick & 0xff) == 0) {
+	CHECK_INTS;		/* better than nothing */
+	stack_check();
+	rb_gc_finalize_deferred();
+    }
+}
+
 static int last_call_status;
 
 #define CSTAT_PRIV  1
@@ -5830,7 +5841,6 @@ rb_call0(klass, recv, id, oid, argc, arg
     NODE *b2;		/* OK */
     volatile VALUE result = Qnil;
     int itr;
-    static int tick;
     TMP_PROTECT;
     volatile int safe = -1;
 
@@ -5849,11 +5859,7 @@ rb_call0(klass, recv, id, oid, argc, arg
 	break;
     }
 
-    if ((++tick & 0xff) == 0) {
-	CHECK_INTS;		/* better than nothing */
-	stack_check();
-	rb_gc_finalize_deferred();
-    }
+    eval_check_tick();
     if (argc < 0) {
 	VALUE tmp;
 	VALUE *nargv;
@@ -6117,13 +6123,14 @@ rb_call(klass, recv, mid, argc, argv, sc
     ent = cache + EXPR1(klass, mid);
     if (ent->mid == mid && ent->klass == klass) {
 	if (!ent->method)
-	    return method_missing(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0);
+	    goto nomethod;
 	klass = ent->origin;
 	id    = ent->mid0;
 	noex  = ent->noex;
 	body  = ent->method;
     }
     else if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) {
+      nomethod:
 	if (scope == 3) {
 	    return method_missing(recv, mid, argc, argv, CSTAT_SUPER);
 	}
@@ -12099,6 +12106,12 @@ rb_thread_alloc(klass)
 
 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)
@@ -12181,7 +12194,9 @@ rb_thread_start_timer()
     void *args[2];
     static pthread_cond_t start = PTHREAD_COND_INITIALIZER;
 
-    if (!thread_init) return;
+    if (thread_init) return;
+    if (rb_thread_alone()) return;
+    CATCH_VTALRM();
     args[0] = &time_thread;
     args[1] = &start;
     safe_mutex_lock(&time_thread.lock);
@@ -12223,6 +12238,8 @@ rb_thread_start_timer()
     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;
@@ -12246,6 +12263,14 @@ rb_thread_stop_timer()
 int rb_thread_tick = THREAD_TICK;
 #endif
 
+#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE)
+#define START_TIMER() (thread_init ? (void)0 : rb_thread_start_timer())
+#define STOP_TIMER() (rb_thread_stop_timer())
+#else
+#define START_TIMER() ((void)0)
+#define STOP_TIMER() ((void)0)
+#endif
+
 static VALUE
 rb_thread_start_0(fn, arg, th)
     VALUE (*fn)();
@@ -12263,18 +12288,6 @@ rb_thread_start_0(fn, arg, th)
 		 "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
-
-	rb_thread_start_timer();
-#endif
-    }
-
     if (THREAD_SAVE_CONTEXT(curr_thread)) {
 	return thread;
     }
@@ -12297,6 +12310,7 @@ rb_thread_start_0(fn, arg, th)
 	th->priority = curr_thread->priority;
 	th->thgroup = curr_thread->thgroup;
     }
+    START_TIMER();
 
     PUSH_TAG(PROT_THREAD);
     if ((state = EXEC_TAG()) == 0) {
@@ -13022,6 +13036,7 @@ rb_thread_atfork()
     main_thread = curr_thread;
     curr_thread->next = curr_thread;
     curr_thread->prev = curr_thread;
+    STOP_TIMER();
 }
 
 
