From e6ed4ea02441dfa9feda486aa97b99362a5b3502 Mon Sep 17 00:00:00 2001 From: Henrik Friedrichsen Date: Mon, 22 May 2023 22:14:59 +0200 Subject: [PATCH] Support multiple IPC sockets (#1171) For instance for when multiple ncspot instances are running. In that case the PID will be appended to the path, i.e. `~/.cache/ncspot/ncspot.20707.sock`. Also ncspot will now delete the socket on shutdown. Fixes #1158 --- src/ipc.rs | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/ipc.rs b/src/ipc.rs index 54d5847..4584493 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -15,6 +15,7 @@ use crate::spotify::PlayerEvent; pub struct IpcSocket { tx: Sender, + path: PathBuf, } #[derive(Clone, Debug, Serialize)] @@ -23,11 +24,25 @@ struct Status { playable: Option, } +impl Drop for IpcSocket { + fn drop(&mut self) { + log::info!("Removing IPC socket: {:?}", self.path); + std::fs::remove_file(&self.path).expect("Could not remove IPC socket"); + } +} + impl IpcSocket { pub fn new(handle: &Handle, path: PathBuf, ev: EventManager) -> io::Result { - if path.exists() { + let path = if path.exists() && Self::is_open_socket(&path) { + let mut new_path = path; + new_path.set_file_name(format!("ncspot.{}.sock", std::process::id())); + new_path + } else if path.exists() && !Self::is_open_socket(&path) { std::fs::remove_file(&path)?; - } + path + } else { + path + }; info!("Creating IPC domain socket at {path:?}"); @@ -37,12 +52,18 @@ impl IpcSocket { }; let (tx, rx) = tokio::sync::watch::channel(status); + let listener_path = path.clone(); handle.spawn(async move { - let listener = UnixListener::bind(path).expect("Could not create IPC domain socket"); + let listener = + UnixListener::bind(listener_path).expect("Could not create IPC domain socket"); Self::worker(listener, ev, rx.clone()).await; }); - Ok(IpcSocket { tx }) + Ok(IpcSocket { tx, path }) + } + + fn is_open_socket(path: &PathBuf) -> bool { + std::os::unix::net::UnixStream::connect(path).is_ok() } pub fn publish(&self, event: &PlayerEvent, playable: Option) {