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.
This commit is contained in:
parent
7535479633
commit
6d03897376
@ -30,7 +30,6 @@ use treemap::TreeMap;
|
||||
|
||||
use std::clone::Clone;
|
||||
use std::comm::{stream, SharedChan, GenericPort, GenericChan};
|
||||
use std::libc;
|
||||
use std::io;
|
||||
use std::result;
|
||||
use std::task;
|
||||
@ -125,8 +124,9 @@ pub type MetricDiff = TreeMap<~str,MetricChange>;
|
||||
pub fn test_main(args: &[~str], tests: ~[TestDescAndFn]) {
|
||||
let opts =
|
||||
match parse_opts(args) {
|
||||
Ok(o) => o,
|
||||
Err(msg) => fail!(msg)
|
||||
Some(Ok(o)) => o,
|
||||
Some(Err(msg)) => fail!(msg),
|
||||
None => return
|
||||
};
|
||||
if !run_tests_console(&opts, tests) { fail!("Some tests failed"); }
|
||||
}
|
||||
@ -189,7 +189,7 @@ fn optgroups() -> ~[getopts::groups::OptGroup] {
|
||||
"A.B")]
|
||||
}
|
||||
|
||||
fn usage(binary: &str, helpstr: &str) -> ! {
|
||||
fn usage(binary: &str, helpstr: &str) {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
let message = fmt!("Usage: %s [OPTIONS] [FILTER]", binary);
|
||||
@ -217,20 +217,19 @@ Test Attributes:
|
||||
tests. This may also be written as #[ignore(cfg(...))] to
|
||||
ignore the test on certain configurations.");
|
||||
}
|
||||
unsafe { libc::exit(0) }
|
||||
}
|
||||
|
||||
// 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 matches =
|
||||
match groups::getopts(args_, optgroups()) {
|
||||
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("help") { usage(args[0], "help"); }
|
||||
if matches.opt_present("h") { usage(args[0], "h"); return None; }
|
||||
if matches.opt_present("help") { usage(args[0], "help"); return None; }
|
||||
|
||||
let filter =
|
||||
if matches.free.len() > 0 {
|
||||
@ -272,7 +271,7 @@ pub fn parse_opts(args: &[~str]) -> OptRes {
|
||||
logfile: logfile
|
||||
};
|
||||
|
||||
Ok(test_opts)
|
||||
Some(Ok(test_opts))
|
||||
}
|
||||
|
||||
pub fn opt_shard(maybestr: Option<~str>) -> Option<(uint,uint)> {
|
||||
@ -1228,7 +1227,7 @@ mod tests {
|
||||
fn first_free_arg_should_be_a_filter() {
|
||||
let args = ~[~"progname", ~"filter"];
|
||||
let opts = match parse_opts(args) {
|
||||
Ok(o) => o,
|
||||
Some(Ok(o)) => o,
|
||||
_ => fail!("Malformed arg in first_free_arg_should_be_a_filter")
|
||||
};
|
||||
assert!("filter" == opts.filter.clone().unwrap());
|
||||
@ -1238,7 +1237,7 @@ mod tests {
|
||||
fn parse_ignored_flag() {
|
||||
let args = ~[~"progname", ~"filter", ~"--ignored"];
|
||||
let opts = match parse_opts(args) {
|
||||
Ok(o) => o,
|
||||
Some(Ok(o)) => o,
|
||||
_ => fail!("Malformed arg in parse_ignored_flag")
|
||||
};
|
||||
assert!((opts.run_ignored));
|
||||
|
@ -45,7 +45,7 @@ impl ValidUsage {
|
||||
|
||||
enum Action {
|
||||
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> {
|
||||
@ -186,18 +186,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()];
|
||||
osargs.push_all_move(args.to_owned());
|
||||
f(osargs);
|
||||
f(osargs)
|
||||
}
|
||||
|
||||
fn do_command(command: &Command, args: &[~str]) -> ValidUsage {
|
||||
match command.action {
|
||||
Call(f) => f(args),
|
||||
CallMain(prog, f) => {
|
||||
invoke(prog, args, f);
|
||||
Valid(0)
|
||||
Valid(invoke(prog, args, f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -394,13 +394,14 @@ pub fn monitor(f: ~fn(@diagnostic::Emitter)) {
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let args = os::args();
|
||||
main_args(args);
|
||||
std::os::set_exit_status(main_args(std::os::args()));
|
||||
}
|
||||
|
||||
pub fn main_args(args: &[~str]) {
|
||||
pub fn main_args(args: &[~str]) -> int {
|
||||
let owned_args = args.to_owned();
|
||||
do monitor |demitter| {
|
||||
run_compiler(owned_args, demitter);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ enum OutputFormat {
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
main_args(std::os::args());
|
||||
std::os::set_exit_status(main_args(std::os::args()));
|
||||
}
|
||||
|
||||
pub fn opts() -> ~[groups::OptGroup] {
|
||||
@ -76,14 +76,14 @@ pub fn usage(argv0: &str) {
|
||||
argv0), opts()));
|
||||
}
|
||||
|
||||
pub fn main_args(args: &[~str]) {
|
||||
pub fn main_args(args: &[~str]) -> int {
|
||||
//use extra::getopts::groups::*;
|
||||
|
||||
let matches = groups::getopts(args.tail(), opts()).unwrap();
|
||||
|
||||
if matches.opt_present("h") || matches.opt_present("help") {
|
||||
usage(args[0]);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
let (format, cratefile) = match matches.free.clone() {
|
||||
@ -92,17 +92,17 @@ pub fn main_args(args: &[~str]) {
|
||||
[s, _] => {
|
||||
println!("Unknown output format: `{}`", s);
|
||||
usage(args[0]);
|
||||
exit(1);
|
||||
return 1;
|
||||
}
|
||||
[_, .._] => {
|
||||
println!("Expected exactly one crate to process");
|
||||
usage(args[0]);
|
||||
exit(1);
|
||||
return 1;
|
||||
}
|
||||
_ => {
|
||||
println!("Expected an output format and then one crate");
|
||||
usage(args[0]);
|
||||
exit(1);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
@ -179,6 +179,8 @@ pub fn main_args(args: &[~str]) {
|
||||
}
|
||||
let ended = time::precise_time_ns();
|
||||
info2!("Took {:.03f}s", (ended as f64 - started as f64) / 1000000000f64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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();
|
||||
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) }
|
||||
}
|
||||
|
@ -517,8 +517,7 @@ pub fn run_line(repl: &mut Repl, input: @io::Reader, out: @io::Writer, line: ~st
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let args = os::args();
|
||||
main_args(args);
|
||||
os::set_exit_status(main_args(os::args()));
|
||||
}
|
||||
|
||||
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)];
|
||||
|
||||
let input = io::stdin();
|
||||
@ -576,6 +575,8 @@ pub fn main_args(args: &[~str]) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -615,11 +615,10 @@ impl CtxMethods for BuildContext {
|
||||
|
||||
pub fn main() {
|
||||
io::println("WARNING: The Rust package manager is experimental and may be unstable");
|
||||
let args = os::args();
|
||||
main_args(args);
|
||||
os::set_exit_status(main_args(os::args()));
|
||||
}
|
||||
|
||||
pub fn main_args(args: &[~str]) {
|
||||
pub fn main_args(args: &[~str]) -> int {
|
||||
let opts = ~[getopts::optflag("h"), getopts::optflag("help"),
|
||||
getopts::optflag("no-link"),
|
||||
getopts::optflag("no-trans"),
|
||||
@ -645,7 +644,7 @@ pub fn main_args(args: &[~str]) {
|
||||
result::Err(f) => {
|
||||
error(fmt!("%s", f.to_err_msg()));
|
||||
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
let mut help = matches.opt_present("h") ||
|
||||
@ -662,7 +661,7 @@ pub fn main_args(args: &[~str]) {
|
||||
if matches.opt_present("v") ||
|
||||
matches.opt_present("version") {
|
||||
rustc::version(args[0]);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
let use_rust_path_hack = matches.opt_present("r") ||
|
||||
@ -701,7 +700,8 @@ pub fn main_args(args: &[~str]) {
|
||||
args.shift();
|
||||
|
||||
if (args.len() < 1) {
|
||||
return usage::general();
|
||||
usage::general();
|
||||
return 1;
|
||||
}
|
||||
|
||||
let rustc_flags = RustcFlags {
|
||||
@ -739,11 +739,14 @@ pub fn main_args(args: &[~str]) {
|
||||
}
|
||||
}
|
||||
let cmd = match cmd_opt {
|
||||
None => return usage::general(),
|
||||
None => {
|
||||
usage::general();
|
||||
return 0;
|
||||
}
|
||||
Some(cmd) => {
|
||||
help |= context::flags_ok_for_cmd(&rustc_flags, cfgs, *cmd, user_supplied_opt_level);
|
||||
if help {
|
||||
return match *cmd {
|
||||
match *cmd {
|
||||
~"build" => usage::build(),
|
||||
~"clean" => usage::clean(),
|
||||
~"do" => usage::do_cmd(),
|
||||
@ -757,6 +760,7 @@ pub fn main_args(args: &[~str]) {
|
||||
~"unprefer" => usage::unprefer(),
|
||||
_ => usage::general()
|
||||
};
|
||||
return 0;
|
||||
} else {
|
||||
cmd
|
||||
}
|
||||
@ -794,8 +798,8 @@ pub fn main_args(args: &[~str]) {
|
||||
// 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
|
||||
// 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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user