-
Notifications
You must be signed in to change notification settings - Fork 373
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add signal handler on *nix with troubleshooting and stacktrace (#1340)
* Add signal handler on *nix with troubleshooting and stacktrace * Add a way to segfault the app in the debug menu * Add debug->crash menu button to trigger a stack overflow
- Loading branch information
Showing
6 changed files
with
187 additions
and
27 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
pub fn install_crash_handlers() { | ||
install_panic_hook(); | ||
|
||
#[cfg(not(target_arch = "wasm32"))] | ||
#[cfg(not(target_os = "windows"))] | ||
install_signal_handler(); | ||
} | ||
|
||
fn install_panic_hook() { | ||
let previous_panic_hook = std::panic::take_hook(); | ||
|
||
std::panic::set_hook(Box::new(move |panic_info: &std::panic::PanicInfo<'_>| { | ||
// This prints the callstack etc | ||
(*previous_panic_hook)(panic_info); | ||
|
||
eprintln!( | ||
"\n\ | ||
Troubleshooting Rerun: https://www.rerun.io/docs/getting-started/troubleshooting" | ||
); | ||
})); | ||
} | ||
|
||
#[cfg(not(target_arch = "wasm32"))] | ||
#[cfg(not(target_os = "windows"))] | ||
#[allow(unsafe_code)] | ||
#[allow(clippy::fn_to_numeric_cast_any)] | ||
fn install_signal_handler() { | ||
// SAFETY: we're installing a signal handler. | ||
unsafe { | ||
for signum in [ | ||
libc::SIGABRT, | ||
libc::SIGBUS, | ||
libc::SIGFPE, | ||
libc::SIGILL, | ||
libc::SIGINT, | ||
libc::SIGSEGV, | ||
libc::SIGTERM, | ||
] { | ||
libc::signal( | ||
signum, | ||
signal_handler as *const fn(libc::c_int) as libc::size_t, | ||
); | ||
} | ||
} | ||
|
||
unsafe extern "C" fn signal_handler(signal_number: libc::c_int) { | ||
let signal_name = match signal_number { | ||
libc::SIGABRT => "SIGABRT", | ||
libc::SIGBUS => "SIGBUS", | ||
libc::SIGFPE => "SIGFPE", | ||
libc::SIGILL => "SIGILL", | ||
libc::SIGINT => "SIGINT", | ||
libc::SIGSEGV => "SIGSEGV", | ||
libc::SIGTERM => "SIGTERM", | ||
_ => "UNKNOWN SIGNAL", | ||
}; | ||
|
||
// There are very few things that are safe to do in a signal handler, | ||
// but writing to stderr is one of them. | ||
// So we first print out what happened to stderr so we're sure that gets out, | ||
// then we do the unsafe things, like logging the stack trace. | ||
// We take care not to allocate any memory along the way. | ||
|
||
write_to_stderr("\n"); | ||
write_to_stderr("Rerun caught a signal: "); | ||
write_to_stderr(signal_name); | ||
write_to_stderr("\n"); | ||
write_to_stderr( | ||
"Troubleshooting Rerun: https://www.rerun.io/docs/getting-started/troubleshooting\n\n", | ||
); | ||
|
||
// Ok, we printed the most important things. | ||
// Let's do less important things that require memory allocations. | ||
// Allocating memory can lead to deadlocks if the signal | ||
// was triggered from the system's memory management functions. | ||
|
||
print_callstack(); | ||
|
||
// We seem to have managed printing the callstack - great! | ||
// Then let's print the important stuff _again_ so it is visible at the bottom of the users terminal: | ||
|
||
write_to_stderr("\n"); | ||
write_to_stderr("Rerun caught a signal: "); | ||
write_to_stderr(signal_name); | ||
write_to_stderr("\n"); | ||
write_to_stderr( | ||
"Troubleshooting Rerun: https://www.rerun.io/docs/getting-started/troubleshooting\n\n", | ||
); | ||
|
||
// We are done! | ||
// Call the default signal handler (which usually terminates the app): | ||
// SAFETY: we're calling a signal handler | ||
unsafe { | ||
libc::signal(signal_number, libc::SIG_DFL); | ||
libc::raise(signal_number); | ||
} | ||
} | ||
|
||
fn write_to_stderr(text: &str) { | ||
// SAFETY: writing to stderr is fine, even in a signal handler. | ||
unsafe { | ||
libc::write(libc::STDERR_FILENO, text.as_ptr().cast(), text.len()); | ||
} | ||
} | ||
|
||
fn print_callstack() { | ||
let backtrace = backtrace::Backtrace::new(); | ||
let stack = format!("{backtrace:?}"); | ||
|
||
// Trim it a bit: | ||
let mut stack = stack.as_str(); | ||
let start_pattern = "install_signal_handler::signal_handler\n"; | ||
if let Some(start_offset) = stack.find(start_pattern) { | ||
stack = &stack[start_offset + start_pattern.len()..]; | ||
} | ||
if let Some(end_offset) = | ||
stack.find("std::sys_common::backtrace::__rust_begin_short_backtrace") | ||
{ | ||
stack = &stack[..end_offset]; | ||
} | ||
|
||
write_to_stderr(stack); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3e4c194
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rust Benchmark
datastore/insert/batch/rects/insert
540725
ns/iter (± 2227
)551948
ns/iter (± 3032
)0.98
datastore/latest_at/batch/rects/query
1755
ns/iter (± 2
)1765
ns/iter (± 3
)0.99
datastore/latest_at/missing_components/primary
353
ns/iter (± 1
)351
ns/iter (± 0
)1.01
datastore/latest_at/missing_components/secondaries
427
ns/iter (± 1
)422
ns/iter (± 1
)1.01
datastore/range/batch/rects/query
150206
ns/iter (± 860
)149580
ns/iter (± 671
)1.00
mono_points_arrow/generate_message_bundles
49609027
ns/iter (± 943220
)49584371
ns/iter (± 909727
)1.00
mono_points_arrow/generate_messages
136498653
ns/iter (± 2062401
)136243566
ns/iter (± 1307667
)1.00
mono_points_arrow/encode_log_msg
162033433
ns/iter (± 1165883
)164503790
ns/iter (± 1219695
)0.98
mono_points_arrow/encode_total
351528716
ns/iter (± 2442649
)353121555
ns/iter (± 1498272
)1.00
mono_points_arrow/decode_log_msg
184181248
ns/iter (± 938139
)183164672
ns/iter (± 884761
)1.01
mono_points_arrow/decode_message_bundles
73907825
ns/iter (± 1050583
)74478398
ns/iter (± 1070390
)0.99
mono_points_arrow/decode_total
256444627
ns/iter (± 1828361
)255247192
ns/iter (± 1733356
)1.00
batch_points_arrow/generate_message_bundles
325834
ns/iter (± 1558
)324669
ns/iter (± 1606
)1.00
batch_points_arrow/generate_messages
6079
ns/iter (± 44
)6185
ns/iter (± 18
)0.98
batch_points_arrow/encode_log_msg
358387
ns/iter (± 1510
)352961
ns/iter (± 1754
)1.02
batch_points_arrow/encode_total
708351
ns/iter (± 3107
)712605
ns/iter (± 2363
)0.99
batch_points_arrow/decode_log_msg
349352
ns/iter (± 1130
)343561
ns/iter (± 1593
)1.02
batch_points_arrow/decode_message_bundles
2011
ns/iter (± 13
)2025
ns/iter (± 14
)0.99
batch_points_arrow/decode_total
355771
ns/iter (± 1410
)355265
ns/iter (± 898
)1.00
arrow_mono_points/insert
7030803564
ns/iter (± 19043358
)7050992884
ns/iter (± 22598620
)1.00
arrow_mono_points/query
1665206
ns/iter (± 13687
)1670825
ns/iter (± 11378
)1.00
arrow_batch_points/insert
2659189
ns/iter (± 15340
)2574940
ns/iter (± 12710
)1.03
arrow_batch_points/query
16791
ns/iter (± 85
)16728
ns/iter (± 94
)1.00
tuid/Tuid::random
34
ns/iter (± 0
)34
ns/iter (± 0
)1
This comment was automatically generated by workflow using github-action-benchmark.