MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Bjorn Munch Date:November 24 2009 8:14am
Subject:bzr commit into mysql-5.1-mtr branch (Bjorn.Munch:2861) Bug#47978
View as plain text  
#At file:///home/bm136801/my/timer-51/ based on revid:bjorn.munch@stripped

 2861 Bjorn Munch	2009-11-24
      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()

    modified:
      mysql-test/lib/My/SafeProcess.pm
      mysql-test/lib/mtr_misc.pl
      mysql-test/mysql-test-run.pl
=== modified file 'mysql-test/lib/My/SafeProcess.pm'
--- a/mysql-test/lib/My/SafeProcess.pm	2009-11-17 11:13:22 +0000
+++ b/mysql-test/lib/My/SafeProcess.pm	2009-11-24 08:12:48 +0000
@@ -188,63 +188,6 @@ sub run {
 }
 
 #
-# 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
 #
@@ -542,6 +485,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
 #
 sub wait_all {

=== modified file 'mysql-test/lib/mtr_misc.pl'
--- a/mysql-test/lib/mtr_misc.pl	2008-02-20 13:55:30 +0000
+++ b/mysql-test/lib/mtr_misc.pl	2009-11-24 08:12:48 +0000
@@ -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;

=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl	2009-11-19 09:19:18 +0000
+++ b/mysql-test/mysql-test-run.pl	2009-11-24 08:12:48 +0000
@@ -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;
   }
 


Attachment: [text/bzr-bundle] bzr/bjorn.munch@sun.com-20091124081248-lcz1z0mo1unpwaxd.bundle
Thread
bzr commit into mysql-5.1-mtr branch (Bjorn.Munch:2861) Bug#47978Bjorn Munch24 Nov