use std::sync::atomic::{AtomicBool, Ordering};
#[derive(Debug)]
pub struct CmdError {
pub code: i32,
pub msg: Option<String>,
}
impl CmdError {
pub fn code_only(code: i32) -> Self {
Self { code, msg: None }
}
}
static TEARING_DOWN: AtomicBool = AtomicBool::new(false);
fn teardown_once() {
if TEARING_DOWN.swap(true, Ordering::SeqCst) {
return;
}
crw_renderer::browser::kill_all_browsers();
}
#[cfg(unix)]
pub fn install_signal_teardown() {
use tokio::signal::unix::{SignalKind, signal};
tokio::spawn(async move {
let mut sigint = signal(SignalKind::interrupt()).expect("install SIGINT handler");
let mut sigterm = signal(SignalKind::terminate()).expect("install SIGTERM handler");
let mut sighup = signal(SignalKind::hangup()).expect("install SIGHUP handler");
let mut sigquit = signal(SignalKind::quit()).expect("install SIGQUIT handler");
let code = tokio::select! {
_ = sigint.recv() => 130,
_ = sigterm.recv() => 143,
_ = sighup.recv() => 129,
_ = sigquit.recv() => 131,
};
teardown_once();
std::process::exit(code);
});
}
#[cfg(not(unix))]
pub fn install_signal_teardown() {}
pub fn finish(result: Result<(), CmdError>) -> ! {
teardown_once();
match result {
Ok(()) => std::process::exit(0),
Err(CmdError { code, msg }) => {
if let Some(m) = msg {
eprintln!("{m}");
}
std::process::exit(code);
}
}
}