diff options
author | Fabio Bas <ctrlaltca@gmail.com> | 2016-02-26 09:27:38 +0100 |
---|---|---|
committer | Fabio Bas <ctrlaltca@gmail.com> | 2016-02-26 09:27:38 +0100 |
commit | b01aac13a3bc71eec9a934050e4cf0a9f58b02e7 (patch) | |
tree | c485e82d8e164744b74841fc1d7a6ad11a557796 | |
parent | 562e322fe595b4d3307ff28a96c8c5fbcc284010 (diff) |
Intercept fatal errors using register_shutdown_function
Related discussion in #569
-rw-r--r-- | framework/Exceptions/TErrorHandler.php | 7 | ||||
-rw-r--r-- | framework/Exceptions/TException.php | 11 | ||||
-rw-r--r-- | framework/PradoBase.php | 21 |
3 files changed, 38 insertions, 1 deletions
diff --git a/framework/Exceptions/TErrorHandler.php b/framework/Exceptions/TErrorHandler.php index f9a120ac..02f86f5e 100644 --- a/framework/Exceptions/TErrorHandler.php +++ b/framework/Exceptions/TErrorHandler.php @@ -345,7 +345,12 @@ class TErrorHandler extends TModule // if PHP exception, we want to show the 2nd stack level context // because the 1st stack level is of little use (it's in error handler) if($exception instanceof TPhpErrorException) - $result=isset($trace[0]['file'])?$trace[0]:$trace[1]; + { + if(isset($trace[0]['file'])) + $result=$trace[0]; + elseif(isset($trace[1])) + $result=$trace[1]; + } else if($exception instanceof TInvalidOperationException) { // in case of getter or setter error, find out the exact file and row diff --git a/framework/Exceptions/TException.php b/framework/Exceptions/TException.php index 651adb5a..033f7667 100644 --- a/framework/Exceptions/TException.php +++ b/framework/Exceptions/TException.php @@ -357,6 +357,17 @@ class TPhpErrorException extends TSystemException $errorType=isset($errorTypes[$errno])?$errorTypes[$errno]:'Unknown Error'; parent::__construct("[$errorType] $errstr (@line $errline in file $errfile)."); } + + /** + * Returns if error is one of fatal type. + * + * @param array $error error got from error_get_last() + * @return boolean if error is one of fatal type + */ + public static function isFatalError($error) + { + return isset($error['type']) && in_array($error['type'], array(E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING)); + } } diff --git a/framework/PradoBase.php b/framework/PradoBase.php index de8c4655..8a0c4a4d 100644 --- a/framework/PradoBase.php +++ b/framework/PradoBase.php @@ -84,6 +84,10 @@ class PradoBase */ set_error_handler(array('PradoBase','phpErrorHandler')); /** + * Sets shutdown function to be Prado::phpFatalErrorHandler + */ + register_shutdown_function(array('PradoBase','phpFatalErrorHandler')); + /** * Sets exception handler to be Prado::exceptionHandler */ set_exception_handler(array('PradoBase','exceptionHandler')); @@ -135,6 +139,23 @@ class PradoBase } /** + * PHP shutdown function used to catch fatal errors. + * This method should be registered as PHP error handler using + * {@link register_shutdown_function}. The method throws an exception that + * contains the error information. + */ + public static function phpFatalErrorHandler() + { + $error = error_get_last(); + if($error && + TPhpErrorException::isFatalError($error) && + error_reporting() & $error['type']) + { + self::exceptionHandler(new TPhpErrorException($error['type'],$error['message'],$error['file'],$error['line'])); + } + } + + /** * Default exception handler. * This method should be registered as default exception handler using * {@link set_exception_handler}. The method tries to use the errorhandler |