use argh::FromArgValue;
use eyre::Result;
use crate::config::Config;
#[derive(Debug)]
pub enum ErrorStrategy {
SegFault,
FPException,
}
impl FromArgValue for ErrorStrategy {
fn from_arg_value(value: &str) -> Result<Self, String> {
match value {
"segfault" => Ok(ErrorStrategy::SegFault),
"divide-by-zero" => Ok(ErrorStrategy::FPException),
_ => Err("valid strategies are 'segfault' and 'divide-by-zero'".to_string()),
}
}
}
pub fn trigger_coredump(config: &Config, error_type: ErrorStrategy) -> Result<()> {
trigger_coredump_inner(config, error_type)
}
#[cfg(feature = "coredump")]
fn trigger_coredump_inner(config: &Config, error_type: ErrorStrategy) -> Result<()> {
use crate::util::ipc::send_flush_signal;
trigger_crash(error_type)?;
if config.config_file.enable_dev_mode {
println!("Signaling memfaultd to upload coredump event...");
std::thread::sleep(std::time::Duration::from_secs(3));
send_flush_signal(false)?;
}
Ok(())
}
#[cfg(not(feature = "coredump"))]
fn trigger_coredump_inner(_config: &Config, _error_type: ErrorStrategy) -> Result<()> {
println!(
"You must enable the coredump feature when building memfault SDK to report coredumps."
);
Ok(())
}
#[cfg(feature = "coredump")]
fn trigger_crash(error_type: ErrorStrategy) -> Result<()> {
use memfaultc_sys::coredump::memfault_trigger_fp_exception;
use nix::unistd::{fork, ForkResult};
println!("Triggering coredump ...");
match unsafe { fork() } {
Ok(ForkResult::Parent { .. }) => Ok(()),
Ok(ForkResult::Child) => {
match error_type {
ErrorStrategy::FPException => {
unsafe {
memfault_trigger_fp_exception();
}
}
ErrorStrategy::SegFault => {
unsafe { std::ptr::null_mut::<i32>().write(42) };
}
}
unreachable!("Child process should have crashed");
}
Err(e) => Err(eyre::eyre!("Failed to fork process: {}", e)),
}
}