diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2022-12-17 23:44:26 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-12-17 23:44:26 +0100 |
| commit | 6d1cdcaee52e357dfb3500091bdd18a2e0c763ff (patch) | |
| tree | 8c77db364a89edb08e1552ac86b4d74a6baae5a1 /library/std/src/sys_common | |
| parent | 5dc0b6ff6d76cefa32b1393800067c743f163dcc (diff) | |
| parent | a94793d8d17e4cfe2e727c30c36e174b8d6b6ee3 (diff) | |
| download | rust-6d1cdcaee52e357dfb3500091bdd18a2e0c763ff.tar.gz rust-6d1cdcaee52e357dfb3500091bdd18a2e0c763ff.zip | |
Rollup merge of #105458 - Ayush1325:blocking_spawn, r=Mark-Simulacrum
Allow blocking `Command::output` ### Problem Currently, `Command::output` is internally implemented using `Command::spawn`. This is problematic because some targets (like UEFI) do not actually support multitasking and thus block while the program is executing. This coupling does not make much sense as `Command::output` is supposed to block until the execution is complete anyway and thus does not need to rely on a non-blocking `Child` or any other intermediate. ### Solution This PR moves the implementation of `Command::output` to `std::sys`. This means targets can choose to implement only `Command::output` without having to implement `Command::spawn`. ### Additional Information This was originally conceived when working on https://github.com/rust-lang/rust/pull/100316. Currently, the only target I know about that will benefit from this change is UEFI. This PR can also be used to implement more efficient `Command::output` since the intermediate `Process` is not actually needed anymore, but that is outside the scope of this PR. Since this is not a public API change, I'm not sure if an RFC is needed or not.
Diffstat (limited to 'library/std/src/sys_common')
| -rw-r--r-- | library/std/src/sys_common/process.rs | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/library/std/src/sys_common/process.rs b/library/std/src/sys_common/process.rs index 9f978789a62..ae11412067b 100644 --- a/library/std/src/sys_common/process.rs +++ b/library/std/src/sys_common/process.rs @@ -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)) +} |
