Swift GCD:为什么信号处理程序在函数中不起作用

Swift GCD: Why signal handler doesn't work in function

使用 答案作为参考,我正在尝试在我的 swift linux 脚本中实现一个信号处理程序,它将使程序保持活动状态直到 Ctrl-C 然后运行 收到 SIGINT 时进行一些清理。使用该答案中的代码在主函数中工作得很好:

import Dispatch
import Foundation

signal(SIGINT, SIG_IGN) // // Make sure the signal does not terminate the application.

let sigintSrc = DispatchSource.makeSignalSource(signal: SIGINT, queue: .main)
sigintSrc.setEventHandler {
    print("Got SIGINT")
    // ...
    exit(0)
}
sigintSrc.resume()
dispatchMain()

但是,如果我尝试将信号处理程序移动到一个函数中,就像这样:

public func registerSigint() {
    signal(SIGINT, SIG_IGN)
    let sigintSrc = DispatchSource.makeSignalSource(signal: SIGINT, queue: .main)
    sigintSrc.setEventHandler {
        print("Got SIGINT")
        exit(0)
    }
    sigintSrc.resume()
}

...

registerSigint()
dispatchMain()

程序在 CTRL-C SIGINT 上无限期挂起。为什么这会有所不同?

DispatchSourceclass, 引用类型。 在您的第二个示例中,调度源存储在函数的 局部变量 中。一旦函数 returns,不存在对调度源的引用,因此它被取消和释放。

您需要将调度源存储在程序运行时它所在的某个地方,例如在全局变量中:

public func registerSigint() -> DispatchSourceSignal {
    signal(SIGINT, SIG_IGN)
    let sigintSrc = DispatchSource.makeSignalSource(signal: SIGINT, queue: .main)
    sigintSrc.setEventHandler {
        print("Got SIGINT")
        exit(0)
    }
    sigintSrc.resume()
    return sigintSrc
}

let source = registerSigint()
dispatchMain()