0

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?

sschilli
  • 2,021
  • 1
  • 13
  • 33

1 Answers1

3

A couple of notes:

  • SIGKILL cannot be caught.
  • if the debugger is attached, it will intercept the signal handlers instead of letting the flowing through the program; a workaround to this can be found here

Try printing the signal and launching the program from the command line


func signalHandler(signal: Int32) {
    print("Caught signal \(signal)")
}

Ctrl+C prints Caught signal 2

Terminating the process from Activity Monitor via Quit (not Force Quit) prints Caught signal 15

Cristik
  • 30,989
  • 25
  • 91
  • 127
  • Are you able to add more detail on how/why lldb interferes with the signal handlers? Is there a way to run with lldb still but have it not interfere? I'm hoping to write some unit tests for signal handling which would require lldb. – sschilli Oct 11 '19 at 19:17
  • @sschilli [this SO answer](https://stackoverflow.com/a/42639333/1974224) might give more insight. – Cristik Oct 15 '19 at 07:22