From 85371a174e15e5f40f0a178895a406204547c241 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 10 Dec 2019 15:07:26 +0100 Subject: [PATCH] [Routing] fix memoryleak when loading compiled routes --- src/Symfony/Component/Routing/Router.php | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Routing/Router.php b/src/Symfony/Component/Routing/Router.php index c4fb3e2151..003bdc3e29 100644 --- a/src/Symfony/Component/Routing/Router.php +++ b/src/Symfony/Component/Routing/Router.php @@ -97,6 +97,8 @@ class Router implements RouterInterface, RequestMatcherInterface */ private $expressionLanguageProviders = []; + private static $cache = []; + /** * @param LoaderInterface $loader A LoaderInterface instance * @param mixed $resource The main resource to load @@ -325,7 +327,7 @@ class Router implements RouterInterface, RequestMatcherInterface ); if ($compiled) { - return $this->matcher = new $this->options['matcher_class'](require $cache->getPath(), $this->context); + return $this->matcher = new $this->options['matcher_class'](self::getCompiledRoutes($cache->getPath()), $this->context); } if (!class_exists($this->options['matcher_cache_class'], false)) { @@ -369,7 +371,7 @@ class Router implements RouterInterface, RequestMatcherInterface ); if ($compiled) { - $this->generator = new $this->options['generator_class'](require $cache->getPath(), $this->context, $this->logger, $this->defaultLocale); + $this->generator = new $this->options['generator_class'](self::getCompiledRoutes($cache->getPath()), $this->context, $this->logger, $this->defaultLocale); } else { if (!class_exists($this->options['generator_cache_class'], false)) { require_once $cache->getPath(); @@ -442,4 +444,21 @@ class Router implements RouterInterface, RequestMatcherInterface @trigger_error(sprintf('Option "%s" given to router %s is deprecated since Symfony 4.3.', $key, static::class), E_USER_DEPRECATED); } } + + private static function getCompiledRoutes(string $path): array + { + if ([] === self::$cache && \function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(ini_get('opcache.enable_cli'), FILTER_VALIDATE_BOOLEAN))) { + self::$cache = null; + } + + if (null === self::$cache) { + return require $path; + } + + if (isset(self::$cache[$path])) { + return self::$cache[$path]; + } + + return self::$cache[$path] = require $path; + } }