CommentFileSizeAuthor
#84 interdiff.txt1016 bytesznerol
#84 drupal-2205295-83.patch22.94 KBznerol
#80 interdiff.txt6.68 KBznerol
#80 drupal-2205295-80.patch23.52 KBznerol
#78 interdiff-delete-cookie.txt969 bytesznerol
#78 interdiff-gc.txt1.07 KBznerol
#78 interdiff-destroy.txt1.44 KBznerol
#78 interdiff-write.txt4.26 KBznerol
#78 interdiff-read.txt4.61 KBznerol
#73 drupal-2205295-72.patch23.73 KBznerol
#68 interdiff.txt1.31 KBznerol
#68 drupal-2205295-68.patch26.94 KBznerol
#65 interdiff.txt483 bytesznerol
#65 drupal-2205295-65.patch28.25 KBznerol
#65 drupal-2205295-65.patch28.25 KBznerol
#64 interdiff.txt1.57 KBznerol
#64 drupal-2205295-63.patch18.54 KBznerol
#61 interdiff.txt2.51 KBskipyT
#61 drupal-2205295-61.patch29.53 KBskipyT
#59 drupal-2205295-58.patch30.07 KBznerol
#57 interdiff.txt609 bytesznerol
#57 drupal-2205295-56.patch30.03 KBznerol
#53 interdiff.txt2.71 KBznerol
#53 drupal-2205295-53.patch29.97 KBznerol
#50 interdiff.txt7.9 KBznerol
#50 drupal-2205295-49.patch31.8 KBznerol
#48 drupal-2205295-47.patch29.92 KBznerol
#42 interdiff.txt3.46 KBParisLiakos
#42 drupal-2205295-42.patch29.97 KBParisLiakos
#20 interdiff.txt504 bytessun
#20 session.20.patch30.42 KBsun
#16 interdiff.txt4.15 KBsun
#16 session.16.patch30.47 KBsun
#14 interdiff.txt8.16 KBsun
#14 session.14.patch27.16 KBsun
#11 2205295_10.patch22.94 KBcosmicdreams
#11 interdiff_10.txt500 bytescosmicdreams
#8 interdiff.txt6.45 KBsun
#8 session.8.patch22.91 KBsun
#7 2205295_7.patch25.29 KBcosmicdreams
#1 session.1.patch25.03 KBsun
#29 Screenshot from 2014-03-04 20:23:42.png85.51 KBcosmicdreams
#31 2205295_31.patch30.33 KBcosmicdreams
#31 interdiff.txt884 bytescosmicdreams
#33 2205295_33.patch30.34 KBianthomas_uk
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

sun’s picture

Status: Active » Needs review
FileSize
25.03 KB

Status: Needs review » Needs work

The last submitted patch, 1: session.1.patch, failed testing.

joelpittet’s picture

+++ b/core/includes/session.inc
@@ -3,247 +3,30 @@
 use Drupal\Core\Session\UserSession;

Do you need to use UserSession in the new SessionHandler class?

larowlan’s picture

Do you need to use UserSession in the new SessionHandler class?

Same namespace (Drupal\Core\Session\) so not needed

cosmicdreams’s picture

