[Debug][ErrorHandler] Preserve next error handler

Co-authored-by: Joe <cuchac@email.cz>
This commit is contained in:
Thomas Calvet 2019-02-15 18:30:30 +01:00
parent 37b0eeb007
commit a8b34348e7
4 changed files with 58 additions and 15 deletions

View File

@ -517,6 +517,11 @@ class ErrorHandler
$errorAsException ? ['exception' => $errorAsException] : [], $errorAsException ? ['exception' => $errorAsException] : [],
]; ];
} else { } else {
if (!\defined('HHVM_VERSION')) {
$currentErrorHandler = set_error_handler('var_dump');
restore_error_handler();
}
try { try {
$this->isRecursive = true; $this->isRecursive = true;
$level = ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG; $level = ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG;
@ -525,7 +530,7 @@ class ErrorHandler
$this->isRecursive = false; $this->isRecursive = false;
if (!\defined('HHVM_VERSION')) { if (!\defined('HHVM_VERSION')) {
set_error_handler([$this, __FUNCTION__]); set_error_handler($currentErrorHandler);
} }
} }
} }

View File

@ -12,12 +12,12 @@
namespace Symfony\Component\Debug\Tests; namespace Symfony\Component\Debug\Tests;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use Psr\Log\NullLogger; use Psr\Log\NullLogger;
use Symfony\Component\Debug\BufferingLogger; use Symfony\Component\Debug\BufferingLogger;
use Symfony\Component\Debug\ErrorHandler; use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\Debug\Exception\SilencedErrorContext; use Symfony\Component\Debug\Exception\SilencedErrorContext;
use Symfony\Component\Debug\Tests\Fixtures\ErrorHandlerThatUsesThePreviousOne;
use Symfony\Component\Debug\Tests\Fixtures\LoggerThatSetAnErrorHandler; use Symfony\Component\Debug\Tests\Fixtures\LoggerThatSetAnErrorHandler;
/** /**
@ -590,26 +590,40 @@ class ErrorHandlerTest extends TestCase
} }
/** /**
* @dataProvider errorHandlerIsNotLostWhenLoggingProvider * @dataProvider errorHandlerWhenLoggingProvider
*/ */
public function testErrorHandlerIsNotLostWhenLogging($customErrorHandlerHasBeenPreviouslyDefined, LoggerInterface $logger) public function testErrorHandlerWhenLogging($previousHandlerWasDefined, $loggerSetsAnotherHandler, $nextHandlerIsDefined)
{ {
try { try {
if ($customErrorHandlerHasBeenPreviouslyDefined) { if ($previousHandlerWasDefined) {
set_error_handler('count'); set_error_handler('count');
} }
$logger = $loggerSetsAnotherHandler ? new LoggerThatSetAnErrorHandler() : new NullLogger();
$handler = ErrorHandler::register(); $handler = ErrorHandler::register();
$handler->setDefaultLogger($logger); $handler->setDefaultLogger($logger);
if ($nextHandlerIsDefined) {
$handler = ErrorHandlerThatUsesThePreviousOne::register();
}
@trigger_error('foo', E_USER_DEPRECATED); @trigger_error('foo', E_USER_DEPRECATED);
@trigger_error('bar', E_USER_DEPRECATED); @trigger_error('bar', E_USER_DEPRECATED);
$this->assertSame([$handler, 'handleError'], set_error_handler('var_dump')); $this->assertSame([$handler, 'handleError'], set_error_handler('var_dump'));
if ($logger instanceof LoggerThatSetAnErrorHandler) {
$this->assertCount(2, $logger->cleanLogs());
}
restore_error_handler(); restore_error_handler();
if ($customErrorHandlerHasBeenPreviouslyDefined) { if ($previousHandlerWasDefined) {
restore_error_handler();
}
if ($nextHandlerIsDefined) {
restore_error_handler(); restore_error_handler();
} }
} finally { } finally {
@ -618,13 +632,14 @@ class ErrorHandlerTest extends TestCase
} }
} }
public function errorHandlerIsNotLostWhenLoggingProvider() public function errorHandlerWhenLoggingProvider()
{ {
return [ foreach ([false, true] as $previousHandlerWasDefined) {
[false, new NullLogger()], foreach ([false, true] as $loggerSetsAnotherHandler) {
[true, new NullLogger()], foreach ([false, true] as $nextHandlerIsDefined) {
[false, new LoggerThatSetAnErrorHandler()], yield [$previousHandlerWasDefined, $loggerSetsAnotherHandler, $nextHandlerIsDefined];
[true, new LoggerThatSetAnErrorHandler()], }
]; }
}
} }
} }

View File

@ -0,0 +1,22 @@
<?php
namespace Symfony\Component\Debug\Tests\Fixtures;
class ErrorHandlerThatUsesThePreviousOne
{
private static $previous;
public static function register()
{
$handler = new static();
self::$previous = set_error_handler([$handler, 'handleError']);
return $handler;
}
public function handleError($type, $message, $file, $line, $context)
{
return \call_user_func(self::$previous, $type, $message, $file, $line, $context);
}
}

View File

@ -2,13 +2,14 @@
namespace Symfony\Component\Debug\Tests\Fixtures; namespace Symfony\Component\Debug\Tests\Fixtures;
use Psr\Log\AbstractLogger; use Symfony\Component\Debug\BufferingLogger;
class LoggerThatSetAnErrorHandler extends AbstractLogger class LoggerThatSetAnErrorHandler extends BufferingLogger
{ {
public function log($level, $message, array $context = []) public function log($level, $message, array $context = [])
{ {
set_error_handler('is_string'); set_error_handler('is_string');
parent::log($level, $message, $context);
restore_error_handler(); restore_error_handler();
} }
} }