Skip to content

Commit

Permalink
Auto merge of #52197 - euclio:exit-code, r=oli-obk
Browse files Browse the repository at this point in the history
overhaul exit codes for rustc and rustdoc

This commit changes the exit status of rustc to 1 in the presence of
compilation errors. In the event of an unexpected panic (ICE) the
standard panic error exit status of 101 remains.

A run-make test is added to ensure that the exit code does not regress,
and compiletest is updated to check for an exit status of 1 or 101,
depending on the mode and suite.

This is a breaking change for custom drivers.

Note that while changes were made to the rustdoc binary, there is no
intended behavior change. rustdoc errors (i.e., failed lints) will still
report 101. While this could *also* hide potential ICEs, I will leave
that work to a future PR.

Fixes #51971.
  • Loading branch information
bors committed Jul 19, 2018
2 parents 5ba2184 + 8f4ccac commit a8247dd
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 25 deletions.
48 changes: 35 additions & 13 deletions src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ use std::cmp::max;
use std::default::Default;
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
use std::env;
use std::error::Error;
use std::ffi::OsString;
use std::fmt::{self, Display};
use std::io::{self, Read, Write};
use std::iter::repeat;
use std::mem;
Expand Down Expand Up @@ -146,6 +148,12 @@ pub mod target_features {
}
}

/// Exit status code used for successful compilation and help output.
pub const EXIT_SUCCESS: isize = 0;

/// Exit status code used for compilation failures and invalid flags.
pub const EXIT_FAILURE: isize = 1;

const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\
md#bug-reports";

Expand Down Expand Up @@ -178,7 +186,7 @@ pub fn abort_on_err<T>(result: Result<T, CompileIncomplete>, sess: &Session) ->
pub fn run<F>(run_compiler: F) -> isize
where F: FnOnce() -> (CompileResult, Option<Session>) + Send + 'static
{
monitor(move || {
let result = monitor(move || {
let (result, session) = run_compiler();
if let Err(CompileIncomplete::Errored(_)) = result {
match session {
Expand All @@ -201,7 +209,11 @@ pub fn run<F>(run_compiler: F) -> isize
}
}
});
0

match result {
Ok(()) => EXIT_SUCCESS,
Err(_) => EXIT_FAILURE,
}
}

fn load_backend_from_dylib(path: &Path) -> fn() -> Box<dyn CodegenBackend> {
Expand Down Expand Up @@ -1625,20 +1637,30 @@ fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
}
}

#[derive(Debug)]
pub struct CompilationFailure;

impl Error for CompilationFailure {}

impl Display for CompilationFailure {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "compilation had errors")
}
}

/// Run a procedure which will detect panics in the compiler and print nicer
/// error messages rather than just failing the test.
///
/// The diagnostic emitter yielded to the procedure should be used for reporting
/// errors of the compiler.
pub fn monitor<F: FnOnce() + Send + 'static>(f: F) {
let result = in_rustc_thread(move || {
pub fn monitor<F: FnOnce() + Send + 'static>(f: F) -> Result<(), CompilationFailure> {
in_rustc_thread(move || {
f()
});

if let Err(value) = result {
// Thread panicked without emitting a fatal diagnostic
if !value.is::<errors::FatalErrorMarker>() {
// Emit a newline
}).map_err(|value| {
if value.is::<errors::FatalErrorMarker>() {
CompilationFailure
} else {
// Thread panicked without emitting a fatal diagnostic
eprintln!("");

let emitter =
Expand Down Expand Up @@ -1677,10 +1699,10 @@ pub fn monitor<F: FnOnce() + Send + 'static>(f: F) {
&note,
errors::Level::Note);
}
}

panic::resume_unwind(Box::new(errors::FatalErrorMarker));
}
panic::resume_unwind(Box::new(errors::FatalErrorMarker));
}
})
}

pub fn diagnostics_registry() -> errors::registry::Registry {
Expand Down
11 changes: 8 additions & 3 deletions src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ use errors::ColorConfig;
use std::collections::{BTreeMap, BTreeSet};
use std::default::Default;
use std::env;
use std::panic;
use std::path::{Path, PathBuf};
use std::process;
use std::sync::mpsc::channel;
Expand Down Expand Up @@ -115,7 +116,7 @@ pub fn main() {
syntax::with_globals(move || {
get_args().map(|args| main_args(&args)).unwrap_or(1)
})
}).unwrap().join().unwrap_or(101);
}).unwrap().join().unwrap_or(rustc_driver::EXIT_FAILURE);
process::exit(res as i32);
}

