8000 bug #31868 [HttpKernel] Fix handling non-catchable fatal errors (nico… · symfony/symfony@a80483c · GitHub
[go: up one dir, main page]

Skip to content

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a80483c

Browse files
committed
bug #31868 [HttpKernel] Fix handling non-catchable fatal errors (nicolas-grekas)
This PR was merged into the 4.2 branch. Discussion ---------- [HttpKernel] Fix handling non-catchable fatal errors | Q | A | ------------- | --- | Branch? | 4.3 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - This reverts PR #27519 this commit 18c2dde, reversing changes made to ac1189a. Right now, the listener is skipped on fatal errors. Commits ------- a1619cc [HttpKernel] Fix handling non-catchable fatal errors
2 parents 846f721 + a1619cc commit a80483c

File tree

7 files changed

+37
-63
lines changed

7 files changed

+37
-63
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -721,9 +721,6 @@ private function registerDebugConfiguration(array $config, ContainerBuilder $con
721721
$container->setParameter('debug.error_handler.throw_at', 0);
722722
}
723723

724-
$definition->replaceArgument(4, $debug);
725-
$definition->replaceArgument(6, $debug);
726-
727724
if ($debug && class_exists(DebugProcessor::class)) {
728725
$definition = new Definition(DebugProcessor::class);
729726
$definition->setPublic(false);

src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@
1818
<argument type="service" id="logger" on-invalid="null" />
1919
<argument>null</argument><!-- Log levels map for enabled error levels -->
2020
<argument>%debug.error_handler.throw_at%</argument>
21-
<argument>true</argument>
21+
<argument>%kernel.debug%</argument>
2222
<argument type="service" id="debug.file_link_formatter"></argument>
23-
<argument>true</argument>
23+
<argument>%kernel.debug%</argument>
24+
<argument>%kernel.charset%</argument>
2425
</service>
2526

2627
<service id="debug.file_link_formatter" class="Symfony\Component\HttpKernel\Debug\FileLinkFormatter">

src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,16 +67,6 @@
6767
<argument type="service" id="router" on-invalid="ignore" />
6868
</service>
6969

70-
<service id="http_exception_listener" class="Symfony\Component\HttpKernel\EventListener\ExceptionListener">
71-
<tag name="kernel.event_listener" event="kernel.exception" method="onKernelException" priority="-2048" />
72-
<tag name="kernel.reset" method="reset" />
73-
<argument>null</argument>
74-
<argument>null</argument>
75-
<argument>%kernel.debug%</argument>
76-
<argument>%kernel.charset%</argument>
77-
<argument>%debug.file_link_format%</argument>
78-
</service>
79-
8070
<service id="validate_request_listener" class="Symfony\Component\HttpKernel\EventListener\ValidateRequestListener">
8171
<tag name="kernel.event_subscriber" />
8272
</service>

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

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@
1919
use Symfony\Component\Debug\ExceptionHandler;
2020
use Symfony\Component\EventDispatcher\Event;
2121
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
22+
use Symfony\Component\HttpFoundation\Request;
23+
use Symfony\Component\HttpFoundation\Response;
2224
use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
25+
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
2326
use Symfony\Component\HttpKernel\Event\KernelEvent;
2427
use Symfony\Component\HttpKernel\KernelEvents;
2528

@@ -37,6 +40,7 @@ class DebugHandlersListener implements EventSubscriberInterface
3740
private $scream;
3841
private $fileLinkFormat;
3942
private $scope;
43+
private $charset;
4044
private $firstCall = true;
4145
private $hasTerminatedWithException;
4246

@@ -49,7 +53,7 @@ class DebugHandlersListener implements EventSubscriberInterface
4953
* @param string|FileLinkFormatter|null $fileLinkFormat The format for links to source files
5054
* @param bool $scope Enables/disables scoping mode
5155
*/
52-
public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, $levels = E_ALL, ?int $throwAt = E_ALL, bool $scream = true, $fileLinkFormat = null, bool $scope = true)
56+
public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, $levels = E_ALL, ?int $throwAt = E_ALL, bool $scream = true, $fileLinkFormat = null, bool $scope = true, string $charset = null)
5357
{
5458
$this->exceptionHandler = $exceptionHandler;
5559
$this->logger = $logger;
@@ -58,6 +62,7 @@ public function __construct(callable $exceptionHandler = null, LoggerInterface $
5862
$this->scream = $scream;
5963
$this->fileLinkFormat = $fileLinkFormat;
6064
$this->scope = $scope;
65+
$this->charset = $charset;
6166
}
6267

6368
/**
@@ -144,6 +149,26 @@ public function configure(Event $event = null)
144149
}
145150
}
146151

152+
/**
153+
* @internal
154+
*/
155+
public function onKernelException(GetResponseForExceptionEvent $event)
156+
{
157+
if (!$this->hasTerminatedWithException || !$event->isMasterRequest()) {
158+
return;
159+
}
160+
161+
$debug = $this->scream && $this->scope;
162+
$controller = function (Request $request) use ($debug) {
163+
$e = $request->attributes->get('exception');
164+
$handler = new ExceptionHandler($debug, $this->charset, $this->fileLinkFormat);
165+
166+
return new Response($handler->getHtml($e), $e->getStatusCode(), $e->getHeaders());
167+
};
168+
169+
(new ExceptionListener($controller, $this->logger, $debug))->onKernelException($event);
170+
}
171+
147172
public static function getSubscribedEvents()
148173
{
149174
$events = [KernelEvents::REQUEST => ['configure', 2048]];
@@ -152,6 +177,8 @@ public static function getSubscribedEvents()
152177
$events[ConsoleEvents::COMMAND] = ['configure', 2048];
153178
}
154179

180+
$events[KernelEvents::EXCEPTION] = ['onKernelException', -2048];
181+
155182
return $events;
156183
}
157184
}

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

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,9 @@
1313

