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? 
 
    