service_toolkit/
panic.rs

1use std::backtrace::Backtrace;
2use std::io::stderr;
3use std::io::Write;
4use std::panic;
5use std::process;
6
7pub fn set_up_panic_hook() {
8  // Currently, even with `panic = abort`, thread panics will still not kill the process, so we'll install our own handler to ensure that any panic exits the process, as most likely some internal state/invariant has become corrupted and it's not safe to continue. Copied from https://stackoverflow.com/a/36031130.
9  let _orig_hook = panic::take_hook();
10  panic::set_hook(Box::new(move |panic_info| {
11    let bt = Backtrace::force_capture();
12    // Don't use `tracing::*` as it may be dangerous to do so from within a panic handler (e.g. it could itself panic).
13    // Do not lock stderr as we could deadlock.
14    // Build string first so we (hopefully) do one write syscall to stderr and don't get it mangled.
15    // Prepend with a newline to avoid mangling with any existing half-written stderr line.
16    let json = format!(
17      "\r\n{}\r\n",
18      serde_json::json!({
19        "level": "CRITICAL",
20        "panic": true,
21        "message": panic_info.to_string(),
22        "stack_trace": bt.to_string(),
23      })
24    );
25    // Try our best to write all and then flush, but don't panic if we don't.
26    let mut out = stderr();
27    let _ = out.write_all(json.as_bytes());
28    let _ = out.flush();
29    process::exit(1);
30  }));
31}