Skip to content

Commit 5de4270

Browse files
Fix #10754 - std::run functions fail after io_error
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
1 parent 00b1adf commit 5de4270

File tree

12 files changed

+275
-153
lines changed

12 files changed

+275
-153
lines changed

src/compiletest/procsrv.rs

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -46,47 +46,57 @@ pub fn run(lib_path: &str,
4646
prog: &str,
4747
args: &[~str],
4848
env: ~[(~str, ~str)],
49-
input: Option<~str>) -> Result {
49+
input: Option<~str>) -> Option<Result> {
5050

5151
let env = env + target_env(lib_path, prog);
52-
let mut process = run::Process::new(prog, args, run::ProcessOptions {
52+
let mut opt_process = run::Process::new(prog, args, run::ProcessOptions {
5353
env: Some(env),
5454
dir: None,
5555
in_fd: None,
5656
out_fd: None,
5757
err_fd: None
5858
});
5959

60-
for input in input.iter() {
61-
process.input().write(input.as_bytes());
62-
}
63-
let run::ProcessOutput { status, output, error } = process.finish_with_output();
60+
match opt_process {
61+
Some(ref mut process) => {
62+
for input in input.iter() {
63+
process.input().write(input.as_bytes());
64+
}
65+
let run::ProcessOutput { status, output, error } = process.finish_with_output();
6466

65-
Result {
66-
status: status,
67-
out: str::from_utf8_owned(output),
68-
err: str::from_utf8_owned(error)
67+
Some(Result {
68+
status: status,
69+
out: str::from_utf8_owned(output),
70+
err: str::from_utf8_owned(error)
71+
})
72+
},
73+
None => None
6974
}
7075
}
7176

7277
pub fn run_background(lib_path: &str,
7378
prog: &str,
7479
args: &[~str],
7580
env: ~[(~str, ~str)],
76-
input: Option<~str>) -> run::Process {
81+
input: Option<~str>) -> Option<run::Process> {
7782

7883
let env = env + target_env(lib_path, prog);
79-
let mut process = run::Process::new(prog, args, run::ProcessOptions {
84+
let opt_process = run::Process::new(prog, args, run::ProcessOptions {
8085
env: Some(env),
8186
dir: None,
8287
in_fd: None,
8388
out_fd: None,
8489
err_fd: None
8590
});
8691

87-
for input in input.iter() {
88-
process.input().write(input.as_bytes());
89-
}
92+
match opt_process {
93+
Some(mut process) => {
94+
for input in input.iter() {
95+
process.input().write(input.as_bytes());
96+
}
9097

91-
return process;
98+
Some(process)
99+
},
100+
None => None
101+
}
92102
}

src/compiletest/runtest.rs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -289,20 +289,23 @@ fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) {
289289
dump_output_file(config, testfile, script_str, "debugger.script");
290290

291291

292-
procsrv::run("", config.adb_path.clone(),
292+
procsrv::run("", config.adb_path,
293293
[~"push", exe_file.as_str().unwrap().to_owned(), config.adb_test_dir.clone()],
294-
~[(~"",~"")], Some(~""));
294+
~[(~"",~"")], Some(~""))
295+
.expect(format!("failed to exec `{}`", config.adb_path));
295296

296297
procsrv::run("", config.adb_path,
297298
[~"forward", ~"tcp:5039", ~"tcp:5039"],
298-
~[(~"",~"")], Some(~""));
299+
~[(~"",~"")], Some(~""))
300+
.expect(format!("failed to exec `{}`", config.adb_path));
299301

300302
let adb_arg = format!("export LD_LIBRARY_PATH={}; gdbserver :5039 {}/{}",
301303
config.adb_test_dir.clone(), config.adb_test_dir.clone(),
302304
str::from_utf8(exe_file.filename().unwrap()));
303305

304-
let mut process = procsrv::run_background("", config.adb_path.clone(),
305-
[~"shell",adb_arg.clone()],~[(~"",~"")], Some(~""));
306+
let mut process = procsrv::run_background("", config.adb_path,
307+
[~"shell",adb_arg.clone()],~[(~"",~"")], Some(~""))
308+
.expect(format!("failed to exec `{}`", config.adb_path));
306309
loop {
307310
//waiting 1 second for gdbserver start
308311
timer::sleep(1000);
@@ -334,10 +337,12 @@ fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) {
334337
let debugger_opts = ~[~"-quiet", ~"-batch", ~"-nx",
335338
"-command=" + debugger_script.as_str().unwrap().to_owned()];
336339

340+
let gdb_path = tool_path.append("/bin/arm-linux-androideabi-gdb");
337341
let procsrv::Result{ out, err, status }=
338342
procsrv::run("",
339-
tool_path.append("/bin/arm-linux-androideabi-gdb"),
340-
debugger_opts, ~[(~"",~"")], None);
343+
gdb_path,
344+
debugger_opts, ~[(~"",~"")], None)
345+
.expect(format!("failed to exec `{}`", gdb_path));
341346
let cmdline = {
342347
let cmdline = make_cmdline("", "arm-linux-androideabi-gdb", debugger_opts);
343348
logv(config, format!("executing {}", cmdline));
@@ -800,7 +805,8 @@ fn program_output(config: &config, testfile: &Path, lib_path: &str, prog: ~str,
800805
cmdline
801806
};
802807
let procsrv::Result{ out, err, status } =
803-
procsrv::run(lib_path, prog, args, env, input);
808+
procsrv::run(lib_path, prog, args, env, input)
809+
.expect(format!("failed to exec `{}`", prog));
804810
dump_output(config, testfile, out, err);
805811
return ProcRes {status: status,
806812
stdout: out,
@@ -908,7 +914,8 @@ fn _arm_exec_compiled_test(config: &config, props: &TestProps,
908914
// copy to target
909915
let copy_result = procsrv::run("", config.adb_path,
910916
[~"push", args.prog.clone(), config.adb_test_dir.clone()],
911-
~[(~"",~"")], Some(~""));
917+
~[(~"",~"")], Some(~""))
918+
.expect(format!("failed to exec `{}`", config.adb_path));
912919

913920
if config.verbose {
914921
println!("push ({}) {} {} {}",
@@ -932,7 +939,8 @@ fn _arm_exec_compiled_test(config: &config, props: &TestProps,
932939
for tv in args.args.iter() {
933940
runargs.push(tv.to_owned());
934941
}
935-
procsrv::run("", config.adb_path, runargs, ~[(~"",~"")], Some(~""));
942+
procsrv::run("", config.adb_path, runargs, ~[(~"",~"")], Some(~""))
943+
.expect(format!("failed to exec `{}`", config.adb_path));
936944

937945
// get exitcode of result
938946
runargs = ~[];
@@ -942,7 +950,8 @@ fn _arm_exec_compiled_test(config: &config, props: &TestProps,
942950

943951
let procsrv::Result{ out: exitcode_out, err: _, status: _ } =
944952
procsrv::run("", config.adb_path, runargs, ~[(~"",~"")],
945-
Some(~""));
953+
Some(~""))
954+
.expect(format!("failed to exec `{}`", config.adb_path));
946955

947956
let mut exitcode : int = 0;
948957
for c in exitcode_out.chars() {
@@ -960,7 +969,8 @@ fn _arm_exec_compiled_test(config: &config, props: &TestProps,
960969
runargs.push(format!("{}/{}.stdout", config.adb_test_dir, prog_short));
961970

962971
let procsrv::Result{ out: stdout_out, err: _, status: _ } =
963-
procsrv::run("", config.adb_path, runargs, ~[(~"",~"")], Some(~""));
972+
procsrv::run("", config.adb_path, runargs, ~[(~"",~"")], Some(~""))
973+
.expect(format!("failed to exec `{}`", config.adb_path));
964974

965975
// get stderr of result
966976
runargs = ~[];
@@ -969,7 +979,8 @@ fn _arm_exec_compiled_test(config: &config, props: &TestProps,
969979
runargs.push(format!("{}/{}.stderr", config.adb_test_dir, prog_short));
970980

971981
let procsrv::Result{ out: stderr_out, err: _, status: _ } =
972-
procsrv::run("", config.adb_path, runargs, ~[(~"",~"")], Some(~""));
982+
procsrv::run("", config.adb_path, runargs, ~[(~"",~"")], Some(~""))
983+
.expect(format!("failed to exec `{}`", config.adb_path));
973984

974985
dump_output(config, testfile, stdout_out, stderr_out);
975986

@@ -1004,7 +1015,8 @@ fn _arm_push_aux_shared_library(config: &config, testfile: &Path) {
10041015
// FIXME (#9639): This needs to handle non-utf8 paths
10051016
let copy_result = procsrv::run("", config.adb_path,
10061017
[~"push", file.as_str().unwrap().to_owned(), config.adb_test_dir.clone()],
1007-
~[(~"",~"")], Some(~""));
1018+
~[(~"",~"")], Some(~""))
1019+
.expect(format!("failed to exec `{}`", config.adb_path));
10081020

10091021
if config.verbose {
10101022
println!("push ({}) {} {} {}",

src/librustc/back/archive.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,25 @@ fn run_ar(sess: Session, args: &str, cwd: Option<&Path>,
4040
Some(p) => { debug!("inside {}", p.display()); }
4141
None => {}
4242
}
43-
let o = Process::new(ar, args.as_slice(), opts).finish_with_output();
44-
if !o.status.success() {
45-
sess.err(format!("{} {} failed with: {}", ar, args.connect(" "),
46-
o.status));
47-
sess.note(format!("stdout ---\n{}", str::from_utf8(o.output)));
48-
sess.note(format!("stderr ---\n{}", str::from_utf8(o.error)));
49-
sess.abort_if_errors();
43+
let mut opt_prog = Process::new(ar, args.as_slice(), opts);
44+
match opt_prog {
45+
Some(ref mut prog) => {
46+
let o = prog.finish_with_output();
47+
if !o.status.success() {
48+
sess.err(format!("{} {} failed with: {}", ar, args.connect(" "),
49+
o.status));
50+
sess.note(format!("stdout ---\n{}", str::from_utf8(o.output)));
51+
sess.note(format!("stderr ---\n{}", str::from_utf8(o.error)));
52+
sess.abort_if_errors();
53+
}
54+
o
55+
},
56+
None => {
57+
sess.err(format!("could not exec `{}`", ar));
58+
sess.abort_if_errors();
59+
fail!("rustc::back::archive::run_ar() should not reach this point");
60+
}
5061
}
51-
o
5262
}
5363

5464
impl Archive {

src/librustc/back/link.rs

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -310,13 +310,19 @@ pub mod write {
310310
assembly.as_str().unwrap().to_owned()];
311311

312312
debug!("{} '{}'", cc, args.connect("' '"));
313-
let prog = run::process_output(cc, args);
314-
315-
if !prog.status.success() {
316-
sess.err(format!("linking with `{}` failed: {}", cc, prog.status));
317-
sess.note(format!("{} arguments: '{}'", cc, args.connect("' '")));
318-
sess.note(str::from_utf8_owned(prog.error + prog.output));
319-
sess.abort_if_errors();
313+
match run::process_output(cc, args) {
314+
Some(prog) => {
315+
if !prog.status.success() {
316+
sess.err(format!("linking with `{}` failed: {}", cc, prog.status));
317+
sess.note(format!("{} arguments: '{}'", cc, args.connect("' '")));
318+
sess.note(str::from_utf8_owned(prog.error + prog.output));
319+
sess.abort_if_errors();
320+
}
321+
},
322+
None => {
323+
sess.err(format!("could not exec `{}`", cc));
324+
sess.abort_if_errors();
325+
}
320326
}
321327
}
322328

@@ -949,14 +955,22 @@ fn link_natively(sess: Session, dylib: bool, obj_filename: &Path,
949955

950956
// Invoke the system linker
951957
debug!("{} {}", cc_prog, cc_args.connect(" "));
952-
let prog = time(sess.time_passes(), "running linker", (), |()|
953-
run::process_output(cc_prog, cc_args));
954-
955-
if !prog.status.success() {
956-
sess.err(format!("linking with `{}` failed: {}", cc_prog, prog.status));
957-
sess.note(format!("{} arguments: '{}'", cc_prog, cc_args.connect("' '")));
958-
sess.note(str::from_utf8_owned(prog.error + prog.output));
959-
sess.abort_if_errors();
958+
let opt_prog = time(sess.time_passes(), "running linker", (), |()|
959+
run::process_output(cc_prog, cc_args));
960+
961+
match opt_prog {
962+
Some(prog) => {
963+
if !prog.status.success() {
964+
sess.err(format!("linking with `{}` failed: {}", cc_prog, prog.status));
965+
sess.note(format!("{} arguments: '{}'", cc_prog, cc_args.connect("' '")));
966+
sess.note(str::from_utf8_owned(prog.error + prog.output));
967+
sess.abort_if_errors();
968+
}
969+
},
970+
None => {
971+
sess.err(format!("could not exec `{}`", cc_prog));
972+
sess.abort_if_errors();
973+
}
960974
}
961975

962976

src/librustpkg/api.rs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,14 @@ pub fn install_pkg(cx: &BuildContext,
142142
/// Builds an arbitrary library whose short name is `output`,
143143
/// by invoking `tool` with arguments `args` plus "-o %s", where %s
144144
/// is the platform-specific library name for `output`.
145-
/// Returns that platform-specific name.
145+
/// Returns that platform-specific name, or None if `tool` could not be started.
146146
pub fn build_library_in_workspace(exec: &mut workcache::Exec,
147147
context: &mut Context,
148148
package_name: &str,
149149
tool: &str,
150150
flags: &[~str],
151151
paths: &[~str],
152-
output: &str) -> ~str {
152+
output: &str) -> Option<~str> {
153153
use command_failed = conditions::command_failed::cond;
154154

155155
let workspace = my_workspace(context, package_name);
@@ -169,16 +169,20 @@ pub fn build_library_in_workspace(exec: &mut workcache::Exec,
169169

170170
let all_args = flags + absolute_paths + cc_args +
171171
~[~"-o", out_name.as_str().unwrap().to_owned()];
172-
let exit_process = run::process_status(tool, all_args);
173-
if exit_process.success() {
174-
let out_name_str = out_name.as_str().unwrap().to_owned();
175-
exec.discover_output("binary",
176-
out_name_str,
177-
digest_only_date(&out_name));
178-
context.add_library_path(out_name.dir_path());
179-
out_name_str
180-
} else {
181-
command_failed.raise((tool.to_owned(), all_args, exit_process))
172+
match run::process_status(tool, all_args) {
173+
Some(exit_process) => {
174+
if exit_process.success() {
175+
let out_name_str = out_name.as_str().unwrap().to_owned();
176+
exec.discover_output("binary",
177+
out_name_str,
178+
digest_only_date(&out_name));
179+
context.add_library_path(out_name.dir_path());
180+
Some(out_name_str)
181+
} else {
182+
Some(command_failed.raise((tool.to_owned(), all_args, exit_process)))
183+
}
184+
},
185+
None => None
182186
}
183187
}
184188

0 commit comments

Comments
 (0)