1414
use Psr\Log\LoggerInterface;
1515
use Symfony\Component\Debug\Exception\FlattenException;
16-
use Symfony\Component\Debug\ExceptionHandler;
1716
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
1817
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
1918
use Symfony\Component\HttpFoundation\Request;
20-
use Symfony\Component\HttpFoundation\Response;
2119
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
2220
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
2321
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
@@ -35,17 +33,12 @@ class ExceptionListener implements EventSubscriberInterface
3533
protected $controller;
3634
protected $logger;
3735
protected $debug;
38-
private $charset;
39-
private $fileLinkFormat;
40-
private $isTerminating = false;
4136

42-
public function __construct($controller, LoggerInterface $logger = null, $debug = false, string $charset = null, $fileLinkFormat = null)
37+
public function __construct($controller, LoggerInterface $logger = null, $debug = false)
4338
{
4439
$this->controller = $controller;
4540
$this->logger = $logger;
4641
$this->debug = $debug;
47-
$this->charset = $charset;
48-
$this->fileLinkFormat = $fileLinkFormat;
4942
}
5043

5144
public function logKernelException(GetResponseForExceptionEvent $event)
@@ -58,16 +51,9 @@ public function logKernelException(GetResponseForExceptionEvent $event)
5851
public function onKernelException(GetResponseForExceptionEvent $event)
5952
{
6053
if (null === $this->controller) {
61-
if (!$event->isMasterRequest()) {
62-
return;
63-
}
64-
if (!$this->isTerminating) {
65-
$this->isTerminating = true;
66-
67-
return;
68-
}
69-
$this->isTerminating = false;
54+
return;
7055
}
56+
7157
$exception = $event->getException();
7258
$request = $this->duplicateRequest($exception, $event->getRequest());
7359
$eventDispatcher = \func_num_args() > 2 ? func_get_arg(2) : null;
@@ -104,11 +90,6 @@ public function onKernelException(GetResponseForExceptionEvent $event)
10490
}
10591
}
10692

107-
public function reset()
108-
{
109-
$this->isTerminating = false;
110-
}
111-
11293
public static function getSubscribedEvents()
11394
{
11495
return [
@@ -147,12 +128,8 @@ protected function logException(\Exception $exception, $message)
147128
protected function duplicateRequest(\Exception $exception, Request $request)
148129
{
149130
$attributes = [
150-
'exception' => $exception = FlattenException::create($exception),
151-
'_controller' => $this->controller ?: function () use ($exception) {
152-
$handler = new ExceptionHandler($this->debug, $this->charset, $this->fileLinkFormat);
153-
154-
return new Response($handler->getHtml($exception), $exception->getStatusCode(), $exception->getHeaders());
155-
},
131+
'_controller' => $this->controller,
132+
'exception' => FlattenException::create($exception),
156133
'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null,
157134
];
158135
$request = $request->duplicate(null, null, $attributes);

src/Symfony/Component/HttpKernel/Tests/EventListener/DebugHandlersListenerTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ public function testConsoleEvent()
104104
$xListeners = [
105105
KernelEvents::REQUEST => [[$listener, 'configure']],
106106
ConsoleEvents::COMMAND => [[$listener, 'configure']],
107+
KernelEvents::EXCEPTION => [[$listener, 'onKernelException']],
107108
];
108109
$this->assertS 1241 ame($xListeners, $dispatcher->getListeners());
109110

src/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -155,25 +155,6 @@ public function testCSPHeaderIsRemoved()
155155
$this->assertFalse($response->headers->has('content-security-policy'), 'CSP header has been removed');
156156
$this->assertFalse($dispatcher->hasListeners(KernelEvents::RESPONSE), 'CSP removal listener has been removed');
157157
}
158-
159-
public function testNullController()
160-
{
161-
$listener = new ExceptionListener(null);
162-
$kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock();
163-
$kernel->expects($this->once())->method('handle')->willReturnCallback(function (Request $request) {
164-
$controller = $request->attributes->get('_controller');
165-
166-
return $controller();
167-
});
168-
$request = Request::create('/');
169-
$event = new GetResponseForExceptionEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, new \Exception('foo'));
170-
171-
$listener->onKernelException($event);
172-
$this->assertNull($event->getResponse());
173-
174-
$listener->onKernelException($event);
175-
$this->assertContains('Whoops, looks like something went wrong.', $event->getResponse()->getContent());
176-
}
177158
}
178159

179160
class TestLogger extends Logger implements DebugLoggerInterface

0 commit comments

Comments
 (0)
0