mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-21 17:52:12 +03:00
Add send_process_group_signal to existing unix_send_signal feature
This function wraps POSIX `killpg()`, and on Linux additionally may be implemented by `pidfd_send_signal`.
This commit is contained in:
@@ -420,6 +420,38 @@ pub trait ChildExt: Sealed {
|
||||
/// }
|
||||
/// ```
|
||||
fn send_signal(&self, signal: i32) -> io::Result<()>;
|
||||
|
||||
/// Sends a signal to a child process's process group.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function will return an error if the signal is invalid or if the
|
||||
/// child process does not have a process group. The integer values
|
||||
/// associated with signals are implementation-specific, so it's encouraged
|
||||
/// to use a crate that provides posix bindings.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(unix_send_signal)]
|
||||
///
|
||||
/// use std::{io, os::unix::process::{ChildExt, CommandExt}, process::{Command, Stdio}};
|
||||
///
|
||||
/// use libc::SIGTERM;
|
||||
///
|
||||
/// fn main() -> io::Result<()> {
|
||||
/// # if cfg!(not(all(target_vendor = "apple", not(target_os = "macos")))) {
|
||||
/// let child = Command::new("cat")
|
||||
/// .stdin(Stdio::piped())
|
||||
/// .process_group(0)
|
||||
/// .spawn()?;
|
||||
/// child.send_process_group_signal(SIGTERM)?;
|
||||
/// # }
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "unix_send_signal", issue = "141975")]
|
||||
fn send_process_group_signal(&self, signal: i32) -> io::Result<()>;
|
||||
}
|
||||
|
||||
#[unstable(feature = "unix_send_signal", issue = "141975")]
|
||||
@@ -427,6 +459,10 @@ impl ChildExt for process::Child {
|
||||
fn send_signal(&self, signal: i32) -> io::Result<()> {
|
||||
self.handle.send_signal(signal)
|
||||
}
|
||||
|
||||
fn send_process_group_signal(&self, signal: i32) -> io::Result<()> {
|
||||
self.handle.send_process_group_signal(signal)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "process_extensions", since = "1.2.0")]
|
||||
|
||||
@@ -95,6 +95,21 @@ pub(crate) fn send_signal(&self, signal: i32) -> io::Result<()> {
|
||||
.map(drop)
|
||||
}
|
||||
|
||||
pub(crate) fn send_process_group_signal(&self, signal: i32) -> io::Result<()> {
|
||||
// since kernel 6.9
|
||||
// https://lore.kernel.org/all/20240210-chihuahua-hinzog-3945b6abd44a@brauner/
|
||||
cvt(unsafe {
|
||||
libc::syscall(
|
||||
libc::SYS_pidfd_send_signal,
|
||||
self.0.as_raw_fd(),
|
||||
signal,
|
||||
crate::ptr::null::<()>(),
|
||||
libc::PIDFD_SIGNAL_PROCESS_GROUP,
|
||||
)
|
||||
})
|
||||
.map(drop)
|
||||
}
|
||||
|
||||
pub fn wait(&self) -> io::Result<ExitStatus> {
|
||||
let r = self.waitid(libc::WEXITED)?;
|
||||
match r {
|
||||
|
||||
@@ -158,6 +158,11 @@ pub fn send_signal(&self, _signal: i32) -> io::Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn send_process_group_signal(&self, _signal: i32) -> io::Result<()> {
|
||||
// Fuchsia doesn't have a direct equivalent for signals
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn wait(&mut self) -> io::Result<ExitStatus> {
|
||||
let mut proc_info: zx_info_process_t = Default::default();
|
||||
let mut actual: size_t = 0;
|
||||
|
||||
@@ -1002,6 +1002,19 @@ pub(crate) fn send_signal(&self, signal: i32) -> io::Result<()> {
|
||||
cvt(unsafe { libc::kill(self.pid, signal) }).map(drop)
|
||||
}
|
||||
|
||||
pub(crate) fn send_process_group_signal(&self, signal: i32) -> io::Result<()> {
|
||||
// See note in `send_signal` regarding recycled PIDs.
|
||||
if self.status.is_some() {
|
||||
return Ok(());
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
if let Some(pid_fd) = self.pidfd.as_ref() {
|
||||
// The `PIDFD_SIGNAL_PROCESS_GROUP` flag requires kernel >= 6.9
|
||||
return pid_fd.send_process_group_signal(signal);
|
||||
}
|
||||
cvt(unsafe { libc::killpg(self.pid, signal) }).map(drop)
|
||||
}
|
||||
|
||||
pub fn wait(&mut self) -> io::Result<ExitStatus> {
|
||||
use crate::sys::cvt_r;
|
||||
if let Some(status) = self.status {
|
||||
|
||||
@@ -49,6 +49,10 @@ pub fn send_signal(&self, _signal: i32) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn send_process_group_signal(&self, _signal: i32) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn wait(&mut self) -> io::Result<ExitStatus> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
@@ -161,6 +161,14 @@ pub fn send_signal(&self, signal: i32) -> io::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_process_group_signal(&self, signal: i32) -> io::Result<()> {
|
||||
// See note in `send_signal` regarding recycled PIDs.
|
||||
if self.status.is_some() {
|
||||
return Ok(());
|
||||
}
|
||||
cvt(unsafe { libc::killpg(self.pid, signal) }).map(drop)
|
||||
}
|
||||
|
||||
pub fn wait(&mut self) -> io::Result<ExitStatus> {
|
||||
use crate::sys::cvt_r;
|
||||
if let Some(status) = self.status {
|
||||
|
||||
Reference in New Issue
Block a user