summaryrefslogtreecommitdiff
path: root/dist/Time-HiRes
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2018-08-07 12:26:31 +0100
committerDavid Mitchell <davem@iabyn.com>2018-08-07 12:26:31 +0100
commitecbf46993f6ffbdc255f6ded3c6c05a8266a71e8 (patch)
tree57c0c772a03cfc1ac871b05f446a3a8b87e54fd2 /dist/Time-HiRes
parentd342516410da8af9d1824e50179d7d6ff3c7ba95 (diff)
downloadperl-ecbf46993f6ffbdc255f6ded3c6c05a8266a71e8.tar.gz
Time-HiRes/t/itimer.t: avoid race condition.
This test script sets a repeating interval timer going, and after 4 'ticks' (SIGVTALRM), disables the timer (by setting it to zero). The main loop which does CPU burning, does a getitmer() every now and again, and when the value is zero, assumes the signal handler has disabled the timer, and so finishes. The trouble was that it was checking the 'time left', which can reach zero because the interval timer has counted down to zero, and the signal handler is about to be called, but the interval hasn't been reset back to 0.4s yet. i.e. the code doesn't distinguish between "timer disabled" and "timer just reached zero". In that scenario, the cleanup code in the test script disables the SIGVTALRM handler while the timer is still active, and so the process gets killed if another signal is raised. This commit changes the test to check the second value returned by getitmer() for being zero rather than the first - the second being the repeat interval, whichb is always 0.4 until the timer is disabled.
Diffstat (limited to 'dist/Time-HiRes')
-rw-r--r--dist/Time-HiRes/t/itimer.t4
1 files changed, 3 insertions, 1 deletions
diff --git a/dist/Time-HiRes/t/itimer.t b/dist/Time-HiRes/t/itimer.t
index e196b1648c..432b224488 100644
--- a/dist/Time-HiRes/t/itimer.t
+++ b/dist/Time-HiRes/t/itimer.t
@@ -51,7 +51,9 @@ ok(defined $virt && abs($virt / 0.5) - 1 < $limit,
printf("# getitimer: %s\n", join(" ",
Time::HiRes::getitimer(&Time::HiRes::ITIMER_VIRTUAL)));
-while (Time::HiRes::getitimer(&Time::HiRes::ITIMER_VIRTUAL)) {
+# burn CPU until the VTALRM signal handler sets the repeat interval to
+# zero, indicating that the timer has fired 4 times.
+while ((Time::HiRes::getitimer(&Time::HiRes::ITIMER_VIRTUAL))[1]) {
my $j;
for (1..1000) { $j++ } # Can't be unbreakable, must test getitimer().
}