auto merge of #9480 : brson/rust/noexit, r=thestinger

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.
This commit is contained in:
bors 2013-09-24 23:40:54 -07:00
commit dad32f703d
6 changed files with 45 additions and 45 deletions

View File

@ -30,7 +30,6 @@ use treemap::TreeMap;
use std::clone::Clone; use std::clone::Clone;
use std::comm::{stream, SharedChan, GenericPort, GenericChan}; use std::comm::{stream, SharedChan, GenericPort, GenericChan};
use std::libc;
use std::io; use std::io;
use std::result; use std::result;
use std::task; use std::task;
@ -125,8 +124,9 @@ pub type MetricDiff = TreeMap<~str,MetricChange>;
pub fn test_main(args: &[~str], tests: ~[TestDescAndFn]) { pub fn test_main(args: &[~str], tests: ~[TestDescAndFn]) {
let opts = let opts =
match parse_opts(args) { match parse_opts(args) {
Ok(o) => o, Some(Ok(o)) => o,
Err(msg) => fail!(msg) Some(Err(msg)) => fail!(msg),
None => return
}; };
if !run_tests_console(&opts, tests) { fail!("Some tests failed"); } if !run_tests_console(&opts, tests) { fail!("Some tests failed"); }
} }
@ -189,7 +189,7 @@ fn optgroups() -> ~[getopts::groups::OptGroup] {
"A.B")] "A.B")]
} }
fn usage(binary: &str, helpstr: &str) -> ! { fn usage(binary: &str, helpstr: &str) {
#[fixed_stack_segment]; #[inline(never)]; #[fixed_stack_segment]; #[inline(never)];
let message = fmt!("Usage: %s [OPTIONS] [FILTER]", binary); let message = fmt!("Usage: %s [OPTIONS] [FILTER]", binary);
@ -217,20 +217,19 @@ Test Attributes:
tests. This may also be written as #[ignore(cfg(...))] to tests. This may also be written as #[ignore(cfg(...))] to
ignore the test on certain configurations."); ignore the test on certain configurations.");
} }
unsafe { libc::exit(0) }
} }
// Parses command line arguments into test options // Parses command line arguments into test options
pub fn parse_opts(args: &[~str]) -> OptRes { pub fn parse_opts(args: &[~str]) -> Option<OptRes> {
let args_ = args.tail(); let args_ = args.tail();
let matches = let matches =
match groups::getopts(args_, optgroups()) { match groups::getopts(args_, optgroups()) {
Ok(m) => m, Ok(m) => m,
Err(f) => return Err(f.to_err_msg()) Err(f) => return Some(Err(f.to_err_msg()))
}; };
if matches.opt_present("h") { usage(args[0], "h"); } if matches.opt_present("h") { usage(args[0], "h"); return None; }
if matches.opt_present("help") { usage(args[0], "help"); } if matches.opt_present("help") { usage(args[0], "help"); return None; }
let filter = let filter =
if matches.free.len() > 0 { if matches.free.len() > 0 {
@ -272,7 +271,7 @@ pub fn parse_opts(args: &[~str]) -> OptRes {
logfile: logfile logfile: logfile
}; };
Ok(test_opts) Some(Ok(test_opts))
} }
pub fn opt_shard(maybestr: Option<~str>) -> Option<(uint,uint)> { pub fn opt_shard(maybestr: Option<~str>) -> Option<(uint,uint)> {
@ -1228,7 +1227,7 @@ mod tests {
fn first_free_arg_should_be_a_filter() { fn first_free_arg_should_be_a_filter() {
let args = ~[~"progname", ~"filter"]; let args = ~[~"progname", ~"filter"];
let opts = match parse_opts(args) { let opts = match parse_opts(args) {
Ok(o) => o, Some(Ok(o)) => o,
_ => fail!("Malformed arg in first_free_arg_should_be_a_filter") _ => fail!("Malformed arg in first_free_arg_should_be_a_filter")
}; };
assert!("filter" == opts.filter.clone().unwrap()); assert!("filter" == opts.filter.clone().unwrap());
@ -1238,7 +1237,7 @@ mod tests {
fn parse_ignored_flag() { fn parse_ignored_flag() {
let args = ~[~"progname", ~"filter", ~"--ignored"]; let args = ~[~"progname", ~"filter", ~"--ignored"];
let opts = match parse_opts(args) { let opts = match parse_opts(args) {
Ok(o) => o, Some(Ok(o)) => o,
_ => fail!("Malformed arg in parse_ignored_flag") _ => fail!("Malformed arg in parse_ignored_flag")
}; };
assert!((opts.run_ignored)); assert!((opts.run_ignored));

View File

@ -44,7 +44,7 @@ impl ValidUsage {
enum Action { enum Action {
Call(extern "Rust" fn(args: &[~str]) -> ValidUsage), Call(extern "Rust" fn(args: &[~str]) -> ValidUsage),
CallMain(&'static str, extern "Rust" fn(&[~str])), CallMain(&'static str, extern "Rust" fn(&[~str]) -> int),
} }
enum UsageSource<'self> { enum UsageSource<'self> {
@ -185,18 +185,17 @@ fn cmd_run(args: &[~str]) -> ValidUsage {
} }
} }
fn invoke(prog: &str, args: &[~str], f: &fn(&[~str])) { fn invoke(prog: &str, args: &[~str], f: &fn(&[~str]) -> int) -> int {
let mut osargs = ~[prog.to_owned()]; let mut osargs = ~[prog.to_owned()];
osargs.push_all_move(args.to_owned()); osargs.push_all_move(args.to_owned());
f(osargs); f(osargs)
} }
fn do_command(command: &Command, args: &[~str]) -> ValidUsage { fn do_command(command: &Command, args: &[~str]) -> ValidUsage {
match command.action { match command.action {
Call(f) => f(args), Call(f) => f(args),
CallMain(prog, f) => { CallMain(prog, f) => {
invoke(prog, args, f); Valid(invoke(prog, args, f))
Valid(0)
} }
} }
} }

View File

@ -394,13 +394,14 @@ pub fn monitor(f: ~fn(@diagnostic::Emitter)) {
} }
pub fn main() { pub fn main() {
let args = os::args(); std::os::set_exit_status(main_args(std::os::args()));
main_args(args);
} }
pub fn main_args(args: &[~str]) { pub fn main_args(args: &[~str]) -> int {
let owned_args = args.to_owned(); let owned_args = args.to_owned();
do monitor |demitter| { do monitor |demitter| {
run_compiler(owned_args, demitter); run_compiler(owned_args, demitter);
} }
return 0;
} }

View File

@ -52,7 +52,7 @@ enum OutputFormat {
} }
pub fn main() { pub fn main() {
main_args(std::os::args()); std::os::set_exit_status(main_args(std::os::args()));
} }
pub fn opts() -> ~[groups::OptGroup] { pub fn opts() -> ~[groups::OptGroup] {
@ -76,14 +76,14 @@ pub fn usage(argv0: &str) {
argv0), opts())); argv0), opts()));
} }
pub fn main_args(args: &[~str]) { pub fn main_args(args: &[~str]) -> int {
//use extra::getopts::groups::*; //use extra::getopts::groups::*;
let matches = groups::getopts(args.tail(), opts()).unwrap(); let matches = groups::getopts(args.tail(), opts()).unwrap();
if matches.opt_present("h") || matches.opt_present("help") { if matches.opt_present("h") || matches.opt_present("help") {
usage(args[0]); usage(args[0]);
return; return 0;
} }
let (format, cratefile) = match matches.free.clone() { let (format, cratefile) = match matches.free.clone() {
@ -92,17 +92,17 @@ pub fn main_args(args: &[~str]) {
[s, _] => { [s, _] => {
println!("Unknown output format: `{}`", s); println!("Unknown output format: `{}`", s);
usage(args[0]); usage(args[0]);
exit(1); return 1;
} }
[_, .._] => { [_, .._] => {
println!("Expected exactly one crate to process"); println!("Expected exactly one crate to process");
usage(args[0]); usage(args[0]);
exit(1); return 1;
} }
_ => { _ => {
println!("Expected an output format and then one crate"); println!("Expected an output format and then one crate");
usage(args[0]); usage(args[0]);
exit(1); return 1;
} }
}; };
@ -179,6 +179,8 @@ pub fn main_args(args: &[~str]) {
} }
let ended = time::precise_time_ns(); let ended = time::precise_time_ns();
info2!("Took {:.03f}s", (ended as f64 - started as f64) / 1000000000f64); info2!("Took {:.03f}s", (ended as f64 - started as f64) / 1000000000f64);
return 0;
} }
fn jsonify(crate: clean::Crate, res: ~[plugins::PluginJson], dst: Path) { fn jsonify(crate: clean::Crate, res: ~[plugins::PluginJson], dst: Path) {
@ -208,9 +210,3 @@ fn jsonify(crate: clean::Crate, res: ~[plugins::PluginJson], dst: Path) {
let output = extra::json::Object(json).to_str(); let output = extra::json::Object(json).to_str();
file.write(output.as_bytes()); file.write(output.as_bytes());
} }
fn exit(status: int) -> ! {
#[fixed_stack_segment]; #[inline(never)];
use std::libc;
unsafe { libc::exit(status as libc::c_int) }
}

View File

@ -517,8 +517,7 @@ pub fn run_line(repl: &mut Repl, input: @io::Reader, out: @io::Writer, line: ~st
} }
pub fn main() { pub fn main() {
let args = os::args(); os::set_exit_status(main_args(os::args()));
main_args(args);
} }
struct Completer; struct Completer;
@ -534,7 +533,7 @@ impl CompletionCb for Completer {
} }
} }
pub fn main_args(args: &[~str]) { pub fn main_args(args: &[~str]) -> int {
#[fixed_stack_segment]; #[inline(never)]; #[fixed_stack_segment]; #[inline(never)];
let input = io::stdin(); let input = io::stdin();
@ -576,6 +575,8 @@ pub fn main_args(args: &[~str]) {
} }
} }
} }
return 0;
} }
#[cfg(test)] #[cfg(test)]

