I have a long-running process with some child processes that must be restarted if they exit. To handle clean restarts of these child processes, I trap the exit signal with
trap("CLD") do
cpid = Process.wait
... handle cleanup ...
end
The long-running process occasionally needs to invoke 'curl' using a backquote as in
`/usr/bin/curl -m 60 http://localhost/central/expire`
The problem is that the backquote invocation is causing me to get a SIGCHLD and making my trap fire. This then gets stuck in the CLD trap because Process.wait does not finish. If there happen to be no (non-backquote) child processes at that time, the Process.wait instead gives an Errno::ECHILD exception.
I can circumvent this problem by wrapping the backquote call with this line before:
sig_handler = trap("CLD", "IGNORE") # Ignore child traps
and this line after the backquote invocation:
trap("CLD", sig_handler) # replace the handler
but this means that I may miss a signal from the (non-backquote) child processes during that window, so I'm not really happy with that.
So, is there a better way to do this? (I am using ruby 1.9.1p243 on GNU/Linux 2.6.22.6 if it matters)
Update: The code below illustrates the problem (and my current solution for it). There seems to be some strange timing issue here since I don't always get the ECHILD exception. But just once is enough to mess things up.
#!/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}"