2010-06-16 37 views
2

给予了非常简单的Ruby脚本:去哪个呼叫系统的信号发送去哪里?

child = fork do 
    system 'sleep 10000' 
end 

5.times do 
    sleep 1 
    puts "send kill to #{child}" 
    Process.kill("QUIT", child) 
end 

QUIT信号只是失去了。它在哪里?一些默认的处理程序,只是忽略它?

如何将信号发送到由该叉创建的所有进程?如果不搜索所有子进程,是否可以这样做?

回答

7

问题是system调用创建另一个子进程在子shell中运行给定的命令,所以实际上有三个进程在你的例子中运行。此外,Ruby Kernel#system命令通过标准C函数system(3)实现,该函数调用forkexec来创建新进程,并且(在大多数系统上)忽略SIGINT和SIGQUIT,并且阻止SIGCHLD。

如果你只是打电话sleep(10000)而不是system("sleep 10000")那么事情应该如你所愿。您还可以在孩子陷阱SIGQUIT优雅地处理它:

child = fork do 
    Signal.trap("QUIT") { puts "CHILD: ok, quitting time!"; exit } 
    sleep(10000) 
end 

如果你确实需要使用从子处理的“系统”的呼叫,那么你可能会使用一个明确的叉/ EXEC对好起来(而不是在system调用中隐含的那些),以便您可以在第三个分岔孩子中执行自己的信号处理。

0

我认为你正在向正确的fork过程发送信号。我认为问题出在系统命令上。系统命令会创建新的分支,并等待它结束,我认为这个等待会阻止您的退出信号。如果你运行你的例子作为test.rb你会看到三个过程:

  • test.rb
  • test.rb
  • 睡眠10000

如果发送信号 “术语” 或“KILL”而不是“QUIT”第二次测试.rb会死,但是睡眠10000会继续!