Given a very simple ruby script:
child = fork do
system 'sleep 10000'
end
5.times do
sleep 1
puts "send kill to #{child}"
Process.kill("QUIT", child)
end
QUIT signal is just lost. Where does it go? Something with default handler which just ignores it?
How to send signal to all processes created by that fork? Is it possible to do that without searching for all child processes?
The problem is that the
systemcall creates yet another child process running the given command in a subshell, so there are actually three processes running in your example. Additionally, the RubyKernel#systemcommand is implemented via the standard C function system(3), which callsforkandexecto create the new process and (on most systems) ignores SIGINT and SIGQUIT, and blocks SIGCHLD.If you simply call
sleep(10000)instead ofsystem("sleep 10000")then things should work as you expect. You can also trap SIGQUIT in the child to handle it gracefully:If you really need to use a “system” call from the child process then you might be better off using an explicit fork/exec pair (instead of the implicit ones in the
systemcall), so that you can perform your own signal handling in the third forked child.