8000 [Console] Fix exit status on uncaught exception with negative code · SanderHagen/symfony@9942ff3 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9942ff3

Browse files
acoultonSanderHagen
authored andcommitted
[Console] Fix exit status on uncaught exception with negative code
As described in symfony#45850, if an application threw an exception with the `code` property set to a negative number this could in some cases cause the process to appear to exit 'successfully' with a zero exit status. Exiting with any negative number produces potentially unexpected results - the reported exit status will not appear to match the value that was set. This is due to the binary handling / truncation of exit codes. This may theoretically break BC for applications that were intentionally throwing exceptions with negative codes and performing some action based on that status. However, given they would have had to implement an algorithm to map e.g. `-10` in PHP to `246` as the actual exit status, it seems unlikely this is a common usage. It is certainly outside the defined behaviour of POSIX exit codes. Therefore I believe it is essentially safe to assume that exceptions with negative codes are e.g. being thrown by lower-level components, and are not intended to set a shell exit status. Coalescing all negative numbers to 1 matches the existing behaviour with other 'invalid' exception codes e.g. empty / zero / non-numeric. This therefore feels the most robust fix and eliminates any potential for confusion. Fixes symfony#45850
1 parent 45d0023 commit 9942ff3

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

src/Symfony/Component/Console/Application.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ public function run(InputInterface $input = null, OutputInterface $output = null
179179
$exitCode = $e->getCode();
180180
if (is_numeric($exitCode)) {
181181
$exitCode = (int) $exitCode;
182-
if (0 === $exitCode) {
182+
if ($exitCode <= 0) {
183183
$exitCode = 1;
184184
}
185185
} else {

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,6 +1172,25 @@ public function testRunDispatchesExitCodeOneForExceptionCodeZero()
11721172
$this->assertTrue($passedRightValue, '-> exit code 1 was passed in the console.terminate event');
11731173
}
11741174

1175+
/**
1176+
* @testWith [-1]
1177+
* [-32000]
1178+
*/
1179+
public function testRunReturnsExitCodeOneForNegativeExceptionCode($exceptionCode)
1180+
{
1181+
$exception = new \Exception('', $exceptionCode);
1182+
1183+
$application = $this->getMockBuilder(Application::class)->setMethods(['doRun'])->getMock();
1184+
$application->setAutoExit(false);
1185+
$application->expects($this->once())
1186+
->method('doRun')
1187+
->willThrowException($exception);
1188+
1189+
$exitCode = $application->run(new ArrayInput([]), new NullOutput());
1190+
1191+
$this->assertSame(1, $exitCode, '->run() returns exit code 1 when exception code is '.$exceptionCode);
1192+
}
1193+
11751194
public function testAddingOptionWithDuplicateShortcut()
11761195
{
11771196
$this->expectException(\LogicException::class);

0 commit comments

Comments
 (0)
0