From 41276479aaa4cf85df30b89cead5b1bbc034223d Mon Sep 17 00:00:00 2001 From: Breadway Date: Fri, 17 Jul 2026 10:05:26 +0800 Subject: [PATCH] bread-utils: add socket timeouts to hypr::request MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Neither original implementation this replaces (breadbox's get_active_workspace, breadclip's hyprctl_json) set a read/write timeout on the Hyprland IPC socket — a wedged or mid-reload Hyprland instance could hang the call indefinitely, and every current caller runs it on the GTK main thread, so a hang here freezes the whole UI. Found while reviewing the crate for this pass's "any existing bugs" sweep; same class of bug as everything else bread_utils::proc/hypr exists to fix, just one I'd introduced myself by porting the original code faithfully without also porting the missing safety net. --- bread-utils/src/hypr.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/bread-utils/src/hypr.rs b/bread-utils/src/hypr.rs index a1b18a7..def3e98 100644 --- a/bread-utils/src/hypr.rs +++ b/bread-utils/src/hypr.rs @@ -51,9 +51,20 @@ pub fn socket_path(kind: Socket) -> Option { /// IPC socket and return the raw response body. Blocking/synchronous — this /// matches every current consumer (breadbox, breadclip), which call it from /// non-async GTK app code. +/// +/// Read/write timeouts are set on the socket (both original hand-rolled +/// implementations this replaces — breadbox's `get_active_workspace`, +/// breadclip's `hyprctl_json` — had none): a Hyprland instance that's +/// wedged or mid-reload could otherwise hang this call, and every current +/// caller runs it on the GTK main thread, so a hang here freezes the whole +/// UI, not just this query. +const REQUEST_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(2); + pub fn request(request: &str) -> Option { let socket = socket_path(Socket::Request)?; let mut stream = UnixStream::connect(&socket).ok()?; + stream.set_read_timeout(Some(REQUEST_TIMEOUT)).ok()?; + stream.set_write_timeout(Some(REQUEST_TIMEOUT)).ok()?; stream.write_all(request.as_bytes()).ok()?; stream.shutdown(std::net::Shutdown::Write).ok()?;