use crate::{
RuntimeError,
futures::signal::{
dispatch,
signal_task::{SendSignalTask, SignalTask},
},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SignalKind {
Interrupt,
Terminate,
Hangup,
Quit,
User1,
User2,
Child,
WindowChange,
Other(i32),
}
impl SignalKind {
pub fn number(self) -> i32 {
match self {
Self::Interrupt => libc::SIGINT,
Self::Terminate => libc::SIGTERM,
Self::Hangup => libc::SIGHUP,
Self::Quit => libc::SIGQUIT,
Self::User1 => libc::SIGUSR1,
Self::User2 => libc::SIGUSR2,
Self::Child => libc::SIGCHLD,
Self::WindowChange => libc::SIGWINCH,
Self::Other(signo) => signo,
}
}
pub fn from_number(signo: i32) -> Self {
match signo {
libc::SIGINT => Self::Interrupt,
libc::SIGTERM => Self::Terminate,
libc::SIGHUP => Self::Hangup,
libc::SIGQUIT => Self::Quit,
libc::SIGUSR1 => Self::User1,
libc::SIGUSR2 => Self::User2,
libc::SIGCHLD => Self::Child,
libc::SIGWINCH => Self::WindowChange,
signo => Self::Other(signo),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum SignalReleasePolicy {
#[default]
Hold,
OnDrop,
}
pub struct Signal;
impl Signal {
pub fn wait(kind: SignalKind) -> SignalTask {
SignalTask::new(kind)
}
pub fn send(pid: i32, kind: SignalKind) -> SendSignalTask {
SendSignalTask::new(pid, kind)
}
pub fn release(kind: SignalKind) -> Result<(), RuntimeError> {
dispatch::release(kind.number())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_named_signal_round_trips() {
let named = [
SignalKind::Interrupt,
SignalKind::Terminate,
SignalKind::Hangup,
SignalKind::Quit,
SignalKind::User1,
SignalKind::User2,
SignalKind::Child,
SignalKind::WindowChange,
];
for kind in named {
assert_eq!(SignalKind::from_number(kind.number()), kind);
}
assert_eq!(SignalKind::Interrupt.number(), libc::SIGINT);
assert_eq!(SignalKind::Other(libc::SIGPIPE).number(), libc::SIGPIPE);
}
#[test]
fn an_unnamed_signal_keeps_its_number() {
assert_eq!(
SignalKind::from_number(libc::SIGALRM),
SignalKind::Other(libc::SIGALRM)
);
}
#[test]
fn releasing_a_non_signal_is_a_bad_signal() {
assert_eq!(
Signal::release(SignalKind::Other(0)),
Err(RuntimeError::BadSignal),
);
}
}