PHP, Sessions, __sleep, and Exceptions

Today I ran into a problem where my PHP Application would throw this fatal error:

Fatal error: Exception thrown without a stack frame in Unknown on line 0

Which is so much fun, because it doesn’t have a line number, so I had no direction as to what exactly was causing the problem. Some quick googling came up with this website stating the following error:

Most often, the error will appear if you use an exception handler combined with an error reporting to exception handler by converting it to an ErrorException, then there a suddenly a whole new magnitude of ways to throw errors within the exception handle, especially if E_NOTICE, E_STRICT and/or E_WARNING errors are converted. This form most often occurs when you use variables without first initializing them. This error may be preventable by wrapping the exception handler within a try/catch block.

A second form of this error occurs when you attempt to throw an exception in a destructor. This is well documented in the PHP manual, but this can still be triggered if you accidentally throw an exception:

Manually – calling “throw new Exception(‘hello world’)’ in a destructor

Implicitly – calling a function that throws an exception (e.g. calling function foo() which throws an exception)

Error handler (ErrorException) – instating a user-defined function as an error handler which throws an ErrorException (which is still an error)

The problem was that the code I was working with wasn’t using a registered exception handler, nor a destructor. So I went through the controller I was working with and commented out each line, and one by one brought each line back. After a few minutes I found the problem: I had a class that would save itself to the Session, and that class also had a __sleep method which is invoked on serialization (see PHP manual). Because I hadn’t manually closed my php session with session_write_close() (PHP Manual), PHP would close the session when cleaning up & closing the request, which is executed outside of the stack. My __sleep() function had an error and would throw an exception, leading to the Fatal Error.

It was a little tricky to track down, but made complete sense once I found it.

Justin is currently the Director of Development for the Deseret News. He is active in the Utah Open Source community. He is an advisory member of the Utah Open Source Foundation, and helps with the anual Utah Open Source Conference. He primarily focuses on PHP, MySQL, Redis, HTML, CSS, jQuery, and JavaScript. When he gets the time, he enjoys to play jazz piano. Read More

Tagged with: , , , ,
Posted in Programming