Skip to content

Commit

Permalink
Process::new etc should support non-utf8 commands/args
Browse files Browse the repository at this point in the history
The existing APIs for spawning processes took strings for the command
and arguments, but the underlying system may not impose utf8 encoding,
so this is overly limiting.

The assumption we actually want to make is just that the command and
arguments are viewable as [u8] slices with no interior NULLs, i.e., as
CStrings. The ToCStr trait is a handy bound for types that meet this
requirement (such as &str and Path).

However, since the commands and arguments are often a mixture of
strings and paths, it would be inconvenient to take a slice with a
single T: ToCStr bound. So this patch revamps the process creation API
to instead use a builder-style interface, called `Command`, allowing
arguments to be added one at a time with differing ToCStr
implementations for each.

The initial cut of the builder API has some drawbacks that can be
addressed once issue rust-lang#13851 (libstd as a facade) is closed. These are
detailed as FIXMEs.

Closes rust-lang#11650.

[breaking-change]
  • Loading branch information
aturon committed May 7, 2014
1 parent 4e32b52 commit bf58bfe
Show file tree
Hide file tree
Showing 22 changed files with 639 additions and 679 deletions.
20 changes: 3 additions & 17 deletions src/compiletest/procsrv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

use std::os;
use std::str;
use std::io::process::{ProcessExit, Process, ProcessConfig, ProcessOutput};
use std::io::process::{ProcessExit, Command, Process, ProcessOutput};

#[cfg(target_os = "win32")]
fn target_env(lib_path: &str, prog: &str) -> Vec<(~str, ~str)> {
Expand Down Expand Up @@ -68,14 +68,7 @@ pub fn run(lib_path: &str,
input: Option<~str>) -> Option<Result> {

let env = env.clone().append(target_env(lib_path, prog).as_slice());
let mut opt_process = Process::configure(ProcessConfig {
program: prog,
args: args,
env: Some(env.as_slice()),
.. ProcessConfig::new()
});

match opt_process {
match Command::new(prog).args(args).env(env.as_slice()).spawn() {
Ok(ref mut process) => {
for input in input.iter() {
process.stdin.get_mut_ref().write(input.as_bytes()).unwrap();
Expand All @@ -99,14 +92,7 @@ pub fn run_background(lib_path: &str,
input: Option<~str>) -> Option<Process> {

let env = env.clone().append(target_env(lib_path, prog).as_slice());
let opt_process = Process::configure(ProcessConfig {
program: prog,
args: args,
env: Some(env.as_slice()),
.. ProcessConfig::new()
});

match opt_process {
match Command::new(prog).args(args).env(env.as_slice()).spawn() {
Ok(mut process) => {
for input in input.iter() {
process.stdin.get_mut_ref().write(input.as_bytes()).unwrap();
Expand Down
7 changes: 3 additions & 4 deletions src/libnative/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,14 @@ use std::c_str::CString;
use std::io;
use std::io::IoError;
use std::io::net::ip::SocketAddr;
use std::io::process::ProcessConfig;
use std::io::signal::Signum;
use libc::c_int;
use libc;
use std::os;
use std::rt::rtio;
use std::rt::rtio::{RtioTcpStream, RtioTcpListener, RtioUdpSocket,
RtioUnixListener, RtioPipe, RtioFileStream, RtioProcess,
RtioSignal, RtioTTY, CloseBehavior, RtioTimer};
RtioSignal, RtioTTY, CloseBehavior, RtioTimer, ProcessConfig};
use ai = std::io::net::addrinfo;

// Local re-exports
Expand Down Expand Up @@ -247,9 +246,9 @@ impl rtio::IoFactory for IoFactory {
fn timer_init(&mut self) -> IoResult<~RtioTimer:Send> {
timer::Timer::new().map(|t| box t as ~RtioTimer:Send)
}
fn spawn(&mut self, config: ProcessConfig)
fn spawn(&mut self, cfg: ProcessConfig)
-> IoResult<(~RtioProcess:Send, ~[Option<~RtioPipe:Send>])> {
process::Process::spawn(config).map(|(p, io)| {
process::Process::spawn(cfg).map(|(p, io)| {
(box p as ~RtioProcess:Send,
io.move_iter().map(|p| p.map(|p| box p as ~RtioPipe:Send)).collect())
})
Expand Down
Loading

0 comments on commit bf58bfe

Please sign in to comment.