Found and Fixed!
The problem is that when php shuts down global variables might already have been deleted when the default session write and close happens. There doesn't seem to be any synchronization between the two processes. Here are the php bug tickets regarding this:
This has all the pertinant info:
https://bugs.php.net/bug.php?id=54157
http://www.mediawiki.org/wiki/Specia...i/83140#c14601
On request shutdown, PHP does things in the following order:
register_shutdown_function() functions
zend_call_destructors()
zend_deactivate_modules()
zend_call_destructors() goes through the $GLOBALS symbol table and identifies every global variable that holds an object which has a reference count of 1. It removes these globals. It doesn't decrement any reference counts. Any globals which are not objects, or have a reference count greater than 1, are left in the symbol table.
I believe the "fixes" that have worked for people have simply moved the symbol table around enough that the global $db is still active when session_write is called in zencart.
The fix is to set a shutdown function that does a session write close itself:
Code:
register_shutdown_function('zc_shutdown');
function zc_shutdown() {
// other shutdown code as needed
// write session now
session_write_close();
}
Then in includes/functions/sessions.php, in _sess_write, change to:
Code:
if (!is_object($db)) {
//error_log('session write with no global db variable! sessions.php .60');
// https://bugs.php.net/bug.php?id=54157
// session could be closed with no global variables
// if so, just exit, nothing we can do
// workaround is to register shutdown function that saves session
// and this last call is no-op
return;
//PHP 5.2.0 bug workaround ...
// if (!class_exists('queryFactory')) require('includes/classes/db/' .DB_TYPE . '/query_factory.php');
// $db = new queryFactory();
// $db->connect(DB_SERVER, DB_SERVER_USERNAME, DB_SERVER_PASSWORD, DB_DATABASE, USE_PCONNECT, false);
}
If we come upon a session write where we don't have global variables, it's probably because they've been destroyed. This is OK because we have already done a session write in our shutdown function, so we can ignore this session write. Of course, do not set any session variables after the shutdown function is called.
This has worked in two cases where I had this strange "session write with no global $db" value in php 5.3 and 5.4.
Bookmarks