summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--test/ruby/test_sleep.rb18
-rw-r--r--thread_pthread.c3
2 files changed, 19 insertions, 2 deletions
diff --git a/test/ruby/test_sleep.rb b/test/ruby/test_sleep.rb
index 991b73ebd5..7ef962db4a 100644
--- a/test/ruby/test_sleep.rb
+++ b/test/ruby/test_sleep.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: false
require 'test/unit'
require 'etc'
+require 'timeout'
class TestSleep < Test::Unit::TestCase
def test_sleep_5sec
@@ -13,4 +14,21 @@ class TestSleep < Test::Unit::TestCase
assert_operator(slept, :<=, 6.0, "[ruby-core:18015]: longer than expected")
end
end
+
+ def test_sleep_forever_not_woken_by_sigchld
+ begin
+ t = Thread.new do
+ sleep 0.5
+ `echo hello`
+ end
+
+ assert_raise Timeout::Error do
+ Timeout.timeout 2 do
+ sleep # Should block forever
+ end
+ end
+ ensure
+ t.join
+ end
+ end
end
diff --git a/thread_pthread.c b/thread_pthread.c
index a2e42da13e..9c7754067b 100644
--- a/thread_pthread.c
+++ b/thread_pthread.c
@@ -1109,10 +1109,9 @@ thread_sched_to_waiting_until_wakeup(struct rb_thread_sched *sched, rb_thread_t
{
if (!RUBY_VM_INTERRUPTED(th->ec)) {
bool can_direct_transfer = !th_has_dedicated_nt(th);
- th->status = THREAD_STOPPED_FOREVER;
+ // NOTE: th->status is set before and after this sleep outside of this function in `sleep_forever`
thread_sched_wakeup_next_thread(sched, th, can_direct_transfer);
thread_sched_wait_running_turn(sched, th, can_direct_transfer);
- th->status = THREAD_RUNNABLE;
}
else {
RUBY_DEBUG_LOG("th:%u interrupted", rb_th_serial(th));