#![cfg(not(windows))]
use std::io::Error;
use std::ptr;
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use signal_hook::consts::signal::*;
use signal_hook::flag;
use signal_hook::low_level;
fn do_test<C: FnOnce()>(child: C) {
unsafe {
libc::alarm(10); match libc::fork() {
-1 => panic!("Fork failed: {}", Error::last_os_error()),
0 => {
child();
loop {
thread::sleep(Duration::from_secs(1));
}
}
pid => {
thread::sleep(Duration::from_millis(250));
libc::kill(pid, libc::SIGTERM);
thread::sleep(Duration::from_millis(50));
let terminated = libc::waitpid(pid, ptr::null_mut(), libc::WNOHANG);
assert_eq!(0, terminated, "Process {} terminated prematurely", pid);
libc::kill(pid, libc::SIGTERM);
let terminated = libc::waitpid(pid, ptr::null_mut(), 0);
assert_eq!(pid, terminated);
}
}
}
}
#[test]
fn cleanup_inside_signal() {
fn hook() {
unsafe { low_level::register(SIGTERM, || ()).unwrap() };
let shutdown_cond = Arc::new(AtomicBool::new(false));
flag::register_conditional_shutdown(SIGTERM, 0, Arc::clone(&shutdown_cond)).unwrap();
flag::register(SIGTERM, shutdown_cond).unwrap();
}
do_test(hook);
}
#[test]
fn cleanup_after_signal() {
fn hook() {
let mut signals = signal_hook::iterator::Signals::new(&[libc::SIGTERM]).unwrap();
assert_eq!(Some(SIGTERM), signals.into_iter().next());
flag::register_conditional_shutdown(SIGTERM, 0, Arc::new(AtomicBool::new(true))).unwrap();
}
do_test(hook);
}