Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
As usual, we're shooting for way too much in #1858196: [meta] Leverage Symfony Session components
→ Baby steps!
→ http://php.net/manual/function.session-set-save-handler.php#example-4765
Comment | File | Size | Author |
---|---|---|---|
#84 | interdiff.txt | 1016 bytes | znerol |
#84 | drupal-2205295-83.patch | 22.94 KB | znerol |
#73 | drupal-2205295-72.patch | 23.73 KB | znerol |
Comments
Comment #1
sunComment #3
joelpittetDo you need to use UserSession in the new SessionHandler class?
Comment #4
larowlanSame namespace (Drupal\Core\Session\) so not needed
Comment #5
cosmicdreams CreditAttribution: cosmicdreams commentedA long time ago, chx made the recommendation of calling this variable "$account" instead of "$user" because that helps us think of the problem the right way.
These are really "people" they are just accounts that people use.
@sun: THANK YOU for this patch. It's so clean. Hopefully in the next few weeks I can have time to help fix test failures.
Comment #6
cosmicdreams CreditAttribution: cosmicdreams commentedThe $sid param should be typed to be string.
This variable of the global user is not really used in this destroy(). It is reset later but never used.
Comment #7
cosmicdreams CreditAttribution: cosmicdreams commentedHere are a few documentation fixes. Also, I'm not sure if this was a good idea, but in order to fix documentation issues for destroy() I had it return TRUE if it can manipulate the session and FALSE if it can not.
Comment #8
sunSorry, I mostly kept the code/docs unchanged in the initial patch, as I exclusively focused on just moving the code.
Here is the proper fix for those docs. :-)
Comment #9
cosmicdreams CreditAttribution: cosmicdreams commentedDid you intentionally exclude the SessionHandlerInterface that your previous patch had?
Thanks for the docs fixes, that's much cleaner.
Comment #10
sunYes, testbots are running Drupal 8 core tests on PHP 5.4 now. :-)
@see
SessionHandlerInterface
→ #2152073: Bump Drupal core's PHP requirement to 5.4.2 :-)
Comment #11
cosmicdreams CreditAttribution: cosmicdreams commentedSmall change to documentation. @sun you might find this change unneeded but it makes my IDE happy.
Comment #14
sunAlright. Figuring out the following did cost me a few hours of badass debugging...
Despite supporting
SessionHandler
object instances, PHP 5.4 still destructs objects before writing and closing the session. PHPWTF++This causes
global $user
to be empty/NULL whenSessionHandler::write()
is invoked (by PHP).→ The session has to be committed before shutdown functions are invoked; i.e., when the kernel is terminated.
→ This inherently requires us to register
SessionHandler
as a service.At the same time, there should only be a single
SessionHandler
instance within the entire lifetime of the PHP process.→ The service is tagged with
'persist'
, so as to retain it across kernel rebuilds.This apparently conflicts with #2190665: Remove persist flag from services that do not need it
#2004086: The Request service must be synthetic revised quite some of the bootstrap code to properly handle the request service, which shares some good level of semantics with the session handler.
So I additionally looked into the question of whether this service should be in
scope: request
, but the Symfony manual clearly states:However, there might be a point in flagging the service as
synchronized
and introducing ascope: session
in the future (which causes the DIC to call thesetSession()
method on all services upon scope change). That is, because we essentially want the session (if any) to be passed forward into sub-requests, and also be able to react to a change in this scope.That is essentially what is being discussed in #2180109: Change the current_user service to a proxy — but the entire discussion there seems to be based on our legacy session handling code. :-/
We really should have modernized session handling before duct-taping a higher-level Authentication system + CurrentUser service on top of the legacy code... Some of the new code doesn't make any sense at all with this new code here.
The Authentication system was introduced in #1890878: Add modular authentication system, including Http Basic; deprecate global $user
The Cookie authentication provider happens to contain a
cleanup()
method, which (1) overlaps withSessionHandler::destruct()
, but which (2) is required for anonymous user sessions to work, because it force-commits the session, even though that should actually be handled theSessionHandler
.I wasn't able to figure out yet why that is, and why it doesn't work with just
SessionHandler::destruct()
.Cookie::cleanup()
calls intodrupal_session_commit()
, which (1) starts a session on-demand, and (2) force-commits the session.This patch happens to reliably reproduce #2108623: Installing via the UI no longer logs in user 1 every time in automated tests out of a sudden, which is AWESOME on one hand, but "unlucky" on the other hand ;-)
I wouldn't have been able to debug this at all without #2176043: WebTestBase does not show request headers in verbose output + response header output is borked
This new patch contains some clarifications and fixes for the cookie handling code in
WebTestBase
andSessionTest
to properly work on Windows.Comment #16
sunComment #20
sunFixed interactive installer prematurely ends with "No active batch." - again.
I happily admit that I do not really have an idea of what's going on with the session handling in the installer anymore — this patch essentially reverts the change from the second to last patch. — The install task dispatching prematurely sends responses for some install task types (e.g., batch), which could possibly be the cause for this back and forth. → Previously, I fixed the CLI, and by that, I broke the interactive installer...
Anyway, for now I just want get some test results again.
Comment #24
Crell CreditAttribution: Crell commentedJust a note that PHP 5.4 testbots are now a thing (woohoo!), so we can ignore the 5.3-support now. Hopefully that makes life easier.
Comment #25
cosmicdreams CreditAttribution: cosmicdreams commented20: session.20.patch queued for re-testing.
Comment #27
cosmicdreams CreditAttribution: cosmicdreams commentedIn my previous adventures in this area it was stressed to me that part of what makes our session implementation uncommon is how we handle masquerading users and transitioning anonymous users to logged in users (for example in ecommerce situations).
As a result I think it may be important to link related session issues together.
#961508: Dual http/https session cookies interfere with drupal_valid_token()
#2180109: Change the current_user service to a proxy
I want to make sure that these issues stay related because I think they're all part of the same puzzle.
Comment #28
cosmicdreams CreditAttribution: cosmicdreams commentedComment #29
cosmicdreams CreditAttribution: cosmicdreams commentedIn testing the installation of this locally I found something interesting.
On my laptop I'm running Ubuntu 13.10 which has PHP 5.5 / Apache to run Drupal. Everything installs fine, but after the installation is complete I notice the following.
1. I'm logged in automatically (THANKS SUN)
2. I get this debug message:
"Debug: Failed to start the session: already started by PHP. in Drupal\Core\Session\Session->start() (line 104 of core/lib/Drupal/Core/Session/Session.php)."
Comment #30
cosmicdreams CreditAttribution: cosmicdreams commentedOne problem seems to be related to http://stackoverflow.com/questions/6249707/check-if-php-session-has-alre...
Which basically says that checks on whether session_id() returns an empty string are no longer sufficient for PHP 5.4. The only function in all of Drupal that this really impacts is drupal_session_started() but that clearly plays a roll in the debug message I'm getting.
It's also worth noting that Symfony's NativeSessionStorage handles this case appropriately. See the start() method, line 133.
Comment #31
cosmicdreams CreditAttribution: cosmicdreams commentedYep that fixed the debug message. Also, some documentation fixes. Let's see how this runs.
Comment #33
ianthomas_ukReroll. This still won't work, but I'm posting it because there was a conflict in the code that was moved (key became keys). Otherwise the reroll was simple.
Comment #34
joelpittetComment #36
cosmicdreams CreditAttribution: cosmicdreams commentedAdded the recent issue about using the DrupalKernel for the installer as that should help address the installer errors we routinely have in this issue.
Comment #37
cosmicdreams CreditAttribution: cosmicdreams commented33: 2205295_33.patch queued for re-testing.
After seeing that this patch merges with #2213357: Use a proper kernel in early installer properly, I am hopeful that we'll get some proper errror messages again. I've tested installing locally with php 5.4 and this patch and everything works fine for me.
Comment #39
cosmicdreams CreditAttribution: cosmicdreams commentedGreat News! I can reliably get the installation to fail now.
I'm running PHP 5.4 and during the installation, after selecting the standing installation profile, I get this error:
Call to a member function isAnonymous() on a non-object in C:\Users\karen_000\Sites\d8\core\includes\session.inc on line 97
So we can start debugging again.
Comment #40
joelpittetWould this help? Since $user the global object is not always an object.
Comment #41
cosmicdreams CreditAttribution: cosmicdreams commentedIt's worth a shot, however I think the reason why we're using the super global $user is because we need to execute this logic before \Drupal can be used.
Either way I was able to fix it for me by checking for an empty() $user on that line. Perhaps despite clearing my files directory, dropping all my tables, and trying to reinstall I didn't clear all the remnants of a previous installation.
Comment #42
ParisLiakos CreditAttribution: ParisLiakos commentedlets try it.
Comment #44
joelpittetThis likely doesn't have to do with the fail but the logic looks funky:
Wouldn't a !$user be also considered a an anonymous? shouldn't it be
if ((!$user || ($user && $user->isAnonymous())) && empty($_SESSION)) {
or something with less parens...Comment #45
cosmicdreams CreditAttribution: cosmicdreams commentedI don't understand all of what's going on with #1808220: Remove run-tests.sh dependency on existing/installed parent site. Maybe with that issue being fixed we'll get a different test result.
Comment #46
cosmicdreams CreditAttribution: cosmicdreams commented42: drupal-2205295-42.patch queued for re-testing.
Comment #48
znerol CreditAttribution: znerol commentedReroll after #2219009: Improve DX of Settings class. I will try to look into this now.
Comment #50
znerol CreditAttribution: znerol commentedLet's see what happens when we actually use the
request_stack
instead of therequest
service.Comment #52
cosmicdreams CreditAttribution: cosmicdreams commentedActual Failures!!!!!! Whoohooo!
was #48 a straight reroll?
Comment #53
znerol CreditAttribution: znerol commentedYes, #48 was a straight reroll. Needs another one after #2178581: Add an AnonymousUserSession object in favour of using drupal_anonymous_user(). Maybe we better stick with the
request
service for the moment and do to switch torequest_stack
afterwards.The interdiff is against #48 with the meta-hunks removed.
Comment #54
znerol CreditAttribution: znerol commentedComment #56
cosmicdreams CreditAttribution: cosmicdreams commentedOne of the leading causes of failure
This seems to be the leading cause for the failures. $user is defined from the use of "global $user" in the first line of this function.
As it was explained to me, the global $user is not always a UserSession and thus we end up in the situation we are now with these failures.
I think we need to either define a constructor where we ensure a UserSession is available or at least check to see if $user is a UserSession.
Comment #57
znerol CreditAttribution: znerol commentedYes, most failures are related to update / authorize scripts. Let's try your constructor-idea.
Comment #59
znerol CreditAttribution: znerol commentedI've been busy debugging the test failures from #57. I found that sometimes it happens that the
$user
object is set to an anonymous session upon request termination in the simpletest parent site. Recalling that the only change introduced with #57 was the initialization of the$user
global, it follows that under some circumstancesSessionHandler
is constructed more than once per request.Let's see what happens when we only initialize
$user
if it has not been set before.Comment #61
skipyT CreditAttribution: skipyT commentedI took out the destructor and now the session write close is happening on the shutdown function, lets see like this.
Comment #63
znerol CreditAttribution: znerol commentedWow! cool, now we only need to fix #2108623: Installing via the UI no longer logs in user 1 every time to make the remaining tests pass.
Comment #64
znerol CreditAttribution: znerol commented#61 removed the dependency on the
DestructableInterface
and therefore the explicit destruction introduced into theinstall_drupal
function is not necessary either. Let's see.Comment #65
znerol CreditAttribution: znerol commentedTest whether we can remove some other presumably unrelated change.
Comment #66
znerol CreditAttribution: znerol commentedComment #68
znerol CreditAttribution: znerol commentedAlso try to remove the hunk from
install_bootstrap_full
.Comment #69
cosmicdreams CreditAttribution: cosmicdreams commentedIt's good to omit that hunk in #65 as I added it only to make some tests pass. However why get rid of drupal_session_start() in install_bootstrap_full().
Very Happy to see this go green.
Comment #70
znerol CreditAttribution: znerol commentedI'm basically trying to remove every bit of this patch which is not directly related to the actual refactoring. The call to
drupal_session_start
does not exist in HEAD.Comment #71
ParisLiakos CreditAttribution: ParisLiakos commentedi say, someone rtbc this quickly and lets get it in, while bot is doing us favors!
Comment #72
klausiNewly introduced variables need to have a docblock. Why do we need to have the array of logged in users?
Otherwise looks good, this is a reasonable start!
Comment #73
znerol CreditAttribution: znerol commentedLet's remove the alterations to the test code and see whether it still turns green.
Comment #74
skipyT CreditAttribution: skipyT commentedWe shall remove these lines, cause those classes aren't used in the session.inc file.
Next steps: convert all of the session related procedural functions as public service methods, split the session handling from the session storage.
What do you think?
Comment #75
cosmicdreams CreditAttribution: cosmicdreams commented@skipyT, I think a step before making session into a service is to objectify it. That should be quick and easy as we only have to convert the procedural functions to static methods to the least work possible. If you want to take it step further and make session into a service that would be cool too.
I'm thinking that given the amount of effort we've put into this over the past year, that it might make sense to shoot for small measurable changes to get to our final solution faster.
Comment #76
skipyT CreditAttribution: skipyT commented@cosmicdreams: I agree with you. I just need this task to be finished ASAP, cause I'm porting session to mongodb and it would be easier if we make this changes. I will see tomorrow with znerol how can I help.
Comment #77
cosmicdreams CreditAttribution: cosmicdreams commentedThere's no reason why we can't achieve both: advancing the code is small measureable steps and getting it all done ASAP. Shooting for major overhauls and trying to do too much is what has kept this task unfinished for more than 1.5 years. I think a lot of the complexities that need to be resolved will expose themselves by attempting to objectify the session.
After that making it a service should be simple.
Comment #78
znerol CreditAttribution: znerol commentedIt feels a bit awkward that the session handler is a service, given that its methods should never be called directly. I think we should aim at converting it into a private service later on (when the remaining stuff from
session.inc
has been converted into services.In order to make this better accessible for reviewers I extracted all the session handler functions from
session.inc
(HEAD) andSessionHandler.php
then diffed each pair.Comment #79
jibranYay!!! patch is green. Great work everyone. Minor feedback.
We still can't mix these.
More then 80 chars.
Can we add comment to explain the query?
more then 80 chars.
Comment #80
znerol CreditAttribution: znerol commentedThanks for the review, incorporated the suggested changes and also the following two things:
session_handler
service. It was introduced anyway as a workaround in #14.I also looked up what PHP actually does with the return value of the session-handler callbacks. They are mostly ignored (or simply used for logging purposes), except for
open
andread
(obviously). I interpret the changes to the return value of session handler callbacks to be just for consistency reasons (@sun perhaps could comment on that).Comment #81
klausiThis is the baby step start that we want. I checked the patch and all we are doing now is moving the session functions to a class, which is fine.
Comment #82
sunAWESOME!
Thank you so much for getting this first baby step to work, @znerol + @skipyT !
Also glad to see usage of the new PHP 5.4
session_status()
.Perfect :-)
Comment #83
dawehnerBoth znerol and I think this change is unnesarry and assume maybe things about our enviroment which is not right. We should change as little as possible
Comment #84
znerol CreditAttribution: znerol commentedIn fact there is already a call to
drupal_is_cli
in order to prevent initiating a session when executed from the command line indrupal_session_start
. I guess that the additional checks were introduced for consistency reasons.One of the next steps will be to move the rest of
session.inc
into a container based service, and therefore we need to touch that code again anyway.Comment #85
klausiFine with me, looking still good otherwise.
Comment #86
znerol CreditAttribution: znerol commentedFollowup #2228341: Objectify session management functions + remove session.inc.
Comment #87
alexpottCommitted 4ac79a1 and pushed to 8.x. Thanks!
Comment #88
joelpittetYay!!! Thanks @sun, @cosmicdreams, @znerol and all for making this happen! It is so much more organized, cleaned up and generally debatably nicer looking as OOP!
Comment #89
ParisLiakos CreditAttribution: ParisLiakos commentedNot yet pushed
Another followup #2228393: Decouple session from cookie based user authentication
Comment #90
sunComment #91
webchickOk, pushed this time. :) Thanks!