Skip to content

Commit 401e125

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 c62e1a9 commit 401e125

25 files changed

+657
-718
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 mut 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(ref mut process) => {
8073
for input in input.iter() {
8174
process.stdin.get_mut_ref().write(input.as_bytes()).unwrap();
@@ -99,14 +92,7 @@ pub fn run_background(lib_path: &str,
9992
input: Option<~str>) -> Option<Process> {
10093

10194
let env = env.clone().append(target_env(lib_path, prog).as_slice());
102-
let opt_process = Process::configure(ProcessConfig {
103-
program: prog,
104-
args: args,
105-
env: Some(env.as_slice()),
106-
.. ProcessConfig::new()
107-
});
108-
109-
match opt_process {
95+
match Command::new(prog).args(args).env(env.as_slice()).spawn() {
11096
Ok(mut process) => {
11197
for input in input.iter() {
11298
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
@@ -408,7 +408,7 @@ fn run_debuginfo_gdb_test(config: &config, props: &TestProps, testfile: &Path) {
408408
}
409409

410410
fn run_debuginfo_lldb_test(config: &config, props: &TestProps, testfile: &Path) {
411-
use std::io::process::{Process, ProcessConfig, ProcessOutput};
411+
use std::io::process::{Command, ProcessOutput};
412412

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

472472
fn run_lldb(config: &config, test_executable: &Path, debugger_script: &Path) -> ProcRes {
473473
// Prepare the lldb_batchmode which executes the debugger script
474-
let lldb_batchmode_script = "./src/etc/lldb_batchmode.py".to_owned();
475-
let test_executable_str = test_executable.as_str().unwrap().to_owned();
476-
let debugger_script_str = debugger_script.as_str().unwrap().to_owned();
477-
let commandline = format!("python {} {} {}",
478-
lldb_batchmode_script.as_slice(),
479-
test_executable_str.as_slice(),
480-
debugger_script_str.as_slice());
481-
482-
let args = &[lldb_batchmode_script, test_executable_str, debugger_script_str];
483-
let env = &[("PYTHONPATH".to_owned(), config.lldb_python_dir.clone().unwrap())];
484-
485-
let mut opt_process = Process::configure(ProcessConfig {
486-
program: "python",
487-
args: args,
488-
env: Some(env),
489-
.. ProcessConfig::new()
490-
});
491-
492-
let (status, out, err) = match opt_process {
474+
let mut cmd = Command::new("python");
475+
cmd.arg("./src/etc/lldb_batchmode.py")
476+
.arg(test_executable)
477+
.arg(debugger_script)
478+
.env([("PYTHONPATH", config.lldb_python_dir.clone().unwrap().as_slice())]);
479+
480+
let (status, out, err) = match cmd.spawn() {
493481
Ok(ref mut process) => {
494482
let ProcessOutput { status, output, error } = process.wait_with_output();
495483

@@ -507,7 +495,7 @@ fn run_debuginfo_lldb_test(config: &config, props: &TestProps, testfile: &Path)
507495
status: status,
508496
stdout: out,
509497
stderr: err,
510-
cmdline: commandline
498+
cmdline: format!("{}", cmd)
511499
};
512500
}
513501
}

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)