【发布时间】:2009-10-01 07:01:02
【问题描述】:
我有一个长时间运行的进程,其中一些子进程在退出时必须重新启动。为了处理这些子进程的干净重启,我使用
捕获退出信号trap("CLD") do
cpid = Process.wait
... handle cleanup ...
end
长时间运行的进程有时需要使用反引号调用“curl”,如
`/usr/bin/curl -m 60 http://localhost/central/expire`
问题是反引号调用导致我得到一个 SIGCHLD 并使我的陷阱着火。然后这会卡在 CLD 陷阱中,因为 Process.wait 没有完成。如果当时碰巧没有(非反引号)子进程,则 Process.wait 会给出 Errno::ECHILD 异常。
我可以通过在之前用这一行包装反引号调用来规避这个问题:
sig_handler = trap("CLD", "IGNORE") # Ignore child traps
反引号调用之后的这一行:
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}"
【问题讨论】:
标签: ruby