[Rt-commit] rt branch, 4.0/dbh-disconnect-after-safe-run-child, updated. rt-4.0.3-49-ga6f29f3
Alex Vandiver
alexmv at bestpractical.com
Fri Dec 16 15:18:38 EST 2011
The branch, 4.0/dbh-disconnect-after-safe-run-child has been updated
via a6f29f34f78bbe09e6417d521594f7b2dbfaed4b (commit)
from fa65b29c46def6414a7b54a250469cddac19b6e0 (commit)
Summary of changes:
t/api/safe-run-child-util.t | 17 +++++++++++++++++
1 files changed, 17 insertions(+), 0 deletions(-)
- Log -----------------------------------------------------------------
commit a6f29f34f78bbe09e6417d521594f7b2dbfaed4b
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Thu Dec 15 15:37:40 2011 -0500
Use sleep() and signals to remove a possible race condition between processes
It is possible that the parent could try to open the first file before
the child has had a chance to write it, which would lead to a spurious
test failure. To avoid this, we establish a 3-second grace period
during which we sleep(). Since any signal ends a sleep() call early, we
will either be woken by a USR1 signal from the child when it is ready,
or we will simply carry on and check for existence after 3 seconds. We
also install a trivial signal handler to allow us to skip the sleep()
entirely if the signal arrives before we would enter the sleep().
It is theoretically possible that on sufficiently heavily-loaded
systems, 3 seconds is insufficient; if the system is that heavily
loaded, however, you likely have other problems.
diff --git a/t/api/safe-run-child-util.t b/t/api/safe-run-child-util.t
index e94f14e..c4d2a8b 100644
--- a/t/api/safe-run-child-util.t
+++ b/t/api/safe-run-child-util.t
@@ -141,12 +141,20 @@ END
require Time::HiRes;
my $start = Time::HiRes::time();
my $pid;
+
+ # Set up a poor man's semaphore
+ my $all_set = 0;
+ $SIG{USR1} = sub {$all_set++};
+
my $res = safe_run_child {
if ($pid = fork) { return 'parent' }
open my $fh, '>', RT::Test->temp_directory .'/first';
print $fh "child";
close $fh;
+ # Signal that the first file is now all set; we need to do this
+ # to avoid a race condition
+ kill 10, getppid(); # USR1
sleep 5;
@@ -157,6 +165,15 @@ END
exit 0;
};
ok( Time::HiRes::time() - $start < 5, "Didn't wait until child finished" );
+
+ # Wait for up to 3 seconds to get signaled that the child has made
+ # the file (the USR1 will break out of the sleep()). This _should_
+ # be immediate, but there's a race between the parent and child
+ # here, since there's no wait()'ing. There's still a tiny race
+ # where the signal could come in betwene the $all_set check and the
+ # sleep, but that just means we sleep for 3 seconds uselessly.
+ sleep 3 unless $all_set;
+
is $res, 'parent', "correct return value";
is( RT::Test->file_content([RT::Test->temp_directory, 'first'], unlink => 1 ),
'child',
-----------------------------------------------------------------------
More information about the Rt-commit
mailing list