diff options
| author | bors <bors@rust-lang.org> | 2013-12-14 12:56:22 -0800 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-12-14 12:56:22 -0800 |
| commit | aafed3ece58be56e5e88c51d32d065254f10309a (patch) | |
| tree | 21d55824a8a38d055f478c1abf5c962787113c87 /src/libstd | |
| parent | 3d3a663d2530dd49fee235667e98f2767dfd1b57 (diff) | |
| parent | 5de42701a87cb0e517921cce7bc3a512e513301c (diff) | |
| download | rust-aafed3ece58be56e5e88c51d32d065254f10309a.tar.gz rust-aafed3ece58be56e5e88c51d32d065254f10309a.zip | |
auto merge of #10936 : cadencemarseille/rust/issue-10754-std-run-unwrap-on-None, r=alexcrichton
The problem was that std::run::Process::new() was unwrap()ing the result of std::io::process::Process::new(), which returns None in the case where the io_error condition is raised to signal failure to start the process. Have std::run::Process::new() similarly return an Option\<run::Process\> to reflect the fact that a subprocess might have failed to start. Update utility functions run::process_status() and run::process_output() to return Option\<ProcessExit\> and Option\<ProcessOutput\>, respectively. Various parts of librustc and librustpkg needed to be updated to reflect these API changes. closes #10754
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/run.rs | 79 |
1 files changed, 52 insertions, 27 deletions
diff --git a/src/libstd/run.rs b/src/libstd/run.rs index 754c02e308f..14d49df59a4 100644 --- a/src/libstd/run.rs +++ b/src/libstd/run.rs @@ -119,7 +119,7 @@ impl Process { * * options - Options to configure the environment of the process, * the working directory and the standard IO streams. */ - pub fn new(prog: &str, args: &[~str], options: ProcessOptions) -> Process { + pub fn new(prog: &str, args: &[~str], options: ProcessOptions) -> Option<Process> { let ProcessOptions { env, dir, in_fd, out_fd, err_fd } = options; let env = env.as_ref().map(|a| a.as_slice()); let cwd = dir.as_ref().map(|a| a.as_str().unwrap()); @@ -138,8 +138,10 @@ impl Process { cwd: cwd, io: rtio, }; - let inner = process::Process::new(rtconfig).unwrap(); - Process { inner: inner } + match process::Process::new(rtconfig) { + Some(inner) => Some(Process { inner: inner }), + None => None + } } /// Returns the unique id of the process @@ -290,17 +292,20 @@ impl Process { * * # Return value * - * The process's exit code + * The process's exit code, or None if the child process could not be started */ -pub fn process_status(prog: &str, args: &[~str]) -> ProcessExit { - let mut prog = Process::new(prog, args, ProcessOptions { +pub fn process_status(prog: &str, args: &[~str]) -> Option<ProcessExit> { + let mut opt_prog = Process::new(prog, args, ProcessOptions { env: None, dir: None, in_fd: Some(unsafe { libc::dup(libc::STDIN_FILENO) }), out_fd: Some(unsafe { libc::dup(libc::STDOUT_FILENO) }), err_fd: Some(unsafe { libc::dup(libc::STDERR_FILENO) }) }); - prog.finish() + match opt_prog { + Some(ref mut prog) => Some(prog.finish()), + None => None + } } /** @@ -313,11 +318,15 @@ pub fn process_status(prog: &str, args: &[~str]) -> ProcessExit { * * # Return value * - * The process's stdout/stderr output and exit code. + * The process's stdout/stderr output and exit code, or None if the child process could not be + * started. */ -pub fn process_output(prog: &str, args: &[~str]) -> ProcessOutput { - let mut prog = Process::new(prog, args, ProcessOptions::new()); - prog.finish_with_output() +pub fn process_output(prog: &str, args: &[~str]) -> Option<ProcessOutput> { + let mut opt_prog = Process::new(prog, args, ProcessOptions::new()); + match opt_prog { + Some(ref mut prog) => Some(prog.finish_with_output()), + None => None + } } #[cfg(test)] @@ -331,24 +340,36 @@ mod tests { use task::spawn; use unstable::running_on_valgrind; use io::native::file; - use io::{Writer, Reader}; + use io::{Writer, Reader, io_error}; #[test] #[cfg(not(target_os="android"))] // FIXME(#10380) fn test_process_status() { - let mut status = run::process_status("false", []); + let mut status = run::process_status("false", []).expect("failed to exec `false`"); assert!(status.matches_exit_status(1)); - status = run::process_status("true", []); + status = run::process_status("true", []).expect("failed to exec `true`"); assert!(status.success()); } #[test] + fn test_process_output_fail_to_start() { + let mut trapped_io_error = false; + let opt_outp = io_error::cond.trap(|_| { + trapped_io_error = true; + }).inside(|| -> Option<run::ProcessOutput> { + run::process_output("no-binary-by-this-name-should-exist", []) + }); + assert!(trapped_io_error); + assert!(opt_outp.is_none()); + } + + #[test] #[cfg(not(target_os="android"))] // FIXME(#10380) fn test_process_output_output() { let run::ProcessOutput {status, output, error} - = run::process_output("echo", [~"hello"]); + = run::process_output("echo", [~"hello"]).expect("failed to exec `echo`"); let output_str = str::from_utf8_owned(output); assert!(status.success()); @@ -364,7 +385,7 @@ mod tests { fn test_process_output_error() { let run::ProcessOutput {status, output, error} - = run::process_output("mkdir", [~"."]); + = run::process_output("mkdir", [~"."]).expect("failed to exec `mkdir`"); assert!(status.matches_exit_status(1)); assert_eq!(output, ~[]); @@ -385,7 +406,7 @@ mod tests { in_fd: Some(pipe_in.input), out_fd: Some(pipe_out.out), err_fd: Some(pipe_err.out) - }); + }).expect("failed to exec `cat`"); os::close(pipe_in.input); os::close(pipe_out.out); @@ -422,14 +443,16 @@ mod tests { #[test] #[cfg(not(target_os="android"))] // FIXME(#10380) fn test_finish_once() { - let mut prog = run::Process::new("false", [], run::ProcessOptions::new()); + let mut prog = run::Process::new("false", [], run::ProcessOptions::new()) + .expect("failed to exec `false`"); assert!(prog.finish().matches_exit_status(1)); } #[test] #[cfg(not(target_os="android"))] // FIXME(#10380) fn test_finish_twice() { - let mut prog = run::Process::new("false", [], run::ProcessOptions::new()); + let mut prog = run::Process::new("false", [], run::ProcessOptions::new()) + .expect("failed to exec `false`"); assert!(prog.finish().matches_exit_status(1)); assert!(prog.finish().matches_exit_status(1)); } @@ -438,7 +461,8 @@ mod tests { #[cfg(not(target_os="android"))] // FIXME(#10380) fn test_finish_with_output_once() { - let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions::new()); + let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions::new()) + .expect("failed to exec `echo`"); let run::ProcessOutput {status, output, error} = prog.finish_with_output(); let output_str = str::from_utf8_owned(output); @@ -455,7 +479,8 @@ mod tests { #[cfg(not(target_os="android"))] // FIXME(#10380) fn test_finish_with_output_twice() { - let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions::new()); + let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions::new()) + .expect("failed to exec `echo`"); let run::ProcessOutput {status, output, error} = prog.finish_with_output(); @@ -484,14 +509,14 @@ mod tests { run::Process::new("pwd", [], run::ProcessOptions { dir: dir, .. run::ProcessOptions::new() - }) + }).expect("failed to exec `pwd`") } #[cfg(unix,target_os="android")] fn run_pwd(dir: Option<&Path>) -> run::Process { run::Process::new("/system/bin/sh", [~"-c",~"pwd"], run::ProcessOptions { dir: dir, .. run::ProcessOptions::new() - }) + }).expect("failed to exec `/system/bin/sh`") } #[cfg(windows)] @@ -499,7 +524,7 @@ mod tests { run::Process::new("cmd", [~"/c", ~"cd"], run::ProcessOptions { dir: dir, .. run::ProcessOptions::new() - }) + }).expect("failed to run `cmd`") } #[test] @@ -539,14 +564,14 @@ mod tests { run::Process::new("env", [], run::ProcessOptions { env: env, .. run::ProcessOptions::new() - }) + }).expect("failed to exec `env`") } #[cfg(unix,target_os="android")] fn run_env(env: Option<~[(~str, ~str)]>) -> run::Process { run::Process::new("/system/bin/sh", [~"-c",~"set"], run::ProcessOptions { env: env, .. run::ProcessOptions::new() - }) + }).expect("failed to exec `/system/bin/sh`") } #[cfg(windows)] @@ -554,7 +579,7 @@ mod tests { run::Process::new("cmd", [~"/c", ~"set"], run::ProcessOptions { env: env, .. run::ProcessOptions::new() - }) + }).expect("failed to run `cmd`") } #[test] |
