diff --git a/src/debug/ipc.rs b/src/debug/ipc.rs index c82440a..b2d4f67 100644 --- a/src/debug/ipc.rs +++ b/src/debug/ipc.rs @@ -11,9 +11,18 @@ use std::{ use crate::error::{CliError, Result}; -#[derive(Clone)] pub struct DebugIpcServer { inner: Arc, + owns_lifecycle: bool, +} + +impl Clone for DebugIpcServer { + fn clone(&self) -> Self { + Self { + inner: Arc::clone(&self.inner), + owns_lifecycle: false, + } + } } struct Inner { @@ -39,7 +48,10 @@ impl DebugIpcServer { let handle = thread::spawn(move || accept_loop(listener, thread_inner)); *inner.thread.lock().unwrap() = Some(handle); - Ok(Self { inner }) + Ok(Self { + inner, + owns_lifecycle: true, + }) } pub fn port(&self) -> u16 { @@ -50,12 +62,11 @@ impl DebugIpcServer { let frame = encode_frame(message_type, payload)?; let mut clients = self.inner.clients.lock().unwrap(); let mut any = false; - clients.retain_mut(|stream| match stream.write(&frame) { - Ok(_) => { + clients.retain_mut(|stream| match stream.write_all(&frame) { + Ok(()) => { any = true; true } - Err(err) if err.kind() == io::ErrorKind::WouldBlock => true, Err(_) => false, }); Ok(any) @@ -81,7 +92,9 @@ impl DebugIpcServer { impl Drop for DebugIpcServer { fn drop(&mut self) { - self.stop(); + if self.owns_lifecycle { + self.stop(); + } } } @@ -99,8 +112,12 @@ fn accept_loop(listener: TcpListener, inner: Arc) { while !inner.stop.load(Ordering::Relaxed) { match listener.accept() { Ok((stream, _)) => { - let _ = stream.set_nonblocking(true); - inner.clients.lock().unwrap().push(stream); + if stream + .set_write_timeout(Some(Duration::from_secs(1))) + .is_ok() + { + inner.clients.lock().unwrap().push(stream); + } } Err(err) if err.kind() == io::ErrorKind::WouldBlock => { thread::sleep(Duration::from_millis(50)); @@ -112,7 +129,7 @@ fn accept_loop(listener: TcpListener, inner: Arc) { #[cfg(test)] mod tests { - use super::encode_frame; + use super::{DebugIpcServer, encode_frame}; #[test] fn encodes_big_endian_ipc_frame() { @@ -120,4 +137,15 @@ mod tests { assert_eq!(&frame[..6], &[0, 2, 0, 0, 0, 7]); assert_eq!(&frame[6..], b"[\"a.b\"]"); } + + #[test] + fn dropping_clone_keeps_server_running() { + let server = DebugIpcServer::start().unwrap(); + let port = server.port(); + + drop(server.clone()); + + assert_eq!(server.port(), port); + server.safe_exit(); + } }