15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Copyright (C) 2010 Andras Becsi (abecsi@inf.u-szeged.hu), University of Szeged 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Copyright (C) 2011 Research In Motion Limited. All rights reserved. 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Redistribution and use in source and binary forms, with or without 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# modification, are permitted provided that the following conditions 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# are met: 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 1. Redistributions of source code must retain the above copyright 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# notice, this list of conditions and the following disclaimer. 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 2. Redistributions in binary form must reproduce the above copyright 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# notice, this list of conditions and the following disclaimer in the 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# documentation and/or other materials provided with the distribution. 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# its contributors may be used to endorse or promote products derived 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# from this software without specific prior written permission. 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Module to share code to start and stop the Apache daemon. 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use strict; 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use warnings; 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use File::Copy; 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use File::Path; 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use File::Spec; 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use File::Spec::Functions; 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use Fcntl ':flock'; 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use IPC::Open2; 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use webkitdirs; 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)BEGIN { 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) use Exporter (); 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS); 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $VERSION = 1.00; 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) @ISA = qw(Exporter); 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) @EXPORT = qw(&getHTTPDPath 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) &hasHTTPD 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) &getHTTPDConfigPathForTestDirectory 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) &getDefaultConfigForTestDirectory 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) &openHTTPD 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) &closeHTTPD 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) &setShouldWaitForUserInterrupt 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) &waitForHTTPDLock 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) &getWaitTime); 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) %EXPORT_TAGS = ( ); 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) @EXPORT_OK = (); 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $tmpDir = "/tmp"; 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $httpdLockPrefix = "WebKitHttpd.lock."; 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $myLockFile; 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $exclusiveLockFile = File::Spec->catfile($tmpDir, "WebKit.lock"); 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $httpdPidDir = File::Spec->catfile($tmpDir, "WebKit"); 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $httpdPidFile = File::Spec->catfile($httpdPidDir, "httpd.pid"); 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $httpdPid; 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $waitForUserInterrupt = 0; 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $waitBeginTime; 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $waitEndTime; 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)$SIG{'INT'} = 'handleInterrupt'; 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)$SIG{'TERM'} = 'handleInterrupt'; 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub getHTTPDPath 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $httpdPath; 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isDebianBased()) { 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $httpdPath = "/usr/sbin/apache2"; 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $httpdPath = "/usr/sbin/httpd"; 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return $httpdPath; 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub hasHTTPD 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my @command = (getHTTPDPath(), "-v"); 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return system(@command) == 0; 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 93926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)sub getApacheVersion 94926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){ 95926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) my $httpdPath = getHTTPDPath(); 96926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) my $version = `$httpdPath -v`; 97926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) $version =~ s/.*Server version: Apache\/(\d+\.\d+).*/$1/s; 98926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return $version; 99926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 100926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub getDefaultConfigForTestDirectory 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my ($testDirectory) = @_; 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) die "No test directory has been specified." unless ($testDirectory); 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $httpdConfig = getHTTPDConfigPathForTestDirectory($testDirectory); 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $documentRoot = "$testDirectory/http/tests"; 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $jsTestResourcesDirectory = $testDirectory . "/fast/js/resources"; 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $mediaResourcesDirectory = $testDirectory . "/media"; 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $typesConfig = "$testDirectory/http/conf/mime.types"; 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $httpdLockFile = File::Spec->catfile($httpdPidDir, "httpd.lock"); 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $httpdScoreBoardFile = File::Spec->catfile($httpdPidDir, "httpd.scoreboard"); 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my @httpdArgs = ( 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "-f", "$httpdConfig", 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "-C", "DocumentRoot \"$documentRoot\"", 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # Setup a link to where the js test templates are stored, use -c so that mod_alias will already be loaded. 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "-c", "Alias /js-test-resources \"$jsTestResourcesDirectory\"", 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "-c", "Alias /media-resources \"$mediaResourcesDirectory\"", 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "-c", "TypesConfig \"$typesConfig\"", 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # Apache wouldn't run CGIs with permissions==700 otherwise 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "-c", "User \"#$<\"", 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "-c", "PidFile \"$httpdPidFile\"", 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "-c", "ScoreBoardFile \"$httpdScoreBoardFile\"", 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ); 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (getApacheVersion() eq "2.2") { 128926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) push(@httpdArgs, "-c", "LockFile \"$httpdLockFile\""); 129926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 130926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # FIXME: Enable this on Windows once <rdar://problem/5345985> is fixed 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # The version of Apache we use with Cygwin does not support SSL 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $sslCertificate = "$testDirectory/http/conf/webkit-httpd.pem"; 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) push(@httpdArgs, "-c", "SSLCertificateFile \"$sslCertificate\"") unless isCygwin(); 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return @httpdArgs; 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub getHTTPDConfigPathForTestDirectory 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my ($testDirectory) = @_; 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) die "No test directory has been specified." unless ($testDirectory); 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $httpdConfig; 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $httpdPath = getHTTPDPath(); 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $httpdConfDirectory = "$testDirectory/http/conf/"; 148926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) my $apacheVersion = getApacheVersion(); 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isCygwin()) { 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $libPHP4DllPath = "/usr/lib/apache/libphp4.dll"; 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # FIXME: run-webkit-tests should not modify the user's system, especially not in this method! 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unless (-x $libPHP4DllPath) { 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) copy("$httpdConfDirectory/libphp4.dll", $libPHP4DllPath); 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) chmod(0755, $libPHP4DllPath); 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $httpdConfig = "cygwin-httpd.conf"; # This is an apache 1.3 config. 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } elsif (isDebianBased()) { 15919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) $httpdConfig = "debian-httpd-$apacheVersion.conf"; 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } elsif (isFedoraBased()) { 161926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) $httpdConfig = "fedora-httpd-$apacheVersion.conf"; 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # All other ports use apache2, so just use our default apache2 config. 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $httpdConfig = "apache2-httpd.conf"; 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return "$httpdConfDirectory/$httpdConfig"; 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub openHTTPD(@) 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my (@args) = @_; 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) die "No HTTPD configuration has been specified" unless (@args); 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) mkdir($httpdPidDir, 0755); 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) die "No write permissions to $httpdPidDir" unless (-w $httpdPidDir); 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (-f $httpdPidFile) { 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) open (PIDFILE, $httpdPidFile); 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $oldPid = <PIDFILE>; 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) chomp $oldPid; 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) close PIDFILE; 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (0 != kill 0, $oldPid) { 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) print "\nhttpd is already running: pid $oldPid, killing...\n"; 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!killHTTPD($oldPid)) { 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cleanUp(); 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) die "Timed out waiting for httpd to quit"; 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unlink $httpdPidFile; 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $httpdPath = getHTTPDPath(); 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) open2(">&1", \*HTTPDIN, $httpdPath, @args); 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $retryCount = 20; 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (!-f $httpdPidFile && $retryCount) { 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sleep 1; 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) --$retryCount; 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!$retryCount) { 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cleanUp(); 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) die "Timed out waiting for httpd to start"; 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $httpdPid = <PIDFILE> if open(PIDFILE, $httpdPidFile); 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) chomp $httpdPid if $httpdPid; 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) close PIDFILE; 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) waitpid($httpdPid, 0) if ($waitForUserInterrupt && $httpdPid); 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 1; 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub closeHTTPD 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) close HTTPDIN; 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $succeeded = killHTTPD($httpdPid); 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cleanUp(); 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unless ($succeeded) { 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) print STDERR "Timed out waiting for httpd to terminate!\n" unless $succeeded; 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 1; 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub killHTTPD 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my ($pid) = @_; 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 1 unless $pid; 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) kill 15, $pid; 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $retryCount = 20; 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (kill(0, $pid) && $retryCount) { 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sleep 1; 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) --$retryCount; 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return $retryCount != 0; 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub setShouldWaitForUserInterrupt 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $waitForUserInterrupt = 1; 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub handleInterrupt 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # On Cygwin, when we receive a signal Apache is still running, so we need 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # to kill it. On other platforms (at least Mac OS X), Apache will have 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # already been killed, and trying to kill it again will cause us to hang. 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # All we need to do in this case is clean up our own files. 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isCygwin()) { 2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) closeHTTPD(); 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cleanUp(); 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) print "\n"; 2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) exit(1); 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub cleanUp 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rmdir $httpdPidDir; 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unlink $exclusiveLockFile; 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unlink $myLockFile if $myLockFile; 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub extractLockNumber 2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my ($lockFile) = @_; 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return -1 unless $lockFile; 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return substr($lockFile, length($httpdLockPrefix)); 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub getLockFiles 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) opendir(TMPDIR, $tmpDir) or die "Could not open " . $tmpDir . "."; 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my @lockFiles = grep {m/^$httpdLockPrefix\d+$/} readdir(TMPDIR); 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) @lockFiles = sort { extractLockNumber($a) <=> extractLockNumber($b) } @lockFiles; 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) closedir(TMPDIR); 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return @lockFiles; 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub getNextAvailableLockNumber 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my @lockFiles = getLockFiles(); 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0 unless @lockFiles; 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return extractLockNumber($lockFiles[-1]) + 1; 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub getLockNumberForCurrentRunning 2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my @lockFiles = getLockFiles(); 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0 unless @lockFiles; 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return extractLockNumber($lockFiles[0]); 2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub waitForHTTPDLock 3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $waitBeginTime = time; 3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) scheduleHttpTesting(); 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # If we are the only one waiting for Apache just run the tests without any further checking 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (scalar getLockFiles() > 1) { 3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $currentLockFile = File::Spec->catfile($tmpDir, "$httpdLockPrefix" . getLockNumberForCurrentRunning()); 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $currentLockPid = <SCHEDULER_LOCK> if (-f $currentLockFile && open(SCHEDULER_LOCK, "<$currentLockFile")); 3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # Wait until we are allowed to run the http tests 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while ($currentLockPid && $currentLockPid != $$) { 3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $currentLockFile = File::Spec->catfile($tmpDir, "$httpdLockPrefix" . getLockNumberForCurrentRunning()); 3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ($currentLockFile eq $myLockFile) { 3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $currentLockPid = <SCHEDULER_LOCK> if open(SCHEDULER_LOCK, "<$currentLockFile"); 3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ($currentLockPid != $$) { 3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) print STDERR "\nPID mismatch.\n"; 3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) last; 3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sleep 1; 3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $waitEndTime = time; 3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub scheduleHttpTesting 3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # We need an exclusive lock file to avoid deadlocks and starvation and ensure that the scheduler lock numbers are sequential. 3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # The scheduler locks are used to schedule the running test sessions in first come first served order. 3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (!(open(SEQUENTIAL_GUARD_LOCK, ">$exclusiveLockFile") && flock(SEQUENTIAL_GUARD_LOCK, LOCK_EX|LOCK_NB))) {} 3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $myLockFile = File::Spec->catfile($tmpDir, "$httpdLockPrefix" . getNextAvailableLockNumber()); 3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) open(SCHEDULER_LOCK, ">$myLockFile"); 3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) print SCHEDULER_LOCK "$$"; 3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) print SEQUENTIAL_GUARD_LOCK "$$"; 3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) close(SCHEDULER_LOCK); 3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) close(SEQUENTIAL_GUARD_LOCK); 3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unlink $exclusiveLockFile; 3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub getWaitTime 3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) my $waitTime = 0; 3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ($waitBeginTime && $waitEndTime) { 3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) $waitTime = $waitEndTime - $waitBeginTime; 3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return $waitTime; 3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 348