summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Williams <samuel.williams@oriontransfer.co.nz>2021-02-12 16:54:52 +1300
committerSamuel Williams <samuel.williams@oriontransfer.co.nz>2021-03-30 18:38:42 +1300
commit92449e0e99ae0e44f0deec5e59a7146824872952 (patch)
tree932ebb123a3ad94d532775f6b4316741130744a2
parentaf1c587546c34190721bb8b72e86985e9b79bdc6 (diff)
Fix handling of timeout accessing scheduler outside of non-blocking context.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4173
-rw-r--r--cont.c15
-rw-r--r--lib/timeout.rb2
-rw-r--r--test/fiber/test_scheduler.rb16
-rw-r--r--test/fiber/test_timeout.rb2
4 files changed, 34 insertions, 1 deletions
diff --git a/cont.c b/cont.c
index 0d95a097b4..bdd308569c 100644
--- a/cont.c
+++ b/cont.c
@@ -1997,6 +1997,20 @@ rb_fiber_s_scheduler(VALUE klass)
/*
* call-seq:
+ * Fiber.current_scheduler -> obj or nil
+ *
+ * Returns the Fiber scheduler, that was last set for the current thread with Fiber.set_scheduler
+ * iff the current fiber is non-blocking.
+ *
+ */
+static VALUE
+rb_fiber_current_scheduler(VALUE klass)
+{
+ return rb_fiber_scheduler_current();
+}
+
+/*
+ * call-seq:
* Fiber.set_scheduler(scheduler) -> scheduler
*
* Sets the Fiber scheduler for the current thread. If the scheduler is set, non-blocking
@@ -3084,6 +3098,7 @@ Init_Cont(void)
rb_define_singleton_method(rb_cFiber, "blocking?", rb_fiber_s_blocking_p, 0);
rb_define_singleton_method(rb_cFiber, "scheduler", rb_fiber_s_scheduler, 0);
rb_define_singleton_method(rb_cFiber, "set_scheduler", rb_fiber_set_scheduler, 1);
+ rb_define_singleton_method(rb_cFiber, "current_scheduler", rb_fiber_current_scheduler, 0);
rb_define_singleton_method(rb_cFiber, "schedule", rb_fiber_s_schedule, -1);
diff --git a/lib/timeout.rb b/lib/timeout.rb
index dc8eb24a10..11db4be973 100644
--- a/lib/timeout.rb
+++ b/lib/timeout.rb
@@ -84,7 +84,7 @@ module Timeout
message ||= "execution expired".freeze
- if (scheduler = Fiber.scheduler)&.respond_to?(:timeout_after)
+ if (scheduler = Fiber.current_scheduler)&.respond_to?(:timeout_after)
return scheduler.timeout_after(sec, klass || Error, message, &block)
end
diff --git a/test/fiber/test_scheduler.rb b/test/fiber/test_scheduler.rb
index 72bde9fcc3..eeb0d67ec5 100644
--- a/test/fiber/test_scheduler.rb
+++ b/test/fiber/test_scheduler.rb
@@ -73,4 +73,20 @@ class TestFiberScheduler < Test::Unit::TestCase
thread.join
end
+
+ def test_current_scheduler
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ assert Fiber.scheduler
+ refute Fiber.current_scheduler
+
+ Fiber.schedule do
+ assert Fiber.current_scheduler
+ end
+ end
+
+ thread.join
+ end
end
diff --git a/test/fiber/test_timeout.rb b/test/fiber/test_timeout.rb
index c17092b8e6..5493606be0 100644
--- a/test/fiber/test_timeout.rb
+++ b/test/fiber/test_timeout.rb
@@ -37,6 +37,8 @@ class TestFiberTimeout < Test::Unit::TestCase
scheduler = Scheduler.new
Fiber.set_scheduler scheduler
+ assert_nil Fiber.current_scheduler
+
Timeout.timeout(1) do
message = MESSAGE
end