summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabio Bas <ctrlaltca@gmail.com>2016-02-26 09:27:38 +0100
committerFabio Bas <ctrlaltca@gmail.com>2016-02-26 09:27:38 +0100
commitb01aac13a3bc71eec9a934050e4cf0a9f58b02e7 (patch)
treec485e82d8e164744b74841fc1d7a6ad11a557796
parent562e322fe595b4d3307ff28a96c8c5fbcc284010 (diff)
Intercept fatal errors using register_shutdown_function
Related discussion in #569
-rw-r--r--framework/Exceptions/TErrorHandler.php7
-rw-r--r--framework/Exceptions/TException.php11
-rw-r--r--framework/PradoBase.php21
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