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}"

      

+2


source to share


1 answer


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.
+1


source







All Articles