I am writing a Mac app that runs as a daemon in the background. How can I detect when the app is killed and run some cleanup code? I have tried catching signals such as SIGTERM
, SIGINT
, and SIGKILL
, but my app structure seems to have some problems with this.
This is the basic flow of my application start from the main thread:
func signalHandler(signal: Int32) { ... }
let signals = [SIGINT, SIGTERM, SIGKILL]
for sig in signals {
signal(sig, signalHandler)
}
// code to kick off background execution that will occasionally need to run some stuff on the main thread
RunLoop.current.run() // SIGTERM shows up in Xcode on this line, signalHandler not called
If I stop the app using Xcode's stop button or force quit from the Activity Monitor, the app just exits with exit code 9 (SIGKILL
). If I choose "Quit" from the activity monitor, the app receives a SIGTERM
but the handler doesn't get called... Xcode just highlights the RunLoop
line and says Thread 1: signal SIGTERM
.
Without the RunLoop
line my application will stop almost immediately but I need to keep it alive. At the same time, I am thinking perhaps that line is blocking the main thread and preventing the signal handler from being run. Are there any ways around this so I can handle my app termination gracefully?