From 9fe526d0bc429679f7e5adb794900608e41e4ac6 Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Wed, 17 Apr 2024 17:48:52 +0100 Subject: [PATCH 1/4] Prevent a double panic --- agb/src/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/agb/src/lib.rs b/agb/src/lib.rs index c3184e4d..14cdddda 100644 --- a/agb/src/lib.rs +++ b/agb/src/lib.rs @@ -325,6 +325,14 @@ pub mod test_runner { #[panic_handler] fn panic_implementation(info: &core::panic::PanicInfo) -> ! { + static IS_PANICKING: portable_atomic::AtomicBool = portable_atomic::AtomicBool::new(false); + if IS_PANICKING.load(portable_atomic::Ordering::SeqCst) { + // we panicked during the panic handler, so not much we can do here + loop {} + } else { + IS_PANICKING.store(true, portable_atomic::Ordering::SeqCst); + } + #[cfg(feature = "backtrace")] let frames = backtrace::unwind_exception(); From 18b25e242ed9ae890fa5d04b9af9cc460d440ce8 Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Wed, 17 Apr 2024 17:49:31 +0100 Subject: [PATCH 2/4] Handle this in both panic handlers --- agb/src/lib.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/agb/src/lib.rs b/agb/src/lib.rs index 14cdddda..cb8f83dc 100644 --- a/agb/src/lib.rs +++ b/agb/src/lib.rs @@ -203,6 +203,9 @@ pub use {agb_alloc::ExternalAllocator, agb_alloc::InternalAllocator}; #[panic_handler] #[allow(unused_must_use)] fn panic_implementation(info: &core::panic::PanicInfo) -> ! { + avoid_double_panic(); + + use core::fmt::Write; if let Some(mut mgba) = mgba::Mgba::new() { let _ = mgba.print(format_args!("{info}"), mgba::DebugLevel::Fatal); } @@ -211,6 +214,16 @@ fn panic_implementation(info: &core::panic::PanicInfo) -> ! { loop {} } +fn avoid_double_panic() { + static IS_PANICKING: portable_atomic::AtomicBool = portable_atomic::AtomicBool::new(false); + if IS_PANICKING.load(portable_atomic::Ordering::SeqCst) { + // we panicked during the panic handler, so not much we can do here + loop {} + } else { + IS_PANICKING.store(true, portable_atomic::Ordering::SeqCst); + } +} + /// The Gba struct is used to control access to the Game Boy Advance's hardware in a way which makes it the /// borrow checker's responsibility to ensure no clashes of global resources. /// @@ -325,13 +338,7 @@ pub mod test_runner { #[panic_handler] fn panic_implementation(info: &core::panic::PanicInfo) -> ! { - static IS_PANICKING: portable_atomic::AtomicBool = portable_atomic::AtomicBool::new(false); - if IS_PANICKING.load(portable_atomic::Ordering::SeqCst) { - // we panicked during the panic handler, so not much we can do here - loop {} - } else { - IS_PANICKING.store(true, portable_atomic::Ordering::SeqCst); - } + avoid_double_panic(); #[cfg(feature = "backtrace")] let frames = backtrace::unwind_exception(); From 642c3c1b7914567d8b3114233d04119c95d21674 Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Wed, 17 Apr 2024 17:52:03 +0100 Subject: [PATCH 3/4] Better comments around the panic handler --- agb/src/lib.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/agb/src/lib.rs b/agb/src/lib.rs index cb8f83dc..0954d778 100644 --- a/agb/src/lib.rs +++ b/agb/src/lib.rs @@ -214,11 +214,15 @@ fn panic_implementation(info: &core::panic::PanicInfo) -> ! { loop {} } +// If we panic during the panic handler, then there isn't much we can do any more. So this code +// just infinite loops halting the CPU. fn avoid_double_panic() { static IS_PANICKING: portable_atomic::AtomicBool = portable_atomic::AtomicBool::new(false); + if IS_PANICKING.load(portable_atomic::Ordering::SeqCst) { - // we panicked during the panic handler, so not much we can do here - loop {} + loop { + syscall::halt(); + } } else { IS_PANICKING.store(true, portable_atomic::Ordering::SeqCst); } From 8c2e079ec20927c962c9202fd840417e726b7256 Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Sun, 12 May 2024 14:08:03 +0100 Subject: [PATCH 4/4] Mark the fact that it was a double panic in the fatal message --- agb/src/lib.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/agb/src/lib.rs b/agb/src/lib.rs index 0954d778..a91a6c67 100644 --- a/agb/src/lib.rs +++ b/agb/src/lib.rs @@ -203,7 +203,7 @@ pub use {agb_alloc::ExternalAllocator, agb_alloc::InternalAllocator}; #[panic_handler] #[allow(unused_must_use)] fn panic_implementation(info: &core::panic::PanicInfo) -> ! { - avoid_double_panic(); + avoid_double_panic(info); use core::fmt::Write; if let Some(mut mgba) = mgba::Mgba::new() { @@ -216,10 +216,16 @@ fn panic_implementation(info: &core::panic::PanicInfo) -> ! { // If we panic during the panic handler, then there isn't much we can do any more. So this code // just infinite loops halting the CPU. -fn avoid_double_panic() { +fn avoid_double_panic(info: &core::panic::PanicInfo) { static IS_PANICKING: portable_atomic::AtomicBool = portable_atomic::AtomicBool::new(false); if IS_PANICKING.load(portable_atomic::Ordering::SeqCst) { + if let Some(mut mgba) = mgba::Mgba::new() { + let _ = mgba.print( + format_args!("Double panic: {info}"), + mgba::DebugLevel::Fatal, + ); + } loop { syscall::halt(); } @@ -342,7 +348,7 @@ pub mod test_runner { #[panic_handler] fn panic_implementation(info: &core::panic::PanicInfo) -> ! { - avoid_double_panic(); + avoid_double_panic(info); #[cfg(feature = "backtrace")] let frames = backtrace::unwind_exception();