summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
}