Skip to content

Commit 6d03897

Browse files
committed
Don't use libc::exit. #9473
This can cause unexpected errors in the runtime when done while scheduler threads are still initializing. Required some restructuring of the main_args functions in our libraries.
1 parent 7535479 commit 6d03897

File tree

6 files changed

+45
-45
lines changed

6 files changed

+45
-45
lines changed

src/libextra/test.rs

+11-12
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ use treemap::TreeMap;
3030

3131
use std::clone::Clone;
3232
use std::comm::{stream, SharedChan, GenericPort, GenericChan};
33-
use std::libc;
3433
use std::io;
3534
use std::result;
3635
use std::task;
@@ -125,8 +124,9 @@ pub type MetricDiff = TreeMap<~str,MetricChange>;
125124
pub fn test_main(args: &[~str], tests: ~[TestDescAndFn]) {
126125
let opts =
127126
match parse_opts(args) {
128-
Ok(o) => o,
129-
Err(msg) => fail!(msg)
127+
Some(Ok(o)) => o,
128+
Some(Err(msg)) => fail!(msg),
129+
None => return
130130
};
131131
if !run_tests_console(&opts, tests) { fail!("Some tests failed"); }
132132
}
@@ -189,7 +189,7 @@ fn optgroups() -> ~[getopts::groups::OptGroup] {
189189
"A.B")]
190190
}
191191

192-
fn usage(binary: &str, helpstr: &str) -> ! {
192+
fn usage(binary: &str, helpstr: &str) {
193193
#[fixed_stack_segment]; #[inline(never)];
194194

195195
let message = fmt!("Usage: %s [OPTIONS] [FILTER]", binary);
@@ -217,20 +217,19 @@ Test Attributes:
217217
tests. This may also be written as #[ignore(cfg(...))] to
218218
ignore the test on certain configurations.");
219219
}
220-
unsafe { libc::exit(0) }
221220
}
222221

223222
// Parses command line arguments into test options
224-
pub fn parse_opts(args: &[~str]) -> OptRes {
223+
pub fn parse_opts(args: &[~str]) -> Option<OptRes> {
225224
let args_ = args.tail();
226225
let matches =
227226
match groups::getopts(args_, optgroups()) {
228227
Ok(m) => m,
229-
Err(f) => return Err(f.to_err_msg())
228+
Err(f) => return Some(Err(f.to_err_msg()))
230229
};
231230

232-
if matches.opt_present("h") { usage(args[0], "h"); }
233-
if matches.opt_present("help") { usage(args[0], "help"); }
231+
if matches.opt_present("h") { usage(args[0], "h"); return None; }
232+
if matches.opt_present("help") { usage(args[0], "help"); return None; }
234233

235234
let filter =
236235
if matches.free.len() > 0 {
@@ -272,7 +271,7 @@ pub fn parse_opts(args: &[~str]) -> OptRes {
272271
logfile: logfile
273272
};
274273

275-
Ok(test_opts)
274+
Some(Ok(test_opts))
276275
}
277276

278277
pub fn opt_shard(maybestr: Option<~str>) -> Option<(uint,uint)> {
@@ -1228,7 +1227,7 @@ mod tests {
12281227
fn first_free_arg_should_be_a_filter() {
12291228
let args = ~[~"progname", ~"filter"];
12301229
let opts = match parse_opts(args) {
1231-
Ok(o) => o,
1230+
Some(Ok(o)) => o,
12321231
_ => fail!("Malformed arg in first_free_arg_should_be_a_filter")
12331232
};
12341233
assert!("filter" == opts.filter.clone().unwrap());
@@ -1238,7 +1237,7 @@ mod tests {
12381237
fn parse_ignored_flag() {
12391238
let args = ~[~"progname", ~"filter", ~"--ignored"];
12401239
let opts = match parse_opts(args) {
1241-
Ok(o) => o,
1240+
Some(Ok(o)) => o,
12421241
_ => fail!("Malformed arg in parse_ignored_flag")
12431242
};
12441243
assert!((opts.run_ignored));

src/librust/rust.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl ValidUsage {
4545

4646
enum Action {
4747
Call(extern "Rust" fn(args: &[~str]) -> ValidUsage),
48-
CallMain(&'static str, extern "Rust" fn(&[~str])),
48+
CallMain(&'static str, extern "Rust" fn(&[~str]) -> int),
4949
}
5050

5151
enum UsageSource<'self> {
@@ -186,18 +186,17 @@ fn cmd_run(args: &[~str]) -> ValidUsage {
186186
}
187187
}
188188

189-
fn invoke(prog: &str, args: &[~str], f: &fn(&[~str])) {
189+
fn invoke(prog: &str, args: &[~str], f: &fn(&[~str]) -> int) -> int {
190190
let mut osargs = ~[prog.to_owned()];
191191
osargs.push_all_move(args.to_owned());
192-
f(osargs);
192+
f(osargs)
193193
}
194194

195195
fn do_command(command: &Command, args: &[~str]) -> ValidUsage {
196196
match command.action {
197197
Call(f) => f(args),
198198
CallMain(prog, f) => {
199-
invoke(prog, args, f);
200-
Valid(0)
199+
Valid(invoke(prog, args, f))
201200
}
202201
}
203202
}

src/librustc/rustc.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -394,13 +394,14 @@ pub fn monitor(f: ~fn(@diagnostic::Emitter)) {
394394
}
395395

396396
pub fn main() {
397-
let args = os::args();
398-
main_args(args);
397+
std::os::set_exit_status(main_args(std::os::args()));
399398
}
400399

401-
pub fn main_args(args: &[~str]) {
400+
pub fn main_args(args: &[~str]) -> int {
402401
let owned_args = args.to_owned();
403402
do monitor |demitter| {
404403
run_compiler(owned_args, demitter);
405404
}
405+
406+
return 0;
406407
}

src/librustdoc/rustdoc.rs

+8-12
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ enum OutputFormat {
5252
}
5353

5454
pub fn main() {
55-
main_args(std::os::args());
55+
std::os::set_exit_status(main_args(std::os::args()));
5656
}
5757

5858
pub fn opts() -> ~[groups::OptGroup] {
@@ -76,14 +76,14 @@ pub fn usage(argv0: &str) {
7676
argv0), opts()));
7777
}
7878

79-
pub fn main_args(args: &[~str]) {
79+
pub fn main_args(args: &[~str]) -> int {
8080
//use extra::getopts::groups::*;
8181

8282
let matches = groups::getopts(args.tail(), opts()).unwrap();
8383

8484
if matches.opt_present("h") || matches.opt_present("help") {
8585
usage(args[0]);
86-
return;
86+
return 0;
8787
}
8888

8989
let (format, cratefile) = match matches.free.clone() {
@@ -92,17 +92,17 @@ pub fn main_args(args: &[~str]) {
9292
[s, _] => {
9393
println!("Unknown output format: `{}`", s);
9494
usage(args[0]);
95-
exit(1);
95+
return 1;
9696
}
9797
[_, .._] => {
9898
println!("Expected exactly one crate to process");
9999
usage(args[0]);
100-
exit(1);
100+
return 1;
101101
}
102102
_ => {
103103
println!("Expected an output format and then one crate");
104104
usage(args[0]);
105-
exit(1);
105+
return 1;
106106
}
107107
};
108108

@@ -179,6 +179,8 @@ pub fn main_args(args: &[~str]) {
179179
}
180180
let ended = time::precise_time_ns();
181181
info2!("Took {:.03f}s", (ended as f64 - started as f64) / 1000000000f64);
182+
183+
return 0;
182184
}
183185

184186
fn jsonify(crate: clean::Crate, res: ~[plugins::PluginJson], dst: Path) {
@@ -208,9 +210,3 @@ fn jsonify(crate: clean::Crate, res: ~[plugins::PluginJson], dst: Path) {
208210
let output = extra::json::Object(json).to_str();
209211
file.write(output.as_bytes());
210212
}
211-
212-
fn exit(status: int) -> ! {
213-
#[fixed_stack_segment]; #[inline(never)];
214-
use std::libc;
215-
unsafe { libc::exit(status as libc::c_int) }
216-
}

src/librusti/rusti.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -517,8 +517,7 @@ pub fn run_line(repl: &mut Repl, input: @io::Reader, out: @io::Writer, line: ~st
517517
}
518518

519519
pub fn main() {
520-
let args = os::args();
521-
main_args(args);
520+
os::set_exit_status(main_args(os::args()));
522521
}
523522

524523
struct Completer;
@@ -534,7 +533,7 @@ impl CompletionCb for Completer {
534533
}
535534
}
536535

537-
pub fn main_args(args: &[~str]) {
536+
pub fn main_args(args: &[~str]) -> int {
538537
#[fixed_stack_segment]; #[inline(never)];
539538

540539
let input = io::stdin();
@@ -576,6 +575,8 @@ pub fn main_args(args: &[~str]) {
576575
}
577576
}
578577
}
578+
579+
return 0;
579580
}
580581

581582
#[cfg(test)]

src/librustpkg/rustpkg.rs

+14-10
Original file line numberDiff line numberDiff line change
@@ -615,11 +615,10 @@ impl CtxMethods for BuildContext {
615615

616616
pub fn main() {
617617
io::println("WARNING: The Rust package manager is experimental and may be unstable");
618-
let args = os::args();
619-
main_args(args);
618+
os::set_exit_status(main_args(os::args()));
620619
}
621620

622-
pub fn main_args(args: &[~str]) {
621+
pub fn main_args(args: &[~str]) -> int {
623622
let opts = ~[getopts::optflag("h"), getopts::optflag("help"),
624623
getopts::optflag("no-link"),
625624
getopts::optflag("no-trans"),
@@ -645,7 +644,7 @@ pub fn main_args(args: &[~str]) {
645644
result::Err(f) => {
646645
error(fmt!("%s", f.to_err_msg()));
647646

648-
return;
647+
return 1;
649648
}
650649
};
651650
let mut help = matches.opt_present("h") ||
@@ -662,7 +661,7 @@ pub fn main_args(args: &[~str]) {
662661
if matches.opt_present("v") ||
663662
matches.opt_present("version") {
664663
rustc::version(args[0]);
665-
return;
664+
return 0;
666665
}
667666

668667
let use_rust_path_hack = matches.opt_present("r") ||
@@ -701,7 +700,8 @@ pub fn main_args(args: &[~str]) {
701700
args.shift();
702701

703702
if (args.len() < 1) {
704-
return usage::general();
703+
usage::general();
704+
return 1;
705705
}
706706

707707
let rustc_flags = RustcFlags {
@@ -739,11 +739,14 @@ pub fn main_args(args: &[~str]) {
739739
}
740740
}
741741
let cmd = match cmd_opt {
742-
None => return usage::general(),
742+
None => {
743+
usage::general();
744+
return 0;
745+
}
743746
Some(cmd) => {
744747
help |= context::flags_ok_for_cmd(&rustc_flags, cfgs, *cmd, user_supplied_opt_level);
745748
if help {
746-
return match *cmd {
749+
match *cmd {
747750
~"build" => usage::build(),
748751
~"clean" => usage::clean(),
749752
~"do" => usage::do_cmd(),
@@ -757,6 +760,7 @@ pub fn main_args(args: &[~str]) {
757760
~"unprefer" => usage::unprefer(),
758761
_ => usage::general()
759762
};
763+
return 0;
760764
} else {
761765
cmd
762766
}
@@ -794,8 +798,8 @@ pub fn main_args(args: &[~str]) {
794798
// and at least one test case succeeds if rustpkg returns COPY_FAILED_CODE,
795799
// when actually, it might set the exit code for that even if a different
796800
// unhandled condition got raised.
797-
if result.is_err() { os::set_exit_status(COPY_FAILED_CODE); }
798-
801+
if result.is_err() { return COPY_FAILED_CODE; }
802+
return 0;
799803
}
800804

801805
/**

0 commit comments

Comments
 (0)