-
Notifications
You must be signed in to change notification settings - Fork 89
Description
I have a stats library which I'd like to have the option of printing its stats on ^C. So I wrote something like this:
pub fn report_on_interrupt() {
let mut signals = Signals::new(&[SIGINT]).unwrap();
thread::Builder::new()
.name("SIGINT helper".to_string())
.spawn(move || {
for _ in signals.forever() {
dump_stat_reports();
let _ = signal_hook::low_level::emulate_default_handler(SIGINT);
std::process::exit(255); // just in case
}
})
.unwrap();
}This works nicely - if you interrupt the program with ^C, a report gets printed, and the program exists as if ^C were pressed (the shell reports an exit status of 130).
But this approach will clobber someone else who installs a SIGINT hook - my cleanup code just executes the default action, where I'd like it to remember the previously installed action and execute that. So I wrote something like this:
pub fn report_on_interrupt() {
// safety: we don't install a useful action, we call this for side effect of getting the previous action
let orig_action = unsafe {
signal_hook::low_level::register(SIGINT, || ()).unwrap()
};
let mut signals = Signals::new(&[SIGINT]).unwrap();
thread::Builder::new()
.name("SIGINT helper".to_string())
.spawn(move || {
for _ in signals.forever() {
dump_stat_reports();
signal_hook::low_level::unregister(orig_action);
let _ = signal_hook::low_level::raise(SIGINT);
std::process::exit(255); // just in case
}
})
.unwrap();
}Of course, the above doesn't work, It always exits with 255 - first, because unregister doesn't restore the previous action, it just removes the dummy one we've installed. And second because unregister docs explicitly specify that it will never restore the default terminating action.
Is it possible to implement the behavior I'd like using signal_hook?