use super::report::{CrashReport, ReportKind, UtcTime, file_stem_at};
use super::write;
use crash_handler::{CrashContext, CrashEventResult, CrashHandler};
use std::sync::OnceLock;
static HANDLER: OnceLock<CrashHandler> = OnceLock::new();
pub(crate) fn install() {
if HANDLER.get().is_some() {
return;
}
let event = unsafe {
crash_handler::make_crash_event(|ctx: &CrashContext| {
report_fault(ctx);
CrashEventResult::Handled(false)
})
};
if let Ok(handler) = CrashHandler::attach(event) {
let _ = HANDLER.set(handler);
}
}
fn report_fault(ctx: &CrashContext) {
let Some(dir) = concinnity_host::store::paths::crashes_dir() else {
return;
};
let time = UtcTime::now();
let stem = write::unique_stem(&dir, &file_stem_at(time));
super::minidump::write_fault_dump(&dir, &stem, ctx);
let mut report = CrashReport::gather_nonblocking(ReportKind::NativeFault, fault_message(ctx));
report.time = time;
let _ = write::write_report_named(&dir, &stem, &report);
write::prune(&dir, write::RETAINED_REPORTS);
}
#[cfg(target_os = "macos")]
fn fault_message(ctx: &CrashContext) -> String {
match ctx.exception {
Some(e) => format!(
"native fault: mach exception kind {:#x}, code {:#x}",
e.kind, e.code
),
None => "native fault: unknown mach exception".to_string(),
}
}
#[cfg(target_os = "windows")]
fn fault_message(ctx: &CrashContext) -> String {
format!(
"native fault: exception code {:#010x} on thread {}",
ctx.exception_code, ctx.thread_id
)
}