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/