PHP - ini_set('session.gc_maxlifetime', 5) - Why it doesn't end the session?

43,590

Solution 1

Even if the garbage collector kicked in and deleted the session file you opened/read with session_start(), it will NOT reach into the guts of that particular PHP process and delete the $_SESSION object array.

Assuming you're on the standard file-based session handler (which contains a serialize()'d copy of $_SESSION), here's what happens.

  1. The session file sits in its temp directory
  2. You session_start(), causing PHP to open/lock the file, read its contents, deserialize the data, and incidentally, possibly update the session file's "last used" timestamp (atime on Unix boxes).
  3. If the stars and moon are aligned correctly with Neptune ascendant in the fifth house, the session garbage collector MAY fire up and delete old session files.
  4. The garbage collector will happily iterate through the session directory, and delete any files which are older than the max_liftime, BUT WILL NOT DELETE ANY FILES CURRENTLY OPEN/IN USE. Since you've not closed()'d your session, your session's file is still in use, so will not get deleted.

Now, if you did something like this:

ini_set(...); // set GC probability to max, short session lifetime, etc...

session_start(); // populate $_SESSION
session_write_close(); // dump $_SESSION out to file, close file, release lock.

sleep(7); // Sleep for 7 seconds;

session_start(); // re-populate $_SESSION;

Now you might just end up with a fresh blank $_SESSION, IF the garbage collector decides to kick in. However, unless you do that second session_start(), the old $_SESSION data from the previous start() call WILL STILL BE PRESENT. The session file may have been trashed, but the garbage collector will not touch what's present in your script's memory as it runs.

Solution 2

session.gc_maxlifetime is the number of seconds after which the session will be considered for garbage collection.

session.gc_probability and session.gc_divisor then determine the probability that garbage collection will be executed on any session initialization

Solution 3

Read the manual (emphasis mine):

session.gc_maxlifetime 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).

In the same page:

session.gc_divisor coupled with session.gc_probability defines the probability that the gc (garbage collection) process is started on every session initialization. The probability is calculated by using gc_probability/gc_divisor, e.g. 1/100 means there is a 1% chance that the GC process starts on each request. session.gc_divisor defaults to 100.

Now do the math and see that it's not very likely the GC will be called on each request.

You should store the in the session a variable that saves the time of the last activity of the user and use that instead of the session is logically "active". Don't rely on garbage collection.

Solution 4

I don't think this is how gc_maxlifetime is supposed to work. The manual says

session.gc_maxlifetime specifies the number of seconds after which data will be seen as 'garbage' and potentially cleaned up.

(emphasis mine)

in your case, the session is still active. Therefore, I don't think it will be subject to garbage collection.

You could try doing a session_write_close() before the sleep(). That might increase the probability that the garbage collector.

Share:
43,590
q0987
Author by

q0987

Updated on August 23, 2022

Comments

  • q0987
    q0987 over 1 year

    The PHP script is as follows:

    <?php // continue.php
    ini_set('session.gc_maxlifetime', 5);
    session_start();
    echo ini_get('session.gc_maxlifetime');
    // wait for 7 seconds
    usleep(7000000);
    if (isset($_SESSION['username']))
    {
        $username = $_SESSION['username'];
        $password = $_SESSION['password'];
        $forename = $_SESSION['forename'];
        $surname  = $_SESSION['surname'];
    
        echo "Welcome back $forename.<br />
              Your full name is $forename $surname.<br />
              Your username is '$username'
              and your password is '$password'.";
    }
    else echo "Please <a href=authenticate2.php>click here</a> to log in.";
    
    ?>
    

    Based on the timeout (i.e. 5 seconds), the script should not print out anything. However, I still receive the following message

    5Welcome back Bill. Your full name is Bill Smith. Your username is 'bsmith' and your password is 'mysecret'.
    

    It seems that the line ini_set('session.gc_maxlifetime', 5) doesn't work as it should be. I am using windowsXP + XAMMP.

    May you tell me how to make it work?

    Thank you