给出一个非常简单的ruby脚本:
child = fork do
system 'sleep 10000'
end
5.times do
sleep 1
puts "send kill to #{child}"
Process.kill("QUIT", child)
end
退出QUIT信号。它去哪儿了?有默认处理程序的东西只是忽略它?
如何向该fork创建的所有进程发送信号?是否可以在不搜索所有子进程的情况下执行此操作?
答案 0 :(得分:7)
问题是system
调用创建了另一个在子shell中运行给定命令的子进程,因此实际上在您的示例中运行了三个进程。另外,Ruby Kernel#system
命令是通过标准C函数system(3)实现的,它调用fork
和exec
来创建新进程,并且(在大多数系统上)忽略SIGINT和SIGQUIT,并阻止SIGCHLD。
如果您只是致电sleep(10000)
而不是system("sleep 10000")
,那么事情应该按照您的预期运作。您还可以在子项中捕获SIGQUIT以优雅地处理它:
child = fork do
Signal.trap("QUIT") { puts "CHILD: ok, quitting time!"; exit }
sleep(10000)
end
如果你确实需要使用来自子进程的“系统”调用,那么最好使用显式的fork / exec对(而不是system
调用中的隐式对),这样你就可以了可以在第三个分叉孩子中执行自己的信号处理。
答案 1 :(得分:0)
我认为你正在向fork进程发送信号。我认为问题出在系统命令上。系统命令创建新的fork并等待它结束,我认为这等待阻止你的退出信号。如果您将示例作为test.rb运行,您将看到三个进程:
如果您发送信号“TERM”或“KILL”而不是“QUIT”,则第二个test.rb将会死亡,但10000将继续睡眠!