Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std: get rid of sys_common::process #139020

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 44 additions & 4 deletions library/std/src/process.rs
Original file line number Diff line number Diff line change
@@ -168,8 +168,6 @@ use crate::num::NonZero;
use crate::path::Path;
use crate::sys::pipe::{AnonPipe, read2};
use crate::sys::process as imp;
#[stable(feature = "command_access", since = "1.57.0")]
pub use crate::sys_common::process::CommandEnvs;
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
use crate::{fmt, fs, str};

@@ -1073,7 +1071,7 @@ impl Command {
/// ```
#[stable(feature = "process", since = "1.0.0")]
pub fn output(&mut self) -> io::Result<Output> {
let (status, stdout, stderr) = self.inner.output()?;
let (status, stdout, stderr) = imp::output(&mut self.inner)?;
Ok(Output { status: ExitStatus(status), stdout, stderr })
}

@@ -1174,7 +1172,7 @@ impl Command {
/// ```
#[stable(feature = "command_access", since = "1.57.0")]
pub fn get_envs(&self) -> CommandEnvs<'_> {
self.inner.get_envs()
CommandEnvs { iter: self.inner.get_envs() }
}

/// Returns the working directory for the child process.
@@ -1264,6 +1262,48 @@ impl<'a> ExactSizeIterator for CommandArgs<'a> {
}
}

/// An iterator over the command environment variables.
///
/// This struct is created by
/// [`Command::get_envs`][crate::process::Command::get_envs]. See its
/// documentation for more.
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "command_access", since = "1.57.0")]
pub struct CommandEnvs<'a> {
iter: imp::CommandEnvs<'a>,
}

#[stable(feature = "command_access", since = "1.57.0")]
impl<'a> Iterator for CommandEnvs<'a> {
type Item = (&'a OsStr, Option<&'a OsStr>);

fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}

fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}

#[stable(feature = "command_access", since = "1.57.0")]
impl<'a> ExactSizeIterator for CommandEnvs<'a> {
fn len(&self) -> usize {
self.iter.len()
}

fn is_empty(&self) -> bool {
self.iter.is_empty()
}
}

#[stable(feature = "command_access", since = "1.57.0")]
impl<'a> fmt::Debug for CommandEnvs<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.iter.fmt(f)
}
}

/// The output of a finished process.
///
/// This is returned in a Result by either the [`output`] method of a
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
#![allow(dead_code)]
#![unstable(feature = "process_internals", issue = "none")]

use crate::collections::BTreeMap;
use crate::ffi::{OsStr, OsString};
use crate::sys::pipe::read2;
use crate::sys::process::{EnvKey, ExitStatus, Process, StdioPipes};
use crate::{env, fmt, io};
use crate::sys::process::EnvKey;
use crate::{env, fmt};

// Stores a set of changes to an environment
/// Stores a set of changes to an environment
#[derive(Clone, Default)]
pub struct CommandEnv {
clear: bool,
@@ -92,30 +88,23 @@ impl CommandEnv {
}
}

/// An iterator over the command environment variables.
///
/// This struct is created by
/// [`Command::get_envs`][crate::process::Command::get_envs]. See its
/// documentation for more.
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "command_access", since = "1.57.0")]
#[derive(Debug)]
pub struct CommandEnvs<'a> {
iter: crate::collections::btree_map::Iter<'a, EnvKey, Option<OsString>>,
}

#[stable(feature = "command_access", since = "1.57.0")]
impl<'a> Iterator for CommandEnvs<'a> {
type Item = (&'a OsStr, Option<&'a OsStr>);

fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|(key, value)| (key.as_ref(), value.as_deref()))
}

fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}

#[stable(feature = "command_access", since = "1.57.0")]
impl<'a> ExactSizeIterator for CommandEnvs<'a> {
fn len(&self) -> usize {
self.iter.len()
@@ -124,30 +113,3 @@ 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))
}
59 changes: 59 additions & 0 deletions library/std/src/sys/process/mod.rs
Original file line number Diff line number Diff line change
@@ -14,6 +14,65 @@ cfg_if::cfg_if! {
}
}

// This module is shared by all platforms, but nearly all platforms except for
// the "normal" UNIX ones leave some of this code unused.
#[cfg_attr(not(target_os = "linux"), allow(dead_code))]
mod env;

pub use env::CommandEnvs;
pub use imp::{
Command, CommandArgs, EnvKey, ExitCode, ExitStatus, ExitStatusError, Process, Stdio, StdioPipes,
};

#[cfg(any(
all(
target_family = "unix",
not(any(
target_os = "espidf",
target_os = "horizon",
target_os = "vita",
target_os = "nuttx"
))
),
target_os = "windows",
))]
pub fn output(cmd: &mut Command) -> crate::io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
use crate::sys::pipe::read2;

let (mut process, mut pipes) = cmd.spawn(Stdio::MakePipe, false)?;

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))
}

