PHP 4.0 Bug #9669: Session write-out race condition
| From: | dave2 at wetstring dot net | Date: | Sat, 10 Mar 2001 09:55:05 +0000 |
| Subject: | PHP 4.0 Bug #9669: Session write-out race condition | ||
| Groups: | php.dev | ||
| Request: | Send a blank email to php-dev+get-48574@lists.php.net to get a copy of this message | ||
From: dave2@wetstring.net
Operating system: Debian GNU/Linux 2.2
PHP version: 4.0.3pl1
PHP Bug Type: *Session related
Bug description: Session write-out race condition
Initally from time to time, very rarely, we'd login to the site (which does logins as a form
submission), and we'd get back to the page we're supposed to be at but without seeming to
be logged in.
The page that the login form submits to does very little, it just checks the details provided by the
form in a database, and sets a session variable with the user's real ID, which all pages
consider to be "logged in". Then, they're redirected back to the refering page.
Works fine, 99.9% of the time, but under situations where access is good (eg, 50ms away from the
webserver over cable + ethernet) sometimes it just wouldn't work. It got a _lot_ worse when we
started pushing session data into a database.
Initally we thought it was our custom session save stuff, but removing it we could still reproduce
the problem (it was just harder to reproduce). Finally, we added a whole lot of debugging calls to
error_log() and found what was going on.
There's a race condition between the end of a page and when the session handler actually writes
out the session data, vs when a new page is requested. If the remote browser requests a page before
PHP has written out the session stuff, it'll get the old session infomation. From our
debugging:
[Sat Mar 10 21:58:49 2001] [error] uri:
/login.php?user=samteste&password=x&uri=%2F sql: select
verifyLogin('samteste','x')
[Sat Mar 10 21:58:49 2001] [error] uri: / sql: SELECT value FROM sessiondata WHERE sesskey =
'35760d1b61748cc467b3c685916c3980' AND expiry > now()
[Sat Mar 10 21:58:49 2001] [error] uri:
/login.php?user=samteste&password=x&uri=%2F sql:
UPDATE sessiondata
SET expiry = now()+'1440s',
value = 'playerid|s:4:\"1542\";attempt|i:1;'
WHERE sesskey = '35760d1b61748cc467b3c685916c3980'
Roughly, we see this sequence as:
- The page that verifies the login is called (/login.php), and the login is verified, which updates
the session variable. Before exit, this page issues a redirect to /.
- The browser then processes the redirect, and requests the new URL (/), retriving the
"current" session data
- The session data from login.php is only just now written out.
We have a workaround in PHP (we have a function called redirect() which first calls our
session_write handler with the session_id() and session_encode(), before outputing the headers..)
but we'd prefer the session handling worked as advertised, so to speak :)
Note: we've verified with a packet sniffer that the browser is closing the connection before
opening a new one for the new URL. It's not the browser jumping the gun.
--
Edit Bug report at: http://bugs.php.net/?id=9669&edit=1