Handle test timeouts in a more understandable way.
authorPaul Smith <psmith@gnu.org>
Sun, 14 Apr 2013 23:09:16 +0000 (19:09 -0400)
committerPaul Smith <psmith@gnu.org>
Sun, 14 Apr 2013 23:11:47 +0000 (19:11 -0400)
tests/ChangeLog
tests/test_driver.pl

index afa1cbe27d6c7ccf0378b30db4e6c9f75361b20d..cf78c58daac7a52f0d4465b63bdef2f343f7bb8b 100644 (file)
@@ -1,3 +1,11 @@
+2013-04-14  Paul Smith  <psmith@gnu.org>
+
+       * test_driver.pl (_run_command): Don't set SIGALRM until after we
+       start the child.  Print errors to the top-level output, which will
+       be stderr.
+       (attach_default_output): Use a list of file handles as the stack.
+       (detach_default_output): Ditto.
+
 2013-02-25  Paul Smith  <psmith@gnu.org>
 
        * run_make_tests.pl (valid_option): Support the -srcdir flag.
index 9cd392ec2681344b0a0527dbce904e9228c02a66..e639c895550ec8bc9f53699f191bfc952a2c8527 100644 (file)
@@ -730,6 +730,9 @@ sub read_file_into_string
   return $slurp;
 }
 
+my @OUTSTACK = ();
+my @ERRSTACK = ();
+
 sub attach_default_output
 {
   local ($filename) = @_;
@@ -742,17 +745,15 @@ sub attach_default_output
     return 1;
   }
 
-  open ("SAVEDOS" . $default_output_stack_level . "out", ">&STDOUT")
-        || &error ("ado: $! duping STDOUT\n", 1);
-  open ("SAVEDOS" . $default_output_stack_level . "err", ">&STDERR")
-        || &error ("ado: $! duping STDERR\n", 1);
+  my $dup = undef;
+  open($dup, '>&', STDOUT) or error("ado: $! duping STDOUT\n", 1);
+  push @OUTSTACK, $dup;
 
-  open (STDOUT, "> " . $filename)
-        || &error ("ado: $filename: $!\n", 1);
-  open (STDERR, ">&STDOUT")
-        || &error ("ado: $filename: $!\n", 1);
+  open($dup, '>&', STDERR) or error("ado: $! duping STDERR\n", 1);
+  push @ERRSTACK, $dup;
 
-  $default_output_stack_level++;
+  open(STDOUT, '>', $filename) or error("ado: $filename: $!\n", 1);
+  open(STDERR, ">&STDOUT") or error("ado: $filename: $!\n", 1);
 }
 
 # close the current stdout/stderr, and restore the previous ones from
@@ -769,23 +770,13 @@ sub detach_default_output
     return 1;
   }
 
-  if (--$default_output_stack_level < 0)
-  {
-    &error ("default output stack has flown under!\n", 1);
-  }
-
-  close (STDOUT);
-  close (STDERR);
+  @OUTSTACK or error("default output stack has flown under!\n", 1);
 
-  open (STDOUT, ">&SAVEDOS" . $default_output_stack_level . "out")
-        || &error ("ddo: $! duping STDOUT\n", 1);
-  open (STDERR, ">&SAVEDOS" . $default_output_stack_level . "err")
-        || &error ("ddo: $! duping STDERR\n", 1);
+  close(STDOUT);
+  close(STDERR);
 
-  close ("SAVEDOS" . $default_output_stack_level . "out")
-        || &error ("ddo: $! closing SCSDOSout\n", 1);
-  close ("SAVEDOS" . $default_output_stack_level . "err")
-         || &error ("ddo: $! closing SAVEDOSerr\n", 1);
+  open (STDOUT, '>&', pop @OUTSTACK) or error("ddo: $! duping STDOUT\n", 1);
+  open (STDERR, '>&', pop @ERRSTACK) or error("ddo: $! duping STDERR\n", 1);
 }
 
 # This runs a command without any debugging info.
@@ -799,14 +790,19 @@ sub _run_command
   resetENV();
 
   eval {
-      local $SIG{ALRM} = sub { die "timeout\n"; };
+      my $pid = fork();
+      if (! $pid) {
+          exec(@_) or die "Cannot execute $_[0]\n";
+      }
+      local $SIG{ALRM} = sub { my $e = $ERRSTACK[0]; print $e "\nTest timed out after $test_timeout seconds\n"; die "timeout\n"; };
       alarm $test_timeout;
-      $code = system(@_);
+      waitpid($pid, 0) > 0 or die "No such pid: $pid\n";
+      $code = $?;
       alarm 0;
   };
   if ($@) {
       # The eval failed.  If it wasn't SIGALRM then die.
-      $@ eq "timeout\n" or die;
+      $@ eq "timeout\n" or die "Command failed: $@";
 
       # Timed out.  Resend the alarm to our process group to kill the children.
       $SIG{ALRM} = 'IGNORE';
@@ -840,8 +836,12 @@ sub run_command_with_output
 
   print "\nrun_command_with_output($filename,$runname): @_\n" if $debug;
   &attach_default_output ($filename);
-  my $code = _run_command(@_);
+  my $code = eval { _run_command(@_) };
+  my $err = $@;
   &detach_default_output;
+
+  $err and die $err;
+
   print "run_command_with_output returned $code.\n" if $debug;
 
   return $code;