I run this script:
t = fork do
Signal.trap "INT" do
puts "child"
exit
end
sleep 10
end
Signal.trap "INT" do
puts "parent"
Process.kill "INT", t
Process.waitpid t
exit
end
Process.waitpid t
When I do CTRL+C, I get
$ ruby sigtest.rb
^Cchild
parent
You can see that "INT" passed to every process and Process.kill "INT", t
try to kill process which already died. Is there way to do so that user INT signal will be passed only to the parent? And output will be:
$ ruby sigtest.rb
^Cparent
child
Solution
Rules:
- W开发者_如何学编程hen you press ctrl+c, SIGINT is passed to whole process group.
- When you fork new process, signal handlers are not passed to new process
So if you want to control child process signals manually, you have to change GID of the process.
See
- http://corelib.rubyonrails.org/classes/Process/Sys.html#M001961
- http://ruby.runpaint.org/processes (paragraph "Options Hash")
def system cmd
pid = fork do
exec cmd, {:pgroup => true}
end
Process.wait pid
$?.success?
end
def ` cmd # `make syntax highlight happy
readme, writeme = IO.pipe
pid = fork do
$stdout.reopen writeme
readme.close
exec cmd, {:pgroup => true}
end
writeme.close
data = readme.read
Process.wait pid
data
end
You could always have the child ignore the INT
signal.
精彩评论