ruby-changes:62993
From: Benoit <ko1@a...>
Date: Thu, 17 Sep 2020 22:04:17 +0900 (JST)
Subject: [ruby-changes:62993] 9472d16061 (master): Call scheduler.block instead of scheduler.kernel_sleep for blocking Queue/SizedQueue operations
https://git.ruby-lang.org/ruby.git/commit/?id=9472d16061 From 9472d160619861201bad91560c06248fef8362dc Mon Sep 17 00:00:00 2001 From: Benoit Daloze <eregontp@g...> Date: Thu, 17 Sep 2020 14:45:44 +0200 Subject: Call scheduler.block instead of scheduler.kernel_sleep for blocking Queue/SizedQueue operations * scheduler.unblock was already already called before but with no corresponding scheduler.block * add test that Queue#pop makes the scheduler wait until it gets an element. diff --git a/test/fiber/scheduler.rb b/test/fiber/scheduler.rb index 1e7f60c..f7a773a 100644 --- a/test/fiber/scheduler.rb +++ b/test/fiber/scheduler.rb @@ -93,6 +93,7 @@ class Scheduler https://github.com/ruby/ruby/blob/trunk/test/fiber/scheduler.rb#L93 end ensure @urgent.each(&:close) + @urgent = nil end def current_time @@ -139,7 +140,7 @@ class Scheduler https://github.com/ruby/ruby/blob/trunk/test/fiber/scheduler.rb#L140 end if io = @urgent&.last - @urgent.last.write_nonblock('.') + io.write_nonblock('.') end end diff --git a/test/fiber/test_mutex.rb b/test/fiber/test_mutex.rb index 1f53ae1..baec559 100644 --- a/test/fiber/test_mutex.rb +++ b/test/fiber/test_mutex.rb @@ -115,6 +115,31 @@ class TestFiberMutex < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/fiber/test_mutex.rb#L115 assert processed == 3 end + def test_queue_pop_waits + queue = Queue.new + running = false + + thread = Thread.new do + scheduler = Scheduler.new + Thread.current.scheduler = scheduler + + result = nil + Fiber.schedule do + result = queue.pop + end + + running = true + scheduler.run + result + end + + Thread.pass until running + sleep 0.1 + + queue << :done + assert_equal :done, thread.value + end + def test_mutex_deadlock err = /No live threads left. Deadlock\?/ assert_in_out_err %W[-I#{__dir__} -], <<-RUBY, ['in synchronize'], err, success: false diff --git a/thread.c b/thread.c index 6b20716..b3b7a69 100644 --- a/thread.c +++ b/thread.c @@ -134,7 +134,7 @@ rb_thread_local_storage(VALUE thread) https://github.com/ruby/ruby/blob/trunk/thread.c#L134 static void sleep_hrtime(rb_thread_t *, rb_hrtime_t, unsigned int fl); static void sleep_forever(rb_thread_t *th, unsigned int fl); -static void rb_thread_sleep_deadly_allow_spurious_wakeup(void); +static void rb_thread_sleep_deadly_allow_spurious_wakeup(VALUE blocker); static int rb_threadptr_dead(rb_thread_t *th); static void rb_check_deadlock(rb_ractor_t *r); static int rb_threadptr_pending_interrupt_empty_p(const rb_thread_t *th); @@ -1485,11 +1485,11 @@ rb_thread_sleep_interruptible(void) https://github.com/ruby/ruby/blob/trunk/thread.c#L1485 } static void -rb_thread_sleep_deadly_allow_spurious_wakeup(void) +rb_thread_sleep_deadly_allow_spurious_wakeup(VALUE blocker) { VALUE scheduler = rb_thread_current_scheduler(); if (scheduler != Qnil) { - rb_scheduler_kernel_sleepv(scheduler, 0, NULL); + rb_scheduler_block(scheduler, blocker); } else { thread_debug("rb_thread_sleep_deadly_allow_spurious_wakeup\n"); sleep_forever(GET_THREAD(), SLEEP_DEADLOCKABLE); diff --git a/thread_sync.c b/thread_sync.c index 5b1e4f2..741bff6 100644 --- a/thread_sync.c +++ b/thread_sync.c @@ -483,9 +483,9 @@ rb_mutex_abandon_all(rb_mutex_t *mutexes) https://github.com/ruby/ruby/blob/trunk/thread_sync.c#L483 #endif static VALUE -rb_mutex_sleep_forever(VALUE time) +rb_mutex_sleep_forever(VALUE self) { - rb_thread_sleep_deadly_allow_spurious_wakeup(); + rb_thread_sleep_deadly_allow_spurious_wakeup(self); return Qnil; } @@ -516,7 +516,7 @@ rb_mutex_sleep(VALUE self, VALUE timeout) https://github.com/ruby/ruby/blob/trunk/thread_sync.c#L516 mutex_lock_uninterruptible(self); } else { if (NIL_P(timeout)) { - rb_ensure(rb_mutex_sleep_forever, Qnil, mutex_lock_uninterruptible, self); + rb_ensure(rb_mutex_sleep_forever, self, mutex_lock_uninterruptible, self); } else { rb_hrtime_t rel = rb_timeval2hrtime(&t); rb_ensure(rb_mutex_wait_for, (VALUE)&rel, mutex_lock_uninterruptible, self); @@ -904,9 +904,9 @@ rb_queue_push(VALUE self, VALUE obj) https://github.com/ruby/ruby/blob/trunk/thread_sync.c#L904 } static VALUE -queue_sleep(VALUE arg) +queue_sleep(VALUE self) { - rb_thread_sleep_deadly_allow_spurious_wakeup(); + rb_thread_sleep_deadly_allow_spurious_wakeup(self); return Qnil; } -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/