I know that the 'thread panicked while panicking' message is almost certainly evidence of something dumb that I did (wrt the second panic, that is). However, I'm wondering if there's a way to get Rust to at least print a file/line number before aborting when this happens? I've got a large codebase and I'm having difficulty tracking it down.
Valgrind to the rescue! I'm not sure if it will work in all cases of panicking-while-panicking, but at least in my case, running my code under valgrind showed a stack trace of the moment the second panic occurred.
I was curious so I thought I'd check it out on my machine.
$ rustc --version
rustc 1.19.0-nightly (2d4ed8e0c 2017-05-03)
The source code:
$ cat main.rs
struct Foo {}
impl Drop for Foo {
fn drop(&mut self) {
panic!("Double panic!");
}
}
pub fn main() {
let d = Foo {};
panic!();
}
And the output:
thread 'main' panicked at 'explicit panic', main.rs:11
note: Run with `RUST_BACKTRACE=1` for a backtrace.
thread 'main' panicked at 'Double panic!', main.rs:5
stack backtrace:
0: 0x5576b4aef533 - std::sys::imp::backtrace::tracing::imp::unwind_backtrace::h0e14f963e590228b
at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
1: 0x5576b4aebf22 - std::sys_common::backtrace::_print::h27334d67e47d33d3
at /checkout/src/libstd/sys_common/backtrace.rs:71
2: 0x5576b4af0d64 - std::panicking::default_hook::{{closure}}::h47b2a7bf24f9ec4b
at /checkout/src/libstd/sys_common/backtrace.rs:60
at /checkout/src/libstd/panicking.rs:355
3: 0x5576b4af092b - std::panicking::default_hook::h96a38c23a922ad21
at /checkout/src/libstd/panicking.rs:371
4: 0x5576b4af115b - std::panicking::rust_panic_with_hook::h2e0c66f95442aa5e
at /checkout/src/libstd/panicking.rs:549
5: 0x5576b4ae78c1 - std::panicking::begin_panic::h32add8ccad0c0f8c
6: 0x5576b4ae7a21 - <main::Foo as core::ops::Drop>::drop::h0772637ccfdbda50
7: 0x5576b4ae7915 - core::ptr::drop_in_place::hcd339a962d1f7c82
8: 0x5576b4ae7a6b - main::main::h94cdd750d4114894
9: 0x5576b4af8c5a - __rust_maybe_catch_panic
at /checkout/src/libpanic_unwind/lib.rs:98
10: 0x5576b4af1791 - std::rt::lang_start::h8126425a59d3b4a0
at /checkout/src/libstd/panicking.rs:433
at /checkout/src/libstd/panic.rs:361
at /checkout/src/libstd/rt.rs:57
11: 0x5576b4ae7aa9 - main
12: 0x7f46f2063510 - __libc_start_main
13: 0x5576b4ae7729 - _start
14: 0x0 - <unknown>
thread panicked while panicking. aborting.
[2] 27536 illegal hardware instruction (core dumped) ./main
Looks like it was added some time recently to nightly because I can see the location of both panic!()
s.
That example seems to work in 1.17 as well: Rust Playground
It looks like printing a backtrace on a second panic was added in 1.7: https://github.com/rust-lang/rust/commit/f1148a540a16ba4ba2635403a9b014da9683851b
EDIT: Actually, it existed before that, I'm not sure exactly when.
Huh weird. I think that, in my case, the issue was caused by a SIGSEGV, which in turn caused a panic, which in turn caused a drop
to panic... maybe. I'm not positive. I'm writing some very unsafe code, so I'm not really sure. In any case, that might explain why I wasn't getting a stack trace.
In this case, you should not need to use valgrind, gdb should be enough.
Yeah, either of them works in this case.