Abort earlier upon multi-panics

The double-panic `abort` is run after the logging code, to provide
feedback in case of a double-panic. This means that if the panic
logging fails with a panic, the `abort` might never be reached.

This should not normally occur, but if the `on_panic` function detects
more than 2 panics, aborting *before* logging makes panic handling
somewhat more robust, as it avoids an infinite recursion, which would
eventually crash the process, but also make the problem harder to
debug.

This handles the FIXME about what to do if the thread printing panics.
This commit is contained in:
Andrea Canciani 2015-09-24 17:21:29 +02:00
parent c7b84909b0
commit 54c0231b14

View File

@ -52,7 +52,6 @@ fn log_panic(obj: &(Any+Send), file: &'static str, line: u32,
let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take());
match (prev, err.as_mut()) {
(Some(mut stderr), _) => {
// FIXME: what to do when the thread printing panics?
write(&mut *stderr);
let mut s = Some(stderr);
LOCAL_STDERR.with(|slot| {
@ -71,6 +70,17 @@ pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) {
count
});
// If this is the third nested call, on_panic triggered the last panic,
// otherwise the double-panic check would have aborted the process.
// Even if it is likely that on_panic was unable to log the backtrace,
// abort immediately to avoid infinite recursion, so that attaching a
// debugger provides a useable stacktrace.
if panics >= 3 {
util::dumb_print(format_args!("thread panicked while processing \
panic. aborting."));
unsafe { intrinsics::abort() }
}
// If this is a double panic, make sure that we print a backtrace
// for this panic. Otherwise only print it if logging is enabled.
let log_backtrace = panics >= 2 || backtrace::log_enabled();