diff --git a/src/delete.rs b/src/delete.rs index 30cf2f54a..2ddf0dc9e 100644 --- a/src/delete.rs +++ b/src/delete.rs @@ -4,13 +4,11 @@ use std::path::PathBuf; use anyhow::{bail, Result}; use clap::Clap; +use nix::sys::signal::Signal; use crate::cgroups; +use crate::container::{Container, ContainerStatus}; use crate::utils; -use crate::{ - container::{Container, ContainerStatus}, - signal, -}; use nix::sys::signal as nix_signal; #[derive(Clap, Debug)] @@ -35,7 +33,7 @@ impl Delete { log::debug!("load the container from {:?}", container_root); let mut container = Container::load(container_root)?.refresh_status()?; if container.can_kill() && self.force { - let sig = signal::from_str("SIGKILL")?; + let sig = Signal::SIGKILL; log::debug!("kill signal {} to {}", sig, container.pid().unwrap()); nix_signal::kill(container.pid().unwrap(), sig)?; container = container.update_status(ContainerStatus::Stopped); diff --git a/src/kill.rs b/src/kill.rs index 9c0eebb2d..734d65b17 100644 --- a/src/kill.rs +++ b/src/kill.rs @@ -6,7 +6,7 @@ use nix::sys::signal as nix_signal; use crate::{ container::{Container, ContainerStatus}, - signal, + signal::ToSignal, }; #[derive(Clap, Debug)] @@ -30,7 +30,7 @@ impl Kill { // it might be possible that kill is invoked on a already stopped container etc. let container = Container::load(container_root)?.refresh_status()?; if container.can_kill() { - let sig = signal::from_str(self.signal.as_str())?; + let sig = self.signal.to_signal()?; log::debug!("kill signal {} to {}", sig, container.pid().unwrap()); nix_signal::kill(container.pid().unwrap(), sig)?; container.update_status(ContainerStatus::Stopped).save()?; diff --git a/src/signal.rs b/src/signal.rs index 39ddbb26d..30b151f13 100644 --- a/src/signal.rs +++ b/src/signal.rs @@ -3,40 +3,99 @@ use anyhow::{bail, Result}; use nix::sys::signal::Signal; -pub fn from_str(signal: &str) -> Result { - use Signal::*; - Ok(match signal.to_ascii_uppercase().as_str() { - "1" | "HUP" | "SIGHUP" => Signal::SIGHUP, - "2" | "INT" | "SIGINT" => Signal::SIGINT, - "3" | "QUIT" | "SIGQUIT" => Signal::SIGQUIT, - "4" | "ILL" | "SIGILL" => Signal::SIGILL, - "5" | "BUS" | "SIGBUS" => Signal::SIGBUS, - "6" | "ABRT" | "IOT" | "SIGABRT" | "SIGIOT" => Signal::SIGABRT, - "7" | "TRAP" | "SIGTRAP" => Signal::SIGTRAP, - "8" | "FPE" | "SIGFPE" => Signal::SIGFPE, - "9" | "KILL" | "SIGKILL" => Signal::SIGKILL, - "10" | "USR1" | "SIGUSR1" => Signal::SIGUSR1, - "11" | "SEGV" | "SIGSEGV" => SIGSEGV, - "12" | "USR2" | "SIGUSR2" => SIGUSR2, - "13" | "PIPE" | "SIGPIPE" => SIGPIPE, - "14" | "ALRM" | "SIGALRM" => SIGALRM, - "15" | "TERM" | "SIGTERM" => SIGTERM, - "16" | "STKFLT" | "SIGSTKFLT" => SIGSTKFLT, - "17" | "CHLD" | "SIGCHLD" => SIGCHLD, - "18" | "CONT" | "SIGCONT" => SIGCONT, - "19" | "STOP" | "SIGSTOP" => SIGSTOP, - "20" | "TSTP" | "SIGTSTP" => SIGTSTP, - "21" | "TTIN" | "SIGTTIN" => SIGTTIN, - "22" | "TTOU" | "SIGTTOU" => SIGTTOU, - "23" | "URG" | "SIGURG" => SIGURG, - "24" | "XCPU" | "SIGXCPU" => SIGXCPU, - "25" | "XFSZ" | "SIGXFSZ" => SIGXFSZ, - "26" | "VTALRM" | "SIGVTALRM" => SIGVTALRM, - "27" | "PROF" | "SIGPROF" => SIGPROF, - "28" | "WINCH" | "SIGWINCH" => SIGWINCH, - "29" | "IO" | "SIGIO" => SIGIO, - "30" | "PWR" | "SIGPWR" => SIGPWR, - "31" | "SYS" | "SIGSYS" => SIGSYS, - _ => bail! {"{} is not a valid signal", signal}, - }) +pub trait ToSignal { + fn to_signal(&self) -> Result; +} + +impl ToSignal for String { + fn to_signal(&self) -> Result { + use Signal::*; + Ok(match self.to_ascii_uppercase().as_str() { + "1" | "HUP" | "SIGHUP" => SIGHUP, + "2" | "INT" | "SIGINT" => SIGINT, + "3" | "QUIT" | "SIGQUIT" => SIGQUIT, + "4" | "ILL" | "SIGILL" => SIGILL, + "5" | "BUS" | "SIGBUS" => SIGBUS, + "6" | "ABRT" | "IOT" | "SIGABRT" | "SIGIOT" => SIGABRT, + "7" | "TRAP" | "SIGTRAP" => SIGTRAP, + "8" | "FPE" | "SIGFPE" => SIGFPE, + "9" | "KILL" | "SIGKILL" => SIGKILL, + "10" | "USR1" | "SIGUSR1" => SIGUSR1, + "11" | "SEGV" | "SIGSEGV" => SIGSEGV, + "12" | "USR2" | "SIGUSR2" => SIGUSR2, + "13" | "PIPE" | "SIGPIPE" => SIGPIPE, + "14" | "ALRM" | "SIGALRM" => SIGALRM, + "15" | "TERM" | "SIGTERM" => SIGTERM, + "16" | "STKFLT" | "SIGSTKFLT" => SIGSTKFLT, + "17" | "CHLD" | "SIGCHLD" => SIGCHLD, + "18" | "CONT" | "SIGCONT" => SIGCONT, + "19" | "STOP" | "SIGSTOP" => SIGSTOP, + "20" | "TSTP" | "SIGTSTP" => SIGTSTP, + "21" | "TTIN" | "SIGTTIN" => SIGTTIN, + "22" | "TTOU" | "SIGTTOU" => SIGTTOU, + "23" | "URG" | "SIGURG" => SIGURG, + "24" | "XCPU" | "SIGXCPU" => SIGXCPU, + "25" | "XFSZ" | "SIGXFSZ" => SIGXFSZ, + "26" | "VTALRM" | "SIGVTALRM" => SIGVTALRM, + "27" | "PROF" | "SIGPROF" => SIGPROF, + "28" | "WINCH" | "SIGWINCH" => SIGWINCH, + "29" | "IO" | "SIGIO" => SIGIO, + "30" | "PWR" | "SIGPWR" => SIGPWR, + "31" | "SYS" | "SIGSYS" => SIGSYS, + _ => bail! {"{} is not a valid signal", self}, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use nix::sys::signal::Signal::*; + use std::collections::HashMap; + + #[test] + fn test_conversion_from_string() { + let mut test_sets = HashMap::new(); + test_sets.insert(SIGHUP, vec!["1", "HUP", "SIGHUP"]); + test_sets.insert(SIGINT, vec!["2", "INT", "SIGINT"]); + test_sets.insert(SIGQUIT, vec!["3", "QUIT", "SIGQUIT"]); + test_sets.insert(SIGILL, vec!["4", "ILL", "SIGILL"]); + test_sets.insert(SIGBUS, vec!["5", "BUS", "SIGBUS"]); + test_sets.insert(SIGABRT, vec!["6", "ABRT", "IOT", "SIGABRT", "SIGIOT"]); + test_sets.insert(SIGTRAP, vec!["7", "TRAP", "SIGTRAP"]); + test_sets.insert(SIGFPE, vec!["8", "FPE", "SIGFPE"]); + test_sets.insert(SIGKILL, vec!["9", "KILL", "SIGKILL"]); + test_sets.insert(SIGUSR1, vec!["10", "USR1", "SIGUSR1"]); + test_sets.insert(SIGSEGV, vec!["11", "SEGV", "SIGSEGV"]); + test_sets.insert(SIGUSR2, vec!["12", "USR2", "SIGUSR2"]); + test_sets.insert(SIGPIPE, vec!["13", "PIPE", "SIGPIPE"]); + test_sets.insert(SIGALRM, vec!["14", "ALRM", "SIGALRM"]); + test_sets.insert(SIGTERM, vec!["15", "TERM", "SIGTERM"]); + test_sets.insert(SIGSTKFLT, vec!["16", "STKFLT", "SIGSTKFLT"]); + test_sets.insert(SIGCHLD, vec!["17", "CHLD", "SIGCHLD"]); + test_sets.insert(SIGCONT, vec!["18", "CONT", "SIGCONT"]); + test_sets.insert(SIGSTOP, vec!["19", "STOP", "SIGSTOP"]); + test_sets.insert(SIGTSTP, vec!["20", "TSTP", "SIGTSTP"]); + test_sets.insert(SIGTTIN, vec!["21", "TTIN", "SIGTTIN"]); + test_sets.insert(SIGTTOU, vec!["22", "TTOU", "SIGTTOU"]); + test_sets.insert(SIGURG, vec!["23", "URG", "SIGURG"]); + test_sets.insert(SIGXCPU, vec!["24", "XCPU", "SIGXCPU"]); + test_sets.insert(SIGXFSZ, vec!["25", "XFSZ", "SIGXFSZ"]); + test_sets.insert(SIGVTALRM, vec!["26", "VTALRM", "SIGVTALRM"]); + test_sets.insert(SIGPROF, vec!["27", "PROF", "SIGPROF"]); + test_sets.insert(SIGWINCH, vec!["28", "WINCH", "SIGWINCH"]); + test_sets.insert(SIGIO, vec!["29", "IO", "SIGIO"]); + test_sets.insert(SIGPWR, vec!["30", "PWR", "SIGPWR"]); + test_sets.insert(SIGSYS, vec!["31", "SYS", "SIGSYS"]); + for (signal, strings) in test_sets { + for s in strings { + assert_eq!(signal, s.to_string().to_signal().unwrap()); + } + } + } + + #[test] + fn test_conversion_from_string_should_be_failed() { + assert!("invalid".to_string().to_signal().is_err()) + } }