use std::{
fs::{read_dir, remove_file},
os::unix::fs::FileTypeExt,
sync::OnceLock,
time::Duration,
};
use anyhow::{anyhow, Result};
use tokio::{io::AsyncWriteExt, net::UnixStream, time};
use crate::ipc::{self, ChannelEndpoint};
pub(crate) static mut ENDPOINT: OnceLock<ChannelEndpoint<(), ()>> =
OnceLock::new();
pub async fn cleanup() -> Result<()> {
let sockets = read_dir(ipc::IPC_DIR)?
.filter_map(Result::ok)
.filter(|f| f.file_type().is_ok_and(|t| t.is_socket()));
for socket in sockets {
let path = socket.path();
let stream = UnixStream::connect(path.as_path()).await;
match stream {
Ok(mut stream) => {
match time::timeout(Duration::from_secs(1), async {
let mut buf = [0; 16];
stream.writable().await?;
stream.try_write(b"ping")?;
stream.readable().await?;
let bytes = stream.try_read(&mut buf)?;
stream.shutdown().await?;
match bytes {
0 => Err(anyhow!("Failed to read from stream")),
_ => Ok(()),
}
})
.await
{
Ok(Ok(())) => {}
Ok(Err(_)) | Err(_) => {
let _ = remove_file(path);
}
}
}
Err(_) => {
let _ = remove_file(path);
}
}
}
Ok(())
}
pub async fn exit(
bar: Option<(&str, bool)>,
in_runtime: bool,
exit_code: i32,
) -> ! {
if let Some((bar, true)) = bar {
let _ = remove_file(format!("/tmp/lazybar-ipc/{bar}"));
}
if in_runtime {
if let Some(mut endpoint) = unsafe { ENDPOINT.take() } {
if endpoint.send.send(()).is_ok() {
let _ =
time::timeout(Duration::from_secs(2), endpoint.recv.recv())
.await;
}
}
}
std::process::exit(exit_code);
}