Skip to content

Commit f028d37

Browse files
committed
test.pl: Use END blocks to cancel watchdog timers
In doing follow up work to a7f3f23 "Turn off watchdog when done in tests", I realized that my solution was suboptimal, and that the code already existed in test.pl to do things better. What that code does is to create an END block to cancel the watchdog upon program exit. I think that is a better solution than to force the addition of explicit calls to watchdog(0). This commit creates a standard way to specify the code that does the cancellation, and to use it, not only when the END block does, but also when the timer is explicitly cancelled. That standard method is to create a string that basically gets evaled. This entailed making any watchdog thread object into a global so that a reference to it could be stringified for the eval. This means the calls to watchdog(0) that occur at the end of the file that were added in a7f3f23 aren't necessary. The END block takes care of it. The reason to keep them would be if we want to add a porting test that every watchdog is cleared.
1 parent c220b63 commit f028d37

File tree

1 file changed

+25
-27
lines changed

1 file changed

+25
-27
lines changed

t/test.pl

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
our $TODO = 0;
3939
our $NO_ENDING = 0;
4040
our $Tests_Are_Passing = 1;
41+
our @watchdog_threads_;
4142

4243
# Use this instead of print to avoid interference while testing globals.
4344
sub _print {
@@ -1834,8 +1835,7 @@ sub warning_like {
18341835
# NOTE: If the test file uses 'threads', then call the watchdog() function
18351836
# _AFTER_ the 'threads' module is loaded.
18361837
{ # Closure
1837-
my $watchdog;
1838-
my $watchdog_thread;
1838+
my $cancel_string;
18391839

18401840
sub watchdog ($;$)
18411841
{
@@ -1844,29 +1844,18 @@ ($;$)
18441844
# If cancelling, use the state variables to know which method was used to
18451845
# create the watchdog.
18461846
if ($timeout == 0) {
1847-
if ($watchdog_thread) {
1848-
$watchdog_thread->kill('KILL');
1849-
undef $watchdog_thread;
1850-
}
1851-
elsif ($watchdog) {
1852-
kill('KILL', $watchdog);
1853-
undef $watchdog;
1854-
}
1855-
else {
1856-
alarm(0);
1857-
}
1858-
1847+
eval $cancel_string if defined $cancel_string;
18591848
return;
18601849
}
18611850

1862-
# Make sure these aren't defined.
1863-
undef $watchdog;
1864-
undef $watchdog_thread;
1865-
18661851
my $method = shift || "";
18671852

18681853
my $timeout_msg = 'Test process timed out - terminating';
18691854

1855+
# Common to all cancellation types; HERE gets replaced below by the
1856+
# individual code
1857+
$cancel_string = 'local $! = 0; local $? = 0; HERE; undef $cancel_string';
1858+
18701859
# Accept either spelling
18711860
my $timeout_factor = $ENV{PERL_TEST_TIME_OUT_FACTOR}
18721861
|| $ENV{PERL_TEST_TIMEOUT_FACTOR}
@@ -1894,6 +1883,8 @@ ($;$)
18941883
|| (defined $ENV{PERL_SIGNALS} && $ENV{PERL_SIGNALS} eq "unsafe")
18951884
|| $method eq "process")
18961885
{
1886+
my $watchdog;
1887+
18971888
# On Windows and VMS, try launching a watchdog process
18981889
# using system(1, ...) (see perlport.pod). system() returns
18991890
# immediately on these platforms with effectively a pid of the new
@@ -1911,7 +1902,6 @@ ($;$)
19111902
return if ($pid_to_kill <= 0);
19121903

19131904
# Launch watchdog process
1914-
undef $watchdog;
19151905
eval {
19161906
local $SIG{'__WARN__'} = sub {
19171907
_diag("Watchdog warning: $_[0]");
@@ -1954,20 +1944,19 @@ ($;$)
19541944

19551945
# Add END block to parent to terminate and clean up watchdog
19561946
# process
1957-
eval("END { local \$! = 0; local \$? = 0;
1958-
wait() if kill('KILL', $watchdog); };");
1947+
$cancel_string =~ s/HERE/wait() if kill('KILL', $watchdog)/;
1948+
eval("END { $cancel_string };");
19591949
return;
19601950
}
19611951

19621952
# Try using fork() to generate a watchdog process
1963-
undef $watchdog;
19641953
eval { $watchdog = fork() };
19651954
if (defined($watchdog)) {
19661955
if ($watchdog) { # Parent process
19671956
# Add END block to parent to terminate and clean up watchdog
19681957
# process
1969-
eval "END { local \$! = 0; local \$? = 0;
1970-
wait() if kill('KILL', $watchdog); };";
1958+
$cancel_string =~ s/HERE/wait() if kill('KILL', $watchdog)/;
1959+
eval("END { $cancel_string };");
19711960
return;
19721961
}
19731962

@@ -2005,7 +1994,9 @@ ($;$)
20051994
# Use a watchdog thread because either 'threads' is loaded, or fork()
20061995
# failed
20071996
if (eval {require threads; 1}) {
2008-
$watchdog_thread = 'threads'->create(sub {
1997+
1998+
# Use an array so can handle multiple timers
1999+
push @watchdog_threads_, 'threads'->create(sub {
20092000
# Load POSIX if available
20102001
eval { require POSIX; };
20112002

@@ -2029,12 +2020,16 @@ ($;$)
20292020
kill($sig, $pid_to_kill);
20302021
});
20312022

2023+
#my $index = scalar @watchd
2024+
$cancel_string =~ s/HERE/\$watchdog_threads_[$#watchdog_threads_]->kill('KILL')/;
2025+
eval "END { $cancel_string }";
2026+
20322027
# Don't proceed until the watchdog has set up its signal handler.
20332028
# (Otherwise there is a possibility that we will exit with threads
20342029
# running.) The watchdog tells us that the handler is set by
20352030
# detaching itself. (The 'is_running()' is a fail-safe.)
2036-
while ( $watchdog_thread->is_running()
2037-
&& ! $watchdog_thread->is_detached())
2031+
while ( $watchdog_threads_[-1]->is_running()
2032+
&& ! $watchdog_threads_[-1]->is_detached())
20382033
{
20392034
'threads'->yield();
20402035
}
@@ -2057,6 +2052,9 @@ ($;$)
20572052
my $sig = $is_vms ? 'TERM' : 'KILL';
20582053
kill($sig, $pid_to_kill);
20592054
};
2055+
2056+
$cancel_string =~ s/HERE/alarm(0)/;
2057+
eval "END { $cancel_string }";
20602058
}
20612059
}
20622060
} # End closure

0 commit comments

Comments
 (0)