From 421bd04339e416477c28dc181bfffa3628e387ba Mon Sep 17 00:00:00 2001 From: Stephen Waits Date: Tue, 7 Apr 2026 12:25:42 -0600 Subject: [PATCH] fix: instant toggle exit via SIGUSR1 poll interruption Remove SA_RESTART from the signal handler so SIGUSR1 interrupts the blocking poll() call with EINTR. Handle EINTR gracefully in the event loop to check should_exit() immediately instead of waiting for timeout. --- src/lock.rs | 4 +++- src/wayland.rs | 11 ++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/lock.rs b/src/lock.rs index 52ecf65..e4ca4f9 100644 --- a/src/lock.rs +++ b/src/lock.rs @@ -73,9 +73,11 @@ pub fn create_lock() -> Result { let path = lock_file_path(); // Install SIGUSR1 handler before writing the lock file. + // No SA_RESTART — let the signal interrupt poll() so the event loop + // notices should_exit() promptly instead of waiting for the timeout. let action = SigAction::new( SigHandler::Handler(handle_sigusr1), - SaFlags::SA_RESTART, + SaFlags::empty(), SigSet::empty(), ); unsafe { signal::sigaction(Signal::SIGUSR1, &action) }.context("install SIGUSR1 handler")?; diff --git a/src/wayland.rs b/src/wayland.rs index 703c64b..f67b3f2 100644 --- a/src/wayland.rs +++ b/src/wayland.rs @@ -163,7 +163,16 @@ impl WaylandBackend { let mut pollfd = [nix::poll::PollFd::new(fd, nix::poll::PollFlags::POLLIN)]; let millis = timeout.as_millis().min(u16::MAX as u128) as u16; - let n = nix::poll::poll(&mut pollfd, millis).context("poll")?; + let n = match nix::poll::poll(&mut pollfd, millis) { + Ok(n) => n, + Err(nix::errno::Errno::EINTR) => { + // Signal interrupted poll — return so the loop + // can check should_exit(). + drop(read_guard); + return Ok(None); + } + Err(e) => return Err(e).context("poll"), + }; if n > 0 { let _ = read_guard.read();