1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
// These tests cannot run as a regular test because cargo would spawn a thread to run it,
// failing the signal masking. So we make our own, non-threaded harnessing
#[cfg(all(target_os = "linux", feature = "signals"))]
fn main() {
for test in self::test::TESTS {
test();
// reset the signal mask between tests
self::test::reset_mask();
}
}
#[cfg(not(all(target_os = "linux", feature = "signals")))]
fn main() {}
#[cfg(all(target_os = "linux", feature = "signals"))]
mod test {
extern crate calloop;
extern crate nix;
use std::time::Duration;
use self::calloop::signals::{Signal, Signals};
use self::calloop::{Dispatcher, EventLoop};
use self::nix::sys::signal::{kill, SigSet};
use self::nix::unistd::Pid;
pub const TESTS: &[fn()] = &[single_usr1, usr2_added_afterwards, usr2_signal_removed];
pub fn reset_mask() {
SigSet::empty().thread_set_mask().unwrap();
}
fn single_usr1() {
let mut event_loop = EventLoop::try_new().unwrap();
let mut signal_received = false;
let _signal_source = event_loop
.handle()
.insert_source(
Signals::new(&[Signal::SIGUSR1]).unwrap(),
move |evt, &mut (), rcv| {
assert!(evt.signal() == Signal::SIGUSR1);
*rcv = true;
},
)
.unwrap();
// send ourselves a SIGUSR1
kill(Pid::this(), Signal::SIGUSR1).unwrap();
event_loop
.dispatch(Some(Duration::from_millis(10)), &mut signal_received)
.unwrap();
assert!(signal_received);
}
fn usr2_added_afterwards() {
let mut event_loop = EventLoop::try_new().unwrap();
let mut signal_received = None;
let dispatcher = Dispatcher::new(
Signals::new(&[Signal::SIGUSR1]).unwrap(),
move |evt, &mut (), rcv| {
*rcv = Some(evt.signal());
},
);
let _signal_token = event_loop
.handle()
.register_dispatcher(dispatcher.clone())
.unwrap();
dispatcher
.as_source_mut()
.add_signals(&[Signal::SIGUSR2])
.unwrap();
// send ourselves a SIGUSR2
kill(Pid::this(), Signal::SIGUSR2).unwrap();
event_loop
.dispatch(Some(Duration::from_millis(10)), &mut signal_received)
.unwrap();
assert_eq!(signal_received, Some(Signal::SIGUSR2));
}
fn usr2_signal_removed() {
let mut event_loop = EventLoop::try_new().unwrap();
let mut signal_received = None;
let dispatcher = Dispatcher::new(
Signals::new(&[Signal::SIGUSR1, Signal::SIGUSR2]).unwrap(),
move |evt, &mut (), rcv| {
*rcv = Some(evt.signal());
},
);
let _signal_token = event_loop
.handle()
.register_dispatcher(dispatcher.clone())
.unwrap();
dispatcher
.as_source_mut()
.remove_signals(&[Signal::SIGUSR2])
.unwrap();
// block sigusr2 anyway, to not be killed by it
let mut set = SigSet::empty();
set.add(Signal::SIGUSR2);
set.thread_block().unwrap();
// send ourselves a SIGUSR2
kill(Pid::this(), Signal::SIGUSR2).unwrap();
event_loop
.dispatch(Some(Duration::from_millis(10)), &mut signal_received)
.unwrap();
// we should not have received anything, as we don't listen to SIGUSR2 any more
assert!(signal_received.is_none());
// swap the signals from [SIGUSR1] to [SIGUSR2]
dispatcher
.as_source_mut()
.set_signals(&[Signal::SIGUSR2])
.unwrap();
event_loop
.dispatch(Some(Duration::from_millis(10)), &mut signal_received)
.unwrap();
// we should get back the pending SIGUSR2 now
assert_eq!(signal_received, Some(Signal::SIGUSR2));
}
}
|