From f2f09554c8cc57b9e2e8961da7611735638de5de Mon Sep 17 00:00:00 2001 From: David Dollar Date: Fri, 3 Jun 2011 01:31:51 -0400 Subject: [PATCH] correct shutdown signals processes are sent SIGTERM followed 3 seconds later by SIGKILL --- bin/foreman-runner | 2 ++ data/example/ticker | 6 ++++++ lib/foreman/engine.rb | 37 +++++++++++++++++++++++++------------ 3 files changed, 33 insertions(+), 12 deletions(-) create mode 100755 bin/foreman-runner diff --git a/bin/foreman-runner b/bin/foreman-runner new file mode 100755 index 0000000..fca2c5e --- /dev/null +++ b/bin/foreman-runner @@ -0,0 +1,2 @@ +#!/usr/bin/env ruby +exec ARGV.join(" ") diff --git a/data/example/ticker b/data/example/ticker index e64c516..e976f6e 100755 --- a/data/example/ticker +++ b/data/example/ticker @@ -1,5 +1,11 @@ #!/usr/bin/env ruby +%w( SIGINT SIGTERM SIGHUP ).each do |signal| + trap(signal) do + puts "received #{signal} but i'm ignoring it!" + end +end + while true puts "tick: #{ARGV.inspect} -- FOO:#{ENV["FOO"]}" sleep 1 diff --git a/lib/foreman/engine.rb b/lib/foreman/engine.rb index d2f8cbd..471f3df 100644 --- a/lib/foreman/engine.rb +++ b/lib/foreman/engine.rb @@ -3,6 +3,7 @@ require "foreman/process" require "foreman/utils" require "pty" require "tempfile" +require "timeout" require "term/ansicolor" require "fileutils" @@ -58,8 +59,8 @@ class Foreman::Engine fork process, options, environment end - trap("TERM") { puts "SIGTERM received"; kill_all("TERM") } - trap("INT") { puts "SIGINT received"; kill_all("TERM") } + trap("TERM") { puts "SIGTERM received"; terminate_gracefully } + trap("INT") { puts "SIGINT received"; terminate_gracefully } watch_for_termination end @@ -69,8 +70,8 @@ class Foreman::Engine fork processes[name], options, environment - trap("TERM") { puts "SIGTERM received"; kill_all("TERM") } - trap("INT") { puts "SIGINT received"; kill_all("TERM") } + trap("TERM") { puts "SIGTERM received"; terminate_gracefully } + trap("INT") { puts "SIGINT received"; terminate_gracefully } watch_for_termination end @@ -107,12 +108,12 @@ private ###################################################################### def run(process) proctitle "ruby: foreman #{process.name}" + trap("SIGINT", "IGNORE") begin Dir.chdir directory do - command = process.command - - PTY.spawn("#{process.command} 2>&1") do |stdin, stdout, pid| + PTY.spawn(runner, process.command) do |stdin, stdout, pid| + trap("SIGTERM") { Process.kill("SIGTERM", pid) } until stdin.eof? info stdin.gets, process end @@ -126,11 +127,9 @@ private ###################################################################### end end - def kill_all(signal="TERM") - info "terminating" + def kill_all(signal="SIGTERM") running_processes.each do |pid, process| - info "killing #{process.name} in pid #{pid}" - Process.kill(signal, pid) + Process.kill(signal, pid) rescue Errno::ESRCH end end @@ -179,8 +178,9 @@ private ###################################################################### pid, status = Process.wait2 process = running_processes.delete(pid) info "process terminated", process + terminate_gracefully kill_all - Process.waitall + rescue Errno::ECHILD end def running_processes @@ -217,4 +217,17 @@ private ###################################################################### environment end + def runner + File.expand_path("../../../bin/foreman-runner", __FILE__) + end + + def terminate_gracefully + info "sending SIGTERM to all processes" + kill_all "SIGTERM" + Timeout.timeout(3) { Process.waitall } + rescue Timeout::Error + info "sending SIGKILL to all processes" + kill_all "SIGKILL" + end + end