I've run over a somewhat little problem over the week. The error message upfront this is about:
[30-Dec-2012 15:19:32] PHP Fatal error: Exception thrown without a stack frame in Unknown on line 0
I think it is because my error handler (see below for details) is turning any error into an exception. I might should prevent that in case there is no stack frame.
Is there an easy way to find out if there is any stack frame or not in PHP?
Details:
On one of my websites I've got an error handler running that is turning every error into an exception, the common ErrorException
to be precise.
I introduced it some time ago because the site is mainly legacy code and I wanted to have any issue result in an exception I can finally "catch" in a streamlined fashion an exception handler and give the request a stop.
I put this into class of it's own, the handler is registered and also in parallel an output buffer is opened to catch the output up until the exception is thrown. Basically code like this:
// register output buffering
$r = ob_start(array($this, 'handleBuffer'));
// register error handler
$this->_originalErrorHandler = set_error_handler(array($this, 'handleError'));
// register exception handler
$this->_originalExceptionHandler = set_exception_handler(array($this, 'handleException'));
This worked all fine and dandy until I decided to add another output buffering class into the mix. Just one that catches as well all output and then can do some "post production" on the website, including checking for HTML problems (yes, it's all a bit legacy so actually this is a bit duck-taped, I know). That also worked very fine btw. however not when I made a mistake in the new component:
[30-Dec-2012 15:19:32] PHP Fatal error: Exception thrown without a stack frame in Unknown on line 0
This is basically my problem. Is there an easy way to prevent getting these errors? I somewhat know why the error is given but I'm not so entirely sure so it's hard for me to really circumvent the problem. I tried to release the new output buffer before the script enters the new shutdown phase because I thought this would cause this. But this didn't make it.
Your problem indicates that you are using an EOL (End Of Life) version of PHP (specifically PHP < 5.3.0), which means it's no longer supported. This issue comes from throwing an exception where no strack frame exists and as such the old engine did not know how to handle those exceptions properly.
This can be due to a couple of different reasons. Some of the most common ones are as follows:
Here's an example that demonstrates your problem under some of those circumstances...
function myErrorHandler($errno, $errstr, $errfile, $errline)
{
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
function myExceptionHandler($exception) {
echo "We got an exception with message: '{$exception->getMessage()}'";
}
function myCallBack($contents) {
trigger_error('ohnoes!'); // You can't throw an error from the output buffer callback function in older versions of PHP < 5.3
}
class Foo {
public function __destruct() {
trigger_error('ohnoes!'); // You can't throw an error from a destructor in older versions of PHP < 5.3
}
}
set_error_handler('myErrorHandler');
set_exception_handler('myExceptionHandler');
The above code would cause you to see the fatal error you described here...
ob_start("myCallBack");
... and here...
$foo = new foo;
This problem has been fixed in PHP >= 5.3.0 so you should not see this issue if you were using the most current version of PHP.
The simplest fix is to upgrade your PHP. If that is not an option you must consider these facts that you can not throw exceptions where PHP does not expect them to be thrown (in callback functions, error handlers, exceptions handlers, etc... -- which are actually all considered to be callbacks to PHP).
The other thing is you should not be turning every error into an exception in this way. If what you are doing is as the code I supplied demonstrates (i.e. throwing an exception from inside the error handler -- thus turning every error into an exception) then you are going to cause yourself a lot of pain and with virtually no benefit. PHP errors are not meant to be handled. They are meant to inform the client of a problem (the client being the person writing the PHP code), or potential problem. Handling the error itself is not as simple as turning every error into an exception and then handling that exception, because not every error should be exceptional. For instance, E_NOTICE level errors have no place in exception handling. They are primarily used to notify you of a potential for a bug, not that there is necessarily something buggy with your code and not to mention that most of them can't even be handled easily in user-space code (they mostly require re-factoring the code itself). I strongly advice against this poor practice.