From: "nagachika (Tomoyuki Chikanaga) via ruby-core" <ruby-core@...>
Date: 2024-05-16T04:30:15+00:00
Subject: [ruby-core:117894] [Ruby master Bug#20490] Process.waitpid2(-1, Process::WNOHANG) misbehaves on Ruby 3.1 & 3.2 with detached process

Issue #20490 has been updated by nagachika (Tomoyuki Chikanaga).

Backport changed from 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN to 3.1: WONTFIX, 3.2: REQUIRED, 3.3: DONTNEED

Thank you for your report. I will look the PRs.
I will set the status of this ticket because of this is a backport ticket.
And currently 3.1 branch is under the security maintenance phase, so I fill the Backport field for 3.1 with "WONTFIX". cc: @hsbt (as the new 3.1 branch maintainer).

----------------------------------------
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-108310

* Author: stanhu (Stan Hu)
* Status: Open
* ruby -v: ruby 3.2.4 (2024-04-23 revision af471c0e01) [x86_64-linux]
* Backport: 3.1: WONTFIX, 3.2: REQUIRED, 3.3: DONTNEED
----------------------------------------
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/