|
12 | 12 | internal import TestingInternals
|
13 | 13 |
|
14 | 14 | #if SWT_TARGET_OS_APPLE || os(Linux)
|
15 |
| -extension ExitCondition { |
16 |
| - /// Initialize an instance of this type from an instance of the POSIX |
17 |
| - /// `siginfo_t` type. |
18 |
| - /// |
19 |
| - /// - Parameters: |
20 |
| - /// - siginfo: The instance of `siginfo_t` to initialize from. |
21 |
| - /// |
22 |
| - /// - Throws: If `siginfo.si_code` does not equal either `CLD_EXITED`, |
23 |
| - /// `CLD_KILLED`, or `CLD_DUMPED` (i.e. it does not represent an exit |
24 |
| - /// condition.) |
25 |
| - fileprivate init(_ siginfo: siginfo_t) throws { |
26 |
| - switch siginfo.si_code { |
27 |
| - case .init(CLD_EXITED): |
28 |
| - self = .exitCode(siginfo.si_status) |
29 |
| - case .init(CLD_KILLED), .init(CLD_DUMPED): |
30 |
| - self = .signal(siginfo.si_status) |
31 |
| - default: |
32 |
| - throw SystemError(description: "Unexpected siginfo_t value. Please file a bug report at https://github.com/apple/swift-testing/issues/new and include this information: \(String(reflecting: siginfo))") |
| 15 | +/// Block the calling thread, wait for the target process to exit, and return |
| 16 | +/// a value describing the conditions under which it exited. |
| 17 | +/// |
| 18 | +/// - Parameters: |
| 19 | +/// - pid: The ID of the process to wait for. |
| 20 | +/// |
| 21 | +/// - Throws: If the exit status of the process with ID `pid` cannot be |
| 22 | +/// determined (i.e. it does not represent an exit condition.) |
| 23 | +fileprivate func _blockAndWait(for pid: pid_t) throws -> ExitCondition { |
| 24 | + // Get the exit status of the process or throw an error (other than EINTR.) |
| 25 | + while true { |
| 26 | + var siginfo = siginfo_t() |
| 27 | + if 0 == waitid(P_PID, id_t(pid), &siginfo, WEXITED) { |
| 28 | + switch siginfo.si_code { |
| 29 | + case .init(CLD_EXITED): |
| 30 | + return .exitCode(siginfo.si_status) |
| 31 | + case .init(CLD_KILLED), .init(CLD_DUMPED): |
| 32 | + return .signal(siginfo.si_status) |
| 33 | + default: |
| 34 | + throw SystemError(description: "Unexpected siginfo_t value. Please file a bug report at https://github.com/apple/swift-testing/issues/new and include this information: \(String(reflecting: siginfo))") |
| 35 | + } |
| 36 | + } else if case let errorCode = swt_errno(), errorCode != EINTR { |
| 37 | + throw CError(rawValue: errorCode) |
33 | 38 | }
|
34 | 39 | }
|
35 | 40 | }
|
@@ -64,9 +69,9 @@ private let _createWaitThreadImpl: Void = {
|
64 | 69 | // and pass the resulting exit condition back to the calling task. If
|
65 | 70 | // there is no continuation, then either it hasn't been stored yet or
|
66 | 71 | // this child process is not tracked by the waiter thread.
|
67 |
| - if let continuation, 0 == waitid(P_PID, id_t(pid), &siginfo, WEXITED) { |
| 72 | + if let continuation { |
68 | 73 | let result = Result {
|
69 |
| - try ExitCondition(siginfo) |
| 74 | + try _blockAndWait(for: pid) |
70 | 75 | }
|
71 | 76 | continuation.resume(with: result)
|
72 | 77 | }
|
@@ -145,15 +150,7 @@ func wait(for pid: pid_t) async throws -> ExitCondition {
|
145 | 150 | }
|
146 | 151 | withExtendedLifetime(source) {}
|
147 | 152 |
|
148 |
| - // Get the exit status of the process or throw an error (other than EINTR.) |
149 |
| - while true { |
150 |
| - var siginfo = siginfo_t() |
151 |
| - if 0 == waitid(P_PID, id_t(pid), &siginfo, WEXITED) { |
152 |
| - return try ExitCondition(siginfo) |
153 |
| - } else if case let errorCode = swt_errno(), errorCode != EINTR { |
154 |
| - throw CError(rawValue: errorCode) |
155 |
| - } |
156 |
| - } |
| 153 | + return try _blockAndWait(for: pid) |
157 | 154 | #else
|
158 | 155 | // Ensure the waiter thread is running.
|
159 | 156 | _createWaitThread()
|
|
0 commit comments