How can I handle (or prevent) SIGCHLD signals from ruby backquote calls?
I have a long running process with some child processes that need to be restarted if they exit. To handle clean reboots of these child processes, I delay the output with
trap("CLD") do
cpid = Process.wait
... handle cleanup ...
end
A long-term process sometimes has to call a curl using a backquote, as in
`/usr/bin/curl -m 60 http://localhost/central/expire`
The problem is that calling backquote causes me to get SIGCHLD and turn my trap to fire. Then it gets stuck in a CLD trap because Process.wait doesn't end. If there were no child processes at the time (no countdown), Process.wait throws an Errno :: ECHILD exception instead.
I can work around this problem by wrapping the call to backquote with this line before:
sig_handler = trap("CLD", "IGNORE") # Ignore child traps
and this line after calling backquote:
trap("CLD", sig_handler) # replace the handler
but that means I can skip a signal from child processes (non-backquote) during this window, so I am not very happy with that.
So, is there a better way to do this? (I'm using ruby 1.9.1p243 in GNU / Linux 2.6.22.6, if that matters)
Update: The code below illustrates the problem (and my current solution for it). There seems to be some strange timing issues as I don't always get an ECHILD exception. But just once is enough to ruin everything.
#!/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}"
source to share
Start controlled subprocesses from within a subprocess
Just start your tracked and monitored babies from the child of your main process that never quits. So he won't notice the back-tek kids coming out ...
And if you do, you can avoid using SIGCHLD entirely, as you could just use a wait loop in it to notice that children are exiting events.
Other ideas:
- ignore one SIGCHLD every time you execute the backtick command. ISTM that you can accidentally ignore the "real" SIGCHLD this way, but that doesn't matter because then you get a "false" one, which you process.
source to share