Add backtrace to panic-handler feature
This commit is contained in:
parent
8e20d33822
commit
210e6def4c
@ -36,16 +36,20 @@ fn bar() {
|
|||||||
foo()
|
foo()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _ = unwind::panic::catch_unwind(|| {
|
||||||
|
bar();
|
||||||
|
println!("done");
|
||||||
|
});
|
||||||
|
println!("caught");
|
||||||
|
let _p = PanicOnDrop;
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
|
||||||
#[start]
|
#[start]
|
||||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
fn start(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
unwind::panic::catch_unwind(|| {
|
unwind::panic::catch_unwind(|| {
|
||||||
let _ = unwind::panic::catch_unwind(|| {
|
main();
|
||||||
bar();
|
|
||||||
println!("done");
|
|
||||||
});
|
|
||||||
println!("caught");
|
|
||||||
let _p = PanicOnDrop;
|
|
||||||
foo();
|
|
||||||
0
|
0
|
||||||
})
|
})
|
||||||
.unwrap_or(101)
|
.unwrap_or(101)
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
|
use crate::abi::*;
|
||||||
use crate::print::*;
|
use crate::print::*;
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use core::any::Any;
|
use core::any::Any;
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
|
use core::ffi::c_void;
|
||||||
use core::panic::{Location, PanicInfo};
|
use core::panic::{Location, PanicInfo};
|
||||||
|
use core::sync::atomic::{AtomicI32, Ordering};
|
||||||
|
|
||||||
#[thread_local]
|
#[thread_local]
|
||||||
static PANIC_COUNT: Cell<usize> = Cell::new(0);
|
static PANIC_COUNT: Cell<usize> = Cell::new(0);
|
||||||
@ -22,12 +25,63 @@ pub(crate) fn panic_caught() {
|
|||||||
PANIC_COUNT.set(0);
|
PANIC_COUNT.set(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_env() -> bool {
|
||||||
|
static ENV: AtomicI32 = AtomicI32::new(-1);
|
||||||
|
|
||||||
|
let env = ENV.load(Ordering::Relaxed);
|
||||||
|
if env != -1 {
|
||||||
|
return env != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let val = unsafe {
|
||||||
|
let ptr = libc::getenv(b"RUST_BACKTRACE\0".as_ptr() as _);
|
||||||
|
if ptr.is_null() {
|
||||||
|
b""
|
||||||
|
} else {
|
||||||
|
let len = libc::strlen(ptr);
|
||||||
|
core::slice::from_raw_parts(ptr as *const u8, len)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let (note, env) = match val {
|
||||||
|
b"" => (true, false),
|
||||||
|
b"1" | b"full" => (false, true),
|
||||||
|
_ => (false, false),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Issue a note for the first panic.
|
||||||
|
if ENV.swap(env as _, Ordering::Relaxed) == -1 && note {
|
||||||
|
eprintln!("note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace");
|
||||||
|
}
|
||||||
|
env
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stack_trace() {
|
||||||
|
struct CallbackData {
|
||||||
|
counter: usize,
|
||||||
|
}
|
||||||
|
extern "C" fn callback(
|
||||||
|
unwind_ctx: &mut UnwindContext<'_>,
|
||||||
|
arg: *mut c_void,
|
||||||
|
) -> UnwindReasonCode {
|
||||||
|
let data = unsafe { &mut *(arg as *mut CallbackData) };
|
||||||
|
data.counter += 1;
|
||||||
|
eprintln!("{:4}:{:#19x} - <unknown>", data.counter, _Unwind_GetIP(unwind_ctx));
|
||||||
|
UnwindReasonCode::NO_REASON
|
||||||
|
}
|
||||||
|
let mut data = CallbackData { counter: 0 };
|
||||||
|
_Unwind_Backtrace(callback, &mut data as *mut _ as _);
|
||||||
|
}
|
||||||
|
|
||||||
fn do_panic(msg: Box<dyn Any + Send>) -> ! {
|
fn do_panic(msg: Box<dyn Any + Send>) -> ! {
|
||||||
if PANIC_COUNT.get() >= 1 {
|
if PANIC_COUNT.get() >= 1 {
|
||||||
|
stack_trace();
|
||||||
eprintln!("thread panicked while processing panic. aborting.");
|
eprintln!("thread panicked while processing panic. aborting.");
|
||||||
core::intrinsics::abort();
|
core::intrinsics::abort();
|
||||||
}
|
}
|
||||||
PANIC_COUNT.set(1);
|
PANIC_COUNT.set(1);
|
||||||
|
if check_env() {
|
||||||
|
stack_trace();
|
||||||
|
}
|
||||||
let code = crate::panic::begin_panic(Box::new(msg));
|
let code = crate::panic::begin_panic(Box::new(msg));
|
||||||
eprintln!("failed to initiate panic, error {}", code.0);
|
eprintln!("failed to initiate panic, error {}", code.0);
|
||||||
core::intrinsics::abort();
|
core::intrinsics::abort();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user