Skip to content

Commit cb4b9ee

Browse files
[Console][DI] Fail gracefully
1 parent b9fb27c commit cb4b9ee

File tree

6 files changed

+40
-22
lines changed

6 files changed

+40
-22
lines changed

src/Symfony/Component/Console/Application.php

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
4141
use Symfony\Component\Console\Exception\CommandNotFoundException;
4242
use Symfony\Component\Console\Exception\LogicException;
43+
use Symfony\Component\Debug\ErrorHandler;
4344
use Symfony\Component\Debug\Exception\FatalThrowableError;
4445
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
4546

@@ -118,28 +119,39 @@ public function run(InputInterface $input = null, OutputInterface $output = null
118119
$output = new ConsoleOutput();
119120
}
120121

122+
$renderException = function ($e) use ($output) {
123+
if (!$e instanceof \Exception) {
124+
$e = class_exists(FatalThrowableError::class) ? new FatalThrowableError($e) : new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine());
125+
}
126+
if ($output instanceof ConsoleOutputInterface) {
127+
$this->renderException($e, $output->getErrorOutput());
128+
} else {
129+
$this->renderException($e, $output);
130+
}
131+
};
132+
if ($phpHandler = set_exception_handler($renderException)) {
133+
restore_exception_handler();
134+
if (!is_array($phpHandler) || !$phpHandler[0] instanceof ErrorHandler) {
135+
$debugHandler = true;
136+
} elseif ($debugHandler = $phpHandler[0]->setExceptionHandler($renderException)) {
137+
$phpHandler[0]->setExceptionHandler($debugHandler);
138+
}
139+
}
140+
121141
if (null !== $this->dispatcher && $this->dispatcher->hasListeners(ConsoleEvents::EXCEPTION)) {
122142
@trigger_error(sprintf('The "ConsoleEvents::EXCEPTION" event is deprecated since Symfony 3.3 and will be removed in 4.0. Listen to the "ConsoleEvents::ERROR" event instead.'), E_USER_DEPRECATED);
123143
}
124144

125145
$this->configureIO($input, $output);
126146

127147
try {
128-
$e = null;
129148
$exitCode = $this->doRun($input, $output);
130149
} catch (\Exception $e) {
131-
}
132-
133-
if (null !== $e) {
134150
if (!$this->catchExceptions) {
135151
throw $e;
136152
}
137153

138-
if ($output instanceof ConsoleOutputInterface) {
139-
$this->renderException($e, $output->getErrorOutput());
140-
} else {
141-
$this->renderException($e, $output);
142-
}
154+
$renderException($e);
143155

144156
$exitCode = $e->getCode();
145157
if (is_numeric($exitCode)) {
@@ -150,6 +162,12 @@ public function run(InputInterface $input = null, OutputInterface $output = null
150162
} else {
151163
$exitCode = 1;
152164
}
165+
} finally {
166+
if (!$phpHandler) {
167+
restore_exception_handler();
168+
} elseif (!$debugHandler) {
169+
$phpHandler[0]->setExceptionHandler(null);
170+
}
153171
}
154172

155173
if ($this->autoExit) {

src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -428,13 +428,13 @@ private function addServiceInclude($cId, Definition $definition, \SplObjectStora
428428
}
429429

430430
foreach (array_diff_key(array_flip($lineage), $this->inlinedRequires) as $file => $class) {
431-
$code .= sprintf(" require_once %s;\n", $file);
431+
$code .= sprintf(" include_once %s;\n", $file);
432432
}
433433
}
434434

435435
foreach ($inlinedDefinitions as $def) {
436436
if ($file = $def->getFile()) {
437-
$code .= sprintf(" require_once %s;\n", $this->dumpValue($file));
437+
$code .= sprintf(" include_once %s;\n", $this->dumpValue($file));
438438
}
439439
}
440440

@@ -1233,7 +1233,7 @@ private function addInlineRequires()
12331233
foreach ($lineage as $file) {
12341234
if (!isset($this->inlinedRequires[$file])) {
12351235
$this->inlinedRequires[$file] = true;
1236-
$code .= sprintf(" require_once %s;\n", $file);
1236+
$code .= sprintf(" include_once %s;\n", $file);
12371237
}
12381238
}
12391239

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ protected function getLazyContextIgnoreInvalidRefService()
297297
*/
298298
protected function getMethodCall1Service()
299299
{
300-
require_once '%path%foo.php';
300+
include_once '%path%foo.php';
301301

302302
$this->services['method_call1'] = $instance = new \Bar\FooClass();
303303

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
198198
// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
199199
// Returns the public 'method_call1' shared service.
200200

201-
require_once ($this->targetDirs[0].'/Fixtures/includes/foo.php');
201+
include_once ($this->targetDirs[0].'/Fixtures/includes/foo.php');
202202

203203
$this->services['method_call1'] = $instance = new \Bar\FooClass();
204204

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ protected function getLazyContextIgnoreInvalidRefService()
307307
*/
308308
protected function getMethodCall1Service()
309309
{
310-
require_once '%path%foo.php';
310+
include_once '%path%foo.php';
311311

312312
$this->services['method_call1'] = $instance = new \Bar\FooClass();
313313

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_inline_requires.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ public function __construct()
4646

4747
$this->aliases = array();
4848

49-
require_once $this->targetDirs[1].'/includes/HotPath/I1.php';
50-
require_once $this->targetDirs[1].'/includes/HotPath/P1.php';
51-
require_once $this->targetDirs[1].'/includes/HotPath/T1.php';
52-
require_once $this->targetDirs[1].'/includes/HotPath/C1.php';
49+
include_once $this->targetDirs[1].'/includes/HotPath/I1.php';
50+
include_once $this->targetDirs[1].'/includes/HotPath/P1.php';
51+
include_once $this->targetDirs[1].'/includes/HotPath/T1.php';
52+
include_once $this->targetDirs[1].'/includes/HotPath/C1.php';
5353
}
5454

5555
public function getRemovedIds()
@@ -104,8 +104,8 @@ protected function getC1Service()
104104
*/
105105
protected function getC2Service()
106106
{
107-
require_once $this->targetDirs[1].'/includes/HotPath/C2.php';
108-
require_once $this->targetDirs[1].'/includes/HotPath/C3.php';
107+
include_once $this->targetDirs[1].'/includes/HotPath/C2.php';
108+
include_once $this->targetDirs[1].'/includes/HotPath/C3.php';
109109

110110
return $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C2'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C2(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C3']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C3'] : $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C3'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C3()) && false ?: '_'});
111111
}
@@ -117,7 +117,7 @@ protected function getC2Service()
117117
*/
118118
protected function getC3Service()
119119
{
120-
require_once $this->targetDirs[1].'/includes/HotPath/C3.php';
120+
include_once $this->targetDirs[1].'/includes/HotPath/C3.php';
121121

122122
return $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C3'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C3();
123123
}

0 commit comments

Comments
 (0)