#[cfg(not(any(
all(
target_family = "unix",
not(any(
target_os = "espidf",
target_os = "horizon",
target_os = "vita",
target_os = "nuttx"
))
),
target_os = "windows",
)))]
pub use imp::output;
98 changes: 49 additions & 49 deletions library/std/src/sys/process/uefi.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use r_efi::protocols::simple_text_output;

use super::env::{CommandEnv, CommandEnvs};
use crate::collections::BTreeMap;
pub use crate::ffi::OsString as EnvKey;
use crate::ffi::{OsStr, OsString};
@@ -10,7 +11,6 @@ use crate::sys::pal::helpers;
use crate::sys::pal::os::error_string;
use crate::sys::pipe::AnonPipe;
use crate::sys::unsupported;
use crate::sys_common::process::{CommandEnv, CommandEnvs};
use crate::{fmt, io};

////////////////////////////////////////////////////////////////////////////////
@@ -121,63 +121,63 @@ impl Command {
Stdio::Inherit => Ok(None),
}
}
}

pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
let mut cmd = uefi_command_internal::Image::load_image(&self.prog)?;

// UEFI adds the bin name by default
if !self.args.is_empty() {
let args = uefi_command_internal::create_args(&self.prog, &self.args);
cmd.set_args(args);
}

// Setup Stdout
let stdout = self.stdout.unwrap_or(Stdio::MakePipe);
let stdout = Self::create_pipe(stdout)?;
if let Some(con) = stdout {
cmd.stdout_init(con)
} else {
cmd.stdout_inherit()
};

// Setup Stderr
let stderr = self.stderr.unwrap_or(Stdio::MakePipe);
let stderr = Self::create_pipe(stderr)?;
if let Some(con) = stderr {
cmd.stderr_init(con)
} else {
cmd.stderr_inherit()
};

let env = env_changes(&self.env);

// Set any new vars
if let Some(e) = &env {
for (k, (_, v)) in e {
match v {
Some(v) => unsafe { crate::env::set_var(k, v) },
None => unsafe { crate::env::remove_var(k) },
}
pub fn output(command: &mut Command) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
let mut cmd = uefi_command_internal::Image::load_image(&command.prog)?;

// UEFI adds the bin name by default
if !command.args.is_empty() {
let args = uefi_command_internal::create_args(&command.prog, &command.args);
cmd.set_args(args);
}

// Setup Stdout
let stdout = command.stdout.unwrap_or(Stdio::MakePipe);
let stdout = Command::create_pipe(stdout)?;
if let Some(con) = stdout {
cmd.stdout_init(con)
} else {
cmd.stdout_inherit()
};

// Setup Stderr
let stderr = command.stderr.unwrap_or(Stdio::MakePipe);
let stderr = Command::create_pipe(stderr)?;
if let Some(con) = stderr {
cmd.stderr_init(con)
} else {
cmd.stderr_inherit()
};

let env = env_changes(&command.env);

// Set any new vars
if let Some(e) = &env {
for (k, (_, v)) in e {
match v {
Some(v) => unsafe { crate::env::set_var(k, v) },
None => unsafe { crate::env::remove_var(k) },
}
}
}

let stat = cmd.start_image()?;
let stat = cmd.start_image()?;

// Rollback any env changes
if let Some(e) = env {
for (k, (v, _)) in e {
match v {
Some(v) => unsafe { crate::env::set_var(k, v) },
None => unsafe { crate::env::remove_var(k) },
}
// Rollback any env changes
if let Some(e) = env {
for (k, (v, _)) in e {
match v {
Some(v) => unsafe { crate::env::set_var(k, v) },
None => unsafe { crate::env::remove_var(k) },
}
}
}

let stdout = cmd.stdout()?;
let stderr = cmd.stderr()?;
let stdout = cmd.stdout()?;
let stderr = cmd.stderr()?;

Ok((ExitStatus(stat), stdout, stderr))
}
Ok((ExitStatus(stat), stdout, stderr))
}

impl From<AnonPipe> for Stdio {
2 changes: 1 addition & 1 deletion library/std/src/sys/process/unix/common.rs
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ use crate::sys::fs::File;
#[cfg(not(target_os = "fuchsia"))]
use crate::sys::fs::OpenOptions;
use crate::sys::pipe::{self, AnonPipe};
use crate::sys_common::process::{CommandEnv, CommandEnvs};
use crate::sys::process::env::{CommandEnv, CommandEnvs};
use crate::sys_common::{FromInner, IntoInner};
use crate::{fmt, io, ptr};

5 changes: 0 additions & 5 deletions library/std/src/sys/process/unix/fuchsia.rs
Original file line number Diff line number Diff line change
@@ -31,11 +31,6 @@ 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_error!(
5 changes: 0 additions & 5 deletions library/std/src/sys/process/unix/unix.rs
Original file line number Diff line number Diff line change
@@ -162,11 +162,6 @@ 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)
}

// WatchOS and TVOS headers mark the `fork`/`exec*` functions with
// `__WATCHOS_PROHIBITED __TVOS_PROHIBITED`, and indicate that the
// `posix_spawn*` functions should be used instead. It isn't entirely clear
Loading
Oops, something went wrong.
Loading
Oops, something went wrong.