Problem/Motivation

As #2547827: PhpStorage: past, present and future documented, currently Drupal 8 can't be used on multiple webheads without writing files to a shared filesystem. This is undesirable because a shared filesystem at best is slow at worst doesn't exist at all if stream wrappers are used to store upload files on some mass file hoster.

Proposed resolution

  1. Use the extension classes + mtime to invalidate template files, once any of those change. This is done using a hash of those values

The following solutions have been proposed:

  1. Add the value of a distributed atomic counter to the file name of the local file. When invalidating the storage, increase the counter. Drawback: it requires an atomic counter query for every read. By default this comes from the database which is a performance hit.
  2. Use the cache as phpstorage in such a way that included files can still be opcode cached. Drawback: since the name of the wrappers that can be opcode cached is hardwired in PHP 5.5-7.0 this is necessarily a hack. We do not want to add hacks to core so this is moved to contrib.
  3. Do not solve the problem in general, just make core work. Change the container to not use phpstorage at all. For Twig add a hash of the things the compiled code can vary on (core version, deployment identifier, twig extensions) to the file name. Drawback: every web frontend needs a local writable disk and also each will need to compile every Twig file for itself which is a small waste of effort (not too big). These are inherent to this solution and are not fixable. The solution in the previous point does not use a disk at all and it's possible to change it via some kind of locking to have only one process building.

Remaining tasks

User interface changes

API changes

Data model changes

Beta phase evaluation

Reference: https://www.drupal.org/core/beta-changes
Issue category Bug, because templates are maybe not invalidated, even they should
Issue priority Critical, because serving wrong output could lead to all kind of problems.
Disruption Existing sites would need to update all their dumped twig files (this happens implicit), so there is no actual problem.

Comments

Anonymous’s picture

yes please.

msonnabaum’s picture

Title: Do not rely on loading php from shared files » Do not rely on loading php from shared file system
catch’s picture

Whenever I'd asked about this before, I was assured that it was a non-issue since it is safe to move the Twig cache out of the shared files directory to a local directory. That makes sense if the cache is just a compiled representation of what was deployed.

However, I learned recently (from Fabianx) that this is not true. If I understand correctly, any module that provides a twig.extension service could change the output of a compiled Twig template. This means that the Twig cache potentially needs to be rebuilt on a module enable/disable, so we are back to PhpStorage in the shared files directory being a requirement for D8.

Yes I'd assumed it was possible to pre-compile Twig templates in a build step (and/or potentially d.o packaging of themes and modules). But given the same filename would be used for different resulting templates, that's not possible at the moment. This came up on #2497281: Add an intermediate cache for Twig templates to avoid regenerating identical templates too.

fabianx’s picture

#3: We could overwrite the used hash based on loaded extensions, which does not change per request.

Then the only thing is when code changes, but never on run-time.

And if someone has a crazy workflow with an extension changing on run-time then likely they already now need to overwrite the TwigExtension service, so that is pre-existing.

dawehner’s picture

So currently the twig filename is determined by using PHPStorage which takes into account:

* The filename
* The secret, which is the hash salt by default.
* the directory mtime

Can't we expand the secret with something like serialize($active_modules)(which is information available in the container), so this will automatically invalidate all usages of the templates?

catch’s picture

