1use std::{
2 fs::{read_dir, remove_file},
3 os::unix::fs::FileTypeExt,
4 sync::Arc,
5 time::Duration,
6};
7
8use anyhow::{anyhow, Result};
9use lazy_static::lazy_static;
10use tokio::{io::AsyncWriteExt, net::UnixStream, sync::Mutex, time};
11
12use crate::ipc::{self, ChannelEndpoint};
13
14lazy_static! {
15 pub(crate) static ref ENDPOINT: Arc<Mutex<Option<ChannelEndpoint<(), ()>>>> =
16 Arc::new(Mutex::new(None));
17}
18
19pub async fn cleanup() -> Result<()> {
21 let sockets = read_dir(ipc::IPC_DIR)?
22 .filter_map(Result::ok)
23 .filter(|f| f.file_type().is_ok_and(|t| t.is_socket()));
24 for socket in sockets {
25 let path = socket.path();
26
27 let stream = UnixStream::connect(path.as_path()).await;
28 match stream {
29 Ok(mut stream) => {
30 match time::timeout(Duration::from_secs(1), async {
31 let mut buf = [0; 16];
32 stream.writable().await?;
33 stream.try_write(b"ping")?;
34 stream.readable().await?;
35 let bytes = stream.try_read(&mut buf)?;
36 stream.shutdown().await?;
37
38 match bytes {
39 0 => Err(anyhow!("Failed to read from stream")),
40 _ => Ok(()),
41 }
42 })
43 .await
44 {
45 Ok(Ok(())) => {}
46 Ok(Err(_)) | Err(_) => {
47 let _ = remove_file(path);
48 }
49 }
50 }
51 Err(_) => {
52 let _ = remove_file(path);
53 }
54 }
55 }
56
57 Ok(())
58}
59
60pub async fn exit(
72 bar: Option<(&str, bool)>,
73 in_runtime: bool,
74 exit_code: i32,
75) -> ! {
76 if let Some((bar, true)) = bar {
77 let _ = remove_file(format!("/tmp/lazybar-ipc/{bar}"));
78 }
79 if in_runtime {
80 if let Some(ref mut endpoint) = *ENDPOINT.lock().await {
81 if endpoint.send.send(()).is_ok() {
82 let _ =
83 time::timeout(Duration::from_secs(2), endpoint.recv.recv())
84 .await;
85 }
86 }
87 }
88 std::process::exit(exit_code);
89}