Commit daacdcfe authored by Bjorn Munch's avatar Bjorn Munch

Bug #47978 timer : expired after 90 seconds

Problems occur after killing threads on Windows
Get rid of the timeout threads, implement simple timer in wait_any_timeout()
parent c7f14b56
...@@ -187,63 +187,6 @@ sub run { ...@@ -187,63 +187,6 @@ sub run {
return $proc->exit_status(); return $proc->exit_status();
} }
#
# Start a process that returns after "duration" seconds
# or when it's parent process does not exist anymore
#
sub timer {
my $class= shift;
my $duration= shift or croak "duration required";
my $parent_pid= $$;
my $pid= My::SafeProcess::Base::_safe_fork();
if ($pid){
# Parent
my $proc= bless
({
SAFE_PID => $pid,
SAFE_NAME => "timer",
PARENT => $$,
}, $class);
# Put the new process in list of running
$running{$pid}= $proc;
return $proc;
}
# Child, install signal handlers and sleep for "duration"
$SIG{INT}= 'IGNORE';
$SIG{TERM}= sub {
#print STDERR "timer $$: woken up, exiting!\n";
exit(0);
};
$0= "safe_timer($duration)";
if (IS_WIN32PERL){
# Just a thread in same process
sleep($duration);
print STDERR "timer $$: expired after $duration seconds\n";
exit(0);
}
my $count_down= $duration;
while($count_down--){
# Check that parent is still alive
if (kill(0, $parent_pid) == 0){
#print STDERR "timer $$: parent gone, exiting!\n";
exit(0);
}
sleep(1);
}
print STDERR "timer $$: expired after $duration seconds\n";
exit(0);
}
# #
# Shutdown process nicely, and wait for shutdown_timeout seconds # Shutdown process nicely, and wait for shutdown_timeout seconds
# If processes hasn't shutdown, kill them hard and wait for return # If processes hasn't shutdown, kill them hard and wait for return
...@@ -541,6 +484,40 @@ sub wait_any { ...@@ -541,6 +484,40 @@ sub wait_any {
} }
#
# Wait for any process to exit, or a timeout
#
# Returns a reference to the SafeProcess that
# exited or a pseudo-process with $proc->{timeout} == 1
#
sub wait_any_timeout {
my $class= shift;
my $timeout= shift;
my $proc;
my $millis=10;
do {
::mtr_milli_sleep($millis);
# Slowly increse interval up to max. 1 second
$millis++ if $millis < 1000;
# Return a "fake" process for timeout
if (::has_expired($timeout)) {
$proc= bless
({
SAFE_PID => 0,
SAFE_NAME => "timer",
timeout => 1,
}, $class);
} else {
$proc= check_any();
}
} while (! $proc);
return $proc;
}
# #
# Wait for all processes to exit # Wait for all processes to exit
# #
......
...@@ -30,7 +30,9 @@ sub mtr_script_exists(@); ...@@ -30,7 +30,9 @@ sub mtr_script_exists(@);
sub mtr_file_exists(@); sub mtr_file_exists(@);
sub mtr_exe_exists(@); sub mtr_exe_exists(@);
sub mtr_exe_maybe_exists(@); sub mtr_exe_maybe_exists(@);
sub mtr_milli_sleep($);
sub start_timer($);
sub has_expired($);
############################################################################## ##############################################################################
# #
...@@ -167,11 +169,18 @@ sub mtr_exe_exists (@) { ...@@ -167,11 +169,18 @@ sub mtr_exe_exists (@) {
} }
sub mtr_milli_sleep { sub mtr_milli_sleep ($) {
die "usage: mtr_milli_sleep(milliseconds)" unless @_ == 1; die "usage: mtr_milli_sleep(milliseconds)" unless @_ == 1;
my ($millis)= @_; my ($millis)= @_;
select(undef, undef, undef, ($millis/1000)); select(undef, undef, undef, ($millis/1000));
} }
# Simple functions to start and check timers (have to be actively polled)
# Timer can be "killed" by setting it to 0
sub start_timer ($) { return time + $_[0]; }
sub has_expired ($) { return $_[0] && time gt $_[0]; }
1; 1;
...@@ -439,7 +439,7 @@ sub run_test_server ($$$) { ...@@ -439,7 +439,7 @@ sub run_test_server ($$$) {
my $result; my $result;
my $exe_mysqld= find_mysqld($basedir) || ""; # Used as hint to CoreDump my $exe_mysqld= find_mysqld($basedir) || ""; # Used as hint to CoreDump
my $suite_timeout_proc= My::SafeProcess->timer(suite_timeout()); my $suite_timeout= start_timer(suite_timeout());
my $s= IO::Select->new(); my $s= IO::Select->new();
$s->add($server); $s->add($server);
...@@ -460,7 +460,6 @@ sub run_test_server ($$$) { ...@@ -460,7 +460,6 @@ sub run_test_server ($$$) {
mtr_verbose("Child closed socket"); mtr_verbose("Child closed socket");
$s->remove($sock); $s->remove($sock);
if (--$childs == 0){ if (--$childs == 0){
$suite_timeout_proc->kill();
return $completed; return $completed;
} }
next; next;
...@@ -529,13 +528,11 @@ sub run_test_server ($$$) { ...@@ -529,13 +528,11 @@ sub run_test_server ($$$) {
if ( !$opt_force ) { if ( !$opt_force ) {
# Test has failed, force is off # Test has failed, force is off
$suite_timeout_proc->kill();
push(@$completed, $result); push(@$completed, $result);
return $completed; return $completed;
} }
elsif ($opt_max_test_fail > 0 and elsif ($opt_max_test_fail > 0 and
$num_failed_test >= $opt_max_test_fail) { $num_failed_test >= $opt_max_test_fail) {
$suite_timeout_proc->kill();
push(@$completed, $result); push(@$completed, $result);
mtr_report_stats("Too many failed", $completed, 1); mtr_report_stats("Too many failed", $completed, 1);
mtr_report("Too many tests($num_failed_test) failed!", mtr_report("Too many tests($num_failed_test) failed!",
...@@ -667,7 +664,7 @@ sub run_test_server ($$$) { ...@@ -667,7 +664,7 @@ sub run_test_server ($$$) {
# ---------------------------------------------------- # ----------------------------------------------------
# Check if test suite timer expired # Check if test suite timer expired
# ---------------------------------------------------- # ----------------------------------------------------
if ( ! $suite_timeout_proc->wait_one(0) ) if ( has_expired($suite_timeout) )
{ {
mtr_report_stats("Timeout", $completed, 1); mtr_report_stats("Timeout", $completed, 1);
mtr_report("Test suite timeout! Terminating..."); mtr_report("Test suite timeout! Terminating...");
...@@ -2944,11 +2941,11 @@ sub check_testcase($$) ...@@ -2944,11 +2941,11 @@ sub check_testcase($$)
# Return immediately if no check proceess was started # Return immediately if no check proceess was started
return 0 unless ( keys %started ); return 0 unless ( keys %started );
my $timeout_proc= My::SafeProcess->timer(check_timeout()); my $timeout= start_timer(check_timeout());
while (1){ while (1){
my $result; my $result;
my $proc= My::SafeProcess->wait_any(); my $proc= My::SafeProcess->wait_any_timeout($timeout);
mtr_report("Got $proc"); mtr_report("Got $proc");
if ( delete $started{$proc->pid()} ) { if ( delete $started{$proc->pid()} ) {
...@@ -2972,9 +2969,6 @@ sub check_testcase($$) ...@@ -2972,9 +2969,6 @@ sub check_testcase($$)
if ( keys(%started) == 0){ if ( keys(%started) == 0){
# All checks completed # All checks completed
$timeout_proc->kill();
return 0; return 0;
} }
# Wait for next process to exit # Wait for next process to exit
...@@ -3015,10 +3009,9 @@ test case was executed:\n"; ...@@ -3015,10 +3009,9 @@ test case was executed:\n";
} }
} }
elsif ( $proc eq $timeout_proc ) { elsif ( $proc->{timeout} ) {
$tinfo->{comment}.= "Timeout $timeout_proc for ". $tinfo->{comment}.= "Timeout for 'check-testcase' expired after "
"'check-testcase' expired after ".check_timeout(). .check_timeout()." seconds";
" seconds";
$result= 4; $result= 4;
} }
else { else {
...@@ -3033,8 +3026,6 @@ test case was executed:\n"; ...@@ -3033,8 +3026,6 @@ test case was executed:\n";
# Kill any check processes still running # Kill any check processes still running
map($_->kill(), values(%started)); map($_->kill(), values(%started));
$timeout_proc->kill();
return $result; return $result;
} }
...@@ -3106,11 +3097,11 @@ sub run_on_all($$) ...@@ -3106,11 +3097,11 @@ sub run_on_all($$)
# Return immediately if no check proceess was started # Return immediately if no check proceess was started
return 0 unless ( keys %started ); return 0 unless ( keys %started );
my $timeout_proc= My::SafeProcess->timer(check_timeout()); my $timeout= start_timer(check_timeout());
while (1){ while (1){
my $result; my $result;
my $proc= My::SafeProcess->wait_any(); my $proc= My::SafeProcess->wait_any_timeout($timeout);
mtr_report("Got $proc"); mtr_report("Got $proc");
if ( delete $started{$proc->pid()} ) { if ( delete $started{$proc->pid()} ) {
...@@ -3129,17 +3120,15 @@ sub run_on_all($$) ...@@ -3129,17 +3120,15 @@ sub run_on_all($$)
if ( keys(%started) == 0){ if ( keys(%started) == 0){
# All completed # All completed
$timeout_proc->kill();
return 0; return 0;
} }
# Wait for next process to exit # Wait for next process to exit
next; next;
} }
elsif ( $proc eq $timeout_proc ) { elsif ($proc->{timeout}) {
$tinfo->{comment}.= "Timeout $timeout_proc for '$run' ". $tinfo->{comment}.= "Timeout for '$run' expired after "
"expired after ". check_timeout(). .check_timeout()." seconds";
" seconds";
} }
else { else {
# Unknown process returned, most likley a crash, abort everything # Unknown process returned, most likley a crash, abort everything
...@@ -3151,8 +3140,6 @@ sub run_on_all($$) ...@@ -3151,8 +3140,6 @@ sub run_on_all($$)
# Kill any check processes still running # Kill any check processes still running
map($_->kill(), values(%started)); map($_->kill(), values(%started));
$timeout_proc->kill();
return 1; return 1;
} }
mtr_error("INTERNAL_ERROR: run_on_all"); mtr_error("INTERNAL_ERROR: run_on_all");
...@@ -3382,7 +3369,7 @@ sub run_testcase ($) { ...@@ -3382,7 +3369,7 @@ sub run_testcase ($) {
} }
} }
my $test_timeout_proc= My::SafeProcess->timer(testcase_timeout()); my $test_timeout= start_timer(testcase_timeout());
do_before_run_mysqltest($tinfo); do_before_run_mysqltest($tinfo);
...@@ -3390,9 +3377,6 @@ sub run_testcase ($) { ...@@ -3390,9 +3377,6 @@ sub run_testcase ($) {
# Failed to record state of server or server crashed # Failed to record state of server or server crashed
report_failure_and_restart($tinfo); report_failure_and_restart($tinfo);
# Stop the test case timer
$test_timeout_proc->kill();
return 1; return 1;
} }
...@@ -3410,20 +3394,20 @@ sub run_testcase ($) { ...@@ -3410,20 +3394,20 @@ sub run_testcase ($) {
if ($proc) if ($proc)
{ {
mtr_verbose ("Found exited process $proc"); mtr_verbose ("Found exited process $proc");
# If that was the timeout, cancel waiting
if ( $proc eq $test_timeout_proc )
{
$keep_waiting_proc = 0;
}
} }
else else
{ {
$proc = $keep_waiting_proc; $proc = $keep_waiting_proc;
# Also check if timer has expired, if so cancel waiting
if ( has_expired($test_timeout) )
{
$keep_waiting_proc = 0;
}
} }
} }
else if (! $keep_waiting_proc)
{ {
$proc= My::SafeProcess->wait_any(); $proc= My::SafeProcess->wait_any_timeout($test_timeout);
} }
# Will be restored if we need to keep waiting # Will be restored if we need to keep waiting
...@@ -3440,9 +3424,6 @@ sub run_testcase ($) { ...@@ -3440,9 +3424,6 @@ sub run_testcase ($) {
# ---------------------------------------------------- # ----------------------------------------------------
if ($proc eq $test) if ($proc eq $test)
{ {
# Stop the test case timer
$test_timeout_proc->kill();
my $res= $test->exit_status(); my $res= $test->exit_status();
if ($res == 0 and $opt_warnings and check_warnings($tinfo) ) if ($res == 0 and $opt_warnings and check_warnings($tinfo) )
...@@ -3545,7 +3526,7 @@ sub run_testcase ($) { ...@@ -3545,7 +3526,7 @@ sub run_testcase ($) {
# ---------------------------------------------------- # ----------------------------------------------------
# Stop the test case timer # Stop the test case timer
# ---------------------------------------------------- # ----------------------------------------------------
$test_timeout_proc->kill(); $test_timeout= 0;
# ---------------------------------------------------- # ----------------------------------------------------
# Check if it was a server that died # Check if it was a server that died
...@@ -3584,7 +3565,7 @@ sub run_testcase ($) { ...@@ -3584,7 +3565,7 @@ sub run_testcase ($) {
# ---------------------------------------------------- # ----------------------------------------------------
# Check if testcase timer expired # Check if testcase timer expired
# ---------------------------------------------------- # ----------------------------------------------------
if ( $proc eq $test_timeout_proc ) if ( $proc->{timeout} )
{ {
my $log_file_name= $opt_vardir."/log/".$tinfo->{shortname}.".log"; my $log_file_name= $opt_vardir."/log/".$tinfo->{shortname}.".log";
$tinfo->{comment}= $tinfo->{comment}=
...@@ -3825,11 +3806,11 @@ sub check_warnings ($) { ...@@ -3825,11 +3806,11 @@ sub check_warnings ($) {
# Return immediately if no check proceess was started # Return immediately if no check proceess was started
return 0 unless ( keys %started ); return 0 unless ( keys %started );
my $timeout_proc= My::SafeProcess->timer(check_timeout()); my $timeout= start_timer(check_timeout());
while (1){ while (1){
my $result= 0; my $result= 0;
my $proc= My::SafeProcess->wait_any(); my $proc= My::SafeProcess->wait_any_timeout($timeout);
mtr_report("Got $proc"); mtr_report("Got $proc");
if ( delete $started{$proc->pid()} ) { if ( delete $started{$proc->pid()} ) {
...@@ -3858,9 +3839,6 @@ sub check_warnings ($) { ...@@ -3858,9 +3839,6 @@ sub check_warnings ($) {
if ( keys(%started) == 0){ if ( keys(%started) == 0){
# All checks completed # All checks completed
$timeout_proc->kill();
return $result; return $result;
} }
# Wait for next process to exit # Wait for next process to exit
...@@ -3877,10 +3855,9 @@ sub check_warnings ($) { ...@@ -3877,10 +3855,9 @@ sub check_warnings ($) {
$result= 2; $result= 2;
} }
} }
elsif ( $proc eq $timeout_proc ) { elsif ( $proc->{timeout} ) {
$tinfo->{comment}.= "Timeout $timeout_proc for ". $tinfo->{comment}.= "Timeout for 'check warnings' expired after "
"'check warnings' expired after ".check_timeout(). .check_timeout()." seconds";
" seconds";
$result= 4; $result= 4;
} }
else { else {
...@@ -3894,8 +3871,6 @@ sub check_warnings ($) { ...@@ -3894,8 +3871,6 @@ sub check_warnings ($) {
# Kill any check processes still running # Kill any check processes still running
map($_->kill(), values(%started)); map($_->kill(), values(%started));
$timeout_proc->kill();
return $result; return $result;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment