blob: 3ed42569e0694e2d7b04e726cd659992d2537325 [file] [log] [blame]
#![cfg(not(windows))]
extern crate signal_hook;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{self, RecvTimeoutError};
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use signal_hook::iterator::Signals;
use signal_hook::{SIGUSR1, SIGUSR2};
#[test]
fn signals_close_forever() {
// The cloned instances are connected to each other. Closing one closes all.
// Closing it terminates the forever that waits for stuff. Well, it terminates all of them.
let signals = Signals::new(&[SIGUSR1]).unwrap();
// Detect early terminations.
let stopped = Arc::new(AtomicBool::new(false));
let threads = (0..5).map(|_| {
let signals_bg = signals.clone();
let stopped_bg = Arc::clone(&stopped);
thread::spawn(move || {
// Eat all the signals there are (might come from a concurrent test, in theory).
// Would wait forever, but it should be terminated by the close below.
for _sig in &signals_bg {}
stopped_bg.store(true, Ordering::SeqCst);
})
});
// Wait a bit… if some thread terminates by itself.
thread::sleep(Duration::from_millis(100));
assert!(!stopped.load(Ordering::SeqCst));
signals.close();
// If they don't terminate correctly, the test just keeps running. Not the best way to do
// tests, but whatever…
for thread in threads {
thread.join().unwrap();
}
}
// A reproducer for #16: if we had the mio-support enabled (which is enabled also by the
// tokio-support feature), blocking no longer works. The .wait() would return immediately (an empty
// iterator, possibly), .forever() would do a busy loop.
// flag)
#[test]
fn signals_block_wait() {
let signals = Signals::new(&[SIGUSR2]).unwrap();
let (s, r) = mpsc::channel();
thread::spawn(move || {
// Technically, it may spuriously return early. But it shouldn't be doing it too much, so
// we just try to wait multiple times ‒ if they *all* return right away, it is broken.
for _ in 0..10 {
for _ in signals.wait() {
panic!("Someone really did send us SIGUSR2, which breaks the test");
}
}
let _ = s.send(());
});
let err = r
.recv_timeout(Duration::from_millis(100))
.expect_err("Wait didn't wait properly");
assert_eq!(err, RecvTimeoutError::Timeout);
}