panic_handler.rs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. use crate::abi::*;
  2. use crate::print::*;
  3. use alloc::boxed::Box;
  4. use core::any::Any;
  5. use core::cell::Cell;
  6. use core::ffi::c_void;
  7. use core::panic::{Location, PanicInfo};
  8. use core::sync::atomic::{AtomicI32, Ordering};
  9. #[thread_local]
  10. static PANIC_COUNT: Cell<usize> = Cell::new(0);
  11. #[link(name = "c")]
  12. extern "C" {}
  13. pub(crate) fn drop_panic() {
  14. eprintln!("Rust panics must be rethrown");
  15. }
  16. pub(crate) fn foreign_exception() {
  17. eprintln!("Rust cannot catch foreign exceptions");
  18. }
  19. pub(crate) fn panic_caught() {
  20. PANIC_COUNT.set(0);
  21. }
  22. fn check_env() -> bool {
  23. static ENV: AtomicI32 = AtomicI32::new(-1);
  24. let env = ENV.load(Ordering::Relaxed);
  25. if env != -1 {
  26. return env != 0;
  27. }
  28. let val = unsafe {
  29. let ptr = libc::getenv(b"RUST_BACKTRACE\0".as_ptr() as _);
  30. if ptr.is_null() {
  31. b""
  32. } else {
  33. let len = libc::strlen(ptr);
  34. core::slice::from_raw_parts(ptr as *const u8, len)
  35. }
  36. };
  37. let (note, env) = match val {
  38. b"" => (true, false),
  39. b"1" | b"full" => (false, true),
  40. _ => (false, false),
  41. };
  42. // Issue a note for the first panic.
  43. if ENV.swap(env as _, Ordering::Relaxed) == -1 && note {
  44. eprintln!("note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace");
  45. }
  46. env
  47. }
  48. fn stack_trace() {
  49. struct CallbackData {
  50. counter: usize,
  51. }
  52. extern "C" fn callback(unwind_ctx: &UnwindContext<'_>, arg: *mut c_void) -> UnwindReasonCode {
  53. let data = unsafe { &mut *(arg as *mut CallbackData) };
  54. data.counter += 1;
  55. eprintln!(
  56. "{:4}:{:#19x} - <unknown>",
  57. data.counter,
  58. _Unwind_GetIP(unwind_ctx)
  59. );
  60. UnwindReasonCode::NO_REASON
  61. }
  62. let mut data = CallbackData { counter: 0 };
  63. _Unwind_Backtrace(callback, &mut data as *mut _ as _);
  64. }
  65. fn do_panic(msg: Box<dyn Any + Send>) -> ! {
  66. if PANIC_COUNT.get() >= 1 {
  67. stack_trace();
  68. eprintln!("thread panicked while processing panic. aborting.");
  69. crate::util::abort();
  70. }
  71. PANIC_COUNT.set(1);
  72. if check_env() {
  73. stack_trace();
  74. }
  75. let code = crate::panic::begin_panic(Box::new(msg));
  76. eprintln!("failed to initiate panic, error {}", code.0);
  77. crate::util::abort();
  78. }
  79. #[panic_handler]
  80. fn panic(info: &PanicInfo<'_>) -> ! {
  81. eprintln!("{}", info);
  82. struct NoPayload;
  83. do_panic(Box::new(NoPayload))
  84. }
  85. #[track_caller]
  86. pub fn panic_any<M: 'static + Any + Send>(msg: M) -> ! {
  87. eprintln!("panicked at {}", Location::caller());
  88. do_panic(Box::new(msg))
  89. }