-
Notifications
You must be signed in to change notification settings - Fork 130
Expand file tree
/
Copy pathProcess+Helpers.swift
More file actions
63 lines (55 loc) · 1.67 KB
/
Process+Helpers.swift
File metadata and controls
63 lines (55 loc) · 1.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import Foundation
extension Process {
/// Launches the process and suspends until the receiver is finished.
///
/// - Parameter onCancel: The action to take if the current
/// task is cancelled.
public func runUntilExit(onCancel: TaskCancelAction = .interrupt) async throws {
try Task.checkCancellation()
let (terminationStream, terminationContinuation) = AsyncStream<Never>.makeStream()
terminationHandler = { _ in
terminationContinuation.finish()
}
do {
try run()
} catch {
terminationContinuation.finish()
throw error
}
await withTaskCancellationHandler {
for await _ in terminationStream {}
} onCancel: {
switch onCancel {
case .interrupt:
interrupt()
case .terminate:
terminate()
case .ignore:
break
}
}
try Task.checkCancellation()
switch terminationReason {
case .exit where terminationStatus == 0:
break
case .exit:
throw Failure.exit(terminationStatus)
case .uncaughtSignal:
throw Failure.uncaughtSignal(terminationStatus)
@unknown default:
break
}
}
public enum Failure: Error {
case exit(CInt)
case uncaughtSignal(CInt)
}
public enum TaskCancelAction: Sendable {
/// Sends `SIGINT` to the process.
case interrupt
/// Sends `SIGTERM` to the process.
case terminate
/// Don't participate in cooperative cancellation.
case ignore
}
}