From 9cc65e70eaf177a602442aa6063fc5a495c22371 Mon Sep 17 00:00:00 2001 From: yamabush1 Date: Mon, 18 May 2026 20:48:35 +0200 Subject: [PATCH] fix(event_loop): walk error source chain for BrokenPipe in OtherError MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous fix checked downcast_ref:: directly on the OtherError payload, but wayland-client wraps the io::Error inside WaylandError::Io — one level deeper. Downcast failed, is_closed stayed false, and the panic arm fired anyway. Replace the single downcast with a source()-chain walk that finds the io::Error at any depth, matching the same BrokenPipe / ConnectionReset check already used for the direct IoError arm. --- src/event_loop/run.rs | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/event_loop/run.rs b/src/event_loop/run.rs index edc99c1..afc9551 100644 --- a/src/event_loop/run.rs +++ b/src/event_loop/run.rs @@ -386,13 +386,25 @@ pub( crate ) fn try_run( app: A ) -> Result<(), RunError> 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 ); + // OtherError wrapping a WaylandError::Io(BrokenPipe) — one + // level deeper than a direct io::Error. Walk the source() + // chain so we catch it regardless of how many wrapper types + // sit between calloop and the raw io::Error. + let mut src: Option<&dyn std::error::Error> = Some( e.as_ref() ); + let mut is_closed = false; + while let Some( err ) = src + { + if let Some( io ) = err.downcast_ref::() + { + if matches!( io.kind(), + std::io::ErrorKind::BrokenPipe | std::io::ErrorKind::ConnectionReset ) + { + is_closed = true; + break; + } + } + src = err.source(); + } if is_closed { eprintln!( "ltk: wayland connection lost; exiting" );