【问题标题】:Swift on macOS: Running code on termination of background appmacOS 上的 Swift:在后台应用程序终止时运行代码
【发布时间】:2020-02-03 00:39:31
【问题描述】:

我正在编写一个在后台作为守护进程运行的 Mac 应用程序。如何检测应用程序何时被终止并运行一些清理代码?我尝试过捕获SIGTERMSIGINTSIGKILL 等信号,但我的应用程序结构似乎存在一些问题。

这是我的应用程序从主线程开始的基本流程:

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 行,我的应用程序几乎会立即停止,但我需要让它保持活动状态。同时,我在想那条线可能阻塞了主线程并阻止了信号处理程序的运行。有什么方法可以解决这个问题,以便我可以优雅地处理我的应用程序终止?

【问题讨论】:

    标签: swift macos kill-process sigint sigterm


    【解决方案1】:

    几点说明:

    • SIGKILLcannot be caught.
    • 如果附加了调试器,它将拦截信号处理程序,而不是让信号流经程序;可以找到解决方法here

    尝试打印信号并从命令行启动程序

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

    Ctrl+C 打印Caught signal 2

    通过Quit(不是Force Quit)从活动监视器终止进程会打印Caught signal 15

    【讨论】:

    • 您能否添加更多关于 lldb 如何/为何干扰信号处理程序的详细信息?有没有办法运行 lldb 但它不会干扰?我希望为需要 lldb 的信号处理编写一些单元测试。
    • @sschilli this SO answer 可能会提供更多见解。
    猜你喜欢
    • 2018-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-26
    • 1970-01-01
    • 2012-05-21
    • 1970-01-01
    相关资源
    最近更新 更多