Skip to content

Commit 74b77b0

Browse files
committed
Process::new etc should support non-utf8 commands/args
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]
1 parent ea5677c commit 74b77b0

27 files changed

+679
-723
lines changed

src/compiletest/procsrv.rs

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use std::os;
1212
use std::str;
13-
use std::io::process::{ProcessExit, Process, ProcessConfig, ProcessOutput};
13+
use std::io::process::{ProcessExit, Command, Process, ProcessOutput};
1414

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

7070
let env = env.clone().append(target_env(lib_path, prog).as_slice());
71-
let opt_process = Process::configure(ProcessConfig {
72-
program: prog,
73-
args: args,
74-
env: Some(env.as_slice()),
75-
.. ProcessConfig::new()
76-
});
77-
78-
match opt_process {
71+
match Command::new(prog).args(args).env(env.as_slice()).spawn() {
7972
Ok(mut process) => {
8073
for input in input.iter() {
8174
process.stdin.get_mut_ref().write(input.as_bytes()).unwrap();
@@ -100,14 +93,7 @@ pub fn run_background(lib_path: &str,
10093
input: Option<~str>) -> Option<Process> {
10194

10295
let env = env.clone().append(target_env(lib_path, prog).as_slice());
103-
let opt_process = Process::configure(ProcessConfig {
104-
program: prog,
105-
args: args,
106-
env: Some(env.as_slice()),
107-
.. ProcessConfig::new()
108-
});
109-
110-
match opt_process {
96+
match Command::new(prog).args(args).env(env.as_slice()).spawn() {
11197
Ok(mut process) => {
11298
for input in input.iter() {
11399
process.stdin.get_mut_ref().write(input.as_bytes()).unwrap();

src/compiletest/runtest.rs

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
428428
}
429429

430430
fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path) {
431-
use std::io::process::{Process, ProcessConfig, ProcessOutput};
431+
use std::io::process::{Command, ProcessOutput};
432432

433433
if config.lldb_python_dir.is_none() {
434434
fatal("Can't run LLDB test because LLDB's python path is not set.".to_owned());
@@ -491,25 +491,13 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path)
491491

492492
fn run_lldb(config: &Config, test_executable: &Path, debugger_script: &Path) -> ProcRes {
493493
// Prepare the lldb_batchmode which executes the debugger script
494-
let lldb_batchmode_script = "./src/etc/lldb_batchmode.py".to_owned();
495-
let test_executable_str = test_executable.as_str().unwrap().to_owned();
496-
let debugger_script_str = debugger_script.as_str().unwrap().to_owned();
497-
let commandline = format!("python {} {} {}",
498-
lldb_batchmode_script.as_slice(),
499-
test_executable_str.as_slice(),
500-
debugger_script_str.as_slice());
501-
502-
let args = &[lldb_batchmode_script, test_executable_str, debugger_script_str];
503-
let env = &[("PYTHONPATH".to_owned(), config.lldb_python_dir.clone().unwrap())];
504-
505-
let opt_process = Process::configure(ProcessConfig {
506-
program: "python",
507-
args: args,
508-
env: Some(env),
509-
.. ProcessConfig::new()
510-
});
511-
512-
let (status, out, err) = match opt_process {
494+
let mut cmd = Command::new("python");
495+
cmd.arg("./src/etc/lldb_batchmode.py")
496+
.arg(test_executable)
497+
.arg(debugger_script)
498+
.env([("PYTHONPATH", config.lldb_python_dir.clone().unwrap().as_slice())]);
499+
500+
let (status, out, err) = match cmd.spawn() {
513501
Ok(process) => {
514502
let ProcessOutput { status, output, error } =
515503
process.wait_with_output().unwrap();
@@ -528,7 +516,7 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path)
528516
status: status,
529517
stdout: out,
530518
stderr: err,
531-
cmdline: commandline
519+
cmdline: format!("{}", cmd)
532520
};
533521
}
534522
}

src/libnative/io/mod.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,12 @@ use std::c_str::CString;
2727
use std::io;
2828
use std::io::IoError;
2929
use std::io::net::ip::SocketAddr;
30-
use std::io::process::ProcessConfig;
3130
use std::io::signal::Signum;
3231
use std::os;
3332
use std::rt::rtio;
3433
use std::rt::rtio::{RtioTcpStream, RtioTcpListener, RtioUdpSocket};
3534
use std::rt::rtio::{RtioUnixListener, RtioPipe, RtioFileStream, RtioProcess};
36-
use std::rt::rtio::{RtioSignal, RtioTTY, CloseBehavior, RtioTimer};
35+
use std::rt::rtio::{RtioSignal, RtioTTY, CloseBehavior, RtioTimer, ProcessConfig};
3736
use ai = std::io::net::addrinfo;
3837

3938
// Local re-exports
@@ -258,10 +257,10 @@ impl rtio::IoFactory for IoFactory {
258257
fn timer_init(&mut self) -> IoResult<Box<RtioTimer:Send>> {
259258
timer::Timer::new().map(|t| box t as Box<RtioTimer:Send>)
260259
}
261-
fn spawn(&mut self, config: ProcessConfig)
260+
fn spawn(&mut self, cfg: ProcessConfig)
262261
-> IoResult<(Box<RtioProcess:Send>,
263262
Vec<Option<Box<RtioPipe:Send>>>)> {
264-
process::Process::spawn(config).map(|(p, io)| {
263+
process::Process::spawn(cfg).map(|(p, io)| {
265264
(box p as Box<RtioProcess:Send>,
266265
io.move_iter().map(|p| p.map(|p| {
267266
box p as Box<RtioPipe:Send>

0 commit comments

Comments
 (0)