From 750eae7a937c13d165f9b6641eb42d99fa291492 Mon Sep 17 00:00:00 2001 From: yamabush1 Date: Sun, 17 May 2026 18:28:50 +0200 Subject: [PATCH] fix(event_loop): exit cleanly on OtherError(BrokenPipe) from compositor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit calloop surfaces the closed-socket condition either as Error::IoError(BrokenPipe) — already handled — or as Error::OtherError wrapping an std::io::Error with kind BrokenPipe, which previously fell through to panic!(). Add a matching arm that downcasts the inner error and treats both forms the same: log and set exit_requested so the run loop terminates gracefully instead of unwinding. --- src/event_loop/run.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/event_loop/run.rs b/src/event_loop/run.rs index 406be74..edc99c1 100644 --- a/src/event_loop/run.rs +++ b/src/event_loop/run.rs @@ -383,6 +383,24 @@ pub( crate ) fn try_run( app: A ) -> Result<(), RunError> data.exit_requested = true; continue; } + Err( calloop::Error::OtherError( ref e ) ) => + { + // wayland-client surfaces the closed-socket condition as an + // OtherError wrapping an IoError rather than as the + // calloop::Error::IoError variant handled above. Treat any + // BrokenPipe / ConnectionReset here the same way: exit cleanly. + let is_closed = e.downcast_ref::() + .map( |io| matches!( io.kind(), + std::io::ErrorKind::BrokenPipe | std::io::ErrorKind::ConnectionReset ) ) + .unwrap_or( false ); + if is_closed + { + eprintln!( "ltk: wayland connection lost; exiting" ); + data.exit_requested = true; + continue; + } + panic!( "dispatch: {e:?}" ); + } Err( e ) => panic!( "dispatch: {e:?}" ), } // Any surface whose press has now crossed `long_press_duration`