process: add missing drop child stdin to wait() (#3421)

This commit is contained in:
Ivan Petkov 2021-01-28 14:08:44 -08:00 committed by GitHub
parent 225e8ea05f
commit 1f9765fb5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -990,7 +990,36 @@ impl Child {
/// before waiting. This helps avoid deadlock: it ensures that the
/// child does not block waiting for input from the parent, while
/// the parent waits for the child to exit.
///
/// If the caller wishes to explicitly control when the child's stdin
/// handle is closed, they may `.take()` it before calling `.wait()`:
///
/// ```no_run
/// use tokio::io::AsyncWriteExt;
/// use tokio::process::Command;
///
/// #[tokio::main]
/// async fn main() {
/// let mut child = Command::new("cat").spawn().unwrap();
///
/// let mut stdin = child.stdin.take().unwrap();
/// tokio::spawn(async move {
/// // do something with stdin here...
/// stdin.write_all(b"hello world\n").await.unwrap();
///
/// // then drop when finished
/// drop(stdin);
/// });
///
/// // wait for the process to complete
/// let _ = child.wait().await;
/// }
/// ```
pub async fn wait(&mut self) -> io::Result<ExitStatus> {
// Ensure stdin is closed so the child isn't stuck waiting on
// input while the parent is waiting for it to exit.
drop(self.stdin.take());
match &mut self.child {
FusedChild::Done(exit) => Ok(*exit),
FusedChild::Child(child) => {
@ -1064,7 +1093,6 @@ impl Child {
Ok(vec)
}
drop(self.stdin.take());
let stdout_fut = read_to_end(self.stdout.take());
let stderr_fut = read_to_end(self.stderr.take());