[2.6][Debug] Fix fatal-errors handling on HHVM
This commit is contained in:
parent
13c5d7cd0d
commit
445de5e828
@ -350,7 +350,7 @@ class ErrorHandler
|
|||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
public function handleError($type, $message, $file, $line, array $context)
|
public function handleError($type, $message, $file, $line, array $context, array $backtrace = null)
|
||||||
{
|
{
|
||||||
$level = error_reporting() | E_RECOVERABLE_ERROR | E_USER_ERROR;
|
$level = error_reporting() | E_RECOVERABLE_ERROR | E_USER_ERROR;
|
||||||
$log = $this->loggedErrors & $type;
|
$log = $this->loggedErrors & $type;
|
||||||
@ -367,6 +367,15 @@ class ErrorHandler
|
|||||||
$context = $e;
|
$context = $e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (null !== $backtrace && $type & E_ERROR) {
|
||||||
|
// E_ERROR fatal errors are triggered on HHVM when
|
||||||
|
// hhvm.error_handling.call_user_handler_on_fatals=1
|
||||||
|
// which is the way to get their backtrace.
|
||||||
|
$this->handleFatalError(compact('type', 'message', 'file', 'line', 'backtrace'));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if ($throw) {
|
if ($throw) {
|
||||||
if (($this->scopedErrors & $type) && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) {
|
if (($this->scopedErrors & $type) && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) {
|
||||||
// Checking for class existence is a work around for https://bugs.php.net/42098
|
// Checking for class existence is a work around for https://bugs.php.net/42098
|
||||||
@ -402,10 +411,17 @@ class ErrorHandler
|
|||||||
if ($this->scopedErrors & $type) {
|
if ($this->scopedErrors & $type) {
|
||||||
$e['scope_vars'] = $context;
|
$e['scope_vars'] = $context;
|
||||||
if ($trace) {
|
if ($trace) {
|
||||||
$e['stack'] = debug_backtrace(true); // Provide object
|
$e['stack'] = $backtrace ?: debug_backtrace(true); // Provide object
|
||||||
}
|
}
|
||||||
} elseif ($trace) {
|
} elseif ($trace) {
|
||||||
$e['stack'] = debug_backtrace(PHP_VERSION_ID >= 50306 ? DEBUG_BACKTRACE_IGNORE_ARGS : false);
|
if (null === $backtrace) {
|
||||||
|
$e['stack'] = debug_backtrace(PHP_VERSION_ID >= 50306 ? DEBUG_BACKTRACE_IGNORE_ARGS : false);
|
||||||
|
} else {
|
||||||
|
foreach ($backtrace as &$frame) {
|
||||||
|
unset($frame['args'], $frame);
|
||||||
|
}
|
||||||
|
$e['stack'] = $backtrace;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -505,7 +521,11 @@ class ErrorHandler
|
|||||||
*/
|
*/
|
||||||
public static function handleFatalError(array $error = null)
|
public static function handleFatalError(array $error = null)
|
||||||
{
|
{
|
||||||
self::$reservedMemory = '';
|
if (null === self::$reservedMemory) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$reservedMemory = null;
|
||||||
|
|
||||||
$handler = set_error_handler('var_dump', 0);
|
$handler = set_error_handler('var_dump', 0);
|
||||||
$handler = is_array($handler) ? $handler[0] : null;
|
$handler = is_array($handler) ? $handler[0] : null;
|
||||||
@ -527,14 +547,15 @@ class ErrorHandler
|
|||||||
// Handled below
|
// Handled below
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($error && ($error['type'] & (E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR))) {
|
if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) {
|
||||||
// Let's not throw anymore but keep logging
|
// Let's not throw anymore but keep logging
|
||||||
$handler->throwAt(0, true);
|
$handler->throwAt(0, true);
|
||||||
|
$trace = isset($error['backtrace']) ? $error['backtrace'] : null;
|
||||||
|
|
||||||
if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) {
|
if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) {
|
||||||
$exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false);
|
$exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false, $trace);
|
||||||
} else {
|
} else {
|
||||||
$exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true);
|
$exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace);
|
||||||
}
|
}
|
||||||
} elseif (!isset($exception)) {
|
} elseif (!isset($exception)) {
|
||||||
return;
|
return;
|
||||||
|
@ -35,11 +35,19 @@ use Symfony\Component\HttpKernel\Exception\FatalErrorException as LegacyFatalErr
|
|||||||
*/
|
*/
|
||||||
class FatalErrorException extends LegacyFatalErrorException
|
class FatalErrorException extends LegacyFatalErrorException
|
||||||
{
|
{
|
||||||
public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true)
|
public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null)
|
||||||
{
|
{
|
||||||
parent::__construct($message, $code, $severity, $filename, $lineno);
|
parent::__construct($message, $code, $severity, $filename, $lineno);
|
||||||
|
|
||||||
if (null !== $traceOffset) {
|
if (null !== $trace) {
|
||||||
|
if (!$traceArgs) {
|
||||||
|
foreach ($trace as &$frame) {
|
||||||
|
unset($frame['args'], $frame['this'], $frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setTrace($trace);
|
||||||
|
} elseif (null !== $traceOffset) {
|
||||||
if (function_exists('xdebug_get_function_stack')) {
|
if (function_exists('xdebug_get_function_stack')) {
|
||||||
$trace = xdebug_get_function_stack();
|
$trace = xdebug_get_function_stack();
|
||||||
if (0 < $traceOffset) {
|
if (0 < $traceOffset) {
|
||||||
@ -48,7 +56,7 @@ class FatalErrorException extends LegacyFatalErrorException
|
|||||||
|
|
||||||
foreach ($trace as &$frame) {
|
foreach ($trace as &$frame) {
|
||||||
if (!isset($frame['type'])) {
|
if (!isset($frame['type'])) {
|
||||||
// XDebug pre 2.1.1 doesn't currently set the call type key http://bugs.xdebug.org/view.php?id=695
|
// XDebug pre 2.1.1 doesn't currently set the call type key http://bugs.xdebug.org/view.php?id=695
|
||||||
if (isset($frame['class'])) {
|
if (isset($frame['class'])) {
|
||||||
$frame['type'] = '::';
|
$frame['type'] = '::';
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user