HowtoForge

PHP session data is not deleted when using custom session management on debian (and ubuntu)

On debian systems (as far as I know this applies to ubuntu, too) the garbage collector for PHP sessions is disabled by default.

The corresponding setting in php.ini is session.gc_probability = 0 which enables the garbage collector when set to something greater than zero. The default value in PHP is 1, so the garbage collector is called with a probability of 1/100 at each PHP script call.

On debian systems this setting is disabled because of the fact that the default path for session storage is not writable for the web server process (and it shouldn't be either). Deleting of outdates session files is done by a system cron job here.

Following an exerpt from the php.ini:

; This is disabled in the Debian packages, due to the strict permissions
; on /var/lib/php5.  Instead of setting this here, see the cronjob at
; /etc/cron.d/php5, which uses the session.gc_maxlifetime setting below.
; php scripts using their own session.save_path should make sure garbage
; collection is enabled by setting session.gc_probability
;session.gc_probability = 0

As this setting is okay for scripts using the default php session handling (file), this can lead to problems when you use you own session handling that defines its own routines for session reading and writing using session_save_handler(). Those session management classes will provide an own function for the garbage collector, too in most cases.

The problem is, that this garbage collector function will never be called on a debian system with the above-mentioned php.ini setting. This is crucial, when session data is stored in a MySQL database of type MEMORY. This table is limited in size by the MySQL config value max_heap_table_size. If this size is reached, all further session writing will fail and with it probably the website will fail to work properly.

Knowing this it is really important to overwrite the php.ini setting for the garbage collection in your own session management class. I will show this with a small example of a session management class (without real writing/reading):

class session {
    function __destruct() {
        session_write_close();
    }
    function __construct() {
        @ini_set("session.use_trans_sid","0");
        @ini_set('session.gc_probability', 1); // in debian this is disabled by default...
         
        // enable customized session handler functions
        session_set_save_handler(array(&$this,"_sess_open"),
                                 array(&$this,"_sess_close"),
                                 array(&$this,"_sess_read"),
                                 array(&$this,"_sess_write"),
                                 array(&$this,"_sess_destroy"),
                                 array(&$this,"_sess_gc"));
        @session_start();
    }
 
    // declare user defined session handler functions
    function _sess_open($sSavePath, $sSessionName) {
        return true;
    }
     
    function _sess_close() {
        return true;
    }
     
    function _sess_read($sKey) {
        // read and return value
    }
     
    function _sess_write($sKey, $val) {
        // write new value
    }
     
    function _sess_destroy($sKey) {
        // destroy session
    }
     
    function _sess_gc($iMaxLifeTime) {
        // delete old sessions (from db)
    } 
}
 
$mySession = new session();

The important thing is the call of @ini_set('session.gc_probability', 1) inside the constructor. After this the session garbage collection should work as expected, even on debian systems with your own session management class.

PHP session data is not deleted when using custom session management on debian (and ubuntu)