From 0b5b3ed7f9b770dbf33735aa36bb1b0bdf2c9b1c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 25 Sep 2019 12:51:31 +0200 Subject: [PATCH] [HttpKernel] wrap compilation of the container in an opportunistic lock --- src/Symfony/Component/HttpKernel/Kernel.php | 91 +++++++++++++++------ 1 file changed, 64 insertions(+), 27 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 0f4be74092a7..2f4198addb0e 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -501,25 +501,72 @@ protected function initializeContainer() $class = $this->getContainerClass(); $cacheDir = $this->warmupDir ?: $this->getCacheDir(); $cache = new ConfigCache($cacheDir.'/'.$class.'.php', $this->debug); - $oldContainer = null; - if ($fresh = $cache->isFresh()) { - // Silence E_WARNING to ignore "include" failures - don't use "@" to prevent silencing fatal errors - $errorLevel = error_reporting(\E_ALL ^ \E_WARNING); - $fresh = $oldContainer = false; - try { - if (file_exists($cache->getPath()) && \is_object($this->container = include $cache->getPath())) { - $this->container->set('kernel', $this); - $oldContainer = $this->container; - $fresh = true; - } - } catch (\Throwable $e) { - } finally { + $cachePath = $cache->getPath(); + + // Silence E_WARNING to ignore "include" failures - don't use "@" to prevent silencing fatal errors + $errorLevel = error_reporting(\E_ALL ^ \E_WARNING); + + try { + if (file_exists($cachePath) && \is_object($this->container = include $cachePath) && (!$this->debug || $cache->isFresh())) { + $this->container->set('kernel', $this); error_reporting($errorLevel); + + return; } + } catch (\Throwable $e) { } - if ($fresh) { - return; + $oldContainer = \is_object($this->container) ? new \ReflectionClass($this->container) : $this->container = null; + + try { + is_dir($cacheDir) ?: mkdir($cacheDir, 0777, true); + + if ($lock = fopen($cachePath, 'w')) { + chmod($cachePath, 0666 & ~umask()); + flock($lock, LOCK_EX | LOCK_NB, $wouldBlock); + + if (!flock($lock, $wouldBlock ? LOCK_SH : LOCK_EX)) { + fclose($lock); + } else { + $cache = new class($cachePath, $this->debug) extends ConfigCache { + public $lock; + + public function write($content, array $metadata = null) + { + rewind($this->lock); + ftruncate($this->lock, 0); + fwrite($this->lock, $content); + + if (null !== $metadata) { + file_put_contents($this->getPath().'.meta', serialize($metadata)); + @chmod($this->getPath().'.meta', 0666 & ~umask()); + } + + if (\function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN)) { + opcache_invalidate($this->getPath(), true); + } + } + + public function __destruct() + { + flock($this->lock, LOCK_UN); + fclose($this->lock); + } + }; + $cache->lock = $lock; + + if (!\is_object($this->container = include $cachePath)) { + $this->container = null; + } elseif (!$oldContainer || \get_class($this->container) !== $oldContainer->name) { + $this->container->set('kernel', $this); + + return; + } + } + } + } catch (\Throwable $e) { + } finally { + error_reporting($errorLevel); } if ($collectDeprecations = $this->debug && !\defined('PHPUNIT_COMPOSER_INSTALL')) { @@ -577,19 +624,9 @@ protected function initializeContainer() } } - if (null === $oldContainer && file_exists($cache->getPath())) { - $errorLevel = error_reporting(\E_ALL ^ \E_WARNING); - try { - $oldContainer = include $cache->getPath(); - } catch (\Throwable $e) { - } finally { - error_reporting($errorLevel); - } - } - $oldContainer = \is_object($oldContainer) ? new \ReflectionClass($oldContainer) : false; - $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); - $this->container = require $cache->getPath(); + unset($cache); + $this->container = require $cachePath; $this->container->set('kernel', $this); if ($oldContainer && \get_class($this->container) !== $oldContainer->name) { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy