Skip to content

Instantly share code, notes, and snippets.

@Diggsey
Created May 7, 2015 17:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Diggsey/715f264f6cb69b3132d6 to your computer and use it in GitHub Desktop.
Save Diggsey/715f264f6cb69b3132d6 to your computer and use it in GitHub Desktop.
Zero-allocation panic handler example
use std::any::Any;
use std::cell::Cell;
use std::marker::PhantomData;
// Built in panic handlers
fn default_panic_handler(msg: &(Any + Send), file: &'static str, line: u32) {
println!("{}:{} - {:?}", file, line, msg);
}
fn silent_panic_handler(_: &(Any + Send), _: &'static str, _: u32) { }
// PanicHandler type alias
type PanicHandler = Fn(&(Any + Send), &'static str, u32) + 'static;
// Current panic handler
thread_local!(static PANIC_HANDLER: Cell<*const PanicHandler> = Cell::new(&default_panic_handler));
// Must not be used directly
struct PanicHandlerGuard<'a> {
old_handler: *const PanicHandler,
phantom: PhantomData<&'a PanicHandler>
}
impl<'a> PanicHandlerGuard<'a> {
fn new(handler: &'a PanicHandler) -> Self {
PANIC_HANDLER.with(|h| {
let old_handler = h.get();
h.set(handler);
PanicHandlerGuard { old_handler: old_handler, phantom: PhantomData }
})
}
fn run<R, B: FnOnce() -> R>(&self, body: B) -> R {
body()
}
}
impl<'a> Drop for PanicHandlerGuard<'a> {
fn drop(&mut self) {
PANIC_HANDLER.with(|h| {
h.set(self.old_handler);
});
}
}
// Publically accessible methods
pub fn with_panic_handler<F: Fn(&(Any + Send), &'static str, u32) + 'static, R, B: FnOnce() -> R>(handler: F, body: B) -> R {
PanicHandlerGuard::new(&handler).run(body)
}
fn panic2(msg: &'static str) {
PANIC_HANDLER.with(|h| {
let handler = h.get();
(unsafe { &*handler })(&msg, "unknown", 0);
});
panic!();
}
fn main() {
with_panic_handler(silent_panic_handler, || {
panic2("Example");
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment