信号发送到哪个系统调用?

时间:2010-06-16 01:49:46

标签: ruby signal-processing

给出一个非常简单的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创建的所有进程发送信号?是否可以在不搜索所有子进程的情况下执行此操作?

2 个答案:

答案 0 :(得分: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

如果你确实需要使用来自子进程的“系统”调用,那么最好使用显式的fork / exec对(而不是system调用中的隐式对),这样你就可以了可以在第三个分叉孩子中执行自己的信号处理。

答案 1 :(得分:0)

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

  • test.rb
  • test.rb
  • sleep 10000

如果您发送信号“TERM”或“KILL”而不是“QUIT”,则第二个test.rb将会死亡,但10000将继续睡眠!