use super::Session;
use crate::{Error, Result, Signal};
impl Session {
pub fn signal_process(&self, signal: Signal) -> Result<()> {
let pid = self.terminal.process_id().ok_or(Error::MissingProcessId)?;
signal_process_id(pid, signal)
}
pub fn signal_group(&self, signal: Signal) -> Result<()> {
let pid = self.terminal.process_id().ok_or(Error::MissingProcessId)?;
signal_process_group(pid, signal)
}
}
#[cfg(unix)]
fn signal_impl(pid: i32, signal: Signal) -> Result<()> {
let sig =
nix::sys::signal::Signal::try_from(signal.number()).map_err(|source| Error::Signal {
signal,
source: std::io::Error::from_raw_os_error(source as i32),
})?;
nix::sys::signal::kill(nix::unistd::Pid::from_raw(pid), sig).map_err(|source| Error::Signal {
signal,
source: source.into(),
})
}
#[cfg(not(unix))]
fn signal_impl(_pid: i32, _signal: Signal) -> Result<()> {
Err(Error::UnsupportedSignal)
}
fn signal_process_id(pid: u32, signal: Signal) -> Result<()> {
signal_impl(pid as i32, signal)
}
fn signal_process_group(pid: u32, signal: Signal) -> Result<()> {
signal_impl(-(pid as i32), signal)
}
pub(super) fn send_group_signal_silencing_esrch(session: &Session, signal: Signal) -> Result<()> {
match session.signal_group(signal) {
Ok(()) => Ok(()),
Err(err) if is_esrch(&err) => Ok(()),
Err(err) => Err(err),
}
}
fn is_esrch(err: &Error) -> bool {
#[cfg(unix)]
{
matches!(
err,
Error::Signal { source, .. }
if source.raw_os_error() == Some(nix::libc::ESRCH)
)
}
#[cfg(not(unix))]
{
let _ = err;
false
}
}