Commit 7523d09c authored by abecsi@webkit.org's avatar abecsi@webkit.org

2010-02-04 Andras Becsi <abecsi@inf.u-szeged.hu>

        
        Reviewed by Tor Arne Vestbø.

        Implement a locking and scheduling mechanism for http testing sessions to be able
        to run multiple instances of run-webkit-tests parallel on the same machine.
        If a test session wants to run http tests and this feature is enabled, the pending
        sessions create lockfiles with sequential lock numbers. These locks are used to schedule
        the running test sessions in first come first served order. An exclusive lock ensures
        that the lock numbers are sequential to avoid deadlocks and starvation.
        Because the buildbot master specifies the flags used by slaves we need an environment
        variable too to be able to use the feature per-slave.
        Exporting WEBKIT_WAIT_FOR_HTTPD=1 before testing or using the --wait-for-httpd
        flag enables this feature, otherwise this patch has no effect on the testing whatsoever.

        https://bugs.webkit.org/show_bug.cgi?id=33153



git-svn-id: svn://svn.chromium.org/blink/trunk@54342 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent ac208885
2010-02-04 Andras Becsi <abecsi@inf.u-szeged.hu>
Reviewed by Tor Arne Vestbø.
Implement a locking and scheduling mechanism for http testing sessions to be able
to run multiple instances of run-webkit-tests parallel on the same machine.
If a test session wants to run http tests and this feature is enabled, the pending
sessions create lockfiles with sequential lock numbers. These locks are used to schedule
the running test sessions in first come first served order. An exclusive lock ensures
that the lock numbers are sequential to avoid deadlocks and starvation.
Because the buildbot master specifies the flags used by slaves we need an environment
variable too to be able to use the feature per-slave.
Exporting WEBKIT_WAIT_FOR_HTTPD=1 before testing or using the --wait-for-httpd
flag enables this feature, otherwise this patch has no effect on the testing whatsoever.
https://bugs.webkit.org/show_bug.cgi?id=33153
* Scripts/run-webkit-tests:
* Scripts/webkitperl/httpd.pm:
2010-01-22 Tor Arne Vestbø <tor.arne.vestbo@nokia.com>
Reviewed by Simon Hausmann.
......
......@@ -154,6 +154,7 @@ my $treatSkipped = "default";
my $useRemoteLinksToTests = 0;
my $useValgrind = 0;
my $verbose = 0;
my $shouldWaitForHTTPD = 0;
my @leaksFilenames;
......@@ -224,6 +225,7 @@ Usage: $programName [options] [testdir|testpath ...]
--exit-after-n-failures N Exit after the first N failures instead of running all tests
-h|--help Show this help message
--[no-]http Run (or do not run) http tests (default: $httpDefault)
--[no-]wait-for-httpd Wait for httpd if some other test session is using it already (same as WEBKIT_WAIT_FOR_HTTPD=1). (default: $shouldWaitForHTTPD)
-i|--ignore-tests Comma-separated list of directories or tests to ignore
--iterations n Number of times to run the set of tests (e.g. ABCABCABC)
--[no-]launch-safari Launch (or do not launch) Safari to display test results (default: $launchSafariDefault)
......@@ -267,6 +269,7 @@ my $getOptionsResult = GetOptions(
'guard-malloc|g' => \$guardMalloc,
'help|h' => \$showHelp,
'http!' => \$testHTTP,
'wait-for-httpd!' => \$shouldWaitForHTTPD,
'ignore-metrics!' => \$ignoreMetrics,
'ignore-tests|i=s' => \$ignoreTests,
'iterations=i' => \$iterations,
......@@ -308,6 +311,8 @@ my $skippedOnly = $treatSkipped eq "only";
my $configuration = configuration();
# We need an environment variable to be able to enable the feature per-slave
$shouldWaitForHTTPD = $ENV{"WEBKIT_WAIT_FOR_HTTPD"} unless ($shouldWaitForHTTPD);
$verbose = 1 if $testsPerDumpTool == 1;
if ($shouldCheckLeaks && $testsPerDumpTool > 1000) {
......@@ -943,7 +948,14 @@ for my $test (@tests) {
}
}
}
printf "\n%0.2fs total testing time\n", (time - $overallStartTime) . "";
my $totalTestingTime = time - $overallStartTime;
my $waitTime = getWaitTime();
if ($waitTime > 0.1) {
my $normalizedTestingTime = $totalTestingTime - $waitTime;
printf "\n%0.2fs HTTPD waiting time\n", $waitTime . "";
printf "%0.2fs normalized testing time", $normalizedTestingTime . "";
}
printf "\n%0.2fs total testing time\n", $totalTestingTime . "";
!$isDumpToolOpen || die "Failed to close $dumpToolName.\n";
......@@ -1360,6 +1372,7 @@ sub configureAndOpenHTTPDIfNeeded()
my @defaultArgs = getDefaultConfigForTestDirectory($testDirectory);
@args = (@defaultArgs, @args);
waitForHTTPDLock() if $shouldWaitForHTTPD;
$isHttpdOpen = openHTTPD(@args);
}
......
......@@ -34,6 +34,7 @@ use warnings;
use File::Path;
use File::Spec;
use File::Spec::Functions;
use Fcntl ':flock';
use IPC::Open2;
use webkitdirs;
......@@ -43,20 +44,25 @@ BEGIN {
our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
$VERSION = 1.00;
@ISA = qw(Exporter);
@EXPORT = qw(&getHTTPDPath &getDefaultConfigForTestDirectory &openHTTPD &closeHTTPD &getHTTPDPid &setShouldWaitForUserInterrupt);
@EXPORT = qw(&getHTTPDPath &getDefaultConfigForTestDirectory &openHTTPD &closeHTTPD &setShouldWaitForUserInterrupt &waitForHTTPDLock &getWaitTime);
%EXPORT_TAGS = ( );
@EXPORT_OK = ();
}
my $tmpDir = "/tmp";
my $httpdLockPrefix = "WebKitHttpd.lock.";
my $myLockFile;
my $exclusiveLockFile = File::Spec->catfile($tmpDir, "WebKit.lock");
my $httpdPath;
my $httpdPidDir = File::Spec->catfile($tmpDir, "WebKit");
my $httpdPidFile = File::Spec->catfile($httpdPidDir, "httpd.pid");
my $httpdPid;
my $waitForUserInterrupt = 0;
my $waitBeginTime;
my $waitEndTime;
$SIG{'INT'} = 'cleanup';
$SIG{'TERM'} = 'cleanup';
$SIG{'INT'} = 'handleInterrupt';
$SIG{'TERM'} = 'handleInterrupt';
sub getHTTPDPath
{
......@@ -141,7 +147,10 @@ sub openHTTPD(@)
--$retryCount;
}
die "Timed out waiting for httpd to quit" unless $retryCount;
if (!$retryCount) {
cleanUp();
die "Timed out waiting for httpd to quit";
}
}
}
......@@ -156,7 +165,7 @@ sub openHTTPD(@)
}
if (!$retryCount) {
rmtree $httpdPidDir;
cleanUp();
die "Timed out waiting for httpd to start";
}
......@@ -172,20 +181,19 @@ sub openHTTPD(@)
sub closeHTTPD
{
close HTTPDIN;
my $retryCount = 20;
if ($httpdPid) {
kill 15, $httpdPid;
my $retryCount = 20;
while (-f $httpdPidFile && $retryCount) {
sleep 1;
--$retryCount;
}
if (!$retryCount) {
print STDERR "Timed out waiting for httpd to terminate!\n";
return 0;
}
}
rmdir $httpdPidDir;
cleanUp();
if (!$retryCount) {
print STDERR "Timed out waiting for httpd to terminate!\n";
return 0;
}
return 1;
}
......@@ -194,9 +202,94 @@ sub setShouldWaitForUserInterrupt
$waitForUserInterrupt = 1;
}
sub cleanup
sub handleInterrupt
{
closeHTTPD();
print "\n";
exit(1);
}
sub cleanUp
{
rmdir $httpdPidDir;
unlink $exclusiveLockFile;
unlink $myLockFile if $myLockFile;
}
sub extractLockNumber
{
my ($lockFile) = @_;
return -1 unless $lockFile;
return substr($lockFile, length($httpdLockPrefix));
}
sub getLockFiles
{
opendir(TMPDIR, $tmpDir) or die "Could not open " . $tmpDir . ".";
my @lockFiles = grep {m/^$httpdLockPrefix\d+$/} readdir(TMPDIR);
@lockFiles = sort { extractLockNumber($a) <=> extractLockNumber($b) } @lockFiles;
closedir(TMPDIR);
return @lockFiles;
}
sub getNextAvailableLockNumber
{
my @lockFiles = getLockFiles();
return 0 unless @lockFiles;
return extractLockNumber($lockFiles[-1]) + 1;
}
sub getLockNumberForCurrentRunning
{
my @lockFiles = getLockFiles();
return 0 unless @lockFiles;
return extractLockNumber($lockFiles[0]);
}
sub waitForHTTPDLock
{
$waitBeginTime = time;
scheduleHttpTesting();
# If we are the only one waiting for Apache just run the tests without any further checking
if (scalar getLockFiles() > 1) {
my $currentLockFile = File::Spec->catfile($tmpDir, "$httpdLockPrefix" . getLockNumberForCurrentRunning());
my $currentLockPid = <SCHEDULER_LOCK> if (-f $currentLockFile && open(SCHEDULER_LOCK, "<$currentLockFile"));
# Wait until we are allowed to run the http tests
while ($currentLockPid && $currentLockPid != $$) {
$currentLockFile = File::Spec->catfile($tmpDir, "$httpdLockPrefix" . getLockNumberForCurrentRunning());
if ($currentLockFile eq $myLockFile) {
$currentLockPid = <SCHEDULER_LOCK> if open(SCHEDULER_LOCK, "<$currentLockFile");
if ($currentLockPid != $$) {
print STDERR "\nPID mismatch.\n";
last;
}
} else {
sleep 1;
}
}
}
$waitEndTime = time;
}
sub scheduleHttpTesting
{
# We need an exclusive lock file to avoid deadlocks and starvation and ensure that the scheduler lock numbers are sequential.
# The scheduler locks are used to schedule the running test sessions in first come first served order.
while (!(open(SEQUENTIAL_GUARD_LOCK, ">$exclusiveLockFile") && flock(SEQUENTIAL_GUARD_LOCK, LOCK_EX|LOCK_NB))) {}
$myLockFile = File::Spec->catfile($tmpDir, "$httpdLockPrefix" . getNextAvailableLockNumber());
open(SCHEDULER_LOCK, ">$myLockFile");
print SCHEDULER_LOCK "$$";
print SEQUENTIAL_GUARD_LOCK "$$";
close(SCHEDULER_LOCK);
close(SEQUENTIAL_GUARD_LOCK);
unlink $exclusiveLockFile;
}
sub getWaitTime
{
my $waitTime = 0;
if ($waitBeginTime && $waitEndTime) {
$waitTime = $waitEndTime - $waitBeginTime;
}
return $waitTime;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment