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 上无限期挂起。为什么这会有所不同?
DispatchSource
是 class, 即 引用类型。 在您的第二个示例中,调度源存储在函数的 局部变量 中。一旦函数 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()
使用
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 上无限期挂起。为什么这会有所不同?
DispatchSource
是 class, 即 引用类型。 在您的第二个示例中,调度源存储在函数的 局部变量 中。一旦函数 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()