MacApp (использующий Swift) не завершает запущенный подпроцесс, если завершен - PullRequest
1 голос
/ 13 марта 2020

У меня есть очень простое приложение MacOS Swift, которое используется в качестве средства запуска для предоставления значка дока. Приложение запускает основной скрипт. Но если приложение завершается (например, нажав на него и выбрав «Закрыть» в контекстном меню), подпроцесс со сценарием продолжает выполняться.

Как изменить это поведение, чтобы убить дочерний процесс, если приложение убит. Используя pgrep я проверил, и скрипт выполняется в подпроцессе:

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    @IBOutlet weak var window: NSWindow!

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        print("App started!\n");

        DispatchQueue.global(qos: .background).async {

            let process = Process()
            process.executableURL = URL(fileURLWithPath:"/usr/local/bin/node")
            process.arguments = ["./build/index.js"]
            process.currentDirectoryPath = "/Users/myaccount/basedir"
            process.terminationHandler = { (process) in
            print("didFinish")
            }
            do {
            try process.run()
            } catch {}

        }

    }

    func applicationWillTerminate(_ aNotification: Notification) {
        print("I'll never show up\n")
    }

}

1 Ответ

0 голосов
/ 15 марта 2020

До сих пор я нашел два возможных решения, также с помощью комментариев к моему вопросу:

1.) "Правильный путь" - с помощью приложения завершить обратный вызов

Объект Process можно сделать глобальным / экземпляром, чтобы убить его в обратном вызове applicationWillTerminate. Но я столкнулся с проблемой, что эта функция никогда не вызывается. С помощью этого вопроса на форуме я обнаружил, что вам нужно установить следующие два параметра в "NO" в Info.plist:

XCode Info.plist

Тогда все работает отлично.

2.) Пусть дочерний процесс наблюдает за родителем

Можно очень легко получить pid родителя (ProcessInfo().processIdentifier) передайте его в качестве параметра при запуске потомка и дайте ребенку посмотреть идентификатор родительского процесса - когда он больше не существует, ребенок может убить себя. Можно наблюдать за процессом, запустив kill -0 PID, что приведет к ошибке, если процесс не существует.

...