2023-03-18 11:23:46 +01:00
|
|
|
#![doc = include_str!("../README.md")]
|
2021-10-15 14:14:17 +02:00
|
|
|
|
2023-03-18 09:32:24 +01:00
|
|
|
use std::fmt;
|
|
|
|
|
|
|
|
#[cfg(feature = "fromstr")]
|
2021-10-15 14:14:17 +02:00
|
|
|
use std::str::FromStr;
|
|
|
|
|
|
|
|
#[cfg(unix)]
|
2023-02-14 23:11:57 +01:00
|
|
|
use nix::sys::signal::Signal as NixSignal;
|
2022-01-16 06:57:40 +01:00
|
|
|
|
2023-03-18 11:23:46 +01:00
|
|
|
/// A notification (signals or Windows control events) sent to a process.
|
|
|
|
///
|
|
|
|
/// This signal type in Watchexec is used for any of:
|
|
|
|
/// - signals sent to the main process by some external actor,
|
|
|
|
/// - signals received from a sub process by the main process,
|
|
|
|
/// - signals sent to a sub process by Watchexec.
|
2021-10-15 14:14:17 +02:00
|
|
|
///
|
|
|
|
/// On Windows, only some signals are supported, as described. Others will be ignored.
|
|
|
|
///
|
|
|
|
/// On Unix, there are several "first-class" signals which have their own variants, and a generic
|
2023-03-18 09:32:24 +01:00
|
|
|
/// [`Custom`][Signal::Custom] variant which can be used to send arbitrary signals.
|
2023-12-09 10:30:58 +01:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
2023-03-18 09:32:24 +01:00
|
|
|
#[non_exhaustive]
|
|
|
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "serde",
|
|
|
|
serde(
|
|
|
|
from = "serde_support::SerdeSignal",
|
|
|
|
into = "serde_support::SerdeSignal"
|
|
|
|
)
|
|
|
|
)]
|
|
|
|
pub enum Signal {
|
2021-10-15 14:14:17 +02:00
|
|
|
/// Indicate that the terminal is disconnected.
|
|
|
|
///
|
|
|
|
/// On Unix, this is `SIGHUP`. On Windows, this is ignored for now but may be supported in the
|
|
|
|
/// future (see [#219](https://github.com/watchexec/watchexec/issues/219)).
|
|
|
|
///
|
|
|
|
/// Despite its nominal purpose, on Unix this signal is often used to reload configuration files.
|
|
|
|
Hangup,
|
|
|
|
|
|
|
|
/// Indicate to the kernel that the process should stop.
|
|
|
|
///
|
|
|
|
/// On Unix, this is `SIGKILL`. On Windows, this is `TerminateProcess`.
|
|
|
|
///
|
|
|
|
/// This signal is not handled by the process, but directly by the kernel, and thus cannot be
|
|
|
|
/// intercepted. Subprocesses may exit in inconsistent states.
|
|
|
|
ForceStop,
|
|
|
|
|
|
|
|
/// Indicate that the process should stop.
|
|
|
|
///
|
|
|
|
/// On Unix, this is `SIGINT`. On Windows, this is ignored for now but may be supported in the
|
|
|
|
/// future (see [#219](https://github.com/watchexec/watchexec/issues/219)).
|
|
|
|
///
|
|
|
|
/// This signal generally indicates an action taken by the user, so it may be handled
|
|
|
|
/// differently than a termination.
|
|
|
|
Interrupt,
|
|
|
|
|
|
|
|
/// Indicate that the process is to stop, the kernel will then dump its core.
|
|
|
|
///
|
|
|
|
/// On Unix, this is `SIGQUIT`. On Windows, it is ignored.
|
|
|
|
///
|
|
|
|
/// This is rarely used.
|
|
|
|
Quit,
|
|
|
|
|
|
|
|
/// Indicate that the process should stop.
|
|
|
|
///
|
|
|
|
/// On Unix, this is `SIGTERM`. On Windows, this is ignored for now but may be supported in the
|
|
|
|
/// future (see [#219](https://github.com/watchexec/watchexec/issues/219)).
|
|
|
|
///
|
|
|
|
/// On Unix, this signal generally indicates an action taken by the system, so it may be handled
|
|
|
|
/// differently than an interruption.
|
|
|
|
Terminate,
|
|
|
|
|
|
|
|
/// Indicate an application-defined behaviour should happen.
|
|
|
|
///
|
|
|
|
/// On Unix, this is `SIGUSR1`. On Windows, it is ignored.
|
|
|
|
///
|
|
|
|
/// This signal is generally used to start debugging.
|
|
|
|
User1,
|
|
|
|
|
|
|
|
/// Indicate an application-defined behaviour should happen.
|
|
|
|
///
|
|
|
|
/// On Unix, this is `SIGUSR2`. On Windows, it is ignored.
|
|
|
|
///
|
|
|
|
/// This signal is generally used to reload configuration.
|
|
|
|
User2,
|
|
|
|
|
|
|
|
/// Indicate using a custom signal.
|
|
|
|
///
|
|
|
|
/// Internally, this is converted to a [`nix::Signal`](https://docs.rs/nix/*/nix/sys/signal/enum.Signal.html)
|
|
|
|
/// but for portability this variant is a raw `i32`.
|
|
|
|
///
|
|
|
|
/// Invalid signals on the current platform will be ignored. Does nothing on Windows.
|
|
|
|
///
|
2023-03-18 09:32:24 +01:00
|
|
|
/// The special value `0` is used to indicate an unknown signal. That is, a signal was received
|
|
|
|
/// or parsed, but it is not known which. This is not a usual case, and should in general be
|
|
|
|
/// ignored rather than hard-erroring.
|
|
|
|
///
|
2021-10-15 14:14:17 +02:00
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2023-02-14 23:11:57 +01:00
|
|
|
/// # #[cfg(unix)]
|
|
|
|
/// # {
|
2023-03-18 09:32:24 +01:00
|
|
|
/// use watchexec_signals::Signal;
|
|
|
|
/// use nix::sys::signal::Signal as NixSignal;
|
|
|
|
/// assert_eq!(Signal::Custom(6), Signal::from(NixSignal::SIGABRT as i32));
|
2023-02-14 23:11:57 +01:00
|
|
|
/// # }
|
2021-10-16 08:08:35 +02:00
|
|
|
/// ```
|
|
|
|
///
|
2023-03-18 09:32:24 +01:00
|
|
|
/// On Unix the [`from_nix`][Signal::from_nix] method should be preferred if converting from
|
2021-10-16 08:08:35 +02:00
|
|
|
/// Nix's `Signal` type:
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// # #[cfg(unix)]
|
|
|
|
/// # {
|
2023-03-18 09:32:24 +01:00
|
|
|
/// use watchexec_signals::Signal;
|
|
|
|
/// use nix::sys::signal::Signal as NixSignal;
|
|
|
|
/// assert_eq!(Signal::Custom(6), Signal::from_nix(NixSignal::SIGABRT));
|
2021-10-16 08:08:35 +02:00
|
|
|
/// # }
|
2021-10-15 14:14:17 +02:00
|
|
|
/// ```
|
|
|
|
Custom(i32),
|
|
|
|
}
|
|
|
|
|
2023-03-18 09:32:24 +01:00
|
|
|
impl Signal {
|
|
|
|
/// Converts to a [`nix::Signal`][NixSignal] if possible.
|
2021-10-16 12:31:00 +02:00
|
|
|
///
|
|
|
|
/// This will return `None` if the signal is not supported on the current platform (only for
|
2023-03-18 09:32:24 +01:00
|
|
|
/// [`Custom`][Signal::Custom], as the first-class ones are always supported).
|
2021-10-15 14:14:17 +02:00
|
|
|
#[cfg(unix)]
|
2023-01-06 14:53:49 +01:00
|
|
|
#[must_use]
|
2021-10-15 14:21:52 +02:00
|
|
|
pub fn to_nix(self) -> Option<NixSignal> {
|
|
|
|
match self {
|
|
|
|
Self::Hangup => Some(NixSignal::SIGHUP),
|
|
|
|
Self::ForceStop => Some(NixSignal::SIGKILL),
|
|
|
|
Self::Interrupt => Some(NixSignal::SIGINT),
|
|
|
|
Self::Quit => Some(NixSignal::SIGQUIT),
|
|
|
|
Self::Terminate => Some(NixSignal::SIGTERM),
|
|
|
|
Self::User1 => Some(NixSignal::SIGUSR1),
|
|
|
|
Self::User2 => Some(NixSignal::SIGUSR2),
|
|
|
|
Self::Custom(sig) => NixSignal::try_from(sig).ok(),
|
|
|
|
}
|
|
|
|
}
|
2021-10-15 14:14:17 +02:00
|
|
|
|
2023-03-18 09:32:24 +01:00
|
|
|
/// Converts from a [`nix::Signal`][NixSignal].
|
2021-10-15 14:14:17 +02:00
|
|
|
#[cfg(unix)]
|
2023-01-06 14:53:49 +01:00
|
|
|
#[allow(clippy::missing_const_for_fn)]
|
|
|
|
#[must_use]
|
2021-10-15 14:14:17 +02:00
|
|
|
pub fn from_nix(sig: NixSignal) -> Self {
|
2021-10-15 14:21:52 +02:00
|
|
|
match sig {
|
2021-10-15 14:14:17 +02:00
|
|
|
NixSignal::SIGHUP => Self::Hangup,
|
|
|
|
NixSignal::SIGKILL => Self::ForceStop,
|
|
|
|
NixSignal::SIGINT => Self::Interrupt,
|
|
|
|
NixSignal::SIGQUIT => Self::Quit,
|
|
|
|
NixSignal::SIGTERM => Self::Terminate,
|
|
|
|
NixSignal::SIGUSR1 => Self::User1,
|
|
|
|
NixSignal::SIGUSR2 => Self::User2,
|
|
|
|
sig => Self::Custom(sig as _),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-18 09:32:24 +01:00
|
|
|
impl From<i32> for Signal {
|
2021-10-16 12:31:00 +02:00
|
|
|
/// Converts from a raw signal number.
|
|
|
|
///
|
|
|
|
/// This uses hardcoded numbers for the first-class signals.
|
2021-10-16 08:08:35 +02:00
|
|
|
fn from(raw: i32) -> Self {
|
|
|
|
match raw {
|
|
|
|
1 => Self::Hangup,
|
|
|
|
2 => Self::Interrupt,
|
|
|
|
3 => Self::Quit,
|
|
|
|
9 => Self::ForceStop,
|
|
|
|
10 => Self::User1,
|
|
|
|
12 => Self::User2,
|
|
|
|
15 => Self::Terminate,
|
|
|
|
_ => Self::Custom(raw),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-18 09:32:24 +01:00
|
|
|
#[cfg(feature = "fromstr")]
|
|
|
|
impl Signal {
|
2023-03-05 02:57:34 +01:00
|
|
|
/// Parse the input as a unix signal.
|
|
|
|
///
|
|
|
|
/// This parses the input as a signal name, or a signal number, in a case-insensitive manner.
|
|
|
|
/// It supports integers, the short name of the signal (like `INT`, `HUP`, `USR1`, etc), and
|
|
|
|
/// the long name of the signal (like `SIGINT`, `SIGHUP`, `SIGUSR1`, etc).
|
|
|
|
///
|
|
|
|
/// Note that this is entirely accurate only when used on unix targets; on other targets it
|
|
|
|
/// falls back to a hardcoded approximation instead of looking up signal tables (via [`nix`]).
|
|
|
|
///
|
|
|
|
/// ```
|
2023-03-18 09:32:24 +01:00
|
|
|
/// # use watchexec_signals::Signal;
|
|
|
|
/// assert_eq!(Signal::Hangup, Signal::from_unix_str("hup").unwrap());
|
|
|
|
/// assert_eq!(Signal::Interrupt, Signal::from_unix_str("SIGINT").unwrap());
|
|
|
|
/// assert_eq!(Signal::ForceStop, Signal::from_unix_str("Kill").unwrap());
|
2023-03-05 02:57:34 +01:00
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// Using [`FromStr`] is recommended for practical use, as it will also parse Windows control
|
2023-03-18 09:32:24 +01:00
|
|
|
/// events, see [`Signal::from_windows_str`].
|
2023-03-05 02:57:34 +01:00
|
|
|
pub fn from_unix_str(s: &str) -> Result<Self, SignalParseError> {
|
|
|
|
Self::from_unix_str_impl(s)
|
|
|
|
}
|
2021-10-15 14:14:17 +02:00
|
|
|
|
|
|
|
#[cfg(unix)]
|
2023-03-05 02:57:34 +01:00
|
|
|
fn from_unix_str_impl(s: &str) -> Result<Self, SignalParseError> {
|
2021-10-15 14:14:17 +02:00
|
|
|
if let Ok(sig) = i32::from_str(s) {
|
|
|
|
if let Ok(sig) = NixSignal::try_from(sig) {
|
|
|
|
return Ok(Self::from_nix(sig));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-15 14:21:52 +02:00
|
|
|
if let Ok(sig) = NixSignal::from_str(&s.to_ascii_uppercase())
|
|
|
|
.or_else(|_| NixSignal::from_str(&format!("SIG{}", s.to_ascii_uppercase())))
|
|
|
|
{
|
2021-10-15 14:14:17 +02:00
|
|
|
return Ok(Self::from_nix(sig));
|
|
|
|
}
|
|
|
|
|
2021-10-16 06:09:21 +02:00
|
|
|
Err(SignalParseError::new(s, "unsupported signal"))
|
2021-10-15 14:21:52 +02:00
|
|
|
}
|
2021-10-15 14:14:17 +02:00
|
|
|
|
2023-03-05 02:57:34 +01:00
|
|
|
#[cfg(not(unix))]
|
|
|
|
fn from_unix_str_impl(s: &str) -> Result<Self, SignalParseError> {
|
|
|
|
match s.to_ascii_uppercase().as_str() {
|
|
|
|
"KILL" | "SIGKILL" | "9" => Ok(Self::ForceStop),
|
|
|
|
"HUP" | "SIGHUP" | "1" => Ok(Self::Hangup),
|
|
|
|
"INT" | "SIGINT" | "2" => Ok(Self::Interrupt),
|
|
|
|
"QUIT" | "SIGQUIT" | "3" => Ok(Self::Quit),
|
|
|
|
"TERM" | "SIGTERM" | "15" => Ok(Self::Terminate),
|
|
|
|
"USR1" | "SIGUSR1" | "10" => Ok(Self::User1),
|
|
|
|
"USR2" | "SIGUSR2" | "12" => Ok(Self::User2),
|
|
|
|
number => match i32::from_str(number) {
|
|
|
|
Ok(int) => Ok(Self::Custom(int)),
|
|
|
|
Err(_) => Err(SignalParseError::new(s, "unsupported signal")),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Parse the input as a windows control event.
|
|
|
|
///
|
|
|
|
/// This parses the input as a control event name, in a case-insensitive manner.
|
|
|
|
///
|
|
|
|
/// The names matched are mostly made up as there's no standard for them, but should be familiar
|
|
|
|
/// to Windows users. They are mapped to the corresponding unix concepts as follows:
|
|
|
|
///
|
|
|
|
/// - `CTRL-CLOSE`, `CTRL+CLOSE`, or `CLOSE` for a hangup
|
|
|
|
/// - `CTRL-BREAK`, `CTRL+BREAK`, or `BREAK` for a terminate
|
|
|
|
/// - `CTRL-C`, `CTRL+C`, or `C` for an interrupt
|
|
|
|
/// - `STOP`, `FORCE-STOP` for a forced stop. This is also mapped to `KILL` and `SIGKILL`.
|
|
|
|
///
|
|
|
|
/// ```
|
2023-03-18 09:32:24 +01:00
|
|
|
/// # use watchexec_signals::Signal;
|
|
|
|
/// assert_eq!(Signal::Hangup, Signal::from_windows_str("ctrl+close").unwrap());
|
|
|
|
/// assert_eq!(Signal::Interrupt, Signal::from_windows_str("C").unwrap());
|
|
|
|
/// assert_eq!(Signal::ForceStop, Signal::from_windows_str("Stop").unwrap());
|
2023-03-05 02:57:34 +01:00
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// Using [`FromStr`] is recommended for practical use, as it will fall back to parsing as a
|
|
|
|
/// unix signal, which can be helpful for portability.
|
|
|
|
pub fn from_windows_str(s: &str) -> Result<Self, SignalParseError> {
|
2021-10-15 14:21:52 +02:00
|
|
|
match s.to_ascii_uppercase().as_str() {
|
2021-10-15 14:14:17 +02:00
|
|
|
"CTRL-CLOSE" | "CTRL+CLOSE" | "CLOSE" => Ok(Self::Hangup),
|
|
|
|
"CTRL-BREAK" | "CTRL+BREAK" | "BREAK" => Ok(Self::Terminate),
|
|
|
|
"CTRL-C" | "CTRL+C" | "C" => Ok(Self::Interrupt),
|
|
|
|
"KILL" | "SIGKILL" | "FORCE-STOP" | "STOP" => Ok(Self::ForceStop),
|
2021-10-16 06:09:21 +02:00
|
|
|
_ => Err(SignalParseError::new(s, "unknown control name")),
|
2021-10-15 14:14:17 +02:00
|
|
|
}
|
2021-10-15 14:21:52 +02:00
|
|
|
}
|
2023-03-05 02:57:34 +01:00
|
|
|
}
|
|
|
|
|
2023-03-18 09:32:24 +01:00
|
|
|
#[cfg(feature = "fromstr")]
|
|
|
|
impl FromStr for Signal {
|
2023-03-05 02:57:34 +01:00
|
|
|
type Err = SignalParseError;
|
2021-10-15 14:14:17 +02:00
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
2023-03-05 02:57:34 +01:00
|
|
|
Self::from_windows_str(s).or_else(|err| Self::from_unix_str(s).map_err(|_| err))
|
2021-10-15 14:14:17 +02:00
|
|
|
}
|
|
|
|
}
|
2023-03-18 09:32:24 +01:00
|
|
|
|
|
|
|
/// Error when parsing a signal from string.
|
|
|
|
#[cfg(feature = "fromstr")]
|
|
|
|
#[cfg_attr(feature = "miette", derive(miette::Diagnostic))]
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
|
|
#[error("invalid signal `{src}`: {err}")]
|
|
|
|
pub struct SignalParseError {
|
|
|
|
// The string that was parsed.
|
|
|
|
#[cfg_attr(feature = "miette", source_code)]
|
|
|
|
src: String,
|
|
|
|
|
|
|
|
// The error that occurred.
|
|
|
|
err: String,
|
|
|
|
|
|
|
|
// The span of the source which is in error.
|
|
|
|
#[cfg_attr(feature = "miette", label = "invalid signal")]
|
|
|
|
span: (usize, usize),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "fromstr")]
|
|
|
|
impl SignalParseError {
|
2024-01-01 06:01:14 +01:00
|
|
|
#[must_use]
|
2023-03-18 09:32:24 +01:00
|
|
|
pub fn new(src: &str, err: &str) -> Self {
|
|
|
|
Self {
|
|
|
|
src: src.to_owned(),
|
|
|
|
err: err.to_owned(),
|
|
|
|
span: (0, src.len()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for Signal {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
write!(
|
|
|
|
f,
|
|
|
|
"{}",
|
|
|
|
match (self, cfg!(windows)) {
|
|
|
|
(Self::Hangup, false) => "SIGHUP",
|
|
|
|
(Self::Hangup, true) => "CTRL-CLOSE",
|
|
|
|
(Self::ForceStop, false) => "SIGKILL",
|
|
|
|
(Self::ForceStop, true) => "STOP",
|
|
|
|
(Self::Interrupt, false) => "SIGINT",
|
|
|
|
(Self::Interrupt, true) => "CTRL-C",
|
|
|
|
(Self::Quit, _) => "SIGQUIT",
|
|
|
|
(Self::Terminate, false) => "SIGTERM",
|
|
|
|
(Self::Terminate, true) => "CTRL-BREAK",
|
|
|
|
(Self::User1, _) => "SIGUSR1",
|
|
|
|
(Self::User2, _) => "SIGUSR2",
|
|
|
|
(Self::Custom(n), _) => {
|
2024-01-01 06:01:14 +01:00
|
|
|
return write!(f, "{n}");
|
2023-03-18 09:32:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "serde")]
|
|
|
|
mod serde_support {
|
2024-01-01 06:01:14 +01:00
|
|
|
use super::Signal;
|
2023-03-18 09:32:24 +01:00
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, serde::Serialize, serde::Deserialize)]
|
|
|
|
#[serde(untagged)]
|
|
|
|
pub enum SerdeSignal {
|
|
|
|
Named(NamedSignal),
|
|
|
|
Number(i32),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, serde::Serialize, serde::Deserialize)]
|
|
|
|
#[serde(rename_all = "kebab-case")]
|
|
|
|
pub enum NamedSignal {
|
|
|
|
#[serde(rename = "SIGHUP")]
|
|
|
|
Hangup,
|
|
|
|
#[serde(rename = "SIGKILL")]
|
|
|
|
ForceStop,
|
|
|
|
#[serde(rename = "SIGINT")]
|
|
|
|
Interrupt,
|
|
|
|
#[serde(rename = "SIGQUIT")]
|
|
|
|
Quit,
|
|
|
|
#[serde(rename = "SIGTERM")]
|
|
|
|
Terminate,
|
|
|
|
#[serde(rename = "SIGUSR1")]
|
|
|
|
User1,
|
|
|
|
#[serde(rename = "SIGUSR2")]
|
|
|
|
User2,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<Signal> for SerdeSignal {
|
|
|
|
fn from(signal: Signal) -> Self {
|
|
|
|
match signal {
|
|
|
|
Signal::Hangup => Self::Named(NamedSignal::Hangup),
|
|
|
|
Signal::Interrupt => Self::Named(NamedSignal::Interrupt),
|
|
|
|
Signal::Quit => Self::Named(NamedSignal::Quit),
|
|
|
|
Signal::Terminate => Self::Named(NamedSignal::Terminate),
|
|
|
|
Signal::User1 => Self::Named(NamedSignal::User1),
|
|
|
|
Signal::User2 => Self::Named(NamedSignal::User2),
|
|
|
|
Signal::ForceStop => Self::Named(NamedSignal::ForceStop),
|
|
|
|
Signal::Custom(number) => Self::Number(number),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<SerdeSignal> for Signal {
|
|
|
|
fn from(signal: SerdeSignal) -> Self {
|
|
|
|
match signal {
|
2023-11-26 03:40:57 +01:00
|
|
|
SerdeSignal::Named(NamedSignal::Hangup) => Self::Hangup,
|
|
|
|
SerdeSignal::Named(NamedSignal::ForceStop) => Self::ForceStop,
|
|
|
|
SerdeSignal::Named(NamedSignal::Interrupt) => Self::Interrupt,
|
|
|
|
SerdeSignal::Named(NamedSignal::Quit) => Self::Quit,
|
|
|
|
SerdeSignal::Named(NamedSignal::Terminate) => Self::Terminate,
|
|
|
|
SerdeSignal::Named(NamedSignal::User1) => Self::User1,
|
|
|
|
SerdeSignal::Named(NamedSignal::User2) => Self::User2,
|
|
|
|
SerdeSignal::Number(number) => Self::Custom(number),
|
2023-03-18 09:32:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|