Skip to content

Commit 29a4366

Browse files
authored
Merge pull request #2381 from gmittert/InterpretiveDancing
Interpret Process Exit Codes on Windows
2 parents 6aa1f7e + 6d3d01b commit 29a4366

File tree

1 file changed

+28
-5
lines changed

1 file changed

+28
-5
lines changed

Foundation/Process.swift

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -469,13 +469,36 @@ open class Process: NSObject {
469469

470470
WaitForSingleObject(process.processHandle, WinSDK.INFINITE)
471471

472+
// On Windows, the top nibble of an NTSTATUS indicates severity, with
473+
// the top two bits both being set (0b11) indicating an error. In
474+
// addition, in a well formed NTSTATUS, the 4th bit must be 0.
475+
// The third bit indicates if the error is a Microsoft defined error
476+
// and may or may not be set.
477+
//
478+
// If we receive such an error, we'll indicate that the process
479+
// exited abnormally (confusingly indicating "signalled" so we match
480+
// POSIX behaviour for abnormal exits).
481+
//
482+
// However, we don't want user programs which normally exit -1, -2,
483+
// etc to count as exited abnormally, so we specifically check for a
484+
// top nibble of 0b11_0 so that e.g. 0xFFFFFFFF, won't trigger an
485+
// abnormal exit.
486+
//
487+
// Additionally, on Windows, an uncaught signal terminates the
488+
// program with the magic exit code 3, regardless of the signal (I'd
489+
// personally love to know the reason for this). So we also consider
490+
// 3 to be an abnormal exit.
472491
var dwExitCode: DWORD = 0
473-
// FIXME(compnerd) how do we handle errors here?
474492
GetExitCodeProcess(process.processHandle, &dwExitCode)
475-
476-
// TODO(compnerd) check if the process terminated abnormally
477-
process._terminationStatus = Int32(dwExitCode)
478-
process._terminationReason = .exit
493+
if (dwExitCode & 0xF0000000) == 0xC0000000
494+
|| (dwExitCode & 0xF0000000) == 0xE0000000
495+
|| dwExitCode == 3 {
496+
process._terminationStatus = Int32(dwExitCode & 0x3FFFFFFF)
497+
process._terminationReason = .uncaughtSignal
498+
} else {
499+
process._terminationStatus = Int32(bitPattern: dwExitCode)
500+
process._terminationReason = .exit
501+
}
479502

480503
if let handler = process.terminationHandler {
481504
let thread: Thread = Thread { handler(process) }

0 commit comments

Comments
 (0)