From 0f1687608dfff1c0f51adb2401bb8d77b7a73ac0 Mon Sep 17 00:00:00 2001 From: Daniel Nichter Date: Tue, 24 Jan 2012 09:55:18 -0700 Subject: [PATCH] Ignore SIGCHLD to avoid zombies. --- bin/pt-kill | 8 +++++ t/pt-kill/execute_command.t | 70 ++++++++++++++++++++++++++++++------- 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/bin/pt-kill b/bin/pt-kill index b89a4b4f..a04fc502 100755 --- a/bin/pt-kill +++ b/bin/pt-kill @@ -3622,6 +3622,14 @@ sub main { . " at " . ($o->get('interval') || 0) . " second intervals"); } + # We don't care about the executed command, and we don't want + # to wait for it, so we ignore dead children so we don't have + # to reap them and they won't become zombies. + # https://bugs.launchpad.net/percona-toolkit/+bug/919819 + if ( $o->get('execute-command') ) { + $SIG{CHLD} = 'IGNORE'; + } + while ( (!$run_time || $now < $end) && !-f $sentinel ) { msg('Checking processlist'); my $proclist; diff --git a/t/pt-kill/execute_command.t b/t/pt-kill/execute_command.t index 51cf3021..fb6fc468 100644 --- a/t/pt-kill/execute_command.t +++ b/t/pt-kill/execute_command.t @@ -9,7 +9,7 @@ BEGIN { use strict; use warnings FATAL => 'all'; use English qw(-no_match_vars); -use Test::More tests => 4; +use Test::More tests => 8; use PerconaTest; use Sandbox; @@ -19,59 +19,103 @@ my $dp = new DSNParser(opts=>$dsn_opts); my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); my $master_dbh = $sb->get_dbh_for('master'); - my $output; -my $cnf='/tmp/12345/my.sandbox.cnf'; +my $cnf ='/tmp/12345/my.sandbox.cnf'; my $cmd = "$trunk/bin/pt-kill -F $cnf -h 127.1"; +my $out = "/tmp/mk-kill-test.txt"; # ############################################################################# # Test --execute-command action. # ############################################################################# -diag(`rm -rf /tmp/mk-kill-test.txt`); +diag(`rm $out 2>/dev/null`); -$output = `$cmd $trunk/t/lib/samples/pl/recset001.txt --match-command Query --execute-command 'echo hello > /tmp/mk-kill-test.txt'`; +$output = `$cmd $trunk/t/lib/samples/pl/recset001.txt --match-command Query --execute-command 'echo hello > $out'`; is( $output, '', 'No output without --print' ); -chomp($output = `cat /tmp/mk-kill-test.txt`), +chomp($output = `cat $out`), is( $output, 'hello', '--execute-command' ); -diag(`rm -rf /tmp/mk-kill-test.txt`); +diag(`rm $out`); SKIP: { skip 'Cannot connect to sandbox master', 2 unless $master_dbh; - system("/tmp/12345/use -e 'select sleep(2)' >/dev/null 2>&1 &"); + system "/tmp/12345/use -e 'select sleep(2)' >/dev/null 2>&1 &"; + + $output = `$cmd --match-info 'select sleep' --run-time 2 --interval 1 --print --execute-command 'echo batty > $out'`; - $output = `$cmd --match-info 'select sleep' --run-time 2 --interval 1 --print --execute-command 'echo batty > /tmp/mk-kill-test.txt'`; like( $output, qr/KILL .+ select sleep\(2\)/, '--print with --execute-command' ); - chomp($output = `cat /tmp/mk-kill-test.txt`), + chomp($output = `cat $out`); is( $output, 'batty', '--execute-command (online)' ); - + # Let our select sleep(2) go away before other tests are ran. sleep 1; -} + diag(`rm $out`); -diag(`rm -rf /tmp/mk-kill-test.txt`); + # Don't make zombies (https://bugs.launchpad.net/percona-toolkit/+bug/919819) + system "/tmp/12345/use -e 'select sleep(2)' >/dev/null 2>&1 &"; + + my $sentinel = "/tmp/pt-kill-test.$PID.stop"; + my $pid_file = "/tmp/pt-kill-test.$PID.pid"; + my $log_file = "/tmp/pt-kill-test.$PID.log"; + diag(`rm $sentinel 2>/dev/null`); + diag(`rm $pid_file 2>/dev/null`); + diag(`rm $log_file 2>/dev/null`); + + `$cmd --daemonize --match-info 'select sleep' --interval 1 --print --execute-command 'echo zombie > $out' --verbose --pid $pid_file --log $log_file --sentinel $sentinel`; + sleep 1; + $output = `grep Executed $log_file`; + like( + $output, + qr/Executed echo zombie/, + "Executed zombie command" + ); + + $output = `ps x | grep Z | grep -v grep`; + is( + $output, + "", + "No zombies" + ); + + diag(`touch $sentinel`); + sleep 1; + ok( + !-f $pid_file, + "pt-kill stopped" + ); + $output = `ps x | grep Z | grep -v grep`; + is( + $output, + "", + "No zombies" + ); + + diag(`rm $sentinel 2>/dev/null`); + diag(`rm $pid_file 2>/dev/null`); + diag(`rm $log_file 2>/dev/null`); +} # ############################################################################# # Done. # ############################################################################# +diag(`rm $out 2>/dev/null`); $sb->wipe_clean($master_dbh) if $master_dbh; exit;