[ruby-core:117883] [Ruby master Bug#20490] Process.waitpid2(-1, Process::WNOHANG) misbehaves on Ruby 3.1 & 3.2 with detached process
From:
"stanhu (Stan Hu) via ruby-core" <ruby-core@...>
Date:
2024-05-15 03:39:09 UTC
List:
ruby-core #117883
Issue #20490 has been updated by stanhu (Stan Hu).
I think this patch in the `ruby_3_2` branch fixes the problem:
```diff
diff --git a/process.c b/process.c
index 354e16fd26..bcf7f5aaf4 100644
--- a/process.c
+++ b/process.c
@@ -1291,6 +1299,9 @@ waitpid_wait(struct waitpid_state *w)
if (w->ret == -1) w->errnum = errno;
}
else if (w->options & WNOHANG) {
+ if (w->pid < 0) {
+ need_sleep = TRUE;
+ }
}
else {
need_sleep = TRUE;
```
----------------------------------------
Bug #20490: Process.waitpid2(-1, Process::WNOHANG) misbehaves on Ruby 3.1 & 3.2 with detached process
https://bugs.ruby-lang.org/issues/20490#change-108298
* Author: stanhu (Stan Hu)
* Status: Open
* ruby -v: ruby 3.2.4 (2024-04-23 revision af471c0e01) [x86_64-linux]
* Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
This is a follow-up issue for a bug that I thought was fixed in https://bugs.ruby-lang.org/issues/19837 and duplicated in https://bugs.ruby-lang.org/issues/20181.
The following script doesn't terminate quickly in Ruby 3.1.5 and 3.2.4, even with the patches to address https://bugs.ruby-lang.org/issues/19837. It works fine in Ruby 3.3. It appears that the `Process::WNOHANG` argument passed to `Process.wait2` causes this script to spin until the child process stops:
```ruby
#!/bin/env ruby
Process.spawn({}, "sh -c 'sleep 600'").tap do |pid|
puts "detaching PID #{pid}"
Process.detach(pid)
end
forked_pid = fork do
loop { sleep 1 }
end
child_waiter = Thread.new do
puts "Waiting for child process to die..."
# The spawned process has to exit before this returns in Ruby 3.1 and 3.2
loop do
pid, status = Process.wait2(-1, Process::WNOHANG)
puts "Exited PID: #{pid}, status: #{status}"
break if pid
sleep 1
end
end
process_killer = Thread.new do
puts "Killing #{forked_pid}"
system("kill #{forked_pid}")
end
child_waiter.join
process_killer.join
```
If I drop the `Process::WNOHANG` argument, it works fine.
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/