Skip to content
Snippets Groups Projects
Commit a4f44cbb authored by catch's avatar catch
Browse files

Issue #3032078 by jrglasgow, dagomar, Berdir, nikitagupta, catch,...

Issue #3032078 by jrglasgow, dagomar, Berdir, nikitagupta, catch, anmolgoyal74, technoveltyco, idebr, ndf, jonas139, nod_: Multiple webheads can cause infinite growth of Twig cache

(cherry picked from commit a59f4db3)
parent b7ac282a
No related branches found
No related tags found
22 merge requests!8394[warning] array_flip(): Can only flip STRING and INTEGER values, when saving a non-revisionable custom content entity,!7780issue 3443822: fix for 'No route found for the specified format html. Supported formats: json, xml.',!5013Issue #3071143: Table Render Array Example Is Incorrect,!4848Issue #1566662: Update module should send notifications on Thursdays,!4792Issue #2230689: Remove redundant "Italic" style,!4220Issue #3368223: Link field > Access to internal links is not checked on display.,!3884Issue #3356842,!3870Issue #3087868,!3812Draft: Issue #3339373 by alexpott, andypost, mondrake:...,!3686Issue #3219967 against 9.5.x,!3683Issue #2939397: Clearing AliasManager cache with root path raises warning,!3543Issue #3344259: Allow ajax dialog to have focus configurable,!3356Issue #3209129: Scrolling problems when adding a block via layout builder,!2280Issue #3280415: Metapackage Generator Breaks Under Composer --no-dev,!2205Quote all names in the regions section.,!2050Issue #3272969: Remove UnqiueField constraint.,!1956Issue #3268872: hook_views_invalidate_cache not called when a view is deleted,!1893Issue #3217260: Add a way to make media captions not editable in CKEditor,!1459Issue #3087632: menu_name max length is too long,!878Issue #3221534: throw an exception when IDs passed to loadMultiple() are badly formed,!866Issue #2845319: The highlighting of the 'Home' menu-link does not respect query strings and fragment identifiers,!204Issue #3040556: It is not possible to react to an entity being duplicated
......@@ -9,7 +9,7 @@
/**
* Adds the twig_extension_hash parameter to the container.
*
* Parameter twig_extension_hash is a hash of all extension mtimes for Twig
* Parameter twig_extension_hash is a crc32 hash of all extensions for Twig
* template invalidation.
*/
class TwigExtensionPass implements CompilerPassInterface {
......@@ -23,8 +23,8 @@ public function process(ContainerBuilder $container) {
$class_name = $container->getDefinition($service_id)->getClass();
$reflection = new \ReflectionClass($class_name);
// We use the class names as hash in order to invalidate on new extensions
// and mtime for every time we change an existing file.
$twig_extension_hash .= $class_name . filemtime($reflection->getFileName());
// and crc32 for every time we change an existing file.
$twig_extension_hash .= $class_name . hash_file('crc32', $reflection->getFileName());
}
$container->setParameter('twig_extension_hash', Crypt::hashBase64($twig_extension_hash));
......
......@@ -6,6 +6,7 @@
use Drupal\Component\Utility\Html;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\Site\Settings;
use Drupal\Core\Template\TwigEnvironment;
use Drupal\Core\Template\TwigPhpStorageCache;
use Drupal\KernelTests\KernelTestBase;
use Symfony\Component\DependencyInjection\Definition;
......@@ -229,4 +230,62 @@ public function testTemplateInvalidation() {
$this->assertEquals($template_after, $output);
}
/**
* Test twig file prefix change.
*/
public function testTwigFilePrefixChange() {
/** @var \Drupal\Core\Template\TwigEnvironment $environment */
$environment = \Drupal::service('twig');
$cache_prefixes = [];
$cache_filenames = [];
// Assume this is the service container of webserver A.
$container_a = $this->container;
$template_name = 'core/modules/system/templates/container.html.twig';
// Request 1 handled by webserver A.
$cache_prefixes[] = \Drupal::state()->get(TwigEnvironment::CACHE_PREFIX_METADATA_KEY)['twig_cache_prefix'];
$cache_filenames[] = $environment->getCache()->generateKey($template_name, $environment->getTemplateClass($template_name));
// Assume this is the service container of webserver B.
// Assume that the files on the webserver B have a different mtime than
// webserver A.
touch('core/lib/Drupal/Core/Template/TwigExtension.php');
clearstatcache(TRUE, 'core/lib/Drupal/Core/Template/TwigExtension.php');
$container_b = \Drupal::service('kernel')->rebuildContainer();
// Request 2 handled by webserver B.
\Drupal::setContainer($container_b);
$environment = \Drupal::service('twig');
$cache_prefixes[] = \Drupal::state()->get(TwigEnvironment::CACHE_PREFIX_METADATA_KEY)['twig_cache_prefix'];
$cache_filenames[] = $environment->getCache()->generateKey($template_name, $environment->getTemplateClass($template_name));
// Request 3 handled by webserver A.
\Drupal::setContainer($container_a);
$container = \Drupal::getContainer();
// Emulate twig service reconstruct on new request.
$container->set('twig', NULL);
$environment = $container->get('twig');
$cache_prefixes[] = \Drupal::state()->get(TwigEnvironment::CACHE_PREFIX_METADATA_KEY)['twig_cache_prefix'];
$cache_filenames[] = $environment->getCache()->generateKey($template_name, $environment->getTemplateClass($template_name));
// Request 4 handled by webserver B.
\Drupal::setContainer($container_b);
$container = \Drupal::getContainer();
// Emulate twig service reconstruct on new request.
$container->set('twig', NULL);
$environment = $container->get('twig');
$cache_prefixes[] = \Drupal::state()->get(TwigEnvironment::CACHE_PREFIX_METADATA_KEY)['twig_cache_prefix'];
$cache_filenames[] = $environment->getCache()->generateKey($template_name, $environment->getTemplateClass($template_name));
// The cache prefix should not have been changed, as this is stored in
// state and thus shared between all (web)servers.
$this->assertEquals(count(array_unique($cache_prefixes)), 1);
// This also applies to twig's file cache resulting in an unlimited growth
// of the cache storage directory.
$this->assertEquals(count(array_unique($cache_filenames)), 1);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment