diff options
| author | Chris HasiĆski <krzysztof.hasinski@gmail.com> | 2026-01-26 16:17:35 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-26 10:17:35 -0500 |
| commit | 5add7c3ea9a13e657fc7cba78b2633b9548a55aa (patch) | |
| tree | c060ff47045033a4063227bc039957877bac57aa | |
| parent | 2947aa41d4e6aa340edb0979c3e59bb6b6aca3a4 (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.rb | 12 | ||||
| -rw-r--r-- | thread_pthread.c | 10 |
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 * |
