On line 84 of memcached-session.inc in the function sess_write(), there is:
if ($user->uid || !empty($value)) {
(memcache write sessions code here)
}
I'm guessing that the original intent of the "if" was to save time by not saving to the current PHP session vars to memcache if there were none to save for the anonymous user. The flaw in this logic is that even though there may be no data to save in memcache, there may very well be stale PHP session vars in memcache to overwrite.
The most common example are probably drupal messages sent to anon after he fills out a form. Before form redirect, the messages are stored as a PHP session var to be presented to anon after redirect. When Drupal presents these messages, it clears the corresponding PHP session var. When anon then navigates to another page in the same site, there is then no message PHP session var to save, but the old one is still stored in memcache and must be cleared. The "if" statement above prevents them from being overwritten with nothing and the messages are therefore not cleared.
Another minor flaw in sess_write() is that the entire $user var is stored in memcache which may cause stale PHP session var persistence (see (2) below). This may surface as a bug later depending on how the function sess_user_load() is modified or patched later.
Suggestions:
(1) Either store the session data in memcache unconditionally (i.e. remove the if statement), or store the empty status of the current memcache session data in a $session var property in the sess_read() function:
$session->is_empty = empty($session->session)
then the problematic "if" in the sess_write() can then be modified as follows:
if ($user->uid || (!empty($value) && $session->is_empty) {
(memcache write sessions code here)
}
(2) The PHP session vars are also stored in the $user->session property. To completely remove the possibility of stale PHP session var persistence and to more faithfully reproduce the core session.inc behaviour, this property should be cleared just before the $user var is stored in memcache in sess_write():
unset($user->session);
dmemcache_set($user->uid, $user, ini_get('session.gc_maxlifetime'), 'users');
Marc
Comments
Comment #1
jvandyk commentedhttp://drupal.org/node/362502