summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Williams <samuel.williams@oriontransfer.co.nz>2023-06-03 12:41:36 +0900
committerGitHub <noreply@github.com>2023-06-03 12:41:36 +0900
commit0402193723647b8c4f57b1453fe2192ad2788d12 (patch)
tree93f20957e7e0f3ee0f5af206fa4a481e21790539
parenta4d92475f69f0ca3dba0f497253e600c7f90a0ad (diff)
Fix `Thread#join(timeout)` when running inside the fiber scheduler. (#7903)
Notes
Notes: Merged-By: ioquatix <samuel@codeotaku.com>
-rw-r--r--test/fiber/test_thread.rb22
-rw-r--r--thread.c5
2 files changed, 27 insertions, 0 deletions
diff --git a/test/fiber/test_thread.rb b/test/fiber/test_thread.rb
index 5c25c43de2..6fae266955 100644
--- a/test/fiber/test_thread.rb
+++ b/test/fiber/test_thread.rb
@@ -20,6 +20,28 @@ class TestFiberThread < Test::Unit::TestCase
assert_equal :done, thread.value
end
+ def test_thread_join_timeout
+ sleeper = nil
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ sleeper = Thread.new{sleep}
+ sleeper.join(0.1)
+ end
+
+ scheduler.run
+ end
+
+ thread.join
+
+ assert_predicate sleeper, :alive?
+ ensure
+ sleeper&.kill
+ end
+
def test_thread_join_implicit
sleeping = false
finished = false
diff --git a/thread.c b/thread.c
index e521d13fb5..5dc0c269f2 100644
--- a/thread.c
+++ b/thread.c
@@ -1053,6 +1053,10 @@ thread_join_sleep(VALUE arg)
if (scheduler != Qnil) {
rb_fiber_scheduler_block(scheduler, target_th->self, p->timeout);
+ // Check if the target thread is finished after blocking:
+ if (thread_finished(target_th)) break;
+ // Otherwise, a timeout occurred:
+ else return Qfalse;
}
else if (!limit) {
sleep_forever(th, SLEEP_DEADLOCKABLE | SLEEP_ALLOW_SPURIOUS | SLEEP_NO_CHECKINTS);
@@ -1070,6 +1074,7 @@ thread_join_sleep(VALUE arg)
RUBY_DEBUG_LOG("interrupted target_th:%u status:%s", rb_th_serial(target_th), thread_status_name(target_th, TRUE));
}
+
return Qtrue;
}