Files
xtool-mirror/Sources/PackLib/Process+Helpers.swift
2024-12-31 17:39:57 +05:30

64 lines
1.7 KiB
Swift

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
}
}