|  | #![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); | 
|  | } |