lib/einhorn/command/interface.rb in einhorn-0.4.5 vs lib/einhorn/command/interface.rb in einhorn-0.4.6

- old
+ new

@@ -145,36 +145,46 @@ File.join(Dir.tmpdir, filename) end ## Signals def self.install_handlers - Signal.trap("INT") do + trap_async("INT") do Einhorn::Command.signal_all("USR2", Einhorn::WorkerPool.workers) Einhorn::Command.stop_respawning end - Signal.trap("TERM") do + trap_async("TERM") do Einhorn::Command.signal_all("TERM", Einhorn::WorkerPool.workers) Einhorn::Command.stop_respawning end # Note that quit is a bit different, in that it will actually # make Einhorn quit without waiting for children to exit. - Signal.trap("QUIT") do + trap_async("QUIT") do Einhorn::Command.signal_all("QUIT", Einhorn::WorkerPool.workers) Einhorn::Command.stop_respawning exit(1) end - Signal.trap("HUP") {Einhorn::Command.reload} - Signal.trap("ALRM") {Einhorn::Command.full_upgrade} - Signal.trap("CHLD") {Einhorn::Event.break_loop} - Signal.trap("USR2") do + trap_async("HUP") {Einhorn::Command.reload} + trap_async("ALRM") {Einhorn::Command.full_upgrade} + trap_async("CHLD") {} + trap_async("USR2") do Einhorn::Command.signal_all("USR2", Einhorn::WorkerPool.workers) Einhorn::Command.stop_respawning end at_exit do if Einhorn::State.kill_children_on_exit && Einhorn::TransientState.whatami == :master Einhorn::Command.signal_all("USR2", Einhorn::WorkerPool.workers) Einhorn::Command.stop_respawning end + end + end + + def self.trap_async(signal, &blk) + Signal.trap(signal) do + # We try to do as little work in the signal handler as + # possible. This avoids potential races between e.g. iteration + # and mutation. + Einhorn::Event.break_loop + Einhorn::Event.register_signal_action(&blk) end end def self.remove_handlers %w{INT TERM QUIT HUP ALRM CHLD USR2}.each do |signal|