diff --git a/CHANGELOG b/CHANGELOG index 69af964..71d5539 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,6 +17,7 @@ TRUNK - [bugfix] made image URLS in stylesheets relative [Anselm Helbig] - [bugfix] Make dashboard xhtml compliant - [bugfix] Recognize OpenBSD as a platform +- Improve daemon_helper to kill all child processes (don't leave any orphans) ------------------------------------------------------------------------------------------------------------------------ * 1.3.0 diff --git a/daemon/daemon_helper.rb b/daemon/daemon_helper.rb index 0265d5b..92cb8eb 100644 --- a/daemon/daemon_helper.rb +++ b/daemon/daemon_helper.rb @@ -29,8 +29,25 @@ def su_if_needed(cmd) cmd end +def cruise_pid_file + "#{CRUISE_HOME}/tmp/pids/mongrel.pid" +end + +def read_cruise_pid + return File.open(cruise_pid_file){|f| f.read } if File.exist?(cruise_pid_file) + nil +end + def start_cruise(start_cmd = "cd #{CRUISE_HOME} && ./cruise start -d") log(:env, ENV.inspect) + + # remove cruise pid file if process is no longer running + cruise_pid = read_cruise_pid + if cruise_pid + cruise_process = `ps -ea -o 'pid'`.grep(/#{cruise_pid}/).first + FileUtils.rm(cruise_pid_file) unless cruise_process + end + output = `#{su_if_needed(start_cmd)} 2>&1` if $?.success? print output + "\n" @@ -44,12 +61,43 @@ end def stop_cruise failed = false - failed ||= !(system "mongrel_rails stop -P #{CRUISE_HOME}/tmp/pids/mongrel.pid") + cruise_pid = read_cruise_pid + unless cruise_pid + error_msg = "unable to read cruisecontrol.rb pid file #{cruise_pid_file}, cannot stop" + log(:err, error_msg) + print error_msg + "\n" + exit 1 + end + cruise_process = `ps -ea -o 'pid pgrp args'`.grep(/^\s*#{cruise_pid}\s+\d+\s+.*/).first + cruise_process =~ /^\s*#{cruise_pid}\s+(\d+)\s+(.*)/ + cruise_process_group = $1 + cruise_process_args = $2 + unless cruise_process_group =~ /^\d+$/ + error_msg = "unable to find cruise process #{cruise_pid}, cannot stop" + log(:err, error_msg) + print error_msg + "\n" + exit 1 + end + + cruise_child_processes = `ps -ea -o 'pid pgrp args'`.grep(/^\s*\d+\s+#{cruise_process_group}\s+/) + + print("Killing cruise process #{cruise_pid}: #{cruise_process_args}\n") + failed ||= !(system "mongrel_rails stop -P #{cruise_pid_file}") + + cruise_child_processes.each do |child_process| + child_process =~ /^\s*(\d+)\s+#{cruise_process_group}\s+(.*)/ + child_pid = $1 + next if child_pid == cruise_pid + child_args = $2 + print("Killing child process #{child_pid}: #{child_args}\n") + system "kill -9 #{child_pid}" + end + Dir["#{CRUISE_HOME}/tmp/pids/builders/*.pid"].each do |pid_file| pid = File.open(pid_file){|f| f.read } - failed ||= !(system "kill -9 #{pid}") rm pid_file end + if failed log(:err, "'stop' command failed") exit 1