Expand Down Expand Up @@ -667,7 +668,7 @@ where R: 'static + Send,

let (tx, rx) = channel();

rustc_driver::monitor(move || syntax::with_globals(move || {
let result = rustc_driver::monitor(move || syntax::with_globals(move || {
use rustc::session::config::Input;

let (mut krate, renderinfo) =
Expand Down Expand Up @@ -771,7 +772,11 @@ where R: 'static + Send,

tx.send(f(Output { krate: krate, renderinfo: renderinfo, passes: passes })).unwrap();
}));
rx.recv().unwrap()

match result {
Ok(()) => rx.recv().unwrap(),
Err(_) => panic::resume_unwind(Box::new(errors::FatalErrorMarker)),
}
}

/// Prints deprecation warnings for deprecated options
Expand Down
11 changes: 11 additions & 0 deletions src/test/run-make-fulldeps/exit-code/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-include ../tools.mk

all:
$(RUSTC) success.rs; [ $$? -eq 0 ]
$(RUSTC) --invalid-arg-foo; [ $$? -eq 1 ]
$(RUSTC) compile-error.rs; [ $$? -eq 1 ]
$(RUSTC) -Ztreat-err-as-bug compile-error.rs; [ $$? -eq 101 ]
$(RUSTDOC) -o $(TMPDIR)/exit-code success.rs; [ $$? -eq 0 ]
$(RUSTDOC) --invalid-arg-foo; [ $$? -eq 1 ]
$(RUSTDOC) compile-error.rs; [ $$? -eq 1 ]
$(RUSTDOC) lint-failure.rs; [ $$? -eq 1 ]
13 changes: 13 additions & 0 deletions src/test/run-make-fulldeps/exit-code/compile-error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn main() {
compile_error!("kaboom");
}
16 changes: 16 additions & 0 deletions src/test/run-make-fulldeps/exit-code/lint-failure.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![deny(intra_doc_link_resolution_failure)]

/// [intradoc::failure]
fn main() {
println!("Hello, world!");
}
14 changes: 14 additions & 0 deletions src/test/run-make-fulldeps/exit-code/success.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/// Main function
fn main() {
println!("Hello, world!");
}
2 changes: 2 additions & 0 deletions src/test/ui/issue-20801.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-test currently ICEs when using NLL (#52416)

// We used to ICE when moving out of a `*mut T` or `*const T`.

struct T(u8);
Expand Down
10 changes: 7 additions & 3 deletions src/tools/compiletest/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ use std::io::prelude::*;
use std::io::BufReader;
use std::path::{Path, PathBuf};

use common;
use common::Config;
use common::{self, Config, Mode};
use util;

use extract_gdb_version;
Expand Down Expand Up @@ -262,7 +261,7 @@ impl TestProps {
disable_ui_testing_normalization: false,
normalize_stdout: vec![],
normalize_stderr: vec![],
failure_status: 101,
failure_status: -1,
run_rustfix: false,
}
}
Expand Down Expand Up @@ -393,6 +392,11 @@ impl TestProps {

if let Some(code) = config.parse_failure_status(ln) {
self.failure_status = code;
} else {
self.failure_status = match config.mode {
Mode::RunFail => 101,
_ => 1,
};
}

if !self.run_rustfix {
Expand Down
10 changes: 4 additions & 6 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1170,12 +1170,10 @@ impl<'test> TestCx<'test> {
}

fn check_no_compiler_crash(&self, proc_res: &ProcRes) {
for line in proc_res.stderr.lines() {
if line.contains("error: internal compiler error") {
self.fatal_proc_rec("compiler encountered internal error", proc_res);
} else if line.contains(" panicked at ") {
self.fatal_proc_rec("compiler panicked", proc_res);
}
match proc_res.status.code() {
Some(101) => self.fatal_proc_rec("compiler encountered internal error", proc_res),
None => self.fatal_proc_rec("compiler terminated by signal", proc_res),
_ => (),
}
}

Expand Down

0 comments on commit a8247dd

Please sign in to comment.