• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![cfg(not(windows))]
2 
3 extern crate signal_hook;
4 
5 use std::collections::HashSet;
6 use std::sync::atomic::{AtomicBool, Ordering};
7 use std::sync::mpsc::{self, RecvTimeoutError};
8 use std::sync::Arc;
9 use std::thread::{self, JoinHandle};
10 use std::time::Duration;
11 
12 use signal_hook::consts::{SIGUSR1, SIGUSR2};
13 use signal_hook::iterator::{Handle, Signals};
14 use signal_hook::low_level::raise;
15 
16 use serial_test::serial;
17 
send_sigusr1()18 fn send_sigusr1() {
19     raise(SIGUSR1).unwrap();
20 }
21 
send_sigusr2()22 fn send_sigusr2() {
23     raise(SIGUSR2).unwrap();
24 }
25 
setup_without_any_signals() -> (Signals, Handle)26 fn setup_without_any_signals() -> (Signals, Handle) {
27     let signals = Signals::new(&[]).unwrap();
28     let controller = signals.handle();
29     (signals, controller)
30 }
31 
setup_for_sigusr2() -> (Signals, Handle)32 fn setup_for_sigusr2() -> (Signals, Handle) {
33     let signals = Signals::new(&[SIGUSR2]).unwrap();
34     let controller = signals.handle();
35     (signals, controller)
36 }
37 
38 macro_rules! assert_signals {
39     ($actual:expr, $($expected:expr),+ $(,)?) => {
40         let actual = $actual.collect::<HashSet<libc::c_int>>();
41         let expected = vec!($($expected),+).into_iter().collect::<HashSet<libc::c_int>>();
42         assert_eq!(actual, expected);
43     };
44 }
45 
46 macro_rules! assert_no_signals {
47     ($signals:expr) => {
48         assert_eq!($signals.next(), None);
49     };
50 }
51 
52 #[test]
53 #[serial]
forever_terminates_when_closed()54 fn forever_terminates_when_closed() {
55     let (mut signals, controller) = setup_for_sigusr2();
56 
57     // Detect early terminations.
58     let stopped = Arc::new(AtomicBool::new(false));
59 
60     let stopped_bg = Arc::clone(&stopped);
61     let thread = thread::spawn(move || {
62         // Eat all the signals there are (might come from a concurrent test, in theory).
63         // Would wait forever, but it should be terminated by the close below.
64         for _sig in &mut signals {}
65 
66         stopped_bg.store(true, Ordering::SeqCst);
67     });
68 
69     // Wait a bit to see if the thread terminates by itself.
70     thread::sleep(Duration::from_millis(100));
71     assert!(!stopped.load(Ordering::SeqCst));
72 
73     controller.close();
74 
75     thread.join().unwrap();
76 
77     assert!(stopped.load(Ordering::SeqCst));
78 }
79 
80 // A reproducer for #16: if we had the mio-support enabled (which is enabled also by the
81 // tokio-support feature), blocking no longer works. The .wait() would return immediately (an empty
82 // iterator, possibly), .forever() would do a busy loop.
83 // flag)
84 #[test]
85 #[serial]
signals_block_wait()86 fn signals_block_wait() {
87     let mut signals = Signals::new(&[SIGUSR2]).unwrap();
88     let (s, r) = mpsc::channel();
89     let finish = Arc::new(AtomicBool::new(false));
90     let thread_id = thread::spawn({
91         let finish = Arc::clone(&finish);
92         move || {
93             // Technically, it may spuriously return early. But it shouldn't be doing it too much,
94             // so we just try to wait multiple times ‒ if they *all* return right away, it is
95             // broken.
96             for _ in 0..10 {
97                 for _ in signals.wait() {
98                     if finish.load(Ordering::SeqCst) {
99                         // Asked to terminate at the end of the thread. Do so (but without
100                         // signalling the receipt).
101                         return;
102                     } else {
103                         panic!("Someone really did send us SIGUSR2, which breaks the test");
104                     }
105                 }
106             }
107             let _ = s.send(());
108         }
109     });
110 
111     // A RAII guard to make sure we shut down the thread even if the test fails.
112     struct ThreadGuard {
113         thread: Option<JoinHandle<()>>,
114         finish: Arc<AtomicBool>,
115     }
116 
117     impl ThreadGuard {
118         fn shutdown(&mut self) {
119             // Tell it to shut down
120             self.finish.store(true, Ordering::SeqCst);
121             // Wake it up
122             send_sigusr2();
123             // Wait for it to actually terminate.
124             if let Some(thread) = self.thread.take() {
125                 thread.join().unwrap(); // Propagate panics
126             }
127         }
128     }
129 
130     impl Drop for ThreadGuard {
131         fn drop(&mut self) {
132             self.shutdown(); // OK if done twice, won't have the thread any more.
133         }
134     }
135 
136     let mut bg_thread = ThreadGuard {
137         thread: Some(thread_id),
138         finish,
139     };
140 
141     let err = r
142         .recv_timeout(Duration::from_millis(100))
143         .expect_err("Wait didn't wait properly");
144     assert_eq!(err, RecvTimeoutError::Timeout);
145 
146     bg_thread.shutdown();
147 }
148 
149 #[test]
150 #[serial]
pending_doesnt_block()151 fn pending_doesnt_block() {
152     let (mut signals, _) = setup_for_sigusr2();
153 
154     let mut recieved_signals = signals.pending();
155 
156     assert_no_signals!(recieved_signals);
157 }
158 
159 #[test]
160 #[serial]
wait_returns_recieved_signals()161 fn wait_returns_recieved_signals() {
162     let (mut signals, _) = setup_for_sigusr2();
163     send_sigusr2();
164 
165     let recieved_signals = signals.wait();
166 
167     assert_signals!(recieved_signals, SIGUSR2);
168 }
169 
170 #[test]
171 #[serial]
forever_returns_recieved_signals()172 fn forever_returns_recieved_signals() {
173     let (mut signals, _) = setup_for_sigusr2();
174     send_sigusr2();
175 
176     let signal = signals.forever().take(1);
177 
178     assert_signals!(signal, SIGUSR2);
179 }
180 
181 #[test]
182 #[serial]
wait_doesnt_block_when_closed()183 fn wait_doesnt_block_when_closed() {
184     let (mut signals, controller) = setup_for_sigusr2();
185     controller.close();
186 
187     let mut recieved_signals = signals.wait();
188 
189     assert_no_signals!(recieved_signals);
190 }
191 
192 #[test]
193 #[serial]
wait_unblocks_when_closed()194 fn wait_unblocks_when_closed() {
195     let (mut signals, controller) = setup_without_any_signals();
196 
197     let thread = thread::spawn(move || {
198         signals.wait();
199     });
200 
201     controller.close();
202 
203     thread.join().unwrap();
204 }
205 
206 #[test]
207 #[serial]
forever_doesnt_block_when_closed()208 fn forever_doesnt_block_when_closed() {
209     let (mut signals, controller) = setup_for_sigusr2();
210     controller.close();
211 
212     let mut signal = signals.forever();
213 
214     assert_no_signals!(signal);
215 }
216 
217 #[test]
218 #[serial]
add_signal_after_creation()219 fn add_signal_after_creation() {
220     let (mut signals, _) = setup_without_any_signals();
221     signals.add_signal(SIGUSR1).unwrap();
222 
223     send_sigusr1();
224 
225     assert_signals!(signals.pending(), SIGUSR1);
226 }
227 
228 #[test]
229 #[serial]
delayed_signal_consumed()230 fn delayed_signal_consumed() {
231     let (mut signals, _) = setup_for_sigusr2();
232     signals.add_signal(SIGUSR1).unwrap();
233 
234     send_sigusr1();
235     let mut recieved_signals = signals.wait();
236     send_sigusr2();
237 
238     assert_signals!(recieved_signals, SIGUSR1, SIGUSR2);
239 
240     // The pipe still contains the byte from the second
241     // signal and so wait won't block but won't return
242     // a signal.
243     recieved_signals = signals.wait();
244     assert_no_signals!(recieved_signals);
245 }
246 
247 #[test]
248 #[serial]
is_closed_initially_returns_false()249 fn is_closed_initially_returns_false() {
250     let (_, controller) = setup_for_sigusr2();
251 
252     assert!(!controller.is_closed());
253 }
254 
255 #[test]
256 #[serial]
is_closed_returns_true_when_closed()257 fn is_closed_returns_true_when_closed() {
258     let (_, controller) = setup_for_sigusr2();
259     controller.close();
260 
261     assert!(controller.is_closed());
262 }
263