Files
wehub-resource-sync 680845cb1c
Linux build / Determine Swift version (push) Waiting to run
Linux build / Linux compile check (push) Blocked by required conditions
Build containerization / Verify commit signatures (push) Has been skipped
Build containerization / containerization (push) Successful in 0s
chore: import upstream snapshot with attribution
2026-07-13 12:25:30 +08:00

303 lines
9.5 KiB
Swift

//===----------------------------------------------------------------------===//
// Copyright © 2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//
#if canImport(Darwin)
import Darwin
#elseif canImport(Glibc)
import Glibc
#elseif canImport(Musl)
import Musl
#else
#error("Signal not supported on this platform.")
#endif
/// A unix signal.
public struct Signal: RawRepresentable, Hashable, Sendable {
public let rawValue: Int32
public init(rawValue: Int32) {
self.rawValue = rawValue
}
/// Parse a signal from a string representation (e.g. "SIGKILL", "KILL", "9").
public init(_ name: String, from map: [String: Int32] = Signal.linux) throws {
var signalUpper = name.uppercased()
signalUpper.trimPrefix("SIG")
if let sig = Int32(signalUpper) {
if !map.values.contains(sig) {
throw SignalError.invalidSignal(name)
}
self.rawValue = sig
return
}
guard let sig = map[signalUpper] else {
throw SignalError.invalidSignal(name)
}
self.rawValue = sig
}
// Signals that are commonly sent to containers and share the same
// number across macOS/Linux.
public static let hup = Signal(rawValue: 1)
public static let int = Signal(rawValue: 2)
public static let quit = Signal(rawValue: 3)
public static let kill = Signal(rawValue: 9)
public static let term = Signal(rawValue: 15)
public static let winch = Signal(rawValue: 28)
/// Linux signals.
public enum Linux {
public static let hup = Signal(rawValue: 1)
public static let int = Signal(rawValue: 2)
public static let quit = Signal(rawValue: 3)
public static let ill = Signal(rawValue: 4)
public static let trap = Signal(rawValue: 5)
public static let abrt = Signal(rawValue: 6)
public static let bus = Signal(rawValue: 7)
public static let fpe = Signal(rawValue: 8)
public static let kill = Signal(rawValue: 9)
public static let usr1 = Signal(rawValue: 10)
public static let segv = Signal(rawValue: 11)
public static let usr2 = Signal(rawValue: 12)
public static let pipe = Signal(rawValue: 13)
public static let alrm = Signal(rawValue: 14)
public static let term = Signal(rawValue: 15)
public static let stkflt = Signal(rawValue: 16)
public static let chld = Signal(rawValue: 17)
public static let cont = Signal(rawValue: 18)
public static let stop = Signal(rawValue: 19)
public static let tstp = Signal(rawValue: 20)
public static let ttin = Signal(rawValue: 21)
public static let ttou = Signal(rawValue: 22)
public static let urg = Signal(rawValue: 23)
public static let xcpu = Signal(rawValue: 24)
public static let xfsz = Signal(rawValue: 25)
public static let vtalrm = Signal(rawValue: 26)
public static let prof = Signal(rawValue: 27)
public static let winch = Signal(rawValue: 28)
public static let io = Signal(rawValue: 29)
public static let poll = Signal(rawValue: 29)
public static let pwr = Signal(rawValue: 30)
public static let sys = Signal(rawValue: 31)
public static func rtmin(offset: Int32 = 0) -> Signal {
Signal(rawValue: 34 + offset)
}
public static let rtmax = Signal(rawValue: 64)
}
/// Darwin signals.
public enum Darwin {
public static let hup = Signal(rawValue: 1)
public static let int = Signal(rawValue: 2)
public static let quit = Signal(rawValue: 3)
public static let ill = Signal(rawValue: 4)
public static let trap = Signal(rawValue: 5)
public static let abrt = Signal(rawValue: 6)
public static let emt = Signal(rawValue: 7)
public static let fpe = Signal(rawValue: 8)
public static let kill = Signal(rawValue: 9)
public static let bus = Signal(rawValue: 10)
public static let segv = Signal(rawValue: 11)
public static let sys = Signal(rawValue: 12)
public static let pipe = Signal(rawValue: 13)
public static let alrm = Signal(rawValue: 14)
public static let term = Signal(rawValue: 15)
public static let urg = Signal(rawValue: 16)
public static let stop = Signal(rawValue: 17)
public static let tstp = Signal(rawValue: 18)
public static let cont = Signal(rawValue: 19)
public static let chld = Signal(rawValue: 20)
public static let ttin = Signal(rawValue: 21)
public static let ttou = Signal(rawValue: 22)
public static let io = Signal(rawValue: 23)
public static let xcpu = Signal(rawValue: 24)
public static let xfsz = Signal(rawValue: 25)
public static let vtalrm = Signal(rawValue: 26)
public static let prof = Signal(rawValue: 27)
public static let winch = Signal(rawValue: 28)
public static let info = Signal(rawValue: 29)
public static let usr1 = Signal(rawValue: 30)
public static let usr2 = Signal(rawValue: 31)
}
/// All Linux signals including real-time signals (RTMIN through RTMAX).
public static let linux: [String: Int32] = [
"ABRT": 6,
"ALRM": 14,
"BUS": 7,
"CHLD": 17,
"CLD": 17,
"CONT": 18,
"FPE": 8,
"HUP": 1,
"ILL": 4,
"INT": 2,
"IO": 29,
"IOT": 6,
"KILL": 9,
"PIPE": 13,
"POLL": 29,
"PROF": 27,
"PWR": 30,
"QUIT": 3,
"SEGV": 11,
"STKFLT": 16,
"STOP": 19,
"SYS": 31,
"TERM": 15,
"TRAP": 5,
"TSTP": 20,
"TTIN": 21,
"TTOU": 22,
"URG": 23,
"USR1": 10,
"USR2": 12,
"VTALRM": 26,
"WINCH": 28,
"XCPU": 24,
"XFSZ": 25,
"RTMIN": 34,
"RTMIN+1": 35,
"RTMIN+2": 36,
"RTMIN+3": 37,
"RTMIN+4": 38,
"RTMIN+5": 39,
"RTMIN+6": 40,
"RTMIN+7": 41,
"RTMIN+8": 42,
"RTMIN+9": 43,
"RTMIN+10": 44,
"RTMIN+11": 45,
"RTMIN+12": 46,
"RTMIN+13": 47,
"RTMIN+14": 48,
"RTMIN+15": 49,
"RTMIN+16": 50,
"RTMIN+17": 51,
"RTMIN+18": 52,
"RTMIN+19": 53,
"RTMIN+20": 54,
"RTMIN+21": 55,
"RTMIN+22": 56,
"RTMIN+23": 57,
"RTMIN+24": 58,
"RTMIN+25": 59,
"RTMIN+26": 60,
"RTMIN+27": 61,
"RTMIN+28": 62,
"RTMIN+29": 63,
"RTMAX": 64,
]
}
#if os(macOS)
extension Signal {
/// All signals for the macOS host.
public static let platform: [String: Int32] = [
"ABRT": SIGABRT,
"ALRM": SIGALRM,
"BUS": SIGBUS,
"CHLD": SIGCHLD,
"CONT": SIGCONT,
"EMT": SIGEMT,
"FPE": SIGFPE,
"HUP": SIGHUP,
"ILL": SIGILL,
"INFO": SIGINFO,
"INT": SIGINT,
"IO": SIGIO,
"IOT": SIGIOT,
"KILL": SIGKILL,
"PIPE": SIGPIPE,
"PROF": SIGPROF,
"QUIT": SIGQUIT,
"SEGV": SIGSEGV,
"STOP": SIGSTOP,
"SYS": SIGSYS,
"TERM": SIGTERM,
"TRAP": SIGTRAP,
"TSTP": SIGTSTP,
"TTIN": SIGTTIN,
"TTOU": SIGTTOU,
"URG": SIGURG,
"USR1": SIGUSR1,
"USR2": SIGUSR2,
"VTALRM": SIGVTALRM,
"WINCH": SIGWINCH,
"XCPU": SIGXCPU,
"XFSZ": SIGXFSZ,
]
}
#elseif os(Linux)
extension Signal {
/// All signals for the Linux host.
public static let platform = linux
}
#endif
extension Signal {
private static let platformToName: [Int32: String] =
Dictionary(Signal.platform.map { ($0.value, $0.key) }, uniquingKeysWith: { first, _ in first })
/// Returns the canonical name for this signal on the current platform.
public func platformName() -> String? {
Self.platformName(self.rawValue)
}
/// Returns the canonical name for a signal number on the current platform.
public static func platformName(_ signal: Int32) -> String? {
platformToName[signal]
}
}
#if os(macOS)
extension Signal {
/// Converts a macOS signal to the equivalent Linux signal.
public func linuxSignal() -> Signal? {
guard let name = Self.platformToName[self.rawValue],
let linuxNumber = Signal.linux[name]
else {
return nil
}
return Signal(rawValue: linuxNumber)
}
}
#endif
extension Signal: ExpressibleByIntegerLiteral {
public init(integerLiteral value: Int32) {
self.rawValue = value
}
}
/// Errors that can be encountered for converting signals.
public enum SignalError: Error, CustomStringConvertible {
case invalidSignal(String)
public var description: String {
switch self {
case .invalidSignal(let sig):
return "invalid signal: \(sig)"
}
}
}