From a4ddcc298d152bd3293163ea600fa59999f019a6 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 18 Jan 2018 09:54:17 +0100 Subject: [PATCH] [HttpKernel] DebugHandlersListener should always replace the existing exception handler --- .travis.yml | 2 +- .../Debug/Tests/ErrorHandlerTest.php | 9 ++++ .../Tests/phpt/decorate_exception_hander.phpt | 47 +++++++++++++++++++ .../phpt/fatal_with_nested_handlers.phpt | 2 +- .../EventListener/DebugHandlersListener.php | 10 ++-- .../DebugHandlersListenerTest.php | 24 +++++++++- 6 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 src/Symfony/Component/Debug/Tests/phpt/decorate_exception_hander.phpt diff --git a/.travis.yml b/.travis.yml index e34ba5a8bc..2a3e945695 100644 --- a/.travis.yml +++ b/.travis.yml @@ -181,7 +181,7 @@ install: elif [[ $deps = low ]]; then echo "$COMPONENTS" | parallel --gnu -j10% "tfold {} 'cd {} && $COMPOSER_UP --prefer-lowest --prefer-stable && $PHPUNIT_X'" elif [[ $PHP = hhvm* ]]; then - $PHPUNIT --exclude-group benchmark,intl-data + $PHPUNIT --exclude-group no-hhvm,benchmark,intl-data else echo "$COMPONENTS" | parallel --gnu "tfold {} $PHPUNIT_X {}" tfold tty-group $PHPUNIT --group tty diff --git a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php index fd9ac577ee..264dc701e7 100644 --- a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php +++ b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php @@ -293,6 +293,9 @@ class ErrorHandlerTest extends TestCase @$handler->handleError(E_USER_DEPRECATED, 'Foo deprecation', __FILE__, __LINE__, array()); } + /** + * @group no-hhvm + */ public function testHandleException() { try { @@ -375,6 +378,9 @@ class ErrorHandlerTest extends TestCase } } + /** + * @group no-hhvm + */ public function testHandleFatalError() { try { @@ -434,6 +440,9 @@ class ErrorHandlerTest extends TestCase $this->assertStringStartsWith("Attempted to load class \"Foo\" from the global namespace.\nDid you forget a \"use\" statement", $args[0]->getMessage()); } + /** + * @group no-hhvm + */ public function testHandleFatalErrorOnHHVM() { try { diff --git a/src/Symfony/Component/Debug/Tests/phpt/decorate_exception_hander.phpt b/src/Symfony/Component/Debug/Tests/phpt/decorate_exception_hander.phpt new file mode 100644 index 0000000000..7ce7b9dc6f --- /dev/null +++ b/src/Symfony/Component/Debug/Tests/phpt/decorate_exception_hander.phpt @@ -0,0 +1,47 @@ +--TEST-- +Test catching fatal errors when handlers are nested +--FILE-- + +--EXPECTF-- +Fatal error: Class 'Symfony\Component\Debug\missing' not found in %s on line %d +object(Symfony\Component\Debug\Exception\ClassNotFoundException)#%d (8) { + ["message":protected]=> + string(131) "Attempted to load class "missing" from namespace "Symfony\Component\Debug". +Did you forget a "use" statement for another namespace?" + ["string":"Exception":private]=> + string(0) "" + ["code":protected]=> + int(0) + ["file":protected]=> + string(%d) "%s" + ["line":protected]=> + int(%d) + ["trace":"Exception":private]=> + array(0) { + } + ["previous":"Exception":private]=> + NULL + ["severity":protected]=> + int(1) +} diff --git a/src/Symfony/Component/Debug/Tests/phpt/fatal_with_nested_handlers.phpt b/src/Symfony/Component/Debug/Tests/phpt/fatal_with_nested_handlers.phpt index 6a17648a2a..897be3eb64 100644 --- a/src/Symfony/Component/Debug/Tests/phpt/fatal_with_nested_handlers.phpt +++ b/src/Symfony/Component/Debug/Tests/phpt/fatal_with_nested_handlers.phpt @@ -35,7 +35,7 @@ array(1) { [0]=> string(37) "Error and exception handlers do match" } -object(Symfony\Component\Debug\Exception\FatalErrorException)#4 (8) { +object(Symfony\Component\Debug\Exception\FatalErrorException)#%d (8) { ["message":protected]=> string(199) "Error: Class Symfony\Component\Debug\Broken contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (Serializable::serialize, Serializable::unserialize)" %a diff --git a/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php b/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php index 0bcef55df9..b560e24d72 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php @@ -117,9 +117,13 @@ class DebugHandlersListener implements EventSubscriberInterface } if ($this->exceptionHandler) { if ($handler instanceof ErrorHandler) { - $h = $handler->setExceptionHandler('var_dump') ?: $this->exceptionHandler; - $handler->setExceptionHandler($h); - $handler = is_array($h) ? $h[0] : null; + $h = $handler->setExceptionHandler('var_dump'); + if (is_array($h) && $h[0] instanceof ExceptionHandler) { + $handler->setExceptionHandler($h); + $handler = $h[0]; + } else { + $handler->setExceptionHandler($this->exceptionHandler); + } } if ($handler instanceof ExceptionHandler) { $handler->setHandler($this->exceptionHandler); diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/DebugHandlersListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/DebugHandlersListenerTest.php index d1349906bb..467b8dde88 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/DebugHandlersListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/DebugHandlersListenerTest.php @@ -29,8 +29,6 @@ use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; /** - * DebugHandlersListenerTest. - * * @author Nicolas Grekas */ class DebugHandlersListenerTest extends TestCase @@ -132,4 +130,26 @@ class DebugHandlersListenerTest extends TestCase $xHandler(new \Exception()); } + + public function testReplaceExistingExceptionHandler() + { + $userHandler = function () {}; + $listener = new DebugHandlersListener($userHandler); + $eHandler = new ErrorHandler(); + $eHandler->setExceptionHandler('var_dump'); + + $exception = null; + set_exception_handler(array($eHandler, 'handleException')); + try { + $listener->configure(); + } catch (\Exception $exception) { + } + restore_exception_handler(); + + if (null !== $exception) { + throw $exception; + } + + $this->assertSame($userHandler, $eHandler->setExceptionHandler('var_dump')); + } }