]> granicus.if.org Git - php/commitdiff
Make gen_stub parallelism safe
authorNikita Popov <nikita.ppv@gmail.com>
Tue, 21 Apr 2020 08:17:19 +0000 (10:17 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 21 Apr 2020 08:20:51 +0000 (10:20 +0200)
If PHP-Parser is not yet installed, make sure we don't try to
install it N times in parallel.

build/gen_stub.php

index d784907048bb3410e0d4d6f11e5622e04d679b2b..5b2fee031784fefbe6caa69d0ecf1a64aae3ee98 100755 (executable)
@@ -997,16 +997,26 @@ function generateFunctionEntries(?string $className, array $funcInfos): string {
     return $code;
 }
 
-function initPhpParser() {
-    $version = "4.3.0";
-    $phpParserDir = __DIR__ . "/PHP-Parser-$version";
-    if (!is_dir($phpParserDir)) {
+function installPhpParser(string $version, string $phpParserDir) {
+    $lockFile = __DIR__ . "/PHP-Parser-install-lock";
+    $lockFd = fopen($lockFile, 'w+');
+    if (!flock($lockFd, LOCK_EX)) {
+        throw new Exception("Failed to acquire installation lock");
+    }
+
+    try {
+        // Check whether a parallel process has already installed PHP-Parser.
+        if (is_dir($phpParserDir)) {
+            return;
+        }
+
         $cwd = getcwd();
         chdir(__DIR__);
 
-        passthru("wget https://github.com/nikic/PHP-Parser/archive/v$version.tar.gz", $exit);
+        $tarName = "v$version.tar.gz";
+        passthru("wget https://github.com/nikic/PHP-Parser/archive/$tarName", $exit);
         if ($exit !== 0) {
-            passthru("curl -LO https://github.com/nikic/PHP-Parser/archive/v$version.tar.gz", $exit);
+            passthru("curl -LO https://github.com/nikic/PHP-Parser/archive/$tarName", $exit);
         }
         if ($exit !== 0) {
             throw new Exception("Failed to download PHP-Parser tarball");
@@ -1014,12 +1024,23 @@ function initPhpParser() {
         if (!mkdir($phpParserDir)) {
             throw new Exception("Failed to create directory $phpParserDir");
         }
-        passthru("tar xvzf v$version.tar.gz -C PHP-Parser-$version --strip-components 1", $exit);
+        passthru("tar xvzf $tarName -C PHP-Parser-$version --strip-components 1", $exit);
         if ($exit !== 0) {
             throw new Exception("Failed to extract PHP-Parser tarball");
         }
-        unlink(__DIR__ . "/v$version.tar.gz");
+        unlink(__DIR__ . "/$tarName");
         chdir($cwd);
+    } finally {
+        flock($lockFd, LOCK_UN);
+        @unlink($lockFile);
+    }
+}
+
+function initPhpParser() {
+    $version = "4.3.0";
+    $phpParserDir = __DIR__ . "/PHP-Parser-$version";
+    if (!is_dir($phpParserDir)) {
+        installPhpParser($version, $phpParserDir);
     }
 
     spl_autoload_register(function(string $class) use($phpParserDir) {