panic.rs 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. use alloc::boxed::Box;
  2. use core::any::Any;
  3. use core::mem::MaybeUninit;
  4. use crate::abi::*;
  5. #[cfg(feature = "panic-handler")]
  6. use crate::panic_handler::*;
  7. use crate::panicking::Exception;
  8. #[repr(transparent)]
  9. struct RustPanic(Box<dyn Any + Send>, ForeignGuard);
  10. struct ForeignGuard;
  11. impl Drop for ForeignGuard {
  12. fn drop(&mut self) {
  13. #[cfg(feature = "panic-handler")]
  14. {
  15. foreign_exception();
  16. }
  17. core::intrinsics::abort();
  18. }
  19. }
  20. #[repr(C)]
  21. struct ExceptionWithPayload {
  22. exception: MaybeUninit<UnwindException>,
  23. payload: RustPanic,
  24. }
  25. unsafe impl Exception for RustPanic {
  26. const CLASS: [u8; 8] = *b"MOZ\0RUST";
  27. fn wrap(this: Self) -> *mut UnwindException {
  28. Box::into_raw(Box::new(ExceptionWithPayload {
  29. exception: MaybeUninit::uninit(),
  30. payload: this,
  31. })) as *mut UnwindException
  32. }
  33. unsafe fn unwrap(ex: *mut UnwindException) -> Self {
  34. let ex = unsafe { Box::from_raw(ex as *mut ExceptionWithPayload) };
  35. ex.payload
  36. }
  37. }
  38. pub fn begin_panic(payload: Box<dyn Any + Send>) -> UnwindReasonCode {
  39. crate::panicking::begin_panic(RustPanic(payload, ForeignGuard))
  40. }
  41. pub fn catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
  42. #[cold]
  43. fn process_panic(p: Option<RustPanic>) -> Box<dyn Any + Send> {
  44. match p {
  45. None => {
  46. #[cfg(feature = "panic-handler")]
  47. {
  48. drop_panic();
  49. }
  50. core::intrinsics::abort();
  51. }
  52. Some(e) => {
  53. panic_caught();
  54. core::mem::forget(e.1);
  55. e.0
  56. }
  57. }
  58. }
  59. crate::panicking::catch_unwind(f).map_err(process_panic)
  60. }