5

core/lib/Drupal/Core/Session/SessionHandler.php defines a method (gc()) to clear expired sessions from the database (sessions table)

when is that triggered ? is there a way to trigger it from the interface ?

i know i can just truncate sessions manually or with a cron or a custom drush command..., but i wonder how does core uses it and what triggers it by default

Thanks

  • I can't say 100% without looking into it fully but my likely guess is part of a cron run, probably by system_cron function in the system.module – Leigh Oct 23 '18 at 15:52
  • looked at system_cron() but it doesn't seem to do so. at least not directly. – izus Oct 24 '18 at 12:23
5
+50

Configuring Garbage Collection

When a session opens, PHP will call the gc handler randomly according to the probability set by session.gc_probability / session.gc_divisor. For example if these were set to 5/100 respectively, it would mean a probability of 5%. Similarly, 3/4 would mean a 3 in 4 chance of being called, i.e. 75%.

If the garbage collection handler is invoked, PHP will pass the value stored in the php.ini directive session.gc_maxlifetime. The meaning in this context is that any stored session that was saved more than gc_maxlifetime ago should be deleted. This allows one to expire records based on idle time.

However, some operating systems (e.g. Debian) do their own session handling and set the session.gc_probability variable to 0 to stop PHP doing garbage collection. That's why Symfony now overwrites this value to 1.

If you wish to use the original value set in your php.ini, add the following configuration:

# config/packages/framework.yaml
framework:
    session:
        gc_probability: null

Source: Symphony's official docs on Configuring Sessions and Save Handlers

In Drupal this is seen in /sites/default/default.settings.php

/**
 * Some distributions of Linux (most notably Debian) ship their PHP
 * installations with garbage collection (gc) disabled. Since Drupal depends on
 * PHP's garbage collection for clearing sessions, ensure that garbage
 * collection occurs by using the most common settings.
 */
ini_set('session.gc_probability', 1);
ini_set('session.gc_divisor', 100);

Since the above "most common settings" is set to 1/100, Garbage Collection would run 1% of the time.

Now, as per the code comment, I presume this does not get put into settings.php when it gets auto-generated if your distribution has one already set one in one of its files as I don't see this in my settings.php

You can also set this in services.yml as seen in this answer.


In Conclusion

Note that while Drupal is built on top of Symphony, it does not rely on Symphony for this. I just quoted their nice explanation from their documentation.

We learned that PHP automatically calls this gc() method every session.gc_probability/session.gc_divisor % of the time and if you look at PHP docs on SessionHandler.

SessionHandler is a special class that can be used to expose the current internal PHP session save handler by inheritance. There are seven methods which wrap the seven internal session save handler callbacks (open, close, read, write, destroy, gc and create_sid).

Source: http://php.net/manual/en/class.sessionhandler.php

core/lib/Drupal/Core/Session/SessionHandler.php

/**
 * Default session handler.
 */

class SessionHandler extends AbstractProxy implements \SessionHandlerInterface { ...

 /**
   * {@inheritdoc}
   */
  public function gc($lifetime) {
    // Be sure to adjust 'php_value session.gc_maxlifetime' to a large enough
    // value. For example, if you want user sessions to stay in your database
    // for three weeks before deleting them, you need to set gc_maxlifetime
    // to '1814400'. At that value, only after a user doesn't log in after
    // three weeks (1814400 seconds) will his/her session be removed.
    $this->connection->delete('sessions')
      ->condition('timestamp', REQUEST_TIME - $lifetime, '<')
      ->execute();
    return TRUE;
  }
  • Now, as per the code comment, I presume this does not get put into settings.php when it gets auto-generated if your distribution has one already set >one in one of its files as I don't see this in my settings.php Actually this is in default.services.yml file in the site folder. – izus Oct 26 '18 at 9:26
  • i configured gc_probability and gc_divisor to 100 (both). i also configured gc_maxlifetime to 20 in default.services.yml and in php.ini (just to be sure) I still have very old sessions in sessions table meaning that the ->gc() method wasn't fired event after login/logout. i still don't know how this can be executed by Drupal core . is the execution order missed between php and symfony or between symfony and Drupal or something else i still ignore – izus Oct 26 '18 at 13:34
  • First of all, if you want to put it in the yml file, copy default.services.yml and rename it services.yml; otherwise, when you update core you will lose your changes. – No Sssweat Oct 26 '18 at 18:33
  • Second, most importantly, I am sure your gc method is running at some point. If you look carefully what Drupal's gc() method does (which is exactly why I included it in my answer) and if you read the gc code comments, it checks against if php_value session.gc_maxlifetime have passed since the last time the user has logged in. If your php_value session.gc_maxlifetime is set to 3 weeks or a year, the old sessions will not be getting deleted any time soon no matter how many times gc runs – No Sssweat Oct 26 '18 at 18:49
  • Take a look at this answer which sets the max life time. – No Sssweat Oct 26 '18 at 18:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.