libobs_wrapper\crash_handler/
mod.rs

1use std::{ffi::c_void, sync::Mutex};
2
3use lazy_static::lazy_static;
4
5#[cfg(feature = "dialog_crash_handler")]
6pub mod dialog;
7
8pub trait ObsCrashHandler: Send {
9    fn handle_crash(&self, message: String);
10}
11
12pub struct ConsoleCrashHandler {
13    _private: (),
14}
15
16impl Default for ConsoleCrashHandler {
17    fn default() -> Self {
18        Self::new()
19    }
20}
21
22impl ConsoleCrashHandler {
23    pub fn new() -> Self {
24        Self { _private: () }
25    }
26}
27impl ObsCrashHandler for ConsoleCrashHandler {
28    fn handle_crash(&self, message: String) {
29        #[cfg(not(feature = "logging_crash_handler"))]
30        eprintln!("OBS crashed: {}", message);
31        #[cfg(feature = "logging_crash_handler")]
32        log::error!("OBS crashed: {}", message);
33    }
34}
35
36lazy_static! {
37    /// We are using this as global variable because there can only be one obs context
38    pub static ref CRASH_HANDLER: Mutex<Box<dyn ObsCrashHandler>> = {
39        #[cfg(feature="dialog_crash_handler")]
40        {
41            Mutex::new(Box::new(dialog::DialogCrashHandler::new()))
42        }
43        #[cfg(not(feature="dialog_crash_handler"))]
44        {
45            Mutex::new(Box::new(ConsoleCrashHandler::new()))
46        }
47    };
48}
49
50pub(crate) unsafe extern "C" fn main_crash_handler<V>(
51    format: *const std::os::raw::c_char,
52    args: *mut V,
53    _params: *mut c_void,
54) {
55    let res = vsprintf::vsprintf(format, args);
56    if res.is_err() {
57        eprintln!("Failed to format crash handler message");
58        return;
59    }
60
61    let res = res.unwrap();
62    CRASH_HANDLER.lock().unwrap().handle_crash(res);
63}