TLDR
- Quicklink has a default setting that turns off the library when it detects a session. It detects sessions using
$session->isStarted() - Starting at Drupal 8.14, this detects a session for anonymous users when there should be none. This is on a basic standard Drupal install.
- This causes the library not to load and breaks functionality.
To reproduce:
1. New install of Drupal 8.6.14 - standard profile under PHP 7.2.14
2. Install Devel, generate 50 content nodes.
3. Install Quicklink. Enable debug mode.
4. Clear cache
5. In incognito mode, quicklink is not being loaded. Looking at module debug log indicates this is because we think there is a session.
| Comment | File | Size | Author |
|---|---|---|---|
| #20 | 3047931-20-1xdev.patch | 3.6 KB | mglaman |
| #20 | 3047931-20-1x.patch | 7.73 KB | mglaman |
| #18 | 3047931-18.patch | 4.92 KB | mglaman |
| #17 | 3047931-17-test-failure.patch | 4.19 KB | mglaman |
| #16 | 3047931-16-test-failure.patch | 3.57 KB | mglaman |
Comments
Comment #2
mherchelWhen I'm anonymous in Xdebug and I'm evaluating expressions,
$session->isStarted()returns true, while$session->start()returns false.I'm not sure what the difference is, and why they would be returning a different value.
I can verify that when I am logged in,
$session->start()returns true.@andyg5000 Can you review this?
Comment #3
mherchelThis is weird. The change record (https://www.drupal.org/node/2228871) indicates the original code should be working.
Comment #4
mherchelComment #5
andyg5000Yea, the patch doesn't make sense to me and seems like it should be working as-is. Is this a vanilla Drupal site you're testing or something that might be using private storage or other session invoking code?
Comment #6
mherchelTroubleshooting log:
1)
$session->isStarted()is set to true.2) When I step into
isStarted(), I see that$this->startedLazyis set to true3) I then set breakpoints everywhere in core where
startedLazyis being set to TRUE (there are only two).4) It breaks at SessionManager.php at line 140. This is where
startedLazyis being set to TRUE.Comment #7
mherchelI uninstalled BigPipe. But the issue persists.
Comment #8
mherchelFound this tidbit on https://www.drupal.org/project/drupal/issues/3044387#comment-13055257
Comment #9
mherchelYeah, so I'm pretty sure this is related to Drupal core issue #3045349: Lazy started sessions with session data are not saved with symfony/http-foundation 3.4.24, where the
isStarted()function is overwritten and now checks for lazy sessions.Comment #10
mherchelYep. Verified this works properly in Drupal 8.6.13 but is broken in Drupal 8.6.14.
This issue definitely seems to be caused by #3045349: Lazy started sessions with session data are not saved with symfony/http-foundation 3.4.24
Comment #11
mherchelComment #12
mherchelComment #13
mglamanThe session manager should never be empty.
Comment #14
mglaman👀looks like you could use some help writing some tests to catch this.
Comment #15
mglamanHere are three patches. The last one using session_configuration should work, and is why page_cache did not break in Drupal core -- this is how it detects a session.
Comment #16
mglamanHere's a patch which has a test that shows HEAD has a failure.
Comment #17
mglamanThis uses a setup script. And fixes another missing config item in the schema.
Comment #18
mglamanHere's a patch with the fix. However, please don't commit this just yet. Tomorrow I'd like to provide a proper patch for the schema.yml. Or at least fix the labels in this one.
Comment #19
mherchelThanks for all your work on this. Note that I just added the config schema to 8.x-1.x-dev within #3042448: Add config schema for quicklink.settings.
Comment #20
mglamanHere is a reroll. I made one against 8.x-1.x and the 8.x-1.x-dev (which shouldn't exist?)
Comment #21
mglamanFWIW you probably need to merge 8.x-1.x-dev into 8.x-1.x and then delete the 8.x-1.x-dev branch, then patch two from #20 will apply.
Comment #23
mherchelFixed and pushed to 8.x-1.1! Thanks @mglaman!
Comment #24
wim leersYep, you want to use
SessionConfigurationInterface::hasSession(), this is also what BigPipe uses to only activate itself for requests with sessions (see https://git.drupalcode.org/project/drupal/blob/c779a82a28c2e9f140f6a11db...).So the committed solution should work fine! 👍
While looking at the code, I did spot two problems, both relating to cacheability:
$variables['#cache']['contexts'][] = 'session.exists';should be inside the "if no_load_when_session" branch, to vary correctly — BigPipe does this too (see https://git.drupalcode.org/project/drupal/blob/c779a82a28c2e9f140f6a11db...) — this is still directly related to the originally reported problem$variables['#cache']['tags'] = $config->getCacheTags();should be added immediately after loading$configto ensure that configuration changes are reflected immediately, without manual clearing of caches :) — this one I just noticed by looking at everything above.