diff --git a/base/src/sys/unix/mod.rs b/base/src/sys/unix/mod.rs index b718b199e6..c4fb9d0773 100644 --- a/base/src/sys/unix/mod.rs +++ b/base/src/sys/unix/mod.rs @@ -30,6 +30,7 @@ mod mmap; pub mod net; mod netlink; mod notifiers; +pub mod panic_handler; pub mod platform_timer_resolution; mod poll; mod priority; diff --git a/base/src/sys/unix/panic_handler.rs b/base/src/sys/unix/panic_handler.rs new file mode 100644 index 0000000000..b831dcc129 --- /dev/null +++ b/base/src/sys/unix/panic_handler.rs @@ -0,0 +1,34 @@ +// Copyright 2022 The ChromiumOS Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +//! A panic handler for better crash signatures for rust apps. + +use super::SharedMemory; +use std::ffi::CString; +use std::io; +use std::mem; +use std::panic; + +const PANIC_MEMFD_NAME: &str = "RUST_PANIC_SIG"; + +/// Inserts a panic handler that writes the panic info to a memfd called +/// "RUST_PANIC_SIG" before calling the original panic handler. This +/// makes it possible for external crash handlers to recover the panic info. +pub fn install_memfd_handler() { + let hook = panic::take_hook(); + panic::set_hook(Box::new(move |p| { + let panic_info = format!("{}\n", &p); + let panic_bytes = panic_info.as_bytes(); + // On failure, ignore the error and call the original handler. + if let Ok(mut panic_memfd) = SharedMemory::new( + &CString::new(PANIC_MEMFD_NAME).unwrap(), + panic_bytes.len() as u64, + ) { + io::Write::write_all(&mut panic_memfd, panic_bytes).ok(); + // Intentionally leak panic_memfd so it is picked up by the crash handler. + mem::forget(panic_memfd); + } + hook(p) + })); +}