summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris HasiƄski <krzysztof.hasinski@gmail.com>2026-01-26 16:17:35 +0100
committerGitHub <noreply@github.com>2026-01-26 10:17:35 -0500
commit5add7c3ea9a13e657fc7cba78b2633b9548a55aa (patch)
treec060ff47045033a4063227bc039957877bac57aa
parent2947aa41d4e6aa340edb0979c3e59bb6b6aca3a4 (diff)
Fix RUBY_MN_THREADS sleep returning prematurely (#15868)
timer_thread_check_exceed() was returning true when the remaining time was less than 1ms, treating it as "too short time". This caused sub-millisecond sleeps (like sleep(0.0001)) to return immediately instead of actually sleeping. The fix removes this optimization that was incorrectly short-circuiting short sleep durations. Now the timeout is only considered exceeded when the actual deadline has passed. Note: There's still a separate performance issue where MN_THREADS mode is slower for sub-millisecond sleeps due to the timer thread using millisecond-resolution polling. This will require a separate fix to use sub-millisecond timeouts in kqueue/epoll. [Bug #21836]
-rw-r--r--test/ruby/test_thread.rb12
-rw-r--r--thread_pthread.c10
2 files changed, 13 insertions, 9 deletions
diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb
index 7f5dbe9155..b2d8e73693 100644
--- a/test/ruby/test_thread.rb
+++ b/test/ruby/test_thread.rb
@@ -1652,4 +1652,16 @@ q.pop
end
end;
end
+
+ # [Bug #21836]
+ def test_mn_threads_sub_millisecond_sleep
+ assert_separately([{'RUBY_MN_THREADS' => '1'}], "#{<<~"begin;"}\n#{<<~'end;'}", timeout: 30)
+ begin;
+ t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ 1000.times { sleep 0.0001 }
+ t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ elapsed = t1 - t0
+ assert_operator elapsed, :>=, 0.1, "sub-millisecond sleeps should not return immediately"
+ end;
+ end
end
diff --git a/thread_pthread.c b/thread_pthread.c
index 9c7754067b..542690eca0 100644
--- a/thread_pthread.c
+++ b/thread_pthread.c
@@ -2947,15 +2947,7 @@ timer_thread_check_signal(rb_vm_t *vm)
static bool
timer_thread_check_exceed(rb_hrtime_t abs, rb_hrtime_t now)
{
- if (abs < now) {
- return true;
- }
- else if (abs - now < RB_HRTIME_PER_MSEC) {
- return true; // too short time
- }
- else {
- return false;
- }
+ return abs <= now;
}
static rb_thread_t *