mio_signals/sys/
mod.rs

1//! Platform dependent implementation of Signals.
2
3use crate::Signal;
4
5#[cfg(any(
6    target_os = "dragonfly",
7    target_os = "freebsd",
8    target_os = "ios",
9    target_os = "macos",
10    target_os = "netbsd",
11    target_os = "openbsd"
12))]
13mod kqueue;
14
15#[cfg(any(
16    target_os = "dragonfly",
17    target_os = "freebsd",
18    target_os = "ios",
19    target_os = "macos",
20    target_os = "netbsd",
21    target_os = "openbsd"
22))]
23pub use self::kqueue::Signals;
24
25#[cfg(any(target_os = "linux", target_os = "android"))]
26mod signalfd;
27
28#[cfg(any(target_os = "linux", target_os = "android"))]
29pub use self::signalfd::Signals;
30
31#[cfg(unix)]
32pub fn send_signal(pid: u32, signal: Signal) -> std::io::Result<()> {
33    if unsafe { libc::kill(pid as libc::pid_t, raw_signal(signal)) } != 0 {
34        Err(std::io::Error::last_os_error())
35    } else {
36        Ok(())
37    }
38}
39
40// TODO: add Windows implementation.
41
42/// Convert a `signal` into a Unix signal.
43fn raw_signal(signal: Signal) -> libc::c_int {
44    match signal {
45        Signal::Interrupt => libc::SIGINT,
46        Signal::Quit => libc::SIGQUIT,
47        Signal::Terminate => libc::SIGTERM,
48        Signal::User1 => libc::SIGUSR1,
49        Signal::User2 => libc::SIGUSR2,
50    }
51}
52
53/// Convert a raw Unix signal into a signal.
54fn from_raw_signal(raw_signal: libc::c_int) -> Option<Signal> {
55    match raw_signal {
56        libc::SIGINT => Some(Signal::Interrupt),
57        libc::SIGQUIT => Some(Signal::Quit),
58        libc::SIGTERM => Some(Signal::Terminate),
59        libc::SIGUSR1 => Some(Signal::User1),
60        libc::SIGUSR2 => Some(Signal::User2),
61        _ => None,
62    }
63}
64
65#[test]
66fn test_from_raw_signal() {
67    assert_eq!(from_raw_signal(libc::SIGINT), Some(Signal::Interrupt));
68    assert_eq!(from_raw_signal(libc::SIGQUIT), Some(Signal::Quit));
69    assert_eq!(from_raw_signal(libc::SIGTERM), Some(Signal::Terminate));
70    assert_eq!(from_raw_signal(libc::SIGUSR1), Some(Signal::User1));
71    assert_eq!(from_raw_signal(libc::SIGUSR2), Some(Signal::User2));
72
73    // Unsupported signals.
74    assert_eq!(from_raw_signal(libc::SIGSTOP), None);
75}
76
77#[test]
78fn test_raw_signal() {
79    assert_eq!(raw_signal(Signal::Interrupt), libc::SIGINT);
80    assert_eq!(raw_signal(Signal::Quit), libc::SIGQUIT);
81    assert_eq!(raw_signal(Signal::Terminate), libc::SIGTERM);
82    assert_eq!(raw_signal(Signal::User1), libc::SIGUSR1);
83    assert_eq!(raw_signal(Signal::User2), libc::SIGUSR2);
84}
85
86#[test]
87fn raw_signal_round_trip() {
88    assert_eq!(
89        raw_signal(from_raw_signal(libc::SIGINT).unwrap()),
90        libc::SIGINT
91    );
92    assert_eq!(
93        raw_signal(from_raw_signal(libc::SIGQUIT).unwrap()),
94        libc::SIGQUIT
95    );
96    assert_eq!(
97        raw_signal(from_raw_signal(libc::SIGTERM).unwrap()),
98        libc::SIGTERM
99    );
100    assert_eq!(
101        raw_signal(from_raw_signal(libc::SIGUSR1).unwrap()),
102        libc::SIGUSR1
103    );
104    assert_eq!(
105        raw_signal(from_raw_signal(libc::SIGUSR2).unwrap()),
106        libc::SIGUSR2
107    );
108}