We discussed this on the critical triage call with myself, Alex Pott, Alex Bronstein, xjm and webchick, and agreed with removing the requirement (I'm not sure if we 100% decided it was a release blocker, so not adding the triaged tag just yet).

In general I think the main change we should do in this issue is #5. Ensure that a changed module list results in different Twig template files on the filesystem (and also add the settings.php $deployment_identifier so a new filename can be forced if necessary). Then two things become possible:

1. Compiling templates in a build step - since you can have the old and new compiled templates next to each other, and the production site should switch from one to the other when the hash updates on production.

2. Putting the templates on a local filesystem, since they never get invalidated, just superceded by new file locations.

That combined with #2497243: Replace Symfony container with a Drupal one, stored in cache means that an individual Drupal install is not required to write PHP to a shared filesystem at all.

However, I don't think we can remove MTimeProtectedFileStorage - since you'll still need to write PHP for Twig on production if you're not pre-compiling - we don't want to make pre-compile of templates a requirement either (especially since that can't happen as part of d.o packaging). So we should also fix #2527478: Resolve infinite stampede in mtime protected PHP storage so that things work for sites that aren't relying on it. We can document strongly that it's there for Twig and discourage anyone else from using it though.

webchick’s picture

Just for clarification:

we don't want to make pre-compile of templates a requirement either (especially since that can't happen as part of d.o packaging).

Can't because it's dependent on site-specific things that Drupal.org can't know about? Or can't because no one has done the work?

catch’s picture

Can't because it's dependent on site-specific things that Drupal.org can't know about?

This.

The eventual compiled template depends on twig extensions, modules can define twig extensions.

Unless we remove that ability (i.e. support a fixed list of core extensions and nothing else), then compiled templates depend on the exact site configuration and state of the code base at the time.

That's also the reason why a shared fileystem is currently a requirement - if the compiled template from a specific twig tpl was always identical we'd not need to do extra work here with the filename hash.

dawehner’s picture

Status: Active » Needs review
StatusFileSize
new3.32 KB

So do we need more than this here?

gábor hojtsy’s picture

StatusFileSize
new3.26 KB
new1.26 KB

Minor cleanups to make it easier to review.

fabianx’s picture

+++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php
@@ -89,6 +100,31 @@ public function updateCompiledTemplate($cache_filename, $name) {
+    $class = substr($this->getTemplateClass($name), strlen($this->templateClassPrefix));
+
+    $hash = hash('crc32b', serialize($this->modules) . \Drupal::VERSION . Settings::get('deployment_identifier', \Drupal::VERSION));
+
+    return $this->getCache() . '/' . substr($class, 0, 2) . '/' . substr($class, 2, 2) . '/' . substr($class, 4) . $hash . '.php';

I don't think we even need the list of enabled modules.

The list of extensions that the Twig_Extension knows should be more than enough. Possibly even the hash of the concatenated spl_object_hash thereof as we have the extensions loaded already anyway.

And I think spl_object_hash is very fast as its just reading an internal value.

Also while we override this thing anyway, I would like to add the basename to the filename, so its easier to find templates, which has been bugging me forever - though that can also be a non-critical follow-up.

Third:

With phpstorage, we don't need the complicated subdir structure, as it is just replacing '/' with '#' anyway.

e.g.


$extensions_hash = '';

foreach ($this->extensions as $extension) {
  $extensions_hash .= spl_object_hash($extension);
}

$hash = hash('crc32b', $class . $extensions_hash . \Drupal::VERSION . Settings::get('deployment_identifier', \Drupal::VERSION));

return basename($name) . '_' . $hash;

would be my proposal.

znerol’s picture

What is the cost in terms of performance if the templates are not dumped at all by default? After so much work has been invested into making every bit of markup cacheable, compiling the templates to PHP files is maybe not strictly required anymore?

fabianx’s picture

StatusFileSize
new2.41 KB

Attached patch should do the trick and also has a nicer filename structure:

e.g.

e00fe710_block.html.twig_66732de10dd61b46ae1fc723ec5e2341206490f047f98d5fb078222a07c80818/
e00fe710_container.html.twig_41cb5940f88378091a5b6e28e8e3630e832bd7d9c05bae0a2687c3afd1ffdf4f/
e00fe710_form-element-label.html.twig_7f6afbcfd5a9fb0c2d3e2e2a3923e26de20f4c4bfff2468aff0acab65969934c/
e00fe710_form-element.html.twig_8ac4a7b74a1b981cb4d431e8df30e30fac3ed27923679078270094d286b19150/
e00fe710_form.html.twig_c9a076ca9afe1d85f27751423eab93e5d0badbc79d102daba1ca3db75d0b2f66/
e00fe710_html.html.twig_f93ec81447a4b9ce0904e32044949245370d21356172dc4ce00c1897ce8e5b72/
e00fe710_input.html.twig_8b90f302a8fdf30fa80c170c8f7bc638d4d3aea4bd964240e3c94cc86a574baf/
e00fe710_item-list.html.twig_e053d564e827154cea07b98eac381482072df8eb0e5dc7a851dea0255e60be0b/
e00fe710_page.html.twig_9b8dca4f11c32a126fd0e492cfa79b787418679c9af827358bb0611bfae82445/
e00fe710_region.html.twig_0b06ed9684d14eb34c3ffe9e25f020c04875677030be0c1b1e856b82544e8852/
e00fe710_status-messages.html.twig_318d28f7f5bd87ff2a9f95545fb98389c2395b00f6df48371426f7a65fc0a7c0/
e00fe710_status-messages.html.twig_34fbdf2ad306d8601db1a559fbe8a1a379ca9c4d485862ef9743288786914a79/

As original author of the code I took the liberty to improve some missing docs.

fabianx’s picture

X-POST with #13:

Not 100% sure, gonna measure real quick.

fabianx’s picture

StatusFileSize
new897 bytes
new2.46 KB

#14 did not take $this->cache into account as I was trying something else.

Fixed here.

The last submitted patch, 14: do_not_rely_on_loading-2544932-14.patch, failed testing.

fabianx’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

#13: Unfortunately that won't be possible:

Number of Function Calls 47,999 235,045 187,046 389.7%
Incl. Wall Time (microsec) 85,800 271,556 185,756 216.5%

So around 4x slower ...

--

We can write a test for this like in core/modules/system/src/Tests/Theme/TwigSettingsTest.php.

chx’s picture

I think this is a duplicate of #2301163: Create a phpstorage backend that works with a local disk but coordinates across multiple webheads but I also would like to make all the issues referred from #2547827: PhpStorage: past, present and future postponed and make the decisions there first.

dawehner’s picture

+++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php
@@ -89,6 +109,36 @@ public function updateCompiledTemplate($cache_filename, $name) {
+
+    // Just check the list of loaded extensions once.
+    if (!isset($this->templateCacheFilenamePrefix)) {
+      $extensions = '';
+      foreach ($this->extensions as $extension) {
+        $r = new \ReflectionObject($extension);
+        $extensions .= $r->getFilename();
+      }

This sounds like something you can easily calculate on container build time, can't you?

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new6.37 KB
new5.04 KB

Let's move it there.

Status: Needs review » Needs work

The last submitted patch, 21: 2544932-21.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new6.37 KB
new800 bytes

Alright, let's be nice today and use valid PHP.

Status: Needs review » Needs work

The last submitted patch, 23: 2544932-23.patch, failed testing.

wim leers’s picture

Status: Needs work » Needs review
StatusFileSize
new6.43 KB
new3.44 KB

Addressed everything below, plus some nitpicks.

  1. +++ b/core/lib/Drupal/Core/CoreServiceProvider.php
    @@ -78,6 +79,8 @@ public function register(ContainerBuilder $container) {
    +    $this->addCompilerPass(new TwigExtensionPass());
    

    s/$this/$container/ -> this will fix the test failures. :)

  2. +++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/TwigExtensionPass.php
    @@ -0,0 +1,30 @@
    + * Adds a hash of all extensions for twig template invalidation.
    

    Comment inconsistent with other parameter-setting compiler passes (such as ListCacheBinsPass and CacheContextsPass).

  3. +++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php
    @@ -89,6 +119,30 @@ public function updateCompiledTemplate($cache_filename, $name) {
    +    return $this->templateCacheFilenamePrefix . '_' . basename($name) . '_' . $class;
    

    Doesn't this mean that we're no longer writing these to .php.
    Confusingly, the implementation in the parent class sets a .php suffix, but that doesn't appear to be important at all.

dawehner’s picture

+++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php
@@ -89,6 +119,30 @@ public function updateCompiledTemplate($cache_filename, $name) {
+    return $this->templateCacheFilenamePrefix . '_' . basename($name) . '_' . $class;

Well right, file extensions don't matter most of the time. I think we though still append .php, just so we have this tiny little bit of protecting to never show the file content to the user, in case someone manages to find the filename itself

wim leers’s picture

Yep, *.php is still appended by the caller of this method. I didn't make that clear, but at this point it's the parent class that is confusing me.

But in any case, I can confirm from brief manual testing that this still works as expected.

dawehner’s picture

Alright working on some simple tests now.

dawehner’s picture

Issue tags: -Needs tests
StatusFileSize
new8.09 KB
new1.66 KB

There we go.

fabianx’s picture

Status: Needs review » Reviewed & tested by the community

Looks good to me :).

alexpott’s picture

Status: Reviewed & tested by the community » Needs review
  1. +++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/TwigExtensionPass.php
    @@ -0,0 +1,32 @@
    +      $twig_extension_hash .= $container->getDefinition($service_id)->getClass();
    

    Don't we need to hash by the mtime of the files that contain the class? As a change to the class could result in changes to the templates right?

  2. +++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php
    @@ -89,6 +119,30 @@ public function updateCompiledTemplate($cache_filename, $name) {
    +      $this->templateCacheFilenamePrefix = hash('crc32b', $this->twigExtensionHash . \Drupal::VERSION . Settings::get('deployment_identifier', \Drupal::VERSION));
    

    Why add \Drupal::version twice?

dawehner’s picture

Why add \Drupal::version twice?

Well, this is just the default value, but you could choose your own custom deployment identifier. Note: \Drupal\Core\DrupalKernel::getClassName uses the same pattern.

dawehner’s picture

StatusFileSize
new8.3 KB
new1.44 KB

There we go.

alexpott’s picture

+++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/TwigExtensionPass.php
@@ -23,7 +24,10 @@ class TwigExtensionPass implements CompilerPassInterface {
+      $twig_extension_hash .= filemtime($reflecton->getFileName());

You're going to hate me - but we need both the mtime and the classname. Sorry I should have been more explicit.

fabianx’s picture

Status: Needs review » Needs work

Yes, lets add the classname or the filename, then back to RTBC, while that is the pattern to test for freshness in theory we would need to check mtime of all NodeVisitors and Token Parsers registered in each extension, so this was only intended for when the list of extensions changes.

Any changes to the extensions itself would likely be a new deployment identifier, but both works equally well.

gábor hojtsy’s picture

Is there an update related requirement here? We are changing the compiler passes, do we need to provide some update for this or is the container rebuilt on update?

Also any change notices that should be made? It seems like an internal change for what the file naming is, so it would be more "informational", so not sure...

catch’s picture

#2507509: Service changes should not result in fatal errors between patch or minor releases was designed to fix this at least for patch-level core releases so it shouldn't need anything specific.

chx’s picture

Issue summary: View changes
chx’s picture

Title: Do not rely on loading php from shared file system » Twig should not rely on loading php from shared file system
chx’s picture

Issue summary: View changes
dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new8.39 KB
new1.28 KB

There we go.

catch’s picture

  1. +++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/TwigExtensionPass.php
    @@ -0,0 +1,37 @@
    +      $twig_extension_hash .= $class_name . filemtime($reflecton->getFileName());
    

    Clever. Had been concerned about this one and there's a fix for it right there in the patch.

  2. +++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php
    @@ -89,6 +119,30 @@ public function updateCompiledTemplate($cache_filename, $name) {
    +    // shared filesystems. The Twig templates for example rely on available Twig
    +    // extensions, so we need to take into account the \Drupal::VERSION
    +    // deployment identifier, much like for the container itself.
    +
    

    \Drupal::VERSION and deployment identifier.

  3. +++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php
    @@ -89,6 +119,30 @@ public function updateCompiledTemplate($cache_filename, $name) {
    +      $this->templateCacheFilenamePrefix = hash('crc32b', $this->twigExtensionHash . \Drupal::VERSION . Settings::get('deployment_identifier', \Drupal::VERSION));
    

    Settings argument could be left off since version is already in the hash?

dawehner’s picture

Issue summary: View changes
StatusFileSize
new8.38 KB
new1.3 KB

\Drupal::VERSION and deployment identifier.

Puh, we had some space left on this row.

Settings argument could be left off since version is already in the hash?

Nice!

catch’s picture

OK so more of an actual review.

- So the filemtime is great for picking up changes to individual classes
- with it, I was wondering if we need the Drupal::VERSION and/or $deployment_identifier bits after all, since the exact classes and age results in a new hash anyway.
- then I thought they'd be useful anyway, since that would allow you to precompile templates to a specific hash location in advance of deployment (to allow read-only filestorage to be used, not just write-once).
- then I realised that depending on how code is deployed, the mtime might be different so you couldn't predict the hash.

So having the mtime in the hash makes 'write once to a local filesystem' much easier, but it also makes 'compile in a build step and deploy templates with code updates' potentially harder. I think it's fine to say that if you compile in a build step, you also need to make sure your deployment process preserves mtime on files. Just bringing it up as a trade-off.

And given all that, since the hash is going to depend on mtime, I'm really not sure we need the version and $deployment identifier in there after all.

Status: Needs review » Needs work

The last submitted patch, 43: 2544932-43.patch, failed testing.

dawehner’s picture

You could argue that the deployment identifier is basically used to clear those stored PHP files, so you could assume that they are cleared if you change the identifier.
At least for now though, the deployment identifier just talks about the container, and not about the twig files.

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new7.9 KB
new1.71 KB

I agree, for now its fine to not take into account the deployment identifier. In contrast to the container we know what the template will vary by.

jibran’s picture

Do we need a change record for new compiler pass? Other then that this is RTBC.

larowlan’s picture

Status: Needs review » Reviewed & tested by the community

agree

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs change record, +Needs issue summary update

There's a bit of issue management we have to do before committing this.

alexpott’s picture

The patch looks great and the new thinking about Drupal version and the deployment identifier makes lots of sense. Nice work. Below are a few of nits...

  1. +++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/TwigExtensionPass.php
    @@ -0,0 +1,37 @@
    +      $reflecton = new \ReflectionClass($class_name);
    ...
    +      $twig_extension_hash .= $class_name . filemtime($reflecton->getFileName());
    

    reflection misspelt.

  2. +++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/TwigExtensionPass.php
    @@ -0,0 +1,37 @@
    +      // and mtime for everytime we change an existing file.
    

    every time is two words.

  3. +++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php
    @@ -11,6 +11,7 @@
    +use Drupal\Core\Site\Settings;
    

    Not used anymore.

dawehner’s picture

Issue summary: View changes
Issue tags: -Needs issue summary update

Changed the IS

gábor hojtsy’s picture

+++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php
@@ -89,6 +119,30 @@ public function updateCompiledTemplate($cache_filename, $name) {
+    // shared filesystems. The Twig templates for example rely on available Twig
+    // extensions, so we need to take into account the \Drupal::VERSION and
+    // deployment identifier, much like for the container itself.

Comment not accurate anymore AFAIS(?)

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new7.67 KB
new1.65 KB

Fixed those points.

dawehner’s picture

StatusFileSize
new7.63 KB
new847 bytes

.

jibran’s picture

Changes look good. Let's create the change record and be done with it.

dawehner’s picture

jibran’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs change record

Ok thanks @dawehner.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/TwigExtensionPass.php
@@ -0,0 +1,37 @@
+    $container->setParameter('twig_extension_hash', $twig_extension_hash);

+++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php
@@ -89,6 +118,30 @@ public function updateCompiledTemplate($cache_filename, $name) {
+      $this->templateCacheFilenamePrefix = hash('crc32b', $this->twigExtensionHash);

Let's done the hashing once in the compiler pass. Was less hashing and also that makes the container parameter twig_extension_hash a hash rather than data to hash and therefore the parameter name and value are a better match. The other thing to consider with crc32b is how worried about collisions are we?

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new7.12 KB
new2.29 KB

Really strong point!

So a) yes, let's not hash on runtime. Once we have done that, we can actually simplify the code a bit.
Regarding cr32b vs. sha ... It doens't matter on runtime at all, so we can choose what we want. This part of the code is not about security, so I always kinda like to avoid using sha.
I like the additioinal semantic information you transport when you use sha vs. not.
Let's get also to a real point, these extensions wont' be changed often, especially given that hopefully not many modules provide twig extensions.

Status: Needs review » Needs work

The last submitted patch, 60: 2544932-60.patch, failed testing.

wim leers’s picture

CRC32 has >4 billion possible values, so collisions are very unlikely.

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new7.12 KB

Reupload the patch, this could be a random fail.

wim leers’s picture

Status: Needs review » Reviewed & tested by the community

Hrm, yes, the 5 failures in #60 look completely unrelated to the changes in this patch, so they're extremely likely to be random failures. Back to RTBC.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 63: 2544932-60.patch, failed testing.

wim leers’s picture

Status: Needs work » Reviewed & tested by the community
alexpott’s picture

Status: Reviewed & tested by the community » Needs work

With my comment about

The other thing to consider with crc32b is how worried about collisions are we?

I didn't mean that we should change the algo I meant we should consider the issue. With crc32b the directory names stay sane with sha256 they get insane. If we need sha256 we should consider the directory structure. Sorry.

wim leers’s picture

It's not clear to me what you mean. Hopefully it's clear to @dawehner.

alexpott’s picture

What i meam is:

SHA256 twig directory names

 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_block--search-form-block.html.twig_6e1889aa8e06902bce8a3851e3a949ab189b29ed9b6ccfc7171cfc4d4510f586
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_block--search-form-block.html.twig_9b03d8118cbf219d6c9ba66cb4cb1acbeb68f73b06764c2ae33217c6c0d73767
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_block--system-menu-block.html.twig_13f98263c76d0637b2b53be380b342c3549a455fb9369c6009a6abbe79796507
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_block--system-menu-block.html.twig_5baaf09323b19f3aba17875da7e36d7a93e16a76db05dee57d2da397ca8b0124
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_block--system-messages-block.html.twig_fc0c6e1c65fc0095077a66301995b7469384bbbdd88483c9b85f77aedc0513dd
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_block.html.twig_f34de612521e743c411473dba9d70da164c7debee450c8348e51cfdaf649c24e
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_breadcrumb.html.twig_144b7771210f97f3b43d202efc1a1e5ae038729561a4a7923237ab3a0727c93d
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_container.html.twig_d69d3f510779dc988797c5879b532988c34085e907a199c6189cca5b2526ed93
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_feed-icon.html.twig_9ad9064fe670e10bb2524538ee81af3ed7059b8f5994ea5129722717f7fc14d5
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_form-element-label.html.twig_680d2a90a356c5a17d10071733b18ae20242fd727a9ae1d73685ea0f37b84e9f
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_form-element.html.twig_4fbc743b76ff2563e7aef60a252d82e2ef985ff8443b51c8273d727f58e4648b
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_form.html.twig_3449c7737d241e3f0b98f84d85240608976058854a1c930110e041d2f003a962
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_html.html.twig_808b2896f82b60ca3494a9cd78e8bdc80370bf9a81bd42ad63a24c4f5a47acf7
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_input.html.twig_cd7c9868821162dab576fa8dc64080f3bf20a4d793ddf02b968ac3c26ae46605
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_links.html.twig_a3de7a974b81eba0507d1f07a6e7c2f6b980c92327997b712f6b67146f7b4679
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_menu--toolbar.html.twig_dfc881e4a6a5ed17547a18c9a96388cbfea347e6e8f345b87776f9dd2d75f630
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_menu.html.twig_851059117b8d64931f1c6b19fb47e0f204b8364c83ae4d8ccaf8c442f9aad41d
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_page.html.twig_e51e318b66e64c6c90c7b29acba93df41c9f8c584d93f6daabfd243cc421a53b
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_pager.html.twig_9734bcc4165bfc9b4cea95aa9fbc8af593e66915544a3e97afe4f3ace4009d5c
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_region.html.twig_d3bd2ee1704933a91622fb76aa029fff0bbcf90c4e95d8d71b3b6a4d247e707f
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_status-messages.html.twig_54c459140007191a6610c1bc150522f3159fd96ef214c74bd21858c744eb4fd2
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_status-messages.html.twig_78f45b7e0140d7990558ec8243420872db0020c0edd81d2996d086fd0925d2c0
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_toolbar.html.twig_51081e0b3fc06737b5c4a6229bf97c5fc4b13507115251c02abcc0b59cb2c011
 |-3527e08b79d47b8219223b7d56144b6ec8d4a1a361c2fc5b12774b682f97d185_views-view.html.twig_ef753936b01bcb86c84cdaa9447d3ae88405e5a5af34e606dc79ed50d4c1c73a

crc32b directory names

 |-55783b3d_block--search-form-block.html.twig_6e1889aa8e06902bce8a3851e3a949ab189b29ed9b6ccfc7171cfc4d4510f586
 |-55783b3d_block--search-form-block.html.twig_9b03d8118cbf219d6c9ba66cb4cb1acbeb68f73b06764c2ae33217c6c0d73767
 |-55783b3d_block--system-menu-block.html.twig_13f98263c76d0637b2b53be380b342c3549a455fb9369c6009a6abbe79796507
 |-55783b3d_block--system-menu-block.html.twig_5baaf09323b19f3aba17875da7e36d7a93e16a76db05dee57d2da397ca8b0124
 |-55783b3d_block--system-messages-block.html.twig_fc0c6e1c65fc0095077a66301995b7469384bbbdd88483c9b85f77aedc0513dd
 |-55783b3d_block.html.twig_f34de612521e743c411473dba9d70da164c7debee450c8348e51cfdaf649c24e
 |-55783b3d_breadcrumb.html.twig_144b7771210f97f3b43d202efc1a1e5ae038729561a4a7923237ab3a0727c93d
 |-55783b3d_container.html.twig_d69d3f510779dc988797c5879b532988c34085e907a199c6189cca5b2526ed93
 |-55783b3d_feed-icon.html.twig_9ad9064fe670e10bb2524538ee81af3ed7059b8f5994ea5129722717f7fc14d5
 |-55783b3d_form-element-label.html.twig_680d2a90a356c5a17d10071733b18ae20242fd727a9ae1d73685ea0f37b84e9f
 |-55783b3d_form-element.html.twig_4fbc743b76ff2563e7aef60a252d82e2ef985ff8443b51c8273d727f58e4648b
 |-55783b3d_form.html.twig_3449c7737d241e3f0b98f84d85240608976058854a1c930110e041d2f003a962
 |-55783b3d_html.html.twig_808b2896f82b60ca3494a9cd78e8bdc80370bf9a81bd42ad63a24c4f5a47acf7
 |-55783b3d_input.html.twig_cd7c9868821162dab576fa8dc64080f3bf20a4d793ddf02b968ac3c26ae46605
 |-55783b3d_links.html.twig_a3de7a974b81eba0507d1f07a6e7c2f6b980c92327997b712f6b67146f7b4679
 |-55783b3d_menu--toolbar.html.twig_dfc881e4a6a5ed17547a18c9a96388cbfea347e6e8f345b87776f9dd2d75f630
 |-55783b3d_menu.html.twig_851059117b8d64931f1c6b19fb47e0f204b8364c83ae4d8ccaf8c442f9aad41d
 |-55783b3d_page.html.twig_e51e318b66e64c6c90c7b29acba93df41c9f8c584d93f6daabfd243cc421a53b
 |-55783b3d_pager.html.twig_9734bcc4165bfc9b4cea95aa9fbc8af593e66915544a3e97afe4f3ace4009d5c
 |-55783b3d_region.html.twig_d3bd2ee1704933a91622fb76aa029fff0bbcf90c4e95d8d71b3b6a4d247e707f
 |-55783b3d_status-messages.html.twig_54c459140007191a6610c1bc150522f3159fd96ef214c74bd21858c744eb4fd2
 |-55783b3d_status-messages.html.twig_78f45b7e0140d7990558ec8243420872db0020c0edd81d2996d086fd0925d2c0
 |-55783b3d_toolbar.html.twig_51081e0b3fc06737b5c4a6229bf97c5fc4b13507115251c02abcc0b59cb2c011
 |-55783b3d_views-view.html.twig_ef753936b01bcb86c84cdaa9447d3ae88405e5a5af34e606dc79ed50d4c1c73a
dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new1.3 KB
new7.19 KB

Alex was faster ...
Expanded the docs a bit.

wim leers’s picture

Ugh, somehow I misread the #60 interdiff, I thought the patch already was using crc32b! My bad.

wim leers’s picture

Status: Needs review » Reviewed & tested by the community
alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed b05a606 and pushed to 8.0.x. Thanks!

  • alexpott committed 9ec0636 on 8.0.x
    Issue #2544932 by dawehner, Fabianx, Wim Leers, Gábor Hojtsy, alexpott,...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

star-szr’s picture

david_garcia’s picture

Template contents were leaking into filenames, so I guess this will also affect POSIX systems if the template contains characters that are invalid on that platform. So this is not just Windows specific, but more likely to happen there because a bigger range of characters are disallowed in path/file names.