Skip to content

Commit c172572

Browse files
committed
[ErrorHandler] Forward \Throwable
1 parent d94c4b4 commit c172572

File tree

7 files changed

+95
-47
lines changed

7 files changed

+95
-47
lines changed

src/Symfony/Bundle/FrameworkBundle/Console/Application.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,8 @@ protected function registerCommands()
174174
if ($bundle instanceof Bundle) {
175175
try {
176176
$bundle->registerCommands($this);
177-
} catch (\Exception $e) {
178-
$this->registrationErrors[] = $e;
179177
} catch (\Throwable $e) {
180-
$this->registrationErrors[] = new FatalThrowableError($e);
178+
$this->registrationErrors[] = $e;
181179
}
182180
}
183181
}
@@ -192,10 +190,8 @@ protected function registerCommands()
192190
if (!isset($lazyCommandIds[$id])) {
193191
try {
194192
$this->add($container->get($id));
195-
} catch (\Exception $e) {
196-
$this->registrationErrors[] = $e;
197193
} catch (\Throwable $e) {
198-
$this->registrationErrors[] = new FatalThrowableError($e);
194+
$this->registrationErrors[] = $e;
199195
}
200196
}
201197
}
@@ -211,6 +207,10 @@ private function renderRegistrationErrors(InputInterface $input, OutputInterface
211207
(new SymfonyStyle($input, $output))->warning('Some commands could not be registered:');
212208

213209
foreach ($this->registrationErrors as $error) {
210+
if (!$error instanceof \Exception) {
211+
$error = new FatalThrowableError($error);
212+
}
213+
214214
$this->doRenderException($error, $output);
215215
}
216216
}

src/Symfony/Component/Console/Application.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ public function run(InputInterface $input = null, OutputInterface $output = null
127127
$output = new ConsoleOutput();
128128
}
129129

