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

ruby-changes:62996

From: Benoit <ko1@a...>
Date: Thu, 17 Sep 2020 22:17:33 +0900 (JST)
Subject: [ruby-changes:62996] 264889ec3d (master): Fix Mutex#unlock with a scheduler and thread contention

https://git.ruby-lang.org/ruby.git/commit/?id=264889ec3d

From 264889ec3d3d38fc1fd23c4fb48402f1367a8deb Mon Sep 17 00:00:00 2001
From: Benoit Daloze <eregontp@g...>
Date: Thu, 17 Sep 2020 15:15:43 +0200
Subject: Fix Mutex#unlock with a scheduler and thread contention

* It would hit "[BUG] unexpected THREAD_STOPPED" before.

diff --git a/test/fiber/test_mutex.rb b/test/fiber/test_mutex.rb
index baec559..a70c699 100644
--- a/test/fiber/test_mutex.rb
+++ b/test/fiber/test_mutex.rb
@@ -47,6 +47,29 @@ class TestFiberMutex < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/fiber/test_mutex.rb#L47
     thread.join
   end
 
+  def test_mutex_thread
+    mutex = Mutex.new
+    mutex.lock
+
+    thread = Thread.new do
+      scheduler = Scheduler.new
+      Thread.current.scheduler = scheduler
+
+      Fiber.schedule do
+        mutex.lock
+        sleep 0.1
+        mutex.unlock
+      end
+
+      scheduler.run
+    end
+
+    sleep 0.1
+    mutex.unlock
+
+    thread.join
+  end
+
   def test_condition_variable
     mutex = Mutex.new
     condition = ConditionVariable.new
diff --git a/thread_sync.c b/thread_sync.c
index 741bff6..10ff9c4 100644
--- a/thread_sync.c
+++ b/thread_sync.c
@@ -402,20 +402,20 @@ rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t *th, rb_fiber_t *fiber) https://github.com/ruby/ruby/blob/trunk/thread_sync.c#L402
 
             if (cur->th->scheduler != Qnil) {
                 rb_scheduler_unblock(cur->th->scheduler, cur->self, rb_fiberptr_self(cur->fiber));
+            } else {
+                switch (cur->th->status) {
+                  case THREAD_RUNNABLE: /* from someone else calling Thread#run */
+                  case THREAD_STOPPED_FOREVER: /* likely (rb_mutex_lock) */
+                    rb_threadptr_interrupt(cur->th);
+                    goto found;
+                  case THREAD_STOPPED: /* probably impossible */
+                    rb_bug("unexpected THREAD_STOPPED");
+                  case THREAD_KILLED:
+                    /* not sure about this, possible in exit GC? */
+                    rb_bug("unexpected THREAD_KILLED");
+                    continue;
+                }
             }
-
-	    switch (cur->th->status) {
-	      case THREAD_RUNNABLE: /* from someone else calling Thread#run */
-	      case THREAD_STOPPED_FOREVER: /* likely (rb_mutex_lock) */
-		rb_threadptr_interrupt(cur->th);
-		goto found;
-	      case THREAD_STOPPED: /* probably impossible */
-		rb_bug("unexpected THREAD_STOPPED");
-	      case THREAD_KILLED:
-                /* not sure about this, possible in exit GC? */
-		rb_bug("unexpected THREAD_KILLED");
-		continue;
-	    }
 	}
       found:
 	while (*th_mutex != mutex) {
-- 
cgit v0.10.2


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

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