From e42412a8e7ceb29eae1a0c3728a20b6942d6501a Mon Sep 17 00:00:00 2001 From: Benjamin Franzke <bfr@qbus.de> Date: Sat, 18 Apr 2020 14:40:55 +0200 Subject: [PATCH] [BUGFIX] Avoid using the symfony container to clear its own caches With the introduction of a custom DI cache in #90418, the container was used to lookup its own cache and the cache identifier. This results in bugs if the container cache is stale: Loading from the cache and flushing the cache will work, but code that runs after the cache has been flushed (ext_localconf loading) will still use the a stale container (configuration), as the instance has been created too early (to be able to clear itself). Therefore we do now avoid instantiating the symfony container before the container cache has been cleared. A positive side effect of this change is that the container cache is warmed up after the flush. Releases: master Resolves: #91114 Related: #90418 Change-Id: I5f10474ab3fab2d17cfdca6cd514b0a95f10bbbc Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/64234 Tested-by: Jonas Eberle <flightvision@googlemail.com> Tested-by: TYPO3com <noreply@typo3.com> Tested-by: Helmut Hummel <typo3@helhum.io> Tested-by: Benjamin Franzke <bfr@qbus.de> Reviewed-by: Susanne Moog <look@susi.dev> Reviewed-by: Helmut Hummel <typo3@helhum.io> Reviewed-by: Benjamin Franzke <bfr@qbus.de> --- .../Cache/ContainerBackend.php | 5 ++++ .../Classes/Service/ClearCacheService.php | 25 ++++++++++++++----- .../install/Classes/ServiceProvider.php | 3 ++- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/typo3/sysext/core/Classes/DependencyInjection/Cache/ContainerBackend.php b/typo3/sysext/core/Classes/DependencyInjection/Cache/ContainerBackend.php index b0feb97d2af1..0f5b1ea762e0 100644 --- a/typo3/sysext/core/Classes/DependencyInjection/Cache/ContainerBackend.php +++ b/typo3/sysext/core/Classes/DependencyInjection/Cache/ContainerBackend.php @@ -35,4 +35,9 @@ class ContainerBackend extends SimpleFileBackend parent::flush(); parent::set($entryIdentifier, $data, $tags, $lifetime); } + + public function forceFlush(): void + { + parent::flush(); + } } diff --git a/typo3/sysext/install/Classes/Service/ClearCacheService.php b/typo3/sysext/install/Classes/Service/ClearCacheService.php index 9eba056caadc..a306b63e30a5 100644 --- a/typo3/sysext/install/Classes/Service/ClearCacheService.php +++ b/typo3/sysext/install/Classes/Service/ClearCacheService.php @@ -16,7 +16,9 @@ namespace TYPO3\CMS\Install\Service; use TYPO3\CMS\Core\Cache\CacheManager; +use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\DependencyInjection\Cache\ContainerBackend; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -34,9 +36,17 @@ class ClearCacheService */ private $lateBootService; - public function __construct(LateBootService $lateBootService) - { + /** + * @var FrontendInterface + */ + private $dependencyInjectionCache; + + public function __construct( + LateBootService $lateBootService, + FrontendInterface $dependencyInjectionCache + ) { $this->lateBootService = $lateBootService; + $this->dependencyInjectionCache = $dependencyInjectionCache; } /** @@ -44,7 +54,7 @@ class ClearCacheService * Goal is to reliably get rid of cache entries, even if some broken * extension is loaded that would kill the backend 'clear cache' action. * - * Therefor this method "knows" implementation details of the cache + * Therefore this method "knows" implementation details of the cache * framework and uses them to clear all file based cache (typo3temp/Cache) * and database caches (tables prefixed with cf_) manually. * @@ -66,9 +76,12 @@ class ClearCacheService $this->flushCaches($baseCaches); // Remove DI container cache (this might be removed in preference of functionality to rebuild this cache) - // We need to remove using the remove method because the DI cache backend disables the flush method - $container = $this->lateBootService->getContainer(); - $container->get('cache.di')->remove(get_class($container)); + if ($this->dependencyInjectionCache->getBackend() instanceof ContainerBackend) { + /** @var ContainerBackend $diCacheBackend */ + $diCacheBackend = $this->dependencyInjectionCache->getBackend(); + // We need to remove using the forceFlush method because the DI cache backend disables the flush method + $diCacheBackend->forceFlush(); + } // From this point on, the code may fatal, if some broken extension is loaded. $this->lateBootService->loadExtLocalconfDatabaseAndExtTables(); diff --git a/typo3/sysext/install/Classes/ServiceProvider.php b/typo3/sysext/install/Classes/ServiceProvider.php index 5226c5ffbf36..714c5671e736 100644 --- a/typo3/sysext/install/Classes/ServiceProvider.php +++ b/typo3/sysext/install/Classes/ServiceProvider.php @@ -107,7 +107,8 @@ class ServiceProvider extends AbstractServiceProvider public static function getClearCacheService(ContainerInterface $container): Service\ClearCacheService { return new Service\ClearCacheService( - $container->get(Service\LateBootService::class) + $container->get(Service\LateBootService::class), + $container->get('cache.di') ); } -- GitLab