Skip to content

Navigation Menu

Sign in
Appearance settings

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 81f48b8

Browse filesBrowse files
committed
bug #22435 [Console] Fix dispatching throwables from ConsoleEvents::COMMAND (nicolas-grekas)
This PR was merged into the 2.7 branch. Discussion ---------- [Console] Fix dispatching throwables from ConsoleEvents::COMMAND | Q | A | ------------- | --- | Branch? | 2.7 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - Exceptions thrown by `ConsoleEvents::COMMAND` listeners should be trigger `ConsoleEvents::EXCEPTION` events. (best reviewed [ignoring whitespaces](https://github.com/symfony/symfony/pull/22435/files?w=1)) Commits ------- 6d6b04a [Console] Fix dispatching throwables from ConsoleEvents::COMMAND
2 parents 93b7530 + 6d6b04a commit 81f48b8
Copy full SHA for 81f48b8

File tree

2 files changed

+85
-64
lines changed
Filter options

2 files changed

+85
-64
lines changed

‎src/Symfony/Component/Console/Application.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Application.php
+32-30Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,17 @@ public function run(InputInterface $input = null, OutputInterface $output = null
119119
$this->configureIO($input, $output);
120120

121121
try {
122+
$e = null;
122123
$exitCode = $this->doRun($input, $output);
123-
} catch (\Exception $e) {
124+
} catch (\Exception $x) {
125+
$e = $x;
126+
} catch (\Throwable $x) {
127+
$e = new FatalThrowableError($x);
128+
}
129+
130+
if (null !== $e) {
124131
if (!$this->catchExceptions) {
125-
throw $e;
132+
throw $x;
126133
}
127134

128135
if ($output instanceof ConsoleOutputInterface) {
@@ -184,6 +191,7 @@ public function doRun(InputInterface $input, OutputInterface $output)
184191
$input = new ArrayInput(array('command' => $this->defaultCommand));
185192
}
186193

194+
$this->runningCommand = null;
187195
// the command name MUST be the first element of the input
188196
$command = $this->find($name);
189197

@@ -841,47 +849,41 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI
841849
}
842850

843851
if (null === $this->dispatcher) {
844-
try {
845-
return $command->run($input, $output);
846-
} catch (\Exception $e) {
847-
throw $e;
848-
} catch (\Throwable $e) {
849-
throw new FatalThrowableError($e);
850-
}
852+
return $command->run($input, $output);
851853
}
852854

853855
$event = new ConsoleCommandEvent($command, $input, $output);
854-
$this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
856+
$e = null;
857+
858+
try {
859+
$this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
855860

856-
if ($event->commandShouldRun()) {
857-
try {
858-
$e = null;
861+
if ($event->commandShouldRun()) {
859862
$exitCode = $command->run($input, $output);
860-
} catch (\Exception $x) {
861-
$e = $x;
862-
} catch (\Throwable $x) {
863-
$e = new FatalThrowableError($x);
863+
} else {
864+
$exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
864865
}
865-
if (null !== $e) {
866-
$event = new ConsoleExceptionEvent($command, $input, $output, $e, $e->getCode());
867-
$this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
868-
869-
if ($e !== $event->getException()) {
870-
$x = $e = $event->getException();
871-
}
872-
873-
$event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode());
874-
$this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
866+
} catch (\Exception $e) {
867+
} catch (\Throwable $e) {
868+
}
869+
if (null !== $e) {
870+
$x = $e instanceof \Exception ? $e : new FatalThrowableError($e);
871+
$event = new ConsoleExceptionEvent($command, $input, $output, $x, $x->getCode());
872+
$this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
875873

876-
throw $x;
874+
if ($x !== $event->getException()) {
875+
$e = $event->getException();
877876
}
878-
} else {
879-
$exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
877+
$exitCode = $e->getCode();
880878
}
881879

882880
$event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
883881
$this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
884882

883+
if (null !== $e) {
884+
throw $e;
885+
}
886+
885887
return $event->getExitCode();
886888
}
887889

‎src/Symfony/Component/Console/Tests/ApplicationTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Tests/ApplicationTest.php
+53-34Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -977,15 +977,28 @@ public function testRunDispatchesAllEventsWithException()
977977
$this->assertContains('before.foo.caught.after.', $tester->getDisplay());
978978
}
979979

980-
public function testRunWithError()
980+
public function testRunDispatchesAllEventsWithExceptionInListener()
981981
{
982-
if (method_exists($this, 'expectException')) {
983-
$this->expectException('Exception');
984-
$this->expectExceptionMessage('dymerr');
985-
} else {
986-
$this->setExpectedException('Exception', 'dymerr');
987-
}
982+
$dispatcher = $this->getDispatcher();
983+
$dispatcher->addListener('console.command', function () {
984+
throw new \RuntimeException('foo');
985+
});
988986

987+
$application = new Application();
988+
$application->setDispatcher($dispatcher);
989+
$application->setAutoExit(false);
990+
991+
$application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
992+
$output->write('foo.');
993+
});
994+
995+
$tester = new ApplicationTester($application);
996+
$tester->run(array('command' => 'foo'));
997+
$this->assertContains('before.caught.after.', $tester->getDisplay());
998+
}
999+
1000+
public function testRunWithError()
1001+
{
9891002
$application = new Application();
9901003
$application->setAutoExit(false);
9911004
$application->setCatchExceptions(false);
@@ -997,7 +1010,13 @@ public function testRunWithError()
9971010
});
9981011