130-
$renderException = function ($e) use ($output) {
130+
$renderException = function (\Throwable $e) use ($output) {
131131
if (!$e instanceof \Exception) {
132132
$e = class_exists(FatalThrowableError::class) ? new FatalThrowableError($e) : (class_exists(LegacyFatalThrowableError::class) ? new LegacyFatalThrowableError($e) : new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()));
133133
}

src/Symfony/Component/ErrorHandler/ErrorHandler.php

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
use Psr\Log\LoggerInterface;
1515
use Psr\Log\LogLevel;
1616
use Symfony\Component\ErrorHandler\Exception\FatalErrorException;
17-
use Symfony\Component\ErrorHandler\Exception\FatalThrowableError;
1817
use Symfony\Component\ErrorHandler\Exception\OutOfMemoryException;
1918
use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext;
2019
use Symfony\Component\ErrorHandler\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
@@ -236,7 +235,7 @@ public function setLoggers(array $loggers): array
236235

237236
if ($flush) {
238237
foreach ($this->bootstrappingLogger->cleanLogs() as $log) {
239-
$type = $log[2]['exception'] instanceof \ErrorException ? $log[2]['exception']->getSeverity() : E_ERROR;
238+
$type = $log[2]['exception'] instanceof \ErrorException ? $log[2]['exception']->getSeverity() : ThrowableUtils::getSeverity($log[2]['exception']);
240239
if (!isset($flush[$type])) {
241240
$this->bootstrappingLogger->log($log[0], $log[1], $log[2]);
242241
} elseif ($this->loggers[$type][0]) {
@@ -251,7 +250,8 @@ public function setLoggers(array $loggers): array
251250
/**
252251
* Sets a user exception handler.
253252
*
254-
* @param callable|null $handler A handler that will be called on Exception
253+
* @param callable|null $handler a handler that will be called on Exception
254+
* It must support \Throwable instances
255255
*
256256
* @return callable|null The previous exception handler
257257
*/
@@ -510,57 +510,65 @@ public function handleError(int $type, string $message, string $file, int $line)
510510
/**
511511
* Handles an exception by logging then forwarding it to another handler.
512512
*
513-
* @param \Exception|\Throwable $exception An exception to handle
514-
* @param array $error An array as returned by error_get_last()
513+
* @param \Throwable $exception An exception to handle
514+
* @param array $error An array as returned by error_get_last()
515515
*
516516
* @internal
517517
*/
518-
public function handleException($exception, array $error = null)
518+
public function handleException(\Throwable $exception, array $error = null)
519519
{
520520
if (null === $error) {
521521
self::$exitCode = 255;
522522
}
523-
if (!$exception instanceof \Exception) {
524-
$exception = new FatalThrowableError($exception);
525-
}
526-
$type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR;
523+
524+
$type = $exception instanceof FatalErrorException ? $exception->getSeverity() : ThrowableUtils::getSeverity($exception);
527525
$handlerException = null;
528526

529-
if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
527+
if (($this->loggedErrors & $type) || $exception instanceof \Error) {
530528
if (false !== strpos($message = $exception->getMessage(), "class@anonymous\0")) {
531529
$message = $this->parseAnonymousClass($message);
532530
}
531+
533532
if ($exception instanceof FatalErrorException) {
534-
if ($exception instanceof FatalThrowableError) {
535-
$error = [
536-
'type' => $type,
537-
'message' => $message,
538-
'file' => $exception->getFile(),
539-
'line' => $exception->getLine(),
540-
];
541-
} else {
542-
$message = 'Fatal '.$message;
543-
}
533+
$message = 'Fatal '.$message;
544534
} elseif ($exception instanceof \ErrorException) {
545535
$message = 'Uncaught '.$message;
536+
} elseif ($exception instanceof \Error) {
537+
$error = [
538+
'type' => $type,
539+
'message' => $message,
540+
'file' => $exception->getFile(),
541+
'line' => $exception->getLine(),
542+
];
543+
$message = 'Uncaught Error: '.$message;
546544
} else {
547545
$message = 'Uncaught Exception: '.$message;
548546
}
549547
}
548+
550549
if ($this->loggedErrors & $type) {
551550
try {
552551
$this->loggers[$type][0]->log($this->loggers[$type][1], $message, ['exception' => $exception]);
553552
} catch (\Throwable $handlerException) {
554553
}
555554
}
555+
556+
// temporary until fatal error handlers rework
557+
$originalException = $exception;
558+
if (!$exception instanceof \Exception) {
559+
$exception = new FatalErrorException($exception->getMessage(), $exception->getCode(), $type, $exception->getFile(), $exception->getLine(), null, true, $exception->getTrace());
560+
}
561+
556562
if ($exception instanceof FatalErrorException && !$exception instanceof OutOfMemoryException && $error) {
557563
foreach ($this->getFatalErrorHandlers() as $handler) {
558564
if ($e = $handler->handleError($error, $exception)) {
559-
$exception = $e;
565+
$convertedException = $e;
560566
break;
561567
}
562568
}
563569
}
570+
571+
$exception = $convertedException ?? $originalException;
564572
$exceptionHandler = $this->exceptionHandler;
565573
$this->exceptionHandler = null;
566574
try {

src/Symfony/Component/ErrorHandler/Exception/FatalThrowableError.php

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\ErrorHandler\Exception;
1313

14+
use Symfony\Component\ErrorHandler\ThrowableUtils;
15+
1416
/**
1517
* Fatal Throwable Error.
1618
*
@@ -24,18 +26,10 @@ public function __construct(\Throwable $e)
2426
{
2527
$this->originalClassName = \get_class($e);
2628

27-
if ($e instanceof \ParseError) {
28-
$severity = E_PARSE;
29-
} elseif ($e instanceof \TypeError) {
30-
$severity = E_RECOVERABLE_ERROR;
31-
} else {
32-
$severity = E_ERROR;
33-
}
34-
3529
\ErrorException::__construct(
3630
$e->getMessage(),
3731
$e->getCode(),
38-
$severity,
32+
ThrowableUtils::getSeverity($e),
3933
$e->getFile(),
4034
$e->getLine(),
4135
$e->getPrevious()

src/Symfony/Component/ErrorHandler/Tests/ErrorHandlerTest.php

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -327,18 +327,19 @@ public function testHandleDeprecation()
327327
restore_error_handler();
328328
}
329329

330-
public function testHandleException()
330+
/**
331+
* @dataProvider handleExceptionProvider
332+
*/
333+
public function testHandleExceptiossssn(string $expectedMessage, \Throwable $exception)
331334
{
332335
try {
333336
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
334337
$handler = ErrorHandler::register();
335338

336-
$exception = new \Exception('foo');
337-
338-
$logArgCheck = function ($level, $message, $context) {
339-
$this->assertSame('Uncaught Exception: foo', $message);
339+
$logArgCheck = function ($level, $message, $context) use ($expectedMessage, $exception) {
340+
$this->assertSame($expectedMessage, $message);
340341
$this->assertArrayHasKey('exception', $context);
341-
$this->assertInstanceOf(\Exception::class, $context['exception']);
342+
$this->assertInstanceOf(\get_class($exception), $context['exception']);
342343
};
343344

344345
$logger
@@ -352,7 +353,7 @@ public function testHandleException()
352353
try {
353354
$handler->handleException($exception);
354355
$this->fail('Exception expected');
355-
} catch (\Exception $e) {
356+
} catch (\Throwable $e) {
356357
$this->assertSame($exception, $e);
357358
}
358359

@@ -367,6 +368,15 @@ public function testHandleException()
367368
}
368369
}
369370

371+
public function handleExceptionProvider(): array
372+
{
373+
return [
374+
['Uncaught Exception: foo', new \Exception('foo')],
375+
['Uncaught Error: bar', new \Error('bar')],
376+
['Uncaught ccc', new \ErrorException('ccc')],
377+
];
378+
}
379+
370380
public function testBootstrappingLogger()
371381
{
372382
$bootLogger = new BufferingLogger();
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\ErrorHandler;
13+
14+
/**
15+
* @internal
16+
*/
17+
class ThrowableUtils
18+
{
19+
public static function getSeverity(\Throwable $throwable): int
20+
{
21+
if ($throwable instanceof \ParseError) {
22+
return E_PARSE;
23+
} elseif ($throwable instanceof \TypeError) {
24+
return E_RECOVERABLE_ERROR;
25+
}
26+
27+
return E_ERROR;
28+
}
29+
}

src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Component\Console\Event\ConsoleEvent;
1717
use Symfony\Component\Console\Output\ConsoleOutputInterface;
1818
use Symfony\Component\ErrorHandler\ErrorHandler;
19+
use Symfony\Component\ErrorHandler\Exception\FatalThrowableError;
1920
use Symfony\Component\ErrorRenderer\ErrorRenderer;
2021
use Symfony\Component\ErrorRenderer\ErrorRenderer\HtmlErrorRenderer;
2122
use Symfony\Component\ErrorRenderer\Exception\ErrorRendererNotFoundException;
@@ -50,7 +51,8 @@ class DebugHandlersListener implements EventSubscriberInterface
5051
private $hasTerminatedWithException;
5152

5253
/**
53-
* @param callable|null $exceptionHandler A handler that will be called on Exception
54+
* @param callable|null $exceptionHandler a handler that will be called on Exception
55+
* It must support \Throwable instances
5456
* @param LoggerInterface|null $logger A PSR-3 logger
5557
* @param array|int $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants
5658
* @param int|null $throwAt Thrown errors in a bit field of E_* constants, or null to keep the current value
@@ -117,10 +119,15 @@ public function configure(Event $event = null)
117119
if (method_exists($kernel = $event->getKernel(), 'terminateWithException')) {
118120
$request = $event->getRequest();
119121
$hasRun = &$this->hasTerminatedWithException;
120-
$this->exceptionHandler = static function (\Exception $e) use ($kernel, $request, &$hasRun) {
122+
$this->exceptionHandler = static function (\Throwable $e) use ($kernel, $request, &$hasRun) {
121123
if ($hasRun) {
122124
throw $e;
123125
}
126+
127+
if (!$e instanceof \Exception) {
128+
$e = new FatalThrowableError($e);
129+
}
130+
124131
$hasRun = true;
125132
$kernel->terminateWithException($e, $request);
126133
};

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy