]> git.lizzy.rs Git - rust.git/commitdiff
Abort earlier upon multi-panics
authorAndrea Canciani <ranma42@gmail.com>
Thu, 24 Sep 2015 15:21:29 +0000 (17:21 +0200)
committerAndrea Canciani <ranma42@gmail.com>
Thu, 24 Sep 2015 21:52:13 +0000 (23:52 +0200)
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.

src/libstd/panicking.rs

index fc242dee99fee987ed8d59ac324885779127c4ae..2b2af350c992cc874737ccfe547e65ef9f7ffc2b 100644 (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();