Swift на macOS: запуск кода при завершении фонового приложения - PullRequest
0 голосов
/ 04 октября 2019

Я пишу приложение для Mac, которое работает в качестве демона в фоновом режиме. Как я могу определить, когда приложение убито, и запустить код очистки? Я пытался перехватить сигналы, такие как SIGTERM, SIGINT и SIGKILL, но в структуре моего приложения, похоже, есть некоторые проблемы.

Это основной поток запуска моего приложения из основногонить:

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

Если я остановлю приложение, используя кнопку остановки Xcode или принудительно выйду из Монитора активности, приложение просто закроется с кодом выхода 9 (SIGKILL). Если я выберу «Выход» на мониторе активности, приложение получит SIGTERM, но обработчик не будет вызван ... Xcode просто выделяет строку RunLoop и говорит: Thread 1: signal SIGTERM.

Безстрока RunLoop мое приложение будет остановлено почти сразу, но мне нужно сохранить его. В то же время я думаю, что, возможно, эта строка блокирует основной поток и не позволяет запустить обработчик сигналов. Есть ли способы обойти это, чтобы я мог изящно обрабатывать завершение моего приложения?

1 Ответ

2 голосов
/ 04 октября 2019

Пара примечаний:

  • SIGKILL не может быть перехвачено .
  • , если отладчик подключен, он будет перехватывать обработчики сигналов вместопропуская программу;Обходной путь к этому можно найти здесь

Попробуйте распечатать сигнал и запустить программу из командной строки


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

Ctrl + C отпечатки Caught signal 2

Завершение процесса из Activity Monitor с помощью Quit (не Force Quit) отпечатков Caught signal 15

...