Using this answer as a reference, I am trying to implement a signal handler in my swift linux script that will keep the program alive until a Ctrl-C and then run some cleanup when the SIGINT is received. Using the code from that answer works just fine in the main function:
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()
However, if I try to move the signal handler into a function, like so:
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()
The program hangs indefinitely on CTRL-C SIGINT. Why is this behaving differently?
DispatchSource
is a class, i.e. a reference type. In your second example the dispatch source is stored in a local variable of the function. As soon as the function returns, no reference exists to the dispatch source, so that it is canceled and deallocated.
You need to store the dispatch source somewhere where it lives as long as the program runs, e.g. in a global variable:
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()