From 25d1f62c394567dc7de9bdf24b907f457db8399a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fe=CC=81lix=20Saparelli?= Date: Sun, 5 Nov 2023 00:06:04 +1300 Subject: [PATCH] Add start_kill() and align kill() to Tokio --- src/tokio/child.rs | 31 +++++++++++++++++++++++-------- src/tokio/child/unix.rs | 2 +- src/tokio/child/windows.rs | 2 +- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/tokio/child.rs b/src/tokio/child.rs index 801fce3..0e003f6 100644 --- a/src/tokio/child.rs +++ b/src/tokio/child.rs @@ -135,13 +135,11 @@ impl AsyncGroupChild { self.imp.into_inner() } - /// Forces the child process group to exit. If the group has already exited, an [`InvalidInput`] - /// error is returned. + /// Forces the child process group to exit. /// - /// This is equivalent to sending a SIGKILL on Unix platforms. + /// If the group has already exited, an [`InvalidInput`] error is returned. /// - /// **Unlike the Tokio implementation**, this method does not wait for the child process group, - /// and only sends the kill. You’ll need to call [`wait()`](Self::wait) yourself. + /// This is equivalent to sending a SIGKILL on Unix platforms. /// /// See [the Tokio documentation](Child::kill) for more. /// @@ -157,7 +155,7 @@ impl AsyncGroupChild { /// /// let mut command = Command::new("yes"); /// if let Ok(mut child) = command.group_spawn() { - /// child.kill().expect("command wasn't running"); + /// child.kill().await.expect("command wasn't running"); /// } else { /// println!("yes command didn't start"); /// } @@ -165,8 +163,25 @@ impl AsyncGroupChild { /// ``` /// /// [`InvalidInput`]: std::io::ErrorKind::InvalidInput - pub fn kill(&mut self) -> Result<()> { - self.imp.kill() + pub async fn kill(&mut self) -> Result<()> { + self.start_kill()?; + self.wait().await?; + Ok(()) + } + + /// Attempts to force the child to exit, but does not wait for the request to take effect. + /// + /// This is equivalent to sending a SIGKILL on Unix platforms. + /// + /// Note that on Unix platforms it is possible for a zombie process to remain after a kill is + /// sent; to avoid this, the caller should ensure that either `child.wait().await` or + /// `child.try_wait()` is invoked successfully. + /// + /// See [the Tokio documentation](Child::start_kill) for more. + /// + /// [`InvalidInput`]: std::io::ErrorKind::InvalidInput + pub fn start_kill(&mut self) -> Result<()> { + self.imp.start_kill() } /// Returns the OS-assigned process group identifier. diff --git a/src/tokio/child/unix.rs b/src/tokio/child/unix.rs index 5c23ad4..6387a5f 100644 --- a/src/tokio/child/unix.rs +++ b/src/tokio/child/unix.rs @@ -61,7 +61,7 @@ impl ChildImp { killpg(self.pgid, sig).map_err(Error::from) } - pub fn kill(&mut self) -> Result<()> { + pub fn start_kill(&mut self) -> Result<()> { self.signal_imp(Signal::SIGKILL) } diff --git a/src/tokio/child/windows.rs b/src/tokio/child/windows.rs index d1290a0..4af01cc 100644 --- a/src/tokio/child/windows.rs +++ b/src/tokio/child/windows.rs @@ -59,7 +59,7 @@ impl ChildImp { self.inner } - pub fn kill(&mut self) -> Result<()> { + pub fn start_kill(&mut self) -> Result<()> { res_bool(unsafe { TerminateJobObject(self.handles.job, 1) }) }