my $pid = open(my $fh, "-|");
if (!$pid) {
# child
- setpgrp();
+ setpgrp(); # Terminal won't send signals to the child
open STDERR, '>&STDOUT' or die("Can't dup stdout: $!\n");
exec(@ARGV);
exit 126; # just in case
}
my $istty = -t STDOUT && $ENV{'TERM'} ne "dumb";
-my $columns = `tput cols` if ($istty);
+my $columns;
+if ($istty) {
+ $columns = `tput cols`;
+} else {
+ $columns = 80;
+}
my @log = ();
my ($gpasses, $gfails) = (0,0);
my $column = 0;
+my $timeout = 120;
+my $died = 0;
-sub bigkill($)
+sub bigkill($$)
{
- my $pid = shift;
-
- if (@log) {
- print "\n" . join("\n", @log) . "\n";
- }
-
- print STDERR "\n! Killed by signal FAILED\n";
-
+ my($sig, $pid) = @_;
($pid > 0) || die("pid is '$pid'?!\n");
- local $SIG{CHLD} = sub { }; # this will wake us from sleep() faster
- kill 15, $pid;
+ $SIG{TERM} = 'IGNORE';
+ local $SIG{CHLD} = sub { $died = 1; }; # this will wake us from sleep() faster
+ # Send TERM to our process group (this includes us, hopefully all children and maybe some of our parents)
+ kill 15, -$pid;
sleep(2);
- if ($pid > 1) {
- kill 9, -$pid;
+ if (!$died) {
+ if ($pid > 1) { kill 9, -$pid; }
+ kill 9, $pid;
}
- kill 9, $pid;
-
- exit(125);
+ if (@log) {
+ print_and_clear_log();
+ }
+ print "\n";
+ print STDERR resultline('', "Killed by signal $sig", "FAILED")."\n";
}
+my $timedout = 0;
# parent
-local $SIG{INT} = sub { bigkill($pid); };
-local $SIG{TERM} = sub { bigkill($pid); };
+local $SIG{INT} = sub { bigkill(shift, $pid); exit(125); };
+local $SIG{TERM} = sub { bigkill(shift, $pid); exit(125); };
local $SIG{ALRM} = sub {
- print STDERR "Alarm timed out! No test results for too long.\n";
- bigkill($pid);
+ $timedout = 1;
+ bigkill(shift, $pid);
+ print STDERR resultline('', "Alarm timed out! No test results for $timeout seconds.", 'FAILED')."\n";
+ exit(125);
};
sub colourize($$)
{
$stop = time();
if ($start) {
- my ($time, $timelength) = mstime($stop - $start, 500, 1000);
+ my ($time, $timelength) = mstime($stop - $start, 60000, 60000);
printf " %s %s\n", $time, colourize($column + 2 + $timelength, "ok");
+ } elsif ($column > 0) {
+ print "\n";
}
+ $column = 0;
}
+sub print_and_clear_log()
+{
+ print "\n" if ($column);
+ print "v"x($columns-1) . "\n"; # Top marker
+ print join("\n", @log) . "\n";
+ print "^"x($columns-1) . "\n"; # Bottom marker
+ $column = 0;
+ @log = ();
+}
+
+alarm($timeout);
while (<$fh>)
{
chomp;
if (/^\s*Testing "(.*)" in (.*):\s*$/)
{
- alarm(120);
+ $timeout = 120;
+ alarm($timeout);
my ($sect, $file) = ($1, $2);
endsect();
print $msg;
$column = length($msg);
@log = ();
- push @log, "-"x78;
$start = $stop;
}
elsif (/^!\s*(.*?)\s+(\S+)\s*$/)
{
- alarm(120);
+ alarm($timeout);
my ($name, $result) = ($1, $2);
my $pass = ($result eq "ok");
if (!$pass) {
$gfails++;
- if (@log) {
- print "\n" . join("\n", @log) . "\n";
- @log = ();
- }
+ print_and_clear_log() if (@log);
} else {
$gpasses++;
print ".";
$column++;
}
}
+ elsif (/^wvtest: timeout (\d+)\s*$/) {
+ push @log, $_;
+ $timeout=$3;
+ alarm($timeout);
+ }
else
{
push @log, $_;
my $code = $?;
my $ret = ($code >> 8);
-# return death-from-signal exits as >128. This is what bash does if you ran
-# the program directly.
-if ($code && !$ret) { $ret = $code | 128; }
-
-if ($ret && @log) {
- print "\n" . join("\n", @log) . "\n";
+if ($code && @log) {
+ print_and_clear_log();
}
-if ($code != 0) {
- print resultline("Program returned non-zero exit code ($ret)", "FAILED");
+if ($ret != 0) { print STDERR resultline("Program returned non-zero exit code ($ret)", "FAILED")."\n"; }
+
+# return death-from-signal exits as >128. This is what bash does if you ran
+# the program directly.
+if ($code && !$ret) {
+ print STDERR resultline("Killed by signal $code", "FAILED")."\n";
+ $ret = $code | 128;
}
+if ($timedout) {print STDERR resultline("Alarm timed out! No test results for $timeout seconds.", 'FAILED')."\n";}
my $gtotal = $gpasses+$gfails;
printf("\nWvTest: %d test%s, %d failure%s, total time %s.\n",
$gtotal, $gtotal==1 ? "" : "s",
$gfails, $gfails==1 ? "" : "s",
- mstime(time() - $allstart, 2000, 5000));
+ mstime(time() - $allstart, 60000, 600000));
print STDERR "\nWvTest result code: $ret\n";
exit( $ret ? $ret : ($gfails ? 125 : 0) );