The Problem
When building an executable CLI product using swift package, especially ones with long running tasks, users can exit the script at anytime by sending exit code to the process, for example, by tapping CTL+C
or execute killall
command.
Sometimes the CLI needs to trap such signals to do cleanup works. For Example, if the CLI is writing data continuously into a file, it might need to close the file properly on exit so that the file will not be corrupted.
The Solution
Using signal
Swift Foundation provides a native signal
API to trigger a signal handler whenever a specific signal code is raised by the system.
@main
struct ScreenCaptureCLI {
static func main() async throws {
let screenRecorder = ScreenRecorder()
signal(SIGINT) { code in
print("Code: \(code)")
screenRecorder.stop()
exit(code)
}
await screenRecorder.start()
}
}
Using BlueSignals package
BlueSignals package provides covenient APIs to trap and handle platform signals by wrapping platform-specific APIs.
import Signals
...
let server: SomeServer = ...
Signals.trap(signal: .int) { signal in
server.shutdownServer()
}
server.run()