Playing with redis/Rediska and sessions, I wanted to get more numbers to compare this solution to a traditional MySQL-based approach which also made me revisit the idea of a CouchDB-based session handler for Zend_Session
.
Implementing this handler, I ran into a weird issue:
Fatal error: Undefined class constant 'ALLOW_ALL' in /usr/home/till/foo/trunk/library/Zend/Uri/Http.php on line 447
Call Stack
# Time Memory Function Location
1 0.7357 3914816 Foo_Session_SaveHandler_Couchdb->write( ) ../Couchdb.php:0
2 0.7358 3916600 Foo_Couchdb->query( ) ../Couchdb.php:94
3 0.7361 3969464 Zend_Http_Client->__construct( ) ../Couchdb.php:368
4 0.7361 3969544 Zend_Http_Client->setUri( ) ../Client.php:250
5 0.7362 3976568 Zend_Uri::factory( ) ../Client.php:267
6 0.7365 4003352 Zend_Uri_Http->__construct( ) ../Uri.php:130
7 0.7367 4006216 Zend_Uri_Http->valid( ) ../Http.php:154
8 0.7368 4006216 Zend_Uri_Http->validateHost( ) ../Http.php:281
The funny thing is that that APC was added (for apc_store()
and apc_fetch()
) at the same time to the game (to cache the configuration) and when I disabled it, the error disappeared.
Talking to to one of the leads of APC — Gopal (Btw, cheers for helping!) — on IRC (#pecl@efnet
) I thought at first that the issue was autoload related and we thought the order in which the extensions are loaded might make a difference. From Rasmus’ comment, I later discovered bug #16745 with a proposed workaround to use session_write_close()
.
On a sidenote: I’m still not sure why the error is expected behavior for some people but yet it works with some PHP and APC versions and breaks with others. From what I gathered it broke for me with 5.2.6
, 5.2.11
and 5.3.2
. Tried all with the latest version of APC (3.1.3p1
).
Here’s how I fixed it for myself
I have a Lagged_Application
class to bootstrap my application. Lagged_Application
is kind of like Zend_Application
sans a lot of safety nets and magic. Since it does a lot less, it’s also quiet a bit faster. To get an idea, check out my Google Code repository (for an alas rather outdated version of it).
I added the following function to it:
<?php
// (...)
public function shutdown()
{
session_write_close();
}
My index.php
looks like the following:
<?php
include 'library/Lagged/Application.php';
$app = new Lagged_Application;
$app->setEnvironment('production');
$app->bootstrap();
register_shutdown_function(array($app, 'shutdown'));
Somewhat related — shutdown()
could be a good start to tear down other objects as well, when needed.
More?
Now that this issue is fixed, I think also the infamous Fatal error: Exception thrown without a stack frame in Unknown on line 0
originates from the same issue. That is, when sessions and APC are around — but I should dig a little deeper to verify this.
All in all, it’s a pretty weird issue and IM(very)HO, objects shouldn’t be torn down or some sort of before hook should be executed to avoid this. But that’s especially easy to say if you don’t do C. :-)
Fin
That’s all. I sure hope this saves someone else some time.