如何处理(或防止)来自ruby反引号调用的SIGCHLD信号?
我有一个长时间运行的进程,其中包含一些子进程,如果它们退出,则必须重新启动这些子进程。为了处理这些子进程的干净重启,我使用如何处理(或防止)来自ruby反引号调用的SIGCHLD信号?,ruby,Ruby,我有一个长时间运行的进程,其中包含一些子进程,如果它们退出,则必须重新启动这些子进程。为了处理这些子进程的干净重启,我使用 trap("CLD") do cpid = Process.wait ... handle cleanup ... end 长时间运行的流程偶尔需要使用backquote调用“curl”,如中所示 `/usr/bin/curl -m 60 http://localhost/central/expire` 问题是,backquote调用导致我得到一个SIGCHLD
trap("CLD") do
cpid = Process.wait
... handle cleanup ...
end
长时间运行的流程偶尔需要使用backquote调用“curl”,如中所示
`/usr/bin/curl -m 60 http://localhost/central/expire`
问题是,backquote调用导致我得到一个SIGCHLD并触发陷阱。然后,由于Process.wait没有完成,这会卡在CLD陷阱中。如果当时恰好没有(非反引号)子进程,则Process.wait会给出一个Errno::ECHILD异常
我可以通过在以下情况之前使用这一行包装反向报价调用来避免此问题:
sig_handler = trap("CLD", "IGNORE") # Ignore child traps
在backquote调用之后的这一行:
trap("CLD", sig_handler) # replace the handler
但这意味着在该窗口期间,我可能会错过(非反引号)子进程的信号,因此我对此并不满意
那么,有没有更好的方法?
(我在GNU/Linux 2.6.22.6上使用ruby 1.9.1p243,如果有必要的话)
更新:
下面的代码说明了这个问题(以及我目前的解决方案)。
这里似乎有一些奇怪的时间问题,因为我并不总是得到ECHILD异常。但仅仅一次就足以把事情搞砸
#!/usr/bin/env ruby
require 'pp'
trap("CLD") do
cpid = nil
begin
puts "\nIn trap(CLD); about to call Process.wait"
cpid = Process.wait
puts "In trap(CLD); Noting that ssh Child pid #{cpid}: terminated"
puts "Finished Child termination trap"
rescue Errno::ECHILD
puts "Got Errno::ECHILD"
rescue Exception => excep
puts "Exception in CLD trap for process [#{cpid}]"
puts PP.pp(excep, '')
puts excep.backtrace.join("\n")
end
end
#Backtick problem shown (we get an ECHILD most of the time)
puts "About to invoke backticked curl"
`/usr/bin/curl -m 6 http://developer.yahooapis.com/TimeService/V1/getTime?appid=YahooDemo`
sleep 2; sleep 2 # Need two sleeps because the 1st gets terminated early by the trap
puts "Backticked curl returns"
# Using spawn
puts "About to invoke curl using spawn"
cpid = spawn("/usr/bin/curl -m 6 http://developer.yahooapis.com/TimeService/V1/getTime?appid=YahooDemo")
puts "spawned child pid is #{cpid} at #{Time.now}"
从子流程启动受监视的子流程
只需从主进程的子进程开始跟踪和监视子进程,该子进程永远不会退出。这样它就不会注意到backtick子项退出
如果您这样做,您可以完全避免使用SIGCHLD,因为您可以使用一个带有等待的循环来通知子退出事件
其他想法:
- 每次执行backtick命令时忽略一个SIGCHLD。我的意思是,你可能会以这种方式意外地忽略一个“真实的”信号,但这并不重要,因为你会得到一个“虚假的”信号,你会处理它