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

ruby-changes:49158

From: nobu <ko1@a...>
Date: Fri, 15 Dec 2017 16:27:09 +0900 (JST)
Subject: [ruby-changes:49158] nobu:r61274 (trunk): thread.c: fix deadlock

nobu	2017-12-15 16:27:04 +0900 (Fri, 15 Dec 2017)

  New Revision: 61274

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

  Log:
    thread.c: fix deadlock
    
    * thread.c (thread_join_sleep): the target thread may exit during
      `RUBY_VM_CHECK_INTS_BLOCKING`, but `sleep_forever` does not
      consider the condition change to wait.
      [ruby-core:84248] [Bug #14181]

  Modified files:
    trunk/test/ruby/test_thread.rb
    trunk/thread.c
Index: test/ruby/test_thread.rb
===================================================================
--- test/ruby/test_thread.rb	(revision 61273)
+++ test/ruby/test_thread.rb	(revision 61274)
@@ -1249,4 +1249,42 @@ q.pop https://github.com/ruby/ruby/blob/trunk/test/ruby/test_thread.rb#L1249
       end
     _end
   end
+
+  def test_signal_at_join
+    if /mswin|mingw/ =~ RUBY_PLATFORM
+      skip "can't trap a signal from another process on Windows"
+      # opt = {new_pgroup: true}
+    end
+    assert_separately([], "#{<<~"{#"}\n#{<<~'};'}")
+    {#
+      n = 1000
+      sig = :INT
+      trap(sig) {}
+      IO.popen([EnvUtil.rubybin, "-e", "#{<<~"{#1"}\n#{<<~'};#1'}"], "r+") do |f|
+        tpid = #{$$}
+        sig = :#{sig}
+        {#1
+          STDOUT.sync = true
+          while gets
+            puts
+            Process.kill(sig, tpid)
+          end
+        };#1
+        assert_nothing_raised do
+          n.times do
+            w = Thread.start do
+              sleep 30
+            end
+            begin
+              f.puts
+              f.gets
+            ensure
+              w.kill
+              w.join
+            end
+          end
+        end
+      end
+    };
+  end
 end
Index: thread.c
===================================================================
--- thread.c	(revision 61273)
+++ thread.c	(revision 61274)
@@ -883,7 +883,13 @@ thread_join_sleep(VALUE arg) https://github.com/ruby/ruby/blob/trunk/thread.c#L883
 
     while (target_th->status != THREAD_KILLED) {
 	if (forever) {
-	    sleep_forever(th, TRUE, FALSE);
+	    th->status = THREAD_STOPPED_FOREVER;
+	    th->vm->sleeper++;
+	    rb_check_deadlock(th->vm);
+	    native_sleep(th, 0);
+	    th->vm->sleeper--;
+	    RUBY_VM_CHECK_INTS_BLOCKING(th->ec);
+	    th->status = THREAD_RUNNABLE;
 	}
 	else {
 	    double now = timeofday();

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

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