Implement blocking output
This allows decoupling `Command::spawn` and `Command::output`. This is useful for targets which do support launching programs in blocking mode but do not support multitasking (Eg: UEFI). This was originally conceived when working on https://github.com/rust-lang/rust/pull/100316 Signed-off-by: Ayush Singh <ayushsingh1325@gmail.com>
This commit is contained in:
parent
5479fe5f70
commit
a94793d8d1
9 changed files with 61 additions and 6 deletions
|
@ -911,10 +911,8 @@ impl Command {
|
|||
/// ```
|
||||
#[stable(feature = "process", since = "1.0.0")]
|
||||
pub fn output(&mut self) -> io::Result<Output> {
|
||||
self.inner
|
||||
.spawn(imp::Stdio::MakePipe, false)
|
||||
.map(Child::from_inner)
|
||||
.and_then(|p| p.wait_with_output())
|
||||
let (status, stdout, stderr) = self.inner.output()?;
|
||||
Ok(Output { status: ExitStatus(status), stdout, stderr })
|
||||
}
|
||||
|
||||
/// Executes a command as a child process, waiting for it to finish and
|
||||
|
|
|
@ -35,6 +35,11 @@ impl Command {
|
|||
Ok((Process { handle: Handle::new(process_handle) }, ours))
|
||||
}
|
||||
|
||||
pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
|
||||
let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
|
||||
crate::sys_common::process::wait_with_output(proc, pipes)
|
||||
}
|
||||
|
||||
pub fn exec(&mut self, default: Stdio) -> io::Error {
|
||||
if self.saw_nul() {
|
||||
return io::const_io_error!(
|
||||
|
|
|
@ -132,6 +132,11 @@ impl Command {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
|
||||
let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
|
||||
crate::sys_common::process::wait_with_output(proc, pipes)
|
||||
}
|
||||
|
||||
// Attempts to fork the process. If successful, returns Ok((0, -1))
|
||||
// in the child, and Ok((child_pid, -1)) in the parent.
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
|
|
|
@ -20,6 +20,10 @@ impl Command {
|
|||
unsupported()
|
||||
}
|
||||
|
||||
pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn exec(&mut self, _default: Stdio) -> io::Error {
|
||||
unsupported_err()
|
||||
}
|
||||
|
|
|
@ -108,6 +108,11 @@ impl Command {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
|
||||
let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
|
||||
crate::sys_common::process::wait_with_output(proc, pipes)
|
||||
}
|
||||
|
||||
pub fn exec(&mut self, default: Stdio) -> io::Error {
|
||||
let ret = Command::spawn(self, default, false);
|
||||
match ret {
|
||||
|
|
|
@ -15,7 +15,7 @@ impl AnonPipe {
|
|||
self.0
|
||||
}
|
||||
|
||||
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
pub fn read_to_end(&self, _buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
|
|
|
@ -75,6 +75,10 @@ impl Command {
|
|||
) -> io::Result<(Process, StdioPipes)> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
|
||||
unsupported()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AnonPipe> for Stdio {
|
||||
|
|
|
@ -351,6 +351,11 @@ impl Command {
|
|||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
|
||||
let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
|
||||
crate::sys_common::process::wait_with_output(proc, pipes)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Command {
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
use crate::collections::BTreeMap;
|
||||
use crate::env;
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::sys::process::EnvKey;
|
||||
use crate::io;
|
||||
use crate::sys::pipe::read2;
|
||||
use crate::sys::process::{EnvKey, ExitStatus, Process, StdioPipes};
|
||||
|
||||
// Stores a set of changes to an environment
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -117,3 +119,30 @@ impl<'a> ExactSizeIterator for CommandEnvs<'a> {
|
|||
self.iter.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wait_with_output(
|
||||
mut process: Process,
|
||||
mut pipes: StdioPipes,
|
||||
) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
|
||||
drop(pipes.stdin.take());
|
||||
|
||||
let (mut stdout, mut stderr) = (Vec::new(), Vec::new());
|
||||
match (pipes.stdout.take(), pipes.stderr.take()) {
|
||||
(None, None) => {}
|
||||
(Some(out), None) => {
|
||||
let res = out.read_to_end(&mut stdout);
|
||||
res.unwrap();
|
||||
}
|
||||
(None, Some(err)) => {
|
||||
let res = err.read_to_end(&mut stderr);
|
||||
res.unwrap();
|
||||
}
|
||||
(Some(out), Some(err)) => {
|
||||
let res = read2(out, &mut stdout, err, &mut stderr);
|
||||
res.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
let status = process.wait()?;
|
||||
Ok((status, stdout, stderr))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue