1use once_cell::sync::Lazy;
6
7use crate::in_test_configuration;
8
9#[macro_export]
10macro_rules! fatal {
11 ($($arg:tt)*) => {{
12 tracing::error!(fatal = true, $($arg)*);
13 panic!($($arg)*);
14 }};
15}
16
17#[inline(always)]
18pub fn crash_on_debug() -> bool {
19 static CRASH_ON_DEBUG: Lazy<bool> = Lazy::new(|| {
20 in_test_configuration() || std::env::var("IOTA_ENABLE_DEBUG_ASSERTIONS").is_ok()
21 });
22
23 *CRASH_ON_DEBUG
24}
25
26#[macro_export]
27macro_rules! debug_fatal {
28 ($($arg:tt)*) => {{
29 if $crate::logging::crash_on_debug() {
30 $crate::fatal!($($arg)*);
31 } else {
32 let stacktrace = std::backtrace::Backtrace::capture();
33 tracing::error!(debug_fatal = true, stacktrace = ?stacktrace, $($arg)*);
34 let location = concat!(file!(), ':', line!());
35 if let Some(metrics) = iota_metrics::get_metrics() {
36 metrics.system_invariant_violations.with_label_values(&[location]).inc();
37 }
38 }
39 }};
40}
41
42mod tests {
43 #[test]
44 #[should_panic]
45 fn test_fatal() {
46 fatal!("This is a fatal error");
47 }
48
49 #[test]
50 #[should_panic]
51 fn test_debug_fatal() {
52 if cfg!(debug_assertions) {
53 debug_fatal!("This is a debug fatal error");
54 } else {
55 fatal!("This is a fatal error");
57 }
58 }
59
60 #[cfg(not(debug_assertions))]
61 #[test]
62 fn test_debug_fatal_release_mode() {
63 debug_fatal!("This is a debug fatal error");
64 }
65}