about summary refs log tree commit diff
path: root/library/std/src/sys_common
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-12-17 23:44:26 +0100
committerGitHub <noreply@github.com>2022-12-17 23:44:26 +0100
commit6d1cdcaee52e357dfb3500091bdd18a2e0c763ff (patch)
tree8c77db364a89edb08e1552ac86b4d74a6baae5a1 /library/std/src/sys_common
parent5dc0b6ff6d76cefa32b1393800067c743f163dcc (diff)
parenta94793d8d17e4cfe2e727c30c36e174b8d6b6ee3 (diff)
downloadrust-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.rs31
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))
+}