Handle signalling to sub process on non-unix

This commit is contained in:
Félix Saparelli 2021-10-16 01:21:52 +13:00
parent 92513a4dc3
commit e577b040b9
No known key found for this signature in database
GPG Key ID: B948C4BAE44FC474
4 changed files with 47 additions and 39 deletions

View File

@ -12,8 +12,6 @@ use tokio::{
}; };
use tracing::{debug, trace, warn}; use tracing::{debug, trace, warn};
pub use command_group::Signal;
use crate::{ use crate::{
command::Supervisor, command::Supervisor,
error::{CriticalError, RuntimeError}, error::{CriticalError, RuntimeError},
@ -232,8 +230,16 @@ async fn apply_outcome(
} }
(Some(p), Outcome::Signal(sig)) => { (Some(p), Outcome::Signal(sig)) => {
// TODO: windows #[cfg(unix)]
p.signal(sig).await; if let Some(sig) = sig.to_nix() {
p.signal(sig).await;
}
#[cfg(windows)]
if let SubSignal::Terminate = sig {
p.kill().await;
}
// else: https://github.com/watchexec/watchexec/issues/219
} }
(Some(p), Outcome::Wait) => { (Some(p), Outcome::Wait) => {

View File

@ -1,4 +1,4 @@
use command_group::Signal; use crate::signal::process::SubSignal;
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive] #[non_exhaustive]
@ -16,7 +16,7 @@ pub enum Outcome {
Wait, Wait,
/// Send this signal to the command. /// Send this signal to the command.
Signal(Signal), Signal(SubSignal),
/// Clear the (terminal) screen. /// Clear the (terminal) screen.
Clear, Clear,

View File

@ -1,4 +1,4 @@
//! Signal handling. //! Signal handling.
pub mod source;
pub mod process; pub mod process;
pub mod source;

View File

@ -95,24 +95,24 @@ pub enum SubSignal {
impl SubSignal { impl SubSignal {
#[cfg(unix)] #[cfg(unix)]
pub fn to_nix(self) -> Option<NixSignal> { pub fn to_nix(self) -> Option<NixSignal> {
use std::convert::TryFrom; use std::convert::TryFrom;
match self { match self {
Self::Hangup => Some(NixSignal::SIGHUP), Self::Hangup => Some(NixSignal::SIGHUP),
Self::ForceStop => Some(NixSignal::SIGKILL), Self::ForceStop => Some(NixSignal::SIGKILL),
Self::Interrupt => Some(NixSignal::SIGINT), Self::Interrupt => Some(NixSignal::SIGINT),
Self::Quit => Some(NixSignal::SIGQUIT), Self::Quit => Some(NixSignal::SIGQUIT),
Self::Terminate => Some(NixSignal::SIGTERM), Self::Terminate => Some(NixSignal::SIGTERM),
Self::User1 => Some(NixSignal::SIGUSR1), Self::User1 => Some(NixSignal::SIGUSR1),
Self::User2 => Some(NixSignal::SIGUSR2), Self::User2 => Some(NixSignal::SIGUSR2),
Self::Custom(sig) => NixSignal::try_from(sig).ok(), Self::Custom(sig) => NixSignal::try_from(sig).ok(),
} }
} }
#[cfg(unix)] #[cfg(unix)]
pub fn from_nix(sig: NixSignal) -> Self { pub fn from_nix(sig: NixSignal) -> Self {
match sig { match sig {
NixSignal::SIGHUP => Self::Hangup, NixSignal::SIGHUP => Self::Hangup,
NixSignal::SIGKILL => Self::ForceStop, NixSignal::SIGKILL => Self::ForceStop,
NixSignal::SIGINT => Self::Interrupt, NixSignal::SIGINT => Self::Interrupt,
@ -126,24 +126,24 @@ impl SubSignal {
} }
impl From<MainSignal> for SubSignal { impl From<MainSignal> for SubSignal {
fn from(main: MainSignal) -> Self { fn from(main: MainSignal) -> Self {
match main { match main {
MainSignal::Hangup => Self::Hangup, MainSignal::Hangup => Self::Hangup,
MainSignal::Interrupt => Self::Interrupt, MainSignal::Interrupt => Self::Interrupt,
MainSignal::Quit => Self::Quit, MainSignal::Quit => Self::Quit,
MainSignal::Terminate => Self::Terminate, MainSignal::Terminate => Self::Terminate,
MainSignal::User1 => Self::User1, MainSignal::User1 => Self::User1,
MainSignal::User2 => Self::User2, MainSignal::User2 => Self::User2,
} }
} }
} }
impl FromStr for SubSignal { impl FromStr for SubSignal {
type Err = ParseSignalError; type Err = ParseSignalError;
#[cfg(unix)] #[cfg(unix)]
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
use std::convert::TryFrom; use std::convert::TryFrom;
if let Ok(sig) = i32::from_str(s) { if let Ok(sig) = i32::from_str(s) {
if let Ok(sig) = NixSignal::try_from(sig) { if let Ok(sig) = NixSignal::try_from(sig) {
@ -151,23 +151,25 @@ impl FromStr for SubSignal {
} }
} }
if let Ok(sig) = NixSignal::from_str(&s.to_ascii_uppercase()).or_else(|_| NixSignal::from_str(&format!("SIG{}", s.to_ascii_uppercase()))) { if let Ok(sig) = NixSignal::from_str(&s.to_ascii_uppercase())
.or_else(|_| NixSignal::from_str(&format!("SIG{}", s.to_ascii_uppercase())))
{
return Ok(Self::from_nix(sig)); return Ok(Self::from_nix(sig));
} }
Err(ParseSignalError::new(s, "unsupported signal")) Err(ParseSignalError::new(s, "unsupported signal"))
} }
#[cfg(windows)] #[cfg(windows)]
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_ascii_uppercase().as_str() { match s.to_ascii_uppercase().as_str() {
"CTRL-CLOSE" | "CTRL+CLOSE" | "CLOSE" => Ok(Self::Hangup), "CTRL-CLOSE" | "CTRL+CLOSE" | "CLOSE" => Ok(Self::Hangup),
"CTRL-BREAK" | "CTRL+BREAK" | "BREAK" => Ok(Self::Terminate), "CTRL-BREAK" | "CTRL+BREAK" | "BREAK" => Ok(Self::Terminate),
"CTRL-C" | "CTRL+C" | "C" => Ok(Self::Interrupt), "CTRL-C" | "CTRL+C" | "C" => Ok(Self::Interrupt),
"KILL" | "SIGKILL" | "FORCE-STOP" | "STOP" => Ok(Self::ForceStop), "KILL" | "SIGKILL" | "FORCE-STOP" | "STOP" => Ok(Self::ForceStop),
_ => Err(ParseSignalError::new(s, "unknown control name")), _ => Err(ParseSignalError::new(s, "unknown control name")),
} }
} }
#[cfg(not(any(unix, windows)))] #[cfg(not(any(unix, windows)))]
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
@ -181,8 +183,8 @@ impl FromStr for SubSignal {
#[diagnostic(code(watchexec::signal::process::parse), url(docsrs))] #[diagnostic(code(watchexec::signal::process::parse), url(docsrs))]
pub struct ParseSignalError { pub struct ParseSignalError {
// The string that was parsed. // The string that was parsed.
#[source_code] #[source_code]
src: String, src: String,
// The error that occurred. // The error that occurred.
err: String, err: String,