Merge pull request #20 from doy/multiple-spawns

don't unconfigure stdio streams on spawn
This commit is contained in:
Taiki Endo 2021-12-31 14:31:29 +09:00 committed by GitHub
commit aa5e6c7cb4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 23 deletions

View File

@ -618,9 +618,9 @@ impl io::AsyncRead for ChildStderr {
/// ```
pub struct Command {
inner: std::process::Command,
stdin: Option<Stdio>,
stdout: Option<Stdio>,
stderr: Option<Stdio>,
stdin: bool,
stdout: bool,
stderr: bool,
reap_on_drop: bool,
kill_on_drop: bool,
}
@ -641,9 +641,9 @@ impl Command {
pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
Command {
inner: std::process::Command::new(program),
stdin: None,
stdout: None,
stderr: None,
stdin: false,
stdout: false,
stderr: false,
reap_on_drop: true,
kill_on_drop: false,
}
@ -785,7 +785,8 @@ impl Command {
/// cmd.stdin(Stdio::null());
/// ```
pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
self.stdin = Some(cfg.into());
self.stdin = true;
self.inner.stdin(cfg);
self
}
@ -800,7 +801,8 @@ impl Command {
/// cmd.stdout(Stdio::piped());
/// ```
pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
self.stdout = Some(cfg.into());
self.stdout = true;
self.inner.stdout(cfg);
self
}
@ -815,7 +817,8 @@ impl Command {
/// cmd.stderr(Stdio::piped());
/// ```
pub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
self.stderr = Some(cfg.into());
self.stderr = true;
self.inner.stderr(cfg);
self
}
@ -865,8 +868,6 @@ impl Command {
///
/// If not configured, stdin, stdout and stderr will be set to [`Stdio::inherit()`].
///
/// After spawning the process, stdin, stdout, and stderr become unconfigured again.
///
/// # Examples
///
/// ```no_run
@ -877,10 +878,15 @@ impl Command {
/// # std::io::Result::Ok(()) });
/// ```
pub fn spawn(&mut self) -> io::Result<Child> {
let (stdin, stdout, stderr) = (self.stdin.take(), self.stdout.take(), self.stderr.take());
self.inner.stdin(stdin.unwrap_or_else(Stdio::inherit));
self.inner.stdout(stdout.unwrap_or_else(Stdio::inherit));
self.inner.stderr(stderr.unwrap_or_else(Stdio::inherit));
if !self.stdin {
self.inner.stdin(Stdio::inherit());
}
if !self.stdout {
self.inner.stdout(Stdio::inherit());
}
if !self.stderr {
self.inner.stderr(Stdio::inherit());
}
Child::new(self)
}
@ -889,8 +895,6 @@ impl Command {
///
/// If not configured, stdin, stdout and stderr will be set to [`Stdio::inherit()`].
///
/// After spawning the process, stdin, stdout, and stderr become unconfigured again.
///
/// # Examples
///
/// ```no_run
@ -914,8 +918,6 @@ impl Command {
/// If not configured, stdin will be set to [`Stdio::null()`], and stdout and stderr will be
/// set to [`Stdio::piped()`].
///
/// After spawning the process, stdin, stdout, and stderr become unconfigured again.
///
/// # Examples
///
/// ```no_run
@ -929,10 +931,15 @@ impl Command {
/// # std::io::Result::Ok(()) });
/// ```
pub fn output(&mut self) -> impl Future<Output = io::Result<Output>> {
let (stdin, stdout, stderr) = (self.stdin.take(), self.stdout.take(), self.stderr.take());
self.inner.stdin(stdin.unwrap_or_else(Stdio::null));
self.inner.stdout(stdout.unwrap_or_else(Stdio::piped));
self.inner.stderr(stderr.unwrap_or_else(Stdio::piped));
if !self.stdin {
self.inner.stdin(Stdio::null());
}
if !self.stdout {
self.inner.stdout(Stdio::piped());
}
if !self.stderr {
self.inner.stderr(Stdio::piped());
}
let child = Child::new(self);
async { child?.output().await }

View File

@ -407,3 +407,25 @@ fn child_as_raw_handle() {
assert_eq!(win_pid, std_pid);
})
}
#[test]
#[cfg(unix)]
fn test_spawn_multiple_with_stdio() {
let mut cmd = Command::new("/bin/sh");
cmd.arg("-c")
.arg("echo foo; echo bar 1>&2")
.stdout(Stdio::piped())
.stderr(Stdio::piped());
future::block_on(async move {
let p1 = cmd.spawn().unwrap();
let out1 = p1.output().await.unwrap();
assert_eq!(out1.stdout, b"foo\n");
assert_eq!(out1.stderr, b"bar\n");
let p2 = cmd.spawn().unwrap();
let out2 = p2.output().await.unwrap();
assert_eq!(out2.stdout, b"foo\n");
assert_eq!(out2.stderr, b"bar\n");
});
}