+++ b/core/lib/Drupal/Core/Session/SessionHandler.php
@@ -0,0 +1,307 @@
+    global $user;
...
+      $user = new UserSession();
...
+      $user = new UserSession($values);
...
+      $user = new UserSession(array(
...
+      $user = new UserSession();
...
+      'value' => $user->session,
...
+    return $user->session;
...
+    global $user;
...
+      if ($user) {
...
+      if ($user && ($is_changed || $needs_update)) {

A 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.

cosmicdreams’s picture

  1. +++ b/core/lib/Drupal/Core/Session/SessionHandler.php
    @@ -0,0 +1,307 @@
    +   * @param $sid
    

    The $sid param should be typed to be string.

  2. +++ b/core/lib/Drupal/Core/Session/SessionHandler.php
    @@ -0,0 +1,307 @@
    +    global $user;
    

    This variable of the global user is not really used in this destroy(). It is reset later but never used.

cosmicdreams’s picture

FileSize
25.29 KB

Here 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.

sun’s picture

Status: Needs work » Needs review
Issue tags: +PHP 5.4
FileSize
22.91 KB
6.45 KB

Sorry, 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. :-)

cosmicdreams’s picture

Did you intentionally exclude the SessionHandlerInterface that your previous patch had?

Thanks for the docs fixes, that's much cleaner.

sun’s picture

Yes, 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 :-)

cosmicdreams’s picture

FileSize
500 bytes
22.94 KB

Small change to documentation. @sun you might find this change unneeded but it makes my IDE happy.

The last submitted patch, 8: session.8.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 11: 2205295_10.patch, failed testing.

sun’s picture

Status: Needs work » Needs review
FileSize
27.16 KB
8.16 KB

Alright. Figuring out the following did cost me a few hours of badass debugging...

  1. 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 when SessionHandler::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.

  2. 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

  3. #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:

    The ContainerAwareHttpKernel also defines a third scope: request. This scope is tied to the request, meaning a new instance is created for each subrequest and is unavailable outside the request (for instance in the CLI).

    However, there might be a point in flagging the service as synchronized and introducing a scope: session in the future (which causes the DIC to call the setSession() 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. :-/

  4. 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 with SessionHandler::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 the SessionHandler.

    I wasn't able to figure out yet why that is, and why it doesn't work with just SessionHandler::destruct().

    Cookie::cleanup() calls into drupal_session_commit(), which (1) starts a session on-demand, and (2) force-commits the session.

  5. 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 ;-)

  6. 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 and SessionTest to properly work on Windows.

Status: Needs review » Needs work

The last submitted patch, 14: session.14.patch, failed testing.

sun’s picture

Status: Needs work » Needs review
FileSize
30.47 KB
4.15 KB

Status: Needs review » Needs work

The last submitted patch, 16: session.16.patch, failed testing.

The last submitted patch, 16: session.16.patch, failed testing.

The last submitted patch, 16: session.16.patch, failed testing.

sun’s picture

Status: Needs work » Needs review
FileSize
30.42 KB
504 bytes

Fixed 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.

Status: Needs review » Needs work

The last submitted patch, 20: session.20.patch, failed testing.

The last submitted patch, 20: session.20.patch, failed testing.

The last submitted patch, 20: session.20.patch, failed testing.

Crell’s picture

Just 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.

cosmicdreams’s picture

20: session.20.patch queued for re-testing.

The last submitted patch, 20: session.20.patch, failed testing.

cosmicdreams’s picture

In 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.

cosmicdreams’s picture

cosmicdreams’s picture

In 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)."

cosmicdreams’s picture

One 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.

cosmicdreams’s picture

Status: Needs work » Needs review
FileSize
30.33 KB
884 bytes

Yep that fixed the debug message. Also, some documentation fixes. Let's see how this runs.

Status: Needs review » Needs work

The last submitted patch, 31: 2205295_31.patch, failed testing.

ianthomas_uk’s picture

FileSize
30.34 KB

Reroll. 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.

joelpittet’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 33: 2205295_33.patch, failed testing.

cosmicdreams’s picture

Added the recent issue about using the DrupalKernel for the installer as that should help address the installer errors we routinely have in this issue.

cosmicdreams’s picture

33: 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.

The last submitted patch, 33: 2205295_33.patch, failed testing.

cosmicdreams’s picture

Great 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.

joelpittet’s picture

+++ b/core/includes/session.inc
@@ -304,14 +301,12 @@ function drupal_session_start() {
-  if ($user->isAnonymous() && empty($_SESSION)) {
+  if (\Drupal::currentUser()->isAnonymous() && empty($_SESSION)) {

Would this help? Since $user the global object is not always an object.

cosmicdreams’s picture

It'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.

ParisLiakos’s picture

Status: Needs work » Needs review
FileSize
29.97 KB
3.46 KB

lets try it.

Status: Needs review » Needs work

The last submitted patch, 42: drupal-2205295-42.patch, failed testing.

joelpittet’s picture

This likely doesn't have to do with the fail but the logic looks funky:

  1. +++ b/core/includes/session.inc
    @@ -306,12 +86,12 @@ function drupal_session_start() {
    -  if ($user->isAnonymous() && empty($_SESSION)) {
    +  if ($user && $user->isAnonymous() && empty($_SESSION)) {
    

    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...

cosmicdreams’s picture

I 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.

cosmicdreams’s picture

42: drupal-2205295-42.patch queued for re-testing.

The last submitted patch, 42: drupal-2205295-42.patch, failed testing.

znerol’s picture

Status: Needs work » Needs review
FileSize
29.92 KB

Reroll after #2219009: Improve DX of Settings class. I will try to look into this now.

Status: Needs review » Needs work

The last submitted patch, 48: drupal-2205295-47.patch, failed testing.

znerol’s picture

Status: Needs work » Needs review
FileSize
31.8 KB
7.9 KB

Let's see what happens when we actually use the request_stack instead of the request service.

Status: Needs review » Needs work

The last submitted patch, 50: drupal-2205295-49.patch, failed testing.

cosmicdreams’s picture

Actual Failures!!!!!! Whoohooo!

was #48 a straight reroll?

znerol’s picture

FileSize
29.97 KB
2.71 KB

Yes, #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 to request_stack afterwards.

The interdiff is against #48 with the meta-hunks removed.

znerol’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 53: drupal-2205295-53.patch, failed testing.

cosmicdreams’s picture

One of the leading causes of failure

+++ b/core/lib/Drupal/Core/Session/SessionHandler.php
@@ -0,0 +1,295 @@
+      $needs_update = !$user->getLastAccessedTime() || REQUEST_TIME - $user->getLastAccessedTime() > Settings::get('session_write_interval', 180);

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.

znerol’s picture

Status: Needs work » Needs review
FileSize
30.03 KB
609 bytes

Yes, most failures are related to update / authorize scripts. Let's try your constructor-idea.

Status: Needs review » Needs work

The last submitted patch, 57: drupal-2205295-56.patch, failed testing.

znerol’s picture

Status: Needs work » Needs review
FileSize
30.07 KB

I'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 circumstances SessionHandler is constructed more than once per request.

Let's see what happens when we only initialize $user if it has not been set before.

Status: Needs review » Needs work

The last submitted patch, 59: drupal-2205295-58.patch, failed testing.

skipyT’s picture

Status: Needs work » Needs review
FileSize
29.53 KB
2.51 KB

I took out the destructor and now the session write close is happening on the shutdown function, lets see like this.

Status: Needs review » Needs work

The last submitted patch, 61: drupal-2205295-61.patch, failed testing.

znerol’s picture

Wow! 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.

znerol’s picture

Status: Needs work » Needs review
FileSize
18.54 KB
1.57 KB

#61 removed the dependency on the DestructableInterface and therefore the explicit destruction introduced into the install_drupal function is not necessary either. Let's see.

znerol’s picture

Test whether we can remove some other presumably unrelated change.

znerol’s picture

The last submitted patch, 64: drupal-2205295-63.patch, failed testing.

znerol’s picture

FileSize
26.94 KB
1.31 KB

Also try to remove the hunk from install_bootstrap_full.

cosmicdreams’s picture

It'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.

znerol’s picture

However why get rid of drupal_session_start() in install_bootstrap_full().

I'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.

ParisLiakos’s picture

i say, someone rtbc this quickly and lets get it in, while bot is doing us favors!

klausi’s picture

Status: Needs review » Needs work
+++ b/core/modules/system/lib/Drupal/system/Tests/Session/SessionTest.php
@@ -20,6 +20,8 @@ class SessionTest extends WebTestBase {
+  protected $loggedInUsers = array();

Newly 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!

znerol’s picture

Status: Needs work » Needs review
FileSize
23.73 KB

Let's remove the alterations to the test code and see whether it still turns green.

skipyT’s picture

+++ b/core/includes/session.inc
@@ -3,249 +3,27 @@
+use Drupal\Core\Session\SessionHandler;
 use Drupal\Core\Utility\Error;

We 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?

cosmicdreams’s picture

@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.

skipyT’s picture

@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.

cosmicdreams’s picture

There'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.

znerol’s picture

It 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) and SessionHandler.php then diffed each pair.

jibran’s picture

Yay!!! patch is green. Great work everyone. Minor feedback.

  1. +++ b/core/lib/Drupal/Core/Session/SessionHandler.php
    @@ -0,0 +1,288 @@
    +   * {@inheritdoc}
    +   *
    +   * Initializes the global $user object for the user associated with the
    +   * session.
    

    We still can't mix these.

  2. +++ b/core/lib/Drupal/Core/Session/SessionHandler.php
    @@ -0,0 +1,288 @@
    +    // that is in the user's cookie is hashed before being stored in the database
    

    More then 80 chars.

  3. +++ b/core/lib/Drupal/Core/Session/SessionHandler.php
    @@ -0,0 +1,288 @@
    +      $values = $this->connection->query("SELECT u.*, s.* FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.ssid = :ssid", array(
    ...
    +          $values = $this->connection->query("SELECT u.*, s.* FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.sid = :sid AND s.uid = 0", array(
    ...
    +      $values = $this->connection->query("SELECT u.*, s.* FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.sid = :sid", array(
    

    Can we add comment to explain the query?

  4. +++ b/core/lib/Drupal/Core/Session/SessionHandler.php
    @@ -0,0 +1,288 @@
    +        // We don't have anything to do if we are not allowed to save the session.
    ...
    +      // $_SESSION has changed or more than 180 has passed since the last update.
    ...
    +          // secure and insecure session cookies. If enabled and both cookies are
    

    more then 80 chars.

znerol’s picture

FileSize
23.52 KB
6.68 KB

Thanks for the review, incorporated the suggested changes and also the following two things:

  • Discussed with @skipyT: We do not like to expose the session handler as a service but rather extract the session storage in a follow-up. Therefore removed the session_handler service. It was introduced anyway as a workaround in #14.
  • Removed two spurious use statements (addressed #74)

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 and read (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).

klausi’s picture

Status: Needs review » Reviewed & tested by the community

This 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.

sun’s picture

AWESOME!

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 :-)

dawehner’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/includes/session.inc
@@ -245,7 +16,14 @@ function _drupal_session_write($sid, $value) {
+  if (drupal_is_cli()) {

@@ -308,7 +86,7 @@ function drupal_session_start() {
+  if (!drupal_save_session() || drupal_is_cli()) {

@@ -358,7 +136,7 @@ function drupal_session_regenerate() {
+  if (!drupal_save_session() || drupal_is_cli()) {

Both 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

znerol’s picture

Status: Needs work » Needs review
FileSize
22.94 KB
1016 bytes

In fact there is already a call to drupal_is_cli in order to prevent initiating a session when executed from the command line in drupal_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.

klausi’s picture

Status: Needs review » Reviewed & tested by the community

Fine with me, looking still good otherwise.

znerol’s picture

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed 4ac79a1 and pushed to 8.x. Thanks!

joelpittet’s picture

Yay!!! 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!

ParisLiakos’s picture

sun’s picture

Status: Fixed » Reviewed & tested by the community
webchick’s picture

Status: Reviewed & tested by the community » Fixed

Ok, pushed this time. :) Thanks!

  • Commit d6cce6e on 8.x by webchick:
    Issue #2205295 by znerol, sun, cosmicdreams, skipyT, ParisLiakos,...

Status: Fixed » Closed (fixed)

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