diff options
| author | Ivan Petkov <ivanppetkov@gmail.com> | 2015-12-19 17:12:19 -0800 |
|---|---|---|
| committer | Ivan Petkov <ivanppetkov@gmail.com> | 2015-12-25 07:09:36 -0800 |
| commit | 7f7a059c4719bbff6c2859802bc50ab2fcaf249f (patch) | |
| tree | 51a9f891865e0ca0f2ad78dcf73ba34cd24f0d96 /src/libstd | |
| parent | 439e1843b9f53a2ad9e83861f47f95227737e998 (diff) | |
| download | rust-7f7a059c4719bbff6c2859802bc50ab2fcaf249f.tar.gz rust-7f7a059c4719bbff6c2859802bc50ab2fcaf249f.zip | |
libstd: unix process spawning: fix bug with setting stdio
* If the requested descriptors to inherit are stdio descriptors there
are situations where they will not be set correctly
* Example: parent's stdout --> child's stderr
parent's stderr --> child's stdout
* Solution: if the requested descriptors for the child are stdio
descriptors, `dup` them before overwriting the child's stdio
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/sys/unix/process.rs | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index 407fcb0a1b8..671cfbd3613 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -288,6 +288,32 @@ impl Process { unsafe { libc::_exit(1) } } + // Make sure that the source descriptors are not an stdio descriptor, + // otherwise the order which we set the child's descriptors may blow + // away a descriptor which we are hoping to save. For example, + // suppose we want the child's stderr to be the parent's stdout, and + // the child's stdout to be the parent's stderr. No matter which we + // dup first, the second will get overwritten prematurely. + let maybe_migrate = |src: Stdio, output: &mut AnonPipe| { + match src { + Stdio::Raw(fd @ libc::STDIN_FILENO) | + Stdio::Raw(fd @ libc::STDOUT_FILENO) | + Stdio::Raw(fd @ libc::STDERR_FILENO) => { + let fd = match cvt_r(|| libc::dup(fd)) { + Ok(fd) => fd, + Err(_) => fail(output), + }; + let fd = FileDesc::new(fd); + fd.set_cloexec(); + Stdio::Raw(fd.into_raw()) + }, + + s @ Stdio::None | + s @ Stdio::Inherit | + s @ Stdio::Raw(_) => s, + } + }; + let setup = |src: Stdio, dst: c_int| { match src { Stdio::Inherit => true, @@ -313,6 +339,12 @@ impl Process { } }; + // Make sure we migrate all source descriptors before + // we start overwriting them + let in_fd = maybe_migrate(in_fd, &mut output); + let out_fd = maybe_migrate(out_fd, &mut output); + let err_fd = maybe_migrate(err_fd, &mut output); + if !setup(in_fd, libc::STDIN_FILENO) { fail(&mut output) } if !setup(out_fd, libc::STDOUT_FILENO) { fail(&mut output) } if !setup(err_fd, libc::STDERR_FILENO) { fail(&mut output) } |
