bread-utils: add socket timeouts to hypr::request

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.
This commit is contained in:
Breadway 2026-07-17 10:05:26 +08:00
parent 49c63c8ccf
commit 41276479aa

View file

@ -51,9 +51,20 @@ pub fn socket_path(kind: Socket) -> Option<PathBuf> {
/// IPC socket and return the raw response body. Blocking/synchronous — this /// IPC socket and return the raw response body. Blocking/synchronous — this
/// matches every current consumer (breadbox, breadclip), which call it from /// matches every current consumer (breadbox, breadclip), which call it from
/// non-async GTK app code. /// 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<String> { pub fn request(request: &str) -> Option<String> {
let socket = socket_path(Socket::Request)?; let socket = socket_path(Socket::Request)?;
let mut stream = UnixStream::connect(&socket).ok()?; 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.write_all(request.as_bytes()).ok()?;
stream.shutdown(std::net::Shutdown::Write).ok()?; stream.shutdown(std::net::Shutdown::Write).ok()?;