Skip to content

Commit 134af57

Browse files
authored
TSCBasic: properly track abnormal exits on Windows
The process handling did not properly account for abnormal process termination. Unlike Unix platforms, Windows does not have a concept of signals. However, a process may be terminated abnormally by means of an exception. The exception code is then transliterated into the exit code for the process. In most circumstances, the exit code for the process in such a case is either a `NTSTATUS` or `HRESULT`. Accordingly, the way to detect the exception is to check the severity code of the exception. The `HRESULT` and `NTSTATUS` codes are similarly structured: ~~~ 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |S|R|C|N|X|F A C I L I T Y |C O D E | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ S: Severity; If set, indicates a failure result. If clear, indicates a success result. R: Reserved; If N is clear, this bit MUST be set to 0. C: Customer; If set, indicates that this a customer defined error code. N: If set, indicates that the error code is a NTSTATUS value. X: Reserved; MBZ Facility: An indicator of the source of the error. Code: The remainder of the error code. ~~~ We would previously only check for the top nibble being 0xC or 0xE. However, a 0x8 value is also permissible and indicates a failure. Plumb this through as an abnormal exit with the specified exception code. (cherry picked from commit 4ec21b0)
1 parent 8e324ae commit 134af57

File tree

1 file changed

+17
-3
lines changed

1 file changed

+17
-3
lines changed

Sources/TSCBasic/Process.swift

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ public struct ProcessResult: CustomStringConvertible {
3434
public enum ExitStatus: Equatable {
3535
/// The process was terminated normally with a exit code.
3636
case terminated(code: Int32)
37-
#if !os(Windows)
37+
#if os(Windows)
38+
/// The process was terminated abnormally.
39+
case abnormal(exception: UInt32)
40+
#else
3841
/// The process was terminated due to a signal.
3942
case signalled(signal: Int32)
4043
#endif
@@ -64,12 +67,17 @@ public struct ProcessResult: CustomStringConvertible {
6467
arguments: [String],
6568
environment: [String: String],
6669
exitStatusCode: Int32,
70+
normal: Bool,
6771
output: Result<[UInt8], Swift.Error>,
6872
stderrOutput: Result<[UInt8], Swift.Error>
6973
) {
7074
let exitStatus: ExitStatus
7175
#if os(Windows)
72-
exitStatus = .terminated(code: exitStatusCode)
76+
if normal {
77+
exitStatus = .terminated(code: exitStatusCode)
78+
} else {
79+
exitStatus = .abnormal(exception: UInt32(exitStatusCode))
80+
}
7381
#else
7482
if WIFSIGNALED(exitStatusCode) {
7583
exitStatus = .signalled(signal: WTERMSIG(exitStatusCode))
@@ -726,6 +734,7 @@ public final class Process {
726734
let p = _process!
727735
p.waitUntilExit()
728736
let exitStatusCode = p.terminationStatus
737+
let normalExit = p.terminationReason == .exit
729738
#else
730739
var exitStatusCode: Int32 = 0
731740
var result = waitpid(processID, &exitStatusCode, 0)
@@ -735,13 +744,15 @@ public final class Process {
735744
if result == -1 {
736745
self.state = .failed(SystemError.waitpid(errno))
737746
}
747+
let normalExit = !WIFSIGNALED(result)
738748
#endif
739749

740750
// Construct the result.
741751
let executionResult = ProcessResult(
742752
arguments: arguments,
743753
environment: environment,
744754
exitStatusCode: exitStatusCode,
755+
normal: normalExit,
745756
output: stdoutResult,
746757
stderrOutput: stderrResult
747758
)
@@ -970,7 +981,10 @@ extension ProcessResult.Error: CustomStringConvertible {
970981
switch result.exitStatus {
971982
case .terminated(let code):
972983
stream <<< "terminated(\(code)): "
973-
#if !os(Windows)
984+
#if os(Windows)
985+
case .abnormal(let exception):
986+
stream <<< "abnormal(\(exception)): "
987+
#else
974988
case .signalled(let signal):
975989
stream <<< "signalled(\(signal)): "
976990
#endif

0 commit comments

Comments
 (0)