import CodexBarCoreimport Dispatchimport Foundation#if canImport(Darwin)import Darwin#elseif canImport(Glibc)import Glibc#elseif canImport(Musl)import Musl#endif private func handleCLITerminationSignal(_: Int32) {} final class CLITerminationSignalMonitor: @unchecked Sendable { static let signalNumbers = [SIGINT, SIGTERM, SIGHUP] private let lock = NSLock() private let sources: [DispatchSourceSignal] private var isCancelled = false init(onSignal: @escaping @Sendable (Int32) -> Void) { self.sources = Self.signalNumbers.map { signalNumber in Self.installCaptureHandler(for: signalNumber) let source = DispatchSource.makeSignalSource(signal: signalNumber, queue: .global(qos: .utility)) source.setEventHandler { onSignal(signalNumber) } source.resume() return source } } func cancel() { self.lock.lock() guard !self.isCancelled else { self.lock.unlock() return } self.isCancelled = true self.lock.unlock() for source in self.sources { source.cancel() } for signalNumber in Self.signalNumbers { Self.restoreDefaultHandler(for: signalNumber) } } deinit { self.cancel() } static func terminateActiveHelpersAndReraise(_ signalNumber: Int32) { TTYCommandRunner.terminateActiveProcessesForAppShutdown() self.restoreDefaultHandler(for: signalNumber) _ = kill(getpid(), signalNumber) } private static func installCaptureHandler(for signalNumber: Int32) { #if canImport(Darwin) _ = Darwin.signal(signalNumber, handleCLITerminationSignal) #elseif canImport(Glibc) _ = Glibc.signal(signalNumber, handleCLITerminationSignal) #elseif canImport(Musl) _ = Musl.signal(signalNumber, handleCLITerminationSignal) #endif } private static func restoreDefaultHandler(for signalNumber: Int32) { #if canImport(Darwin) _ = Darwin.signal(signalNumber, SIG_DFL) #elseif canImport(Glibc) _ = Glibc.signal(signalNumber, SIG_DFL) #elseif canImport(Musl) _ = Musl.signal(signalNumber, SIG_DFL) #endif }}
import CodexBarCore
import Dispatch
import Foundation
#if canImport(Darwin)
import Darwin
#elseif canImport(Glibc)
import Glibc
#elseif canImport(Musl)
import Musl
#endif
private func handleCLITerminationSignal(_: Int32) {}
final class CLITerminationSignalMonitor: @unchecked Sendable {
static let signalNumbers = [SIGINT, SIGTERM, SIGHUP]
private let lock = NSLock()
private let sources: [DispatchSourceSignal]
private var isCancelled = false
init(onSignal: @escaping @Sendable (Int32) -> Void) {
self.sources = Self.signalNumbers.map { signalNumber in
Self.installCaptureHandler(for: signalNumber)
let source = DispatchSource.makeSignalSource(signal: signalNumber, queue: .global(qos: .utility))
source.setEventHandler {
onSignal(signalNumber)
}
source.resume()
return source
}
}
func cancel() {
self.lock.lock()
guard !self.isCancelled else {
self.lock.unlock()
return
}
self.isCancelled = true
self.lock.unlock()
for source in self.sources {
source.cancel()
}
for signalNumber in Self.signalNumbers {
Self.restoreDefaultHandler(for: signalNumber)
}
}
deinit {
self.cancel()
}
static func terminateActiveHelpersAndReraise(_ signalNumber: Int32) {
TTYCommandRunner.terminateActiveProcessesForAppShutdown()
self.restoreDefaultHandler(for: signalNumber)
_ = kill(getpid(), signalNumber)
}
private static func installCaptureHandler(for signalNumber: Int32) {
#if canImport(Darwin)
_ = Darwin.signal(signalNumber, handleCLITerminationSignal)
#elseif canImport(Glibc)
_ = Glibc.signal(signalNumber, handleCLITerminationSignal)
#elseif canImport(Musl)
_ = Musl.signal(signalNumber, handleCLITerminationSignal)
#endif
}
private static func restoreDefaultHandler(for signalNumber: Int32) {
#if canImport(Darwin)
_ = Darwin.signal(signalNumber, SIG_DFL)
#elseif canImport(Glibc)
_ = Glibc.signal(signalNumber, SIG_DFL)
#elseif canImport(Musl)
_ = Musl.signal(signalNumber, SIG_DFL)
#endif
}
}