Skip to content

Commit 4a40ff3

Browse files
[FrameworkBundle] enable ErrorHandler in prod
1 parent 4b6776e commit 4a40ff3

File tree

6 files changed

+132
-7
lines changed

6 files changed

+132
-7
lines changed

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,6 @@ public function load(array $configs, ContainerBuilder $container)
133133
if ($container->getParameter('kernel.debug')) {
134134
$loader->load('debug.xml');
135135

136-
$definition->replaceArgument(0, array(new Reference('http_kernel', ContainerInterface::NULL_ON_INVALID_REFERENCE), 'terminateWithException'));
137-
138136
$definition = $container->findDefinition('http_kernel');
139137
$definition->replaceArgument(2, new Reference('debug.controller_resolver'));
140138

@@ -145,11 +143,15 @@ public function load(array $configs, ContainerBuilder $container)
145143
$container->setAlias('event_dispatcher', 'debug.event_dispatcher');
146144
} else {
147145
$definition->replaceArgument(2, E_COMPILE_ERROR | E_PARSE | E_ERROR | E_CORE_ERROR);
146+
147+
$container->findDefinition('debug.error_handler')->addMethodCall('throwAt', array(0));
148148
}
149149

150150
$this->addClassesToCompile(array(
151151
'Symfony\\Component\\Config\\FileLocator',
152152

153+
'Symfony\\Component\\Debug\\ErrorHandler',
154+
153155
'Symfony\\Component\\EventDispatcher\\Event',
154156
'Symfony\\Component\\EventDispatcher\\ContainerAwareEventDispatcher',
155157

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

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
<parameters>
88
<parameter key="debug.debug_handlers_listener.class">Symfony\Component\HttpKernel\EventListener\DebugHandlersListener</parameter>
9+
<parameter key="debug.error_handler.class">Symfony\Component\Debug\ErrorHandler</parameter>
910
<parameter key="debug.stopwatch.class">Symfony\Component\Stopwatch\Stopwatch</parameter>
1011
</parameters>
1112

@@ -20,6 +21,8 @@
2021
<argument>null</argument><!-- %templating.helper.code.file_link_format% -->
2122
</service>
2223

24+
<service id="debug.error_handler" class="%debug.error_handler.class%" factory-class="%debug.error_handler.class%" factory-method="register" />
25+
2326
<service id="debug.stopwatch" class="%debug.stopwatch.class%" />
2427
</services>
2528
</container>

src/Symfony/Component/Debug/ErrorHandler.php

+8-2
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,15 @@ public static function register($levels = -1, $throw = true)
124124

125125
$handler = new static();
126126
$levels &= $handler->thrownErrors;
127-
set_error_handler(array($handler, 'handleError'), $levels);
127+
$prev = set_error_handler(array($handler, 'handleError'), $levels);
128+
$prev = is_array($prev) ? $prev[0] : null;
129+
if ($prev instanceof self) {
130+
restore_error_handler();
131+
$handler = $prev;
132+
} else {
133+
$handler->setExceptionHandler(set_exception_handler(array($handler, 'handleException')));
134+
}
128135
$handler->throwAt($throw ? $levels : 0, true);
129-
$handler->setExceptionHandler(set_exception_handler(array($handler, 'handleException')));
130136

131137
return $handler;
132138
}

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

+24
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,30 @@ public function tearDown()
4646
error_reporting($this->errorReporting);
4747
}
4848

