Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 54bd905

Browse files
author
Robin Chalas
committed
bug #28545 [Console] Send the right exit code to console.terminate listeners (mpdude)
This PR was squashed before being merged into the 2.8 branch (closes #28545). Discussion ---------- [Console] Send the right exit code to console.terminate listeners | Q | A | ------------- | --- | Branch? | 2.8 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | | License | MIT | Doc PR | When a Console command throws an exception without a status code, `Application::run()` takes care of setting the exit code to `1` when the exception does not provide a code itself. This happens slightly too late, as `console.terminate` event listeners that are called from within `Application::doRunCommand()` are given the plain exeception code, before this conversion. The result is that `console.*` event listeners that you might be using to log exit code e. g. for cron jobs will see a `0` code instead of the real value used to terminate the script. ***Todo:*** - [x] Make sure we've got tests covering this, i. e. do not mock out `doRunCommand()`. Commits ------- b90a3f1 [Console] Send the right exit code to console.terminate listeners
2 parents 57a3413 + b90a3f1 commit 54bd905

File tree

2 files changed

+75
-10
lines changed

2 files changed

+75
-10
lines changed

src/Symfony/Component/Console/Application.php

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,7 @@ public function run(InputInterface $input = null, OutputInterface $output = null
129129
$this->renderException($e, $output);
130130
}
131131

132-
$exitCode = $e->getCode();
133-
if (is_numeric($exitCode)) {
134-
$exitCode = (int) $exitCode;
135-
if (0 === $exitCode) {
136-
$exitCode = 1;
137-
}
138-
} else {
139-
$exitCode = 1;
140-
}
132+
$exitCode = $this->getExitCodeForThrowable($e);
141133
}
142134

143135
if ($this->autoExit) {
@@ -873,7 +865,8 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI
873865
if ($x !== $event->getException()) {
874866
$e = $event->getException();
875867
}
876-
$exitCode = $e->getCode();
868+
869+
$exitCode = $this->getExitCodeForThrowable($e);
877870
}
878871

879872
$event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
@@ -1148,4 +1141,26 @@ private function init()
11481141
$this->add($command);
11491142
}
11501143
}
1144+
1145+
/**
1146+
* Type hint omitted to be PHP5 compatible.
1147+
*
1148+
* @param \Exception|\Throwable $throwable
1149+
*
1150+
* @return int
1151+
*/
1152+
private function getExitCodeForThrowable($throwable)
1153+
{
1154+
$exitCode = $throwable->getCode();
1155+
if (is_numeric($exitCode)) {
1156+
$exitCode = (int) $exitCode;
1157+
if (0 === $exitCode) {
1158+
$exitCode = 1;
1159+
}
1160+
} else {
1161+
$exitCode = 1;
1162+
}
1163+
1164+
return $exitCode;
1165+
}
11511166
}

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

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,31 @@ public function testRunReturnsIntegerExitCode()
774774
$this->assertSame(4, $exitCode, '->run() returns integer exit code extracted from raised exception');
775775
}
776776

777+
public function testRunDispatchesIntegerExitCode()
778+
{
779+
$passedRightValue = false;
780+
781+
// We can assume here that some other test asserts that the event is dispatched at all
782+
$dispatcher = new EventDispatcher();
783+
$self = $this;
784+
$dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use ($self, &$passedRightValue) {
785+
$passedRightValue = (4 === $event->getExitCode());
786+
});
787+
788+
$application = new Application();
789+
$application->setDispatcher($dispatcher);
790+
$application->setAutoExit(false);
791+
792+
$application->register('test')->setCode(function (InputInterface $input, OutputInterface $output) {
793+
throw new \Exception('', 4);
794+
});
795+
796+
$tester = new ApplicationTester($application);
797+
$tester->run(array('command' => 'test'));
798+
799+
$this->assertTrue($passedRightValue, '-> exit code 4 was passed in the console.terminate event');
800+
}
801+
777802
public function testRunReturnsExitCodeOneForExceptionCodeZero()
778803
{
779804
$exception = new \Exception('', 0);
@@ -789,6 +814,31 @@ public function testRunReturnsExitCodeOneForExceptionCodeZero()
789814
$this->assertSame(1, $exitCode, '->run() returns exit code 1 when exception code is 0');
790815
}
791816

817+
public function testRunDispatchesExitCodeOneForExceptionCodeZero()
818+
{
819+
$passedRightValue = false;
820+
821+
// We can assume here that some other test asserts that the event is dispatched at all
822+
$dispatcher = new EventDispatcher();
823+
$self = $this;
824+
$dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use ($self, &$passedRightValue) {
825+
$passedRightValue = (1 === $event->getExitCode());
826+
});
827+
828+
$application = new Application();
829+
$application->setDispatcher($dispatcher);
830+
$application->setAutoExit(false);
831+
832+
$application->register('test')->setCode(function (InputInterface $input, OutputInterface $output) {
833+
throw new \Exception();
834+
});
835+
836+
$tester = new ApplicationTester($application);
837+
$tester->run(array('command' => 'test'));
838+
839+
$this->assertTrue($passedRightValue, '-> exit code 1 was passed in the console.terminate event');
840+
}
841+
792842
/**
793843
* @expectedException \LogicException
794844
* @expectedExceptionMessage An option with shortcut "e" already exists.

0 commit comments

Comments
 (0)