PHP: Premature Session Termination

approximately 3 minutes of reading

When it comes to coding in PHP, sooner or later sessions will come into play. If your application is based on Ubuntu Server, this may lead to a situation where the default session length (24 minutes) is too short and there is a need to extend it. This article covers some tricky parts that you should be aware of when dealing with short-length session duration or premature session termination in your code.

This article assumes that we are dealing here with a framework-agnostic code. Just raw PHP, running on a bare-metal server, where there is no Docker or Vagrant.

Context

Normally the fastest approach would be to simply overwrite the default value on-fly by calling ini_set() method to change a specific configuration option. Setting name that we are interested in is called session.gc_maxlifetime and it:

Specifies the number of seconds after which data will be seen as 'garbage' and potentially cleaned up. Garbage collection may occur during session start (depending on session.gc_probability and session.gc_divisor). Defaults to 1440 (24 minutes).

At this point you probably think that a one-liner like:

ini_set('session.gc_maxlifetime', 21600); // six hours in seconds

inserted immediately after session_start() would solve the issue by upkeeping session for 6 hours (or earlier in case browser window is closed). Unfortunately this will not work as expected and existing session will be still terminated in a timespan between 24 minutes to an hour.

Culprit

This happens because Ubuntu Server changes how sessions behave in PHP. Let's figure out what is the current value for session.gc_probability. This can be done by simply checking the result of phpinfo() method. If the value is set to 0, it means that the built-in Garbage Collector will not be triggered. Instead, a recurring cron task will wipe out all of the existing session roughly every 30 minutes.

Based on my further investigation it looks like the Garbage Collector based on a cron task, relies on the value of session.gc_maxlifetime, taken from the global php.ini file and it has a higher priority that what we define through ini_set().

Solution

To solve the problem in a most convenient way, we have to set values for the following session-related settings:

  • session.gc_maxlifetime
  • session.gc_probability
  • session.gc_divisor

We also have to specify the location to store session files. This is done via session_save_path() method.

Any examples?

Right before you call session_start(), type:

<?php

ini_set('session.gc_maxlifetime', 21600);
ini_set('session.gc_probability', 1);
ini_set('session.gc_divisor', 100);

session_save_path('/var/www/sessions');
session_start();

What does it mean?

The session.gc_probability is used to manage probability, that the Garbage Collector routine is started. This works in conjunction with session.gc_divisor, that is used to define the probability, that the Garbage Collector process will start on every session initialization. Refer to the official documentation for more details.

Altering Default Session Location

This change is significant as it prevents Ubuntu Server from cleaning our sessions. Keep in mind that the location you specify must be writable. This can be done by using the chmod command.

This is it. I hope you find this article useful.


Words: 533
Published in: Linux · PHP · Ubuntu