The linux backtrace unwinder relies on unwind tables to work properly, and generating and printing a backtrace is done by for example the default panic hook. Begin emitting unwind tables by default again with `-C panic=abort` (see history below) so that backtraces work. History ======= Backtraces with `-C panic=abort` used to work in Rust 1.22 but broke in Rust 1.23, because in 1.23 we stopped emitting unwind tables with `-C panic=abort` (see24cc38e3b0). In 1.45 (seecda994633e) a workaround in the form of `-C force-unwind-tables=yes` was added. `-C panic=abort` was added in [Rust 1.10](https://blog.rust-lang.org/2016/07/07/Rust-1.10/#what-s-in-1-10-stable) and the motivation was binary size and compile time. But given how confusing that behavior has turned out to be, it is better to make binary size optimization opt-in with `-C force-unwind-tables=no` rather than default since the current default breaks backtraces. Besides, if binary size is a primary concern, there are many other tricks that can be used that has a higher impact.
58 lines
2.0 KiB
Rust
58 lines
2.0 KiB
Rust
//! Test that with `-C panic=abort` the backtrace is not cut off by default
|
|
//! (i.e. without using `-C force-unwind-tables=yes`) by ensuring that our own
|
|
//! functions are in the backtrace. If we just check one function it might be
|
|
//! the last function, so make sure the backtrace can continue by checking for
|
|
//! two functions. Regression test for
|
|
//! <https://github.com/rust-lang/rust/issues/81902>.
|
|
|
|
//@ run-pass
|
|
//@ needs-subprocess
|
|
// We want to test if unwind tables are emitted by default. We must make sure
|
|
// to disable debuginfo to test that, because enabling debuginfo also means that
|
|
// unwind tables are emitted, which prevents us from testing what we want.
|
|
// We also need to set opt-level=0 to avoid optimizing away our functions.
|
|
//@ compile-flags: -C panic=abort -C opt-level=0 -C debuginfo=0
|
|
//@ no-prefer-dynamic
|
|
//@ ignore-apple
|
|
//@ ignore-arm-unknown-linux-gnueabihf FIXME(#146996) Try removing this once #146996 has been fixed.
|
|
//@ ignore-msvc Backtraces on Windows requires debuginfo which we can't use here
|
|
|
|
static FN_1: &str = "this_function_must_be_in_the_backtrace";
|
|
fn this_function_must_be_in_the_backtrace() {
|
|
and_this_function_too();
|
|
}
|
|
|
|
static FN_2: &str = "and_this_function_too";
|
|
fn and_this_function_too() {
|
|
panic!("generate panic backtrace");
|
|
}
|
|
|
|
fn run_test() {
|
|
let output = std::process::Command::new(std::env::current_exe().unwrap())
|
|
.arg("whatever")
|
|
.env("RUST_BACKTRACE", "full")
|
|
.output()
|
|
.unwrap();
|
|
let backtrace = std::str::from_utf8(&output.stderr).unwrap();
|
|
|
|
fn assert(function_name: &str, backtrace: &str) {
|
|
assert!(
|
|
backtrace.contains(function_name),
|
|
"ERROR: no `{}` in stderr! actual stderr: {}",
|
|
function_name,
|
|
backtrace
|
|
);
|
|
}
|
|
assert(FN_1, backtrace);
|
|
assert(FN_2, backtrace);
|
|
}
|
|
|
|
fn main() {
|
|
let args: Vec<String> = std::env::args().collect();
|
|
if args.len() == 1 {
|
|
run_test();
|
|
} else {
|
|
this_function_must_be_in_the_backtrace();
|
|
}
|
|
}
|