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#[cfg(not(target_arch = "wasm32"))]
27#[macro_export]
28macro_rules! debug_fatal {
29 ($($arg:tt)*) => {{
30 if $crate::logging::crash_on_debug() {
31 $crate::fatal!($($arg)*);
32 } else {
33 let stacktrace = std::backtrace::Backtrace::capture();
34 tracing::error!(debug_fatal = true, stacktrace = ?stacktrace, $($arg)*);
35 let location = concat!(file!(), ':', line!());
36 if let Some(metrics) = iota_metrics::get_metrics() {
37 metrics.system_invariant_violations.with_label_values(&[location]).inc();
38 }
39 }
40 }};
41}
42
43#[cfg(target_arch = "wasm32")]
46#[macro_export]
47macro_rules! debug_fatal {
48 ($($arg:tt)*) => {{
49 if $crate::logging::crash_on_debug() {
50 $crate::fatal!($($arg)*);
51 } else {
52 tracing::error!(debug_fatal = true, $($arg)*);
53 }
54 }};
55}
56
57mod tests {
58 #[test]
59 #[should_panic]
60 fn test_fatal() {
61 fatal!("This is a fatal error");
62 }
63
64 #[test]
65 #[should_panic]
66 fn test_debug_fatal() {
67 if cfg!(debug_assertions) {
68 debug_fatal!("This is a debug fatal error");
69 } else {
70 fatal!("This is a fatal error");
72 }
73 }
74
75 #[cfg(not(debug_assertions))]
76 #[test]
77 fn test_debug_fatal_release_mode() {
78 debug_fatal!("This is a debug fatal error");
79 }
80}