Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

process: make Child::kill async #2823

Merged
merged 2 commits into from Sep 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
36 changes: 23 additions & 13 deletions tokio/src/process/mod.rs
Expand Up @@ -774,6 +774,23 @@ impl Child {
}
}

/// Attempts to force the child to exit, but does not wait for the request
/// to take effect.
///
/// On Unix platforms, this is the equivalent to sending a SIGKILL. 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.
pub fn start_kill(&mut self) -> io::Result<()> {
match &mut self.child {
FusedChild::Child(child) => child.kill(),
FusedChild::Done(_) => Err(io::Error::new(
io::ErrorKind::InvalidInput,
"invalid argument: can't kill an exited process",
)),
}
}

/// Forces the child to exit.
///
/// This is equivalent to sending a SIGKILL on unix platforms.
Expand All @@ -795,21 +812,14 @@ impl Child {
/// tokio::spawn(async move { send.send(()) });
/// tokio::select! {
/// _ = child.wait() => {}
/// _ = recv => {
/// child.kill().expect("kill failed");
/// // NB: await the child here to avoid a zombie process on Unix platforms
/// child.wait().await.unwrap();
/// }
/// _ = recv => child.kill().await.expect("kill failed"),
/// }
/// }
pub fn kill(&mut self) -> io::Result<()> {
match &mut self.child {
FusedChild::Child(child) => child.kill(),
FusedChild::Done(_) => Err(io::Error::new(
io::ErrorKind::InvalidInput,
"invalid argument: can't kill an exited process",
)),
}
/// ```
pub async fn kill(&mut self) -> io::Result<()> {
self.start_kill()?;
self.wait().await?;
Ok(())
}

/// Waits for the child to exit completely, returning the status that it
Expand Down
3 changes: 1 addition & 2 deletions tokio/tests/process_issue_2174.rs
Expand Up @@ -39,8 +39,7 @@ async fn issue_2174() {
time::delay_for(Duration::from_secs(1)).await;

// Kill the child process.
child.kill().unwrap();
let _ = child.wait().await;
child.kill().await.unwrap();

assert_err!(handle.await);
}