Tuesday, June 15, 2010

PHP Session issue

A PHP Session Cookie (mostly defined as PHPSESSID) has a default life time until the browser is closed. Another session-relevant issue is the PHP garbage collector. When a session is created, a flat-file is created on the server - e.g. in /tmp on linux servers. Since the session ID is a unique identifier, those session files will accumulate over time - the garbage collector will take care of these files and delete old files from time to time. PHP has a sort of built-in "load-balancing" feature for this garbage collector, so that old session files are not deleted on each and every session request, but with a certain probability. The default timeout for session files is 1440 seconds or 24 minutes. So a session file can be deleted after that timeout, but it may reside on the server longer, depending on the amount of sessions created - here comes the probability into the game.

So we have a session cookie with a lifetime until the browser is closed, but the garbage collector might delete the session file much earlier. In this case, and if there is a session request after the session file has been deleted, a new session is created and the old session information is lost. This can be very annoying if e.g. the users is writing some message in a web-based interface and this task takes longer than the session file on the server is available.

There are 3 PHP.ini variables, which deal with the garbage collector:PHP ini value name default Changeable
session.gc_maxlifetime 1440 seconds PHP_INI_ALL
session.gc_probability 1 PHP_INI_ALL
session.gc_divisor 100 PHP_INI_ALL

session.gc_probability in conjunction with session.gc_divisor is used to manage probability that the gc (garbage collection) routine is started. 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.

The most important variable is session.gc_maxlifetime:-
As discussed earlier, this variable sets the timeout for session file deletion.
All three variables can be set in the php.ini configuration file, but more important, those can be also set during runtime due the PHP_INI_ALL permission.

we can be also set those 3 PHP.ini variables during runtime due the PHP_INI_ALL permission. so we can create another directory *within* the regular session file directory and set the new path for the session files. Now our session files are stored in the new directory and the regular garbage collector will not see them, so those files will survive at least that long as defined in gc_maxlifetime.

But make sure that all these changes MUST be made before the actual session is opened with session_start() or session_register(). need to include at top of index file.

// path for cookies
$cookie_path = "/";

// timeout value for the cookie
$cookie_timeout = 60 * 30; // in seconds

// timeout value for the garbage collector
//   we add 300 seconds, just in case the user's computer clock
//   was synchronized meanwhile; 600 secs (10 minutes) should be
//   enough - just to ensure there is session data until the
//   cookie expires
$garbage_timeout = $cookie_timeout + 600; // in seconds

// set the PHP session id (PHPSESSID) cookie to a custom value
session_set_cookie_params($cookie_timeout, $cookie_path);

// set the garbage collector - who will clean the session files -
//   to our custom timeout
ini_set('session.gc_maxlifetime', $garbage_timeout);

// we need a distinct directory for the session files,
//   otherwise another garbage collector with a lower gc_maxlifetime
//   will clean our files aswell - but in an own directory, we only
//   clean sessions with our "own" garbage collector (which has a
//   custom timeout/maxlifetime set each time one of our scripts is
//   executed)
strstr(strtoupper(substr($_SERVER["OS"], 0, 3)), "WIN") ?
$sep = "\\" : $sep = "/";
$sessdir = ini_get('session.save_path').$sep."my_sessions";
if (!is_dir($sessdir)) { mkdir($sessdir, 0777); }
ini_set('session.save_path', $sessdir);

// now we're ready to start the session

print "mytest=".$_SESSION['mytest']."

$_SESSION['mytest'] = "captain";

No comments:

Post a Comment