9991012
$tester = new ApplicationTester($application);
1000-
$tester->run(array('command' => 'dym'));
1013+
1014+
try {
1015+
$tester->run(array('command' => 'dym'));
1016+
$this->fail('Error expected.');
1017+
} catch (\Error $e) {
1018+
$this->assertSame('dymerr', $e->getMessage());
1019+
}
10011020
}
10021021

10031022
/**
@@ -1087,32 +1106,6 @@ public function testTerminalDimensions()
10871106
$this->assertSame(array($width, 80), $application->getTerminalDimensions());
10881107
}
10891108

1090-
protected function getDispatcher($skipCommand = false)
1091-
{
1092-
$dispatcher = new EventDispatcher();
1093-
$dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use ($skipCommand) {
1094-
$event->getOutput()->write('before.');
1095-
1096-
if ($skipCommand) {
1097-
$event->disableCommand();
1098-
}
1099-
});
1100-
$dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use ($skipCommand) {
1101-
$event->getOutput()->writeln('after.');
1102-
1103-
if (!$skipCommand) {
1104-
$event->setExitCode(113);
1105-
}
1106-
});
1107-
$dispatcher->addListener('console.exception', function (ConsoleExceptionEvent $event) {
1108-
$event->getOutput()->write('caught.');
1109-
1110-
$event->setException(new \LogicException('caught.', $event->getExitCode(), $event->getException()));
1111-
});
1112-
1113-
return $dispatcher;
1114-
}
1115-
11161109
public function testSetRunCustomDefaultCommand()
11171110
{
11181111
$command = new \FooCommand();
@@ -1151,6 +1144,32 @@ public function testCanCheckIfTerminalIsInteractive()
11511144
$inputStream = $application->getHelperSet()->get('question')->getInputStream();
11521145
$this->assertEquals($tester->getInput()->isInteractive(), @posix_isatty($inputStream));
11531146
}
1147+
1148+
protected function getDispatcher($skipCommand = false)
1149+
{
1150+
$dispatcher = new EventDispatcher();
1151+
$dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use ($skipCommand) {
1152+
$event->getOutput()->write('before.');
1153+
1154+
if ($skipCommand) {
1155+
$event->disableCommand();
1156+
}
1157+
});
1158+
$dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use ($skipCommand) {
1159+
$event->getOutput()->writeln('after.');
1160+
1161+
if (!$skipCommand) {
1162+
$event->setExitCode(ConsoleCommandEvent::RETURN_CODE_DISABLED);
1163+
}
1164+
});
1165+
$dispatcher->addListener('console.exception', function (ConsoleExceptionEvent $event) {
1166+
$event->getOutput()->write('caught.');
1167+
1168+
$event->setException(new \LogicException('caught.', $event->getExitCode(), $event->getException()));
1169+
});
1170+
1171+
return $dispatcher;
1172+
}
11541173
}
11551174

11561175
class CustomApplication extends Application

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.