mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 04:53:01 +01:00
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()
This commit is contained in:
parent
db1b1160dd
commit
8e04f4c73c
3 changed files with 72 additions and 111 deletions
|
@ -187,63 +187,6 @@ sub run {
|
|||
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
|
||||
# If processes hasn't shutdown, kill them hard and wait for return
|
||||
|
@ -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
|
||||
#
|
||||
|
|
|
@ -30,7 +30,9 @@ sub mtr_script_exists(@);
|
|||
sub mtr_file_exists(@);
|
||||
sub mtr_exe_exists(@);
|
||||
sub mtr_exe_maybe_exists(@);
|
||||
|
||||
sub mtr_milli_sleep($);
|
||||
sub start_timer($);
|
||||
sub has_expired($);
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
|
@ -167,11 +169,18 @@ sub mtr_exe_exists (@) {
|
|||
}
|
||||
|
||||
|
||||
sub mtr_milli_sleep {
|
||||
sub mtr_milli_sleep ($) {
|
||||
die "usage: mtr_milli_sleep(milliseconds)" unless @_ == 1;
|
||||
my ($millis)= @_;
|
||||
|
||||
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;
|
||||
|
|
|
@ -439,7 +439,7 @@ sub run_test_server ($$$) {
|
|||
my $result;
|
||||
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();
|
||||
$s->add($server);
|
||||
|
@ -460,7 +460,6 @@ sub run_test_server ($$$) {
|
|||
mtr_verbose("Child closed socket");
|
||||
$s->remove($sock);
|
||||
if (--$childs == 0){
|
||||
$suite_timeout_proc->kill();
|
||||
return $completed;
|
||||
}
|
||||
next;
|
||||
|
@ -529,13 +528,11 @@ sub run_test_server ($$$) {
|
|||
|
||||
if ( !$opt_force ) {
|
||||
# Test has failed, force is off
|
||||
$suite_timeout_proc->kill();
|
||||
push(@$completed, $result);
|
||||
return $completed;
|
||||
}
|
||||
elsif ($opt_max_test_fail > 0 and
|
||||
$num_failed_test >= $opt_max_test_fail) {
|
||||
$suite_timeout_proc->kill();
|
||||
push(@$completed, $result);
|
||||
mtr_report_stats("Too many failed", $completed, 1);
|
||||
mtr_report("Too many tests($num_failed_test) failed!",
|
||||
|
@ -667,7 +664,7 @@ sub run_test_server ($$$) {
|
|||
# ----------------------------------------------------
|
||||
# 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("Test suite timeout! Terminating...");
|
||||
|
@ -2944,11 +2941,11 @@ sub check_testcase($$)
|
|||
# Return immediately if no check proceess was started
|
||||
return 0 unless ( keys %started );
|
||||
|
||||
my $timeout_proc= My::SafeProcess->timer(check_timeout());
|
||||
my $timeout= start_timer(check_timeout());
|
||||
|
||||
while (1){
|
||||
my $result;
|
||||
my $proc= My::SafeProcess->wait_any();
|
||||
my $proc= My::SafeProcess->wait_any_timeout($timeout);
|
||||
mtr_report("Got $proc");
|
||||
|
||||
if ( delete $started{$proc->pid()} ) {
|
||||
|
@ -2972,9 +2969,6 @@ sub check_testcase($$)
|
|||
|
||||
if ( keys(%started) == 0){
|
||||
# All checks completed
|
||||
|
||||
$timeout_proc->kill();
|
||||
|
||||
return 0;
|
||||
}
|
||||
# Wait for next process to exit
|
||||
|
@ -3015,10 +3009,9 @@ test case was executed:\n";
|
|||
|
||||
}
|
||||
}
|
||||
elsif ( $proc eq $timeout_proc ) {
|
||||
$tinfo->{comment}.= "Timeout $timeout_proc for ".
|
||||
"'check-testcase' expired after ".check_timeout().
|
||||
" seconds";
|
||||
elsif ( $proc->{timeout} ) {
|
||||
$tinfo->{comment}.= "Timeout for 'check-testcase' expired after "
|
||||
.check_timeout()." seconds";
|
||||
$result= 4;
|
||||
}
|
||||
else {
|
||||
|
@ -3033,8 +3026,6 @@ test case was executed:\n";
|
|||
# Kill any check processes still running
|
||||
map($_->kill(), values(%started));
|
||||
|
||||
$timeout_proc->kill();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
@ -3106,11 +3097,11 @@ sub run_on_all($$)
|
|||
# Return immediately if no check proceess was started
|
||||
return 0 unless ( keys %started );
|
||||
|
||||
my $timeout_proc= My::SafeProcess->timer(check_timeout());
|
||||
my $timeout= start_timer(check_timeout());
|
||||
|
||||
while (1){
|
||||
my $result;
|
||||
my $proc= My::SafeProcess->wait_any();
|
||||
my $proc= My::SafeProcess->wait_any_timeout($timeout);
|
||||
mtr_report("Got $proc");
|
||||
|
||||
if ( delete $started{$proc->pid()} ) {
|
||||
|
@ -3129,17 +3120,15 @@ sub run_on_all($$)
|
|||
|
||||
if ( keys(%started) == 0){
|
||||
# All completed
|
||||
$timeout_proc->kill();
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Wait for next process to exit
|
||||
next;
|
||||
}
|
||||
elsif ( $proc eq $timeout_proc ) {
|
||||
$tinfo->{comment}.= "Timeout $timeout_proc for '$run' ".
|
||||
"expired after ". check_timeout().
|
||||
" seconds";
|
||||
elsif ($proc->{timeout}) {
|
||||
$tinfo->{comment}.= "Timeout for '$run' expired after "
|
||||
.check_timeout()." seconds";
|
||||
}
|
||||
else {
|
||||
# Unknown process returned, most likley a crash, abort everything
|
||||
|
@ -3151,8 +3140,6 @@ sub run_on_all($$)
|
|||
# Kill any check processes still running
|
||||
map($_->kill(), values(%started));
|
||||
|
||||
$timeout_proc->kill();
|
||||
|
||||
return 1;
|
||||
}
|
||||
mtr_error("INTERNAL_ERROR: run_on_all");
|
||||
|
@ -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);
|
||||
|
||||
|
@ -3390,9 +3377,6 @@ sub run_testcase ($) {
|
|||
# Failed to record state of server or server crashed
|
||||
report_failure_and_restart($tinfo);
|
||||
|
||||
# Stop the test case timer
|
||||
$test_timeout_proc->kill();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -3410,20 +3394,20 @@ sub run_testcase ($) {
|
|||
if ($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
|
||||
{
|
||||
$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
|
||||
|
@ -3440,9 +3424,6 @@ sub run_testcase ($) {
|
|||
# ----------------------------------------------------
|
||||
if ($proc eq $test)
|
||||
{
|
||||
# Stop the test case timer
|
||||
$test_timeout_proc->kill();
|
||||
|
||||
my $res= $test->exit_status();
|
||||
|
||||
if ($res == 0 and $opt_warnings and check_warnings($tinfo) )
|
||||
|
@ -3545,7 +3526,7 @@ sub run_testcase ($) {
|
|||
# ----------------------------------------------------
|
||||
# Stop the test case timer
|
||||
# ----------------------------------------------------
|
||||
$test_timeout_proc->kill();
|
||||
$test_timeout= 0;
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Check if it was a server that died
|
||||
|
@ -3584,7 +3565,7 @@ sub run_testcase ($) {
|
|||
# ----------------------------------------------------
|
||||
# Check if testcase timer expired
|
||||
# ----------------------------------------------------
|
||||
if ( $proc eq $test_timeout_proc )
|
||||
if ( $proc->{timeout} )
|
||||
{
|
||||
my $log_file_name= $opt_vardir."/log/".$tinfo->{shortname}.".log";
|
||||
$tinfo->{comment}=
|
||||
|
@ -3825,11 +3806,11 @@ sub check_warnings ($) {
|
|||
# Return immediately if no check proceess was started
|
||||
return 0 unless ( keys %started );
|
||||
|
||||
my $timeout_proc= My::SafeProcess->timer(check_timeout());
|
||||
my $timeout= start_timer(check_timeout());
|
||||
|
||||
while (1){
|
||||
my $result= 0;
|
||||
my $proc= My::SafeProcess->wait_any();
|
||||
my $proc= My::SafeProcess->wait_any_timeout($timeout);
|
||||
mtr_report("Got $proc");
|
||||
|
||||
if ( delete $started{$proc->pid()} ) {
|
||||
|
@ -3858,9 +3839,6 @@ sub check_warnings ($) {
|
|||
|
||||
if ( keys(%started) == 0){
|
||||
# All checks completed
|
||||
|
||||
$timeout_proc->kill();
|
||||
|
||||
return $result;
|
||||
}
|
||||
# Wait for next process to exit
|
||||
|
@ -3877,10 +3855,9 @@ sub check_warnings ($) {
|
|||
$result= 2;
|
||||
}
|
||||
}
|
||||
elsif ( $proc eq $timeout_proc ) {
|
||||
$tinfo->{comment}.= "Timeout $timeout_proc for ".
|
||||
"'check warnings' expired after ".check_timeout().
|
||||
" seconds";
|
||||
elsif ( $proc->{timeout} ) {
|
||||
$tinfo->{comment}.= "Timeout for 'check warnings' expired after "
|
||||
.check_timeout()." seconds";
|
||||
$result= 4;
|
||||
}
|
||||
else {
|
||||
|
@ -3894,8 +3871,6 @@ sub check_warnings ($) {
|
|||
# Kill any check processes still running
|
||||
map($_->kill(), values(%started));
|
||||
|
||||
$timeout_proc->kill();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue