[Debug] Made code in ErrorHandler easier to read

This commit is contained in:
Grégoire Pineau 2015-04-02 14:57:42 +02:00
parent ba84ac87b8
commit 15ef182b99

View File

@ -356,69 +356,71 @@ class ErrorHandler
$throw = $this->thrownErrors & $type & $level; $throw = $this->thrownErrors & $type & $level;
$type &= $level | $this->screamedErrors; $type &= $level | $this->screamedErrors;
if ($type && ($log || $throw)) { if (!$type || (!$log && !$throw)) {
if (PHP_VERSION_ID < 50400 && isset($context['GLOBALS']) && ($this->scopedErrors & $type)) { return $type && $log;
$e = $context; // Whatever the signature of the method, }
unset($e['GLOBALS'], $context); // $context is always a reference in 5.3
$context = $e;
}
if ($throw) { if (PHP_VERSION_ID < 50400 && isset($context['GLOBALS']) && ($this->scopedErrors & $type)) {
if (($this->scopedErrors & $type) && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) { $e = $context; // Whatever the signature of the method,
// Checking for class existence is a work around for https://bugs.php.net/42098 unset($e['GLOBALS'], $context); // $context is always a reference in 5.3
$throw = new ContextErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line, $context); $context = $e;
} else { }
$throw = new \ErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line);
}
if (PHP_VERSION_ID <= 50407 && (PHP_VERSION_ID >= 50400 || PHP_VERSION_ID <= 50317)) { if ($throw) {
// Exceptions thrown from error handlers are sometimes not caught by the exception if (($this->scopedErrors & $type) && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) {
// handler and shutdown handlers are bypassed before 5.4.8/5.3.18. // Checking for class existence is a work around for https://bugs.php.net/42098
// We temporarily re-enable display_errors to prevent any blank page related to this bug. $throw = new ContextErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line, $context);
$throw->errorHandlerCanary = new ErrorHandlerCanary();
}
throw $throw;
}
// For duplicated errors, log the trace only once
$e = md5("{$type}/{$line}/{$file}\x00{$message}", true);
$trace = true;
if (!($this->tracedErrors & $type) || isset($this->loggedTraces[$e])) {
$trace = false;
} else { } else {
$this->loggedTraces[$e] = 1; $throw = new \ErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line);
} }
$e = compact('type', 'file', 'line', 'level'); if (PHP_VERSION_ID <= 50407 && (PHP_VERSION_ID >= 50400 || PHP_VERSION_ID <= 50317)) {
// Exceptions thrown from error handlers are sometimes not caught by the exception
// handler and shutdown handlers are bypassed before 5.4.8/5.3.18.
// We temporarily re-enable display_errors to prevent any blank page related to this bug.
if ($type & $level) { $throw->errorHandlerCanary = new ErrorHandlerCanary();
if ($this->scopedErrors & $type) {
$e['context'] = $context;
if ($trace) {
$e['stack'] = debug_backtrace(true); // Provide object
}
} elseif ($trace) {
$e['stack'] = debug_backtrace(PHP_VERSION_ID >= 50306 ? DEBUG_BACKTRACE_IGNORE_ARGS : false);
}
} }
if ($this->isRecursive) { throw $throw;
$log = 0; }
} elseif (self::$stackedErrorLevels) {
self::$stackedErrors[] = array($this->loggers[$type], $message, $e);
} else {
try {
$this->isRecursive = true;
$this->loggers[$type][0]->log($this->loggers[$type][1], $message, $e);
$this->isRecursive = false;
} catch (\Exception $e) {
$this->isRecursive = false;
throw $e; // For duplicated errors, log the trace only once
$e = md5("{$type}/{$line}/{$file}\x00{$message}", true);
$trace = true;
if (!($this->tracedErrors & $type) || isset($this->loggedTraces[$e])) {
$trace = false;
} else {
$this->loggedTraces[$e] = 1;
}
$e = compact('type', 'file', 'line', 'level');
if ($type & $level) {
if ($this->scopedErrors & $type) {
$e['context'] = $context;
if ($trace) {
$e['stack'] = debug_backtrace(true); // Provide object
} }
} elseif ($trace) {
$e['stack'] = debug_backtrace(PHP_VERSION_ID >= 50306 ? DEBUG_BACKTRACE_IGNORE_ARGS : false);
}
}
if ($this->isRecursive) {
$log = 0;
} elseif (self::$stackedErrorLevels) {
self::$stackedErrors[] = array($this->loggers[$type], $message, $e);
} else {
try {
$this->isRecursive = true;
$this->loggers[$type][0]->log($this->loggers[$type][1], $message, $e);
$this->isRecursive = false;
} catch (\Exception $e) {
$this->isRecursive = false;
throw $e;
} }
} }
@ -487,40 +489,44 @@ class ErrorHandler
public static function handleFatalError(array $error = null) public static function handleFatalError(array $error = null)
{ {
self::$reservedMemory = ''; self::$reservedMemory = '';
$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;
restore_error_handler(); restore_error_handler();
if ($handler instanceof self) {
if (null === $error) {
$error = error_get_last();
}
try { if (!$handler instanceof self) {
while (self::$stackedErrorLevels) { return;
static::unstackErrors(); }
}
} catch (\Exception $exception) {
// Handled below
}
if ($error && ($error['type'] & (E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR))) { if (null === $error) {
// Let's not throw anymore but keep logging $error = error_get_last();
$handler->throwAt(0, true); }
if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) { try {
$exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false); while (self::$stackedErrorLevels) {
} else { static::unstackErrors();
$exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true);
}
} elseif (!isset($exception)) {
return;
} }
} catch (\Exception $exception) {
// Handled below
}
try { if ($error && ($error['type'] & (E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR))) {
$handler->handleException($exception, $error); // Let's not throw anymore but keep logging
} catch (FatalErrorException $e) { $handler->throwAt(0, true);
// Ignore this re-throw
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);
} else {
$exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true);
} }
} elseif (!isset($exception)) {
return;
}
try {
$handler->handleException($exception, $error);
} catch (FatalErrorException $e) {
// Ignore this re-throw
} }
} }