49+
public function testRegister()
50+
{
51+
$handler = ErrorHandler::register();
52+
53+
try {
54+
$this->assertInstanceOf('Symfony\Component\Debug\ErrorHandler', $handler);
55+
56+
try {
57+
$this->assertSame($handler, ErrorHandler::register());
58+
} catch (\Exception $e) {
59+
restore_error_handler();
60+
restore_exception_handler();
61+
}
62+
} catch (\Exception $e) {
63+
}
64+
65+
restore_error_handler();
66+
restore_exception_handler();
67+
68+
if (isset($e)) {
69+
throw $e;
70+
}
71+
}
72+
4973
public function testNotice()
5074
{
5175
ErrorHandler::register();

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

+41-3
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,14 @@
1414
use Psr\Log\LoggerInterface;
1515
use Symfony\Component\Debug\ErrorHandler;
1616
use Symfony\Component\Debug\ExceptionHandler;
17+
use Symfony\Component\EventDispatcher\Event;
18+
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
1719
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
20+
use Symfony\Component\HttpKernel\Event\KernelEvent;
1821
use Symfony\Component\HttpKernel\KernelEvents;
22+
use Symfony\Component\Console\ConsoleEvents;
23+
use Symfony\Component\Console\Event\ConsoleEvent;
24+
use Symfony\Component\Console\Output\ConsoleOutputInterface;
1925

2026
/**
2127
* Configures errors and exceptions handlers.
@@ -28,6 +34,7 @@ class DebugHandlersListener implements EventSubscriberInterface
2834
private $logger;
2935
private $levels;
3036
private $debug;
37+
private $fileLinkFormat;
3138

3239
/**
3340
* @param callable $exceptionHandler A handler that will be called on Exception
@@ -45,8 +52,20 @@ public function __construct($exceptionHandler, LoggerInterface $logger = null, $
4552
$this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
4653
}
4754

48-
public function configure()
55+
/**
56+
* Configures the error handler.
57+
*
58+
* @param Event|null $event The triggering event
59+
* @param string|null $eventName The triggering event name
60+
* @param EventDispatcherInterface|null $eventDispatcher The dispatcher used to trigger $event
61+
*/
62+
public function configure(Event $event = null, $eventName = null, EventDispatcherInterface $eventDispatcher = null)
4963
{
64+
if (null !== $eventDispatcher) {
65+
foreach (array_keys(static::getSubscribedEvents()) as $name) {
66+
$eventDispatcher->removeListener($name, array($this, 'configure'));
67+
}
68+
}
5069
if ($this->logger) {
5170
$handler = set_error_handler('var_dump', 0);
5271
$handler = is_array($handler) ? $handler[0] : null;
@@ -65,7 +84,20 @@ public function configure()
6584
}
6685
$handler->screamAt($this->levels);
6786
}
68-
$this->logger = $this->levels = null;
87+
$this->logger = null;
88+
}
89+
if (!$this->exceptionHandler) {
90+
if ($event instanceof KernelEvent) {
91+
$this->exceptionHandler = array($event->getKernel(), 'terminateWithException');
92+
} elseif ($event instanceof ConsoleEvent && $app = $event->getCommand()->getApplication()) {
93+
$output = $event->getOutput();
94+
if ($output instanceof ConsoleOutputInterface) {
95+
$output = $output->getErrorOutput();
96+
}
97+
$this->exceptionHandler = function ($e) use ($app, $output) {
98+
$app->renderException($e, $output);
99+
};
100+
}
69101
}
70102
if ($this->exceptionHandler) {
71103
$handler = set_exception_handler('var_dump');
@@ -86,6 +118,12 @@ public function configure()
86118

87119
public static function getSubscribedEvents()
88120
{
89-
return array(KernelEvents::REQUEST => array('configure', 2048));
121+
$events = array(KernelEvents::REQUEST => array('configure', 2048));
122+
123+
if (defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) {
124+
$events[ConsoleEvents::COMMAND] = array('configure', 2048);
125+
}
126+
127+
return $events;
90128
}
91129
}

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

+52
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,17 @@
1212
namespace Symfony\Component\HttpKernel\Tests\EventListener;
1313

1414
use Psr\Log\LogLevel;
15+
use Symfony\Component\Console\Event\ConsoleEvent;
16+
use Symfony\Component\Console\Command\Command;
17+
use Symfony\Component\Console\ConsoleEvents;
18+
use Symfony\Component\Console\Helper\HelperSet;
19+
use Symfony\Component\Console\Input\ArgvInput;
20+
use Symfony\Component\Console\Output\ConsoleOutput;
1521
use Symfony\Component\Debug\ErrorHandler;
1622
use Symfony\Component\Debug\ExceptionHandler;
23+
use Symfony\Component\EventDispatcher\EventDispatcher;
1724
use Symfony\Component\HttpKernel\EventListener\DebugHandlersListener;
25+
use Symfony\Component\HttpKernel\KernelEvents;
1826

1927
/**
2028
* DebugHandlersListenerTest
@@ -53,4 +61,48 @@ public function testConfigure()
5361
$this->assertArrayHasKey(E_DEPRECATED, $loggers);
5462
$this->assertSame(array($logger, LogLevel::INFO), $loggers[E_DEPRECATED]);
5563
}
64+
65+
public function testConsoleEvent()
66+
{
67+
$dispatcher = new EventDispatcher();
68+
$listener = new DebugHandlersListener(null);
69+
$app = $this->getMock('Symfony\Component\Console\Application');
70+
$app->expects($this->once())->method('getHelperSet')->will($this->returnValue(new HelperSet()));
71+
$command = new Command(__FUNCTION__);
72+
$command->setApplication($app);
73+
$event = new ConsoleEvent($command, new ArgvInput(), new ConsoleOutput());
74+
75+
$dispatcher->addSubscriber($listener);
76+
77+
$xListeners = array(
78+
KernelEvents::REQUEST => array(array($listener, 'configure')),
79+
ConsoleEvents::COMMAND => array(array($listener, 'configure')),
80+
);
81+
$this->assertSame($xListeners, $dispatcher->getListeners());
82+
83+
$exception = null;
84+
$eHandler = new ErrorHandler();
85+
set_error_handler(array($eHandler, 'handleError'));
86+
set_exception_handler(array($eHandler, 'handleException'));
87+
try {
88+
$dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
89+
} catch (\Exception $exception) {
90+
}
91+
restore_exception_handler();
92+
restore_error_handler();
93+
94+
if (null !== $exception) {
95+
throw $exception;
96+
}
97+
98+
$this->assertSame(array(), $dispatcher->getListeners());
99+
100+
$xHandler = $eHandler->setExceptionHandler('var_dump');
101+
$this->assertInstanceOf('Closure', $xHandler);
102+
103+
$app->expects($this->once())
104+
->method('renderException');
105+
106+
$xHandler(new \Exception());
107+
}
56108
}

0 commit comments

Comments
 (0)