Thanks to visit codestin.com
Credit goes to bugs.ruby-lang.org

Project

General

Profile

Actions

Bug #21812

closed

Kernel#sleep without arguments returns immediately when subprocess exits in another thread (regression in Ruby 4.0)

Bug #21812: Kernel#sleep without arguments returns immediately when subprocess exits in another thread (regression in Ruby 4.0)

Added by jaimevelaz (Jaime Velaz) about 1 month ago. Updated 17 days ago.

Status:
Closed
Target version:
-
ruby -v:
ruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin25]
[ruby-core:124383]

Description

Description

In Ruby 4.0.0, Kernel#sleep without arguments returns 0 immediately when a subprocess (spawned via backticks in another thread) exits. This is a regression from Ruby 3.4.8 where sleep blocks indefinitely as expected.

Note: sleep(N) with an argument is not affected.


Steps to reproduce

# test_sleep.rb
Thread.new do
  sleep 0.3
  `echo hello`  # Spawns subprocess
  puts "Subprocess exited"
end

puts "Main thread sleeping..."
result = sleep  # Should block forever
puts "sleep returned: #{result.inspect}"

Run with:
$ ruby test_sleep.rb


Actual result (Ruby 4.0.0):

Main thread sleeping...
Subprocess exited
sleep returned: 0

The program exits immediately after the subprocess completes.


Expected result (Ruby 3.4.8 behavior):

Main thread sleeping...
Subprocess exited
(process blocks indefinitely until interrupted by signal)

The program should block forever until explicitly interrupted by SIGINT/SIGTERM.

Updated by mame (Yusuke Endoh) about 1 month ago Actions #1 [ruby-core:124384]

  • Status changed from Open to Assigned
  • Assignee set to luke-gru (Luke Gruber)

Thanks for the nice catch.

git bisect points to 8d8159e7d87e4fd1594ce2fad3d2653e47fb1026. The changes in that commit seem relevant to this issue.

@luke-gru (Luke Gruber) Could you take a look?

Updated by luke-gru (Luke Gruber) 25 days ago ยท Edited Actions #2

@mame (Yusuke Endoh) Yes no problem, I have a fix coming. Thanks for the bisect btw, it saved me quite a bit of time ๐Ÿ˜Š

Updated by Anonymous 25 days ago Actions #3

  • Status changed from Assigned to Closed

Applied in changeset git|7e81bf5c0c8f43602e6d901f4253dca2f3d71745.


Fix sleep spurious wakeup from sigchld (#15802)

When sleeping with sleep, currently the main thread can get woken up from sigchld
from any thread (subprocess exited). The timer thread wakes up the main thread when this
happens, as it checks for signals. The main thread then executes the ruby sigchld handler
if one is registered and is supposed to go back to sleep immediately. This is not ideal but
it's the way it's worked for a while. In commit 8d8159e7d8 I added writes to th->status
before and after wait_running_turn in thread_sched_to_waiting_until_wakeup, which is
called from sleep. This is usually the right way to set the thread's status, but sleep
is an exception because the writes to th->status are done in sleep_forever. There's a
loop that checks th->status in sleep_forever. When the main thread got woken up from
sigchld it saw the changed th->status and continued to run the main thread instead of
going back to sleep.

The following script shows the error. It was returning instead of sleeping forever.

t = Thread.new do
  sleep 0.3
  `echo hello`  # Spawns subprocess
  puts "Subprocess exited"
end

puts "Main thread sleeping..."
result = sleep  # Should block forever
puts "sleep returned: #{result.inspect}"

Fixes [Bug #21812]

Updated by jhawthorn (John Hawthorn) 25 days ago Actions #4

  • Backport changed from 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN to 3.2: DONTNEED, 3.3: DONTNEED, 3.4: DONTNEED, 4.0: REQUIRED

Updated by k0kubun (Takashi Kokubun) 17 days ago Actions #5 [ruby-core:124493]

  • Backport changed from 3.2: DONTNEED, 3.3: DONTNEED, 3.4: DONTNEED, 4.0: REQUIRED to 3.2: DONTNEED, 3.3: DONTNEED, 3.4: DONTNEED, 4.0: DONE
Actions

Also available in: PDF Atom