[前][次][番号順一覧][スレッド一覧]

ruby-changes:38819

From: kosaki <ko1@a...>
Date: Mon, 15 Jun 2015 07:52:16 +0900 (JST)
Subject: [ruby-changes:38819] kosaki:r50900 (trunk): * thread.c (thread_start_func_2): don't interrupt when last thread exit

kosaki	2015-06-15 07:52:01 +0900 (Mon, 15 Jun 2015)

  New Revision: 50900

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=50900

  Log:
    * thread.c (thread_start_func_2): don't interrupt when last thread exit
      unless main thread is already exited. Otherwise main thread could be
      wrongly interrupted when it uses rb_thread_call_without_gvl(). Patch
      by Takehiro Kubo. [Bug #11237][ruby-dev:49044][GH-898]
    * test/-ext-/gvl/test_last_thread.rb: new test for the above fix.
    * ext/-test-/gvl/call_without_gvl/call_without_gvl.c: new ext for the
      above test.
    * ext/-test-/gvl/call_without_gvl/extconf.rb: ditto.

  Added directories:
    trunk/ext/-test-/gvl/
    trunk/ext/-test-/gvl/call_without_gvl/
    trunk/test/-ext-/gvl/
  Added files:
    trunk/ext/-test-/gvl/call_without_gvl/call_without_gvl.c
    trunk/ext/-test-/gvl/call_without_gvl/extconf.rb
    trunk/test/-ext-/gvl/test_last_thread.rb
  Modified files:
    trunk/ChangeLog
    trunk/thread.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 50899)
+++ ChangeLog	(revision 50900)
@@ -1,3 +1,16 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sat Jun 13 07:21:18 2015  KOSAKI Motohiro  <kosaki.motohiro@g...>
+
+	* thread.c (thread_start_func_2): don't interrupt when last thread
+	  exit unless main thread is already exited. Otherwise main thread
+	  could be wrongly interrupted when it uses rb_thread_call_without_gvl().
+	  Patch by Takehiro Kubo. [Bug #11237][ruby-dev:49044][GH-898]
+
+	* test/-ext-/gvl/test_last_thread.rb: new test for the above fix.
+
+	* ext/-test-/gvl/call_without_gvl/call_without_gvl.c: new ext for
+	  the above test.
+	* ext/-test-/gvl/call_without_gvl/extconf.rb: ditto.
+
 Mon Jun 15 00:14:33 2015  Tanaka Akira  <akr@f...>
 
 	* ext/pathname/lib/pathname.rb (descend): Blockless form supported.
Index: thread.c
===================================================================
--- thread.c	(revision 50899)
+++ thread.c	(revision 50900)
@@ -629,7 +629,7 @@ thread_start_func_2(rb_thread_t *th, VAL https://github.com/ruby/ruby/blob/trunk/thread.c#L629
 
 	/* delete self other than main thread from living_threads */
 	rb_vm_living_threads_remove(th->vm, th);
-	if (rb_thread_alone()) {
+	if (main_th->status == THREAD_KILLED && rb_thread_alone()) {
 	    /* I'm last thread. wake up main thread from rb_thread_terminate_all */
 	    rb_threadptr_interrupt(main_th);
 	}
Index: ext/-test-/gvl/call_without_gvl/call_without_gvl.c
===================================================================
--- ext/-test-/gvl/call_without_gvl/call_without_gvl.c	(revision 0)
+++ ext/-test-/gvl/call_without_gvl/call_without_gvl.c	(revision 50900)
@@ -0,0 +1,35 @@ https://github.com/ruby/ruby/blob/trunk/ext/-test-/gvl/call_without_gvl/call_without_gvl.c#L1
+#include "ruby/ruby.h"
+#include "ruby/thread.h"
+#include <sys/select.h>
+
+static void*
+native_sleep_callback(void *data)
+{
+    struct timeval *timeval = data;
+    select(0, NULL, NULL, NULL, timeval);
+
+    return NULL;
+}
+
+
+static VALUE
+thread_runnable_sleep(VALUE thread, VALUE timeout)
+{
+    struct timeval timeval;
+
+    if (NIL_P(timeout)) {
+	rb_raise(rb_eArgError, "timeout must be non nil");
+    }
+
+    timeval = rb_time_interval(timeout);
+
+    rb_thread_call_without_gvl(native_sleep_callback, &timeval, RUBY_UBF_IO, NULL);
+
+    return thread;
+}
+
+void
+Init_call_without_gvl(void)
+{
+    rb_define_method(rb_cThread, "__runnable_sleep__", thread_runnable_sleep, 1);
+}
Index: ext/-test-/gvl/call_without_gvl/extconf.rb
===================================================================
--- ext/-test-/gvl/call_without_gvl/extconf.rb	(revision 0)
+++ ext/-test-/gvl/call_without_gvl/extconf.rb	(revision 50900)
@@ -0,0 +1 @@
+create_makefile("-test-/gvl/call_without_gvl")
Index: test/-ext-/gvl/test_last_thread.rb
===================================================================
--- test/-ext-/gvl/test_last_thread.rb	(revision 0)
+++ test/-ext-/gvl/test_last_thread.rb	(revision 50900)
@@ -0,0 +1,22 @@ https://github.com/ruby/ruby/blob/trunk/test/-ext-/gvl/test_last_thread.rb#L1
+class TestLastThread < Test::Unit::TestCase
+
+  # [Bug #11237]
+  def test_last_thread
+
+    assert_separately([], <<-"end;") #do
+      require '-test-/gvl/call_without_gvl'
+
+      Thread.new {
+        sleep 0.2
+      }
+
+      t0 = Time.now
+      Thread.current.__runnable_sleep__ 1
+      t1 = Time.now
+      t = t1 - t0
+
+      assert_operator(t, :>=, 1)
+    end;
+  end
+end
+

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]