From 9e67c8a48bbbed059bb8cbef617656cba90b158c Mon Sep 17 00:00:00 2001 From: Daniel Nichter Date: Sat, 15 Jun 2013 19:44:52 -0700 Subject: [PATCH] Fix serious bug: run STOP-service not service in stop_service(), else a fork-bomb ensues. Make run_service() write PID-specific PIDs, then check for too_many_agents() first thing on start. --- bin/pt-agent | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/bin/pt-agent b/bin/pt-agent index bbaed7fc..4b24c64f 100755 --- a/bin/pt-agent +++ b/bin/pt-agent @@ -5287,6 +5287,23 @@ sub main { $o->usage_or_errors(); $OUTPUT_AUTOFLUSH = 1 if $o->get('interactive') || $o->get('install'); + + # ######################################################################## + # Fail-safe: if the agent somehow runs away, i.e. starts to fork-bomb, + # stop everything. + # ######################################################################## + my $lib_dir = $o->get('lib-dir'); + if ( too_many_agents(lib_dir => $lib_dir) ) { + schedule_services( + services => [], + lib_dir => $lib_dir, + ); + die "Too many agents are running. Remove the PID files in " + . "$lib_dir/pids/ if the agents are no longer running. Else, " + . "check the log files in $lib_dir/logs/ and online to see " + . "if the agent is stuck in a loop. Please contact Percona " + . "if you need urgent help.\n"; + } # ######################################################################## # Connect to MysSQL later, maybe. @@ -6834,7 +6851,7 @@ sub run_service { my $daemon = Daemon->new( daemonize => 0, # no need: we're running from cron - # no pid_file because --run-service X must handle concurrent runs of X + pid_file => "$lib_dir/pids/$service.$PID", log_file => "$lib_dir/logs/$service.run", force_log_file => 1, ); @@ -7915,7 +7932,7 @@ sub stop_service { my $stop_log = "$lib_dir/logs/$service.stop"; my $run_log = "$lib_dir/logs/$service.run"; my $cmd = ($env_vars ? "$env_vars " : '') - . "${bin_dir}pt-agent --run-service $service" + . "${bin_dir}pt-agent --run-service $stop_service" . " $stop_log 2>&1"; $logger->info("Stopping $service..."); @@ -8729,6 +8746,17 @@ sub check_if_mysql_restarted { return; } +sub too_many_agents { + my (%args) = @_; + have_required_args(\%args, qw( + lib_dir + )) or die; + my $lib_dir = $args{lib_dir}; + return unless -d "$lib_dir/pids"; + my @pids = glob "$lib_dir/pids/*"; + return scalar @pids > 10 ? 1 : 0; +} + sub _state { return $state; }