View File

@ -615,11 +615,10 @@ impl CtxMethods for BuildContext {
pub fn main() { pub fn main() {
io::println("WARNING: The Rust package manager is experimental and may be unstable"); io::println("WARNING: The Rust package manager is experimental and may be unstable");
let args = os::args(); os::set_exit_status(main_args(os::args()));
main_args(args);
} }
pub fn main_args(args: &[~str]) { pub fn main_args(args: &[~str]) -> int {
let opts = ~[getopts::optflag("h"), getopts::optflag("help"), let opts = ~[getopts::optflag("h"), getopts::optflag("help"),
getopts::optflag("no-link"), getopts::optflag("no-link"),
getopts::optflag("no-trans"), getopts::optflag("no-trans"),
@ -645,7 +644,7 @@ pub fn main_args(args: &[~str]) {
result::Err(f) => { result::Err(f) => {
error(fmt!("%s", f.to_err_msg())); error(fmt!("%s", f.to_err_msg()));
return; return 1;
} }
}; };
let mut help = matches.opt_present("h") || let mut help = matches.opt_present("h") ||
@ -662,7 +661,7 @@ pub fn main_args(args: &[~str]) {
if matches.opt_present("v") || if matches.opt_present("v") ||
matches.opt_present("version") { matches.opt_present("version") {
rustc::version(args[0]); rustc::version(args[0]);
return; return 0;
} }
let use_rust_path_hack = matches.opt_present("r") || let use_rust_path_hack = matches.opt_present("r") ||
@ -701,7 +700,8 @@ pub fn main_args(args: &[~str]) {
args.shift(); args.shift();
if (args.len() < 1) { if (args.len() < 1) {
return usage::general(); usage::general();
return 1;
} }
let rustc_flags = RustcFlags { let rustc_flags = RustcFlags {
@ -739,11 +739,14 @@ pub fn main_args(args: &[~str]) {
} }
} }
let cmd = match cmd_opt { let cmd = match cmd_opt {
None => return usage::general(), None => {
usage::general();
return 0;
}
Some(cmd) => { Some(cmd) => {
help |= context::flags_ok_for_cmd(&rustc_flags, cfgs, *cmd, user_supplied_opt_level); help |= context::flags_ok_for_cmd(&rustc_flags, cfgs, *cmd, user_supplied_opt_level);
if help { if help {
return match *cmd { match *cmd {
~"build" => usage::build(), ~"build" => usage::build(),
~"clean" => usage::clean(), ~"clean" => usage::clean(),
~"do" => usage::do_cmd(), ~"do" => usage::do_cmd(),
@ -757,6 +760,7 @@ pub fn main_args(args: &[~str]) {
~"unprefer" => usage::unprefer(), ~"unprefer" => usage::unprefer(),
_ => usage::general() _ => usage::general()
}; };
return 0;
} else { } else {
cmd cmd
} }
@ -794,8 +798,8 @@ pub fn main_args(args: &[~str]) {
// and at least one test case succeeds if rustpkg returns COPY_FAILED_CODE, // and at least one test case succeeds if rustpkg returns COPY_FAILED_CODE,
// when actually, it might set the exit code for that even if a different // when actually, it might set the exit code for that even if a different
// unhandled condition got raised. // unhandled condition got raised.
if result.is_err() { os::set_exit_status(COPY_FAILED_CODE); } if result.is_err() { return COPY_FAILED_CODE; }
return 0;
} }
/** /**