From 9514b4945edc2656b38a34419c3a8618f490cb17 Mon Sep 17 00:00:00 2001 From: v0up3r Date: Mon, 27 Jul 2026 19:21:35 -0300 Subject: [PATCH] fix(kms): don't panic when renderer creation fails after a GPU reset When the DRM device is lost transiently, for example when the amdgpu driver performs a GPU reset and recovers ("device wedged, but recovered through reset"), acquiring a renderer in `SurfaceThreadState::redraw` fails. The three `renderer`/`single_renderer` calls used `.unwrap()`, so the failure panicked the surface's render thread. Because that panic unwinds across the EGL/GBM FFI boundary it aborts the whole process (SIGABRT), dropping the session back to the greeter and closing every running application. `redraw` is already fallible and its caller logs the error and reschedules a redraw, and the frame-submission path (`render_frame`/`queue_frame`) already propagates errors the same way. Propagate the renderer-acquisition errors too, so a transient device loss is retried on the next frame, once the device is back, instead of taking down the compositor. Relates to #649. Assisted by an AI coding tool; I have reviewed and fully understand the change and am able to maintain it and respond to review. --- src/backend/kms/surface/mod.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/backend/kms/surface/mod.rs b/src/backend/kms/surface/mod.rs index bb28bc3c..eb232377 100644 --- a/src/backend/kms/surface/mod.rs +++ b/src/backend/kms/surface/mod.rs @@ -1006,12 +1006,16 @@ impl SurfaceThreadState { &self.shell.read(), ); + // Acquiring a renderer can fail transiently when the underlying DRM + // device is lost (e.g. after a GPU reset). let mut renderer = if render_node != self.target_node { self.api .renderer(&render_node, &self.target_node, compositor.format()) - .unwrap() + .map_err(|err| anyhow::format_err!("Failed to create renderer: {:?}", err))? } else { - self.api.single_renderer(&self.target_node).unwrap() + self.api + .single_renderer(&self.target_node) + .map_err(|err| anyhow::format_err!("Failed to create renderer: {:?}", err))? }; self.timings.start_render(&self.clock); @@ -1267,7 +1271,10 @@ impl SurfaceThreadState { }) .context("Failed to draw to offscreen render target")?; - renderer = self.api.single_renderer(&self.target_node).unwrap(); + renderer = self + .api + .single_renderer(&self.target_node) + .map_err(|err| anyhow::format_err!("Failed to create renderer: {:?}", err))?; elements = postprocess_elements( &mut renderer,