bug #29190 [Debug][HttpKernel] remove frames added by DebugClassLoader in stack traces (nicolas-grekas)

This PR was merged into the 4.2-dev branch.

Discussion
----------

[Debug][HttpKernel] remove frames added by DebugClassLoader in stack traces

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #28818
| License       | MIT
| Doc PR        | -

![image](https://user-images.githubusercontent.com/243674/48362054-14ee0100-e6a3-11e8-82e1-b185af45fb8b.png)

Commits
-------

76e7944460 [Debug][HttpKernel] remove frames added by DebugClassLoader in stack traces
This commit is contained in:
Fabien Potencier 2018-11-16 06:03:01 +01:00
commit 429f500cbc
2 changed files with 22 additions and 5 deletions

View File

@ -417,8 +417,8 @@ class ErrorHandler
self::$toStringException = null;
} elseif (!$throw && !($type & $level)) {
if (!isset(self::$silencedErrorCache[$id = $file.':'.$line])) {
$lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3), $type, $file, $line, false) : array();
$errorAsException = new SilencedErrorContext($type, $file, $line, $lightTrace);
$lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5), $type, $file, $line, false) : array();
$errorAsException = new SilencedErrorContext($type, $file, $line, isset($lightTrace[1]) ? array($lightTrace[0]) : $lightTrace);
} elseif (isset(self::$silencedErrorCache[$id][$message])) {
$lightTrace = null;
$errorAsException = self::$silencedErrorCache[$id][$message];
@ -441,7 +441,6 @@ class ErrorHandler
} else {
$errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line);
// Clean the trace by removing function arguments and the first frames added by the error handler itself.
if ($throw || $this->tracedErrors & $type) {
$backtrace = $errorAsException->getTrace();
$lightTrace = $this->cleanTrace($backtrace, $type, $file, $line, $throw);
@ -669,6 +668,9 @@ class ErrorHandler
);
}
/**
* Cleans the trace by removing function arguments and the frames added by the error handler and DebugClassLoader.
*/
private function cleanTrace($backtrace, $type, $file, $line, $throw)
{
$lightTrace = $backtrace;
@ -679,6 +681,13 @@ class ErrorHandler
break;
}
}
if (class_exists(DebugClassLoader::class, false)) {
for ($i = \count($lightTrace) - 2; 0 < $i; --$i) {
if (DebugClassLoader::class === ($lightTrace[$i]['class'] ?? null)) {
array_splice($lightTrace, --$i, 2);
}
}
}
if (!($throw || $this->scopedErrors & $type)) {
for ($i = 0; isset($lightTrace[$i]); ++$i) {
unset($lightTrace[$i]['args'], $lightTrace[$i]['object']);

View File

@ -16,6 +16,7 @@ use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
use Symfony\Component\Config\ConfigCache;
use Symfony\Component\Config\Loader\DelegatingLoader;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Debug\DebugClassLoader;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@ -504,7 +505,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
return;
}
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5);
// Clean the trace by removing first frames added by the error handler itself.
for ($i = 0; isset($backtrace[$i]); ++$i) {
if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) {
@ -512,13 +513,20 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
break;
}
}
// Remove frames added by DebugClassLoader.
for ($i = \count($backtrace) - 2; 0 < $i; --$i) {
if (DebugClassLoader::class === ($backtrace[$i]['class'] ?? null)) {
$backtrace = array($backtrace[$i + 1]);
break;
}
}
$collectedLogs[$message] = array(
'type' => $type,
'message' => $message,
'file' => $file,
'line' => $line,
'trace' => $backtrace,
'trace' => array($backtrace[0]),
'count' => 1,
);
});