use std::{
path::PathBuf,
sync::{atomic::AtomicBool, Arc},
thread,
};
use anyhow::Context;
use signal_hook::{consts::TERM_SIGNALS, flag, iterator::Signals};
use tracing::{error, info};
pub struct Handler {
socks_to_clean: Vec<PathBuf>,
}
impl Handler {
pub fn new(socks_to_clean: Vec<PathBuf>) -> Self {
Handler { socks_to_clean }
}
pub fn spawn(self) -> anyhow::Result<()> {
info!("spawning signal handler thread");
let term_now = Arc::new(AtomicBool::new(false));
for sig in TERM_SIGNALS {
flag::register_conditional_shutdown(*sig, 1, Arc::clone(&term_now))?;
flag::register(*sig, Arc::clone(&term_now))?;
}
let mut signals = Signals::new(TERM_SIGNALS).context("creating signal iterator")?;
thread::spawn(move || {
#[allow(clippy::never_loop)]
for signal in &mut signals {
assert!(TERM_SIGNALS.contains(&signal));
info!("term sig handler: cleaning up sockets");
for sock in &self.socks_to_clean {
info!("term sig handler: cleaning up socket: {:?}", sock);
match std::fs::remove_file(sock) {
Ok(()) => {}
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {}
Err(e) => error!("error cleaning up socket {:?}: {}", sock, e),
}
}
info!("term sig handler: exiting");
std::process::exit(0);
}
});
Ok(())
}
}