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.
This commit is contained in:
v0up3r 2026-07-27 19:21:35 -03:00 • committed by Victoria Brekenfeld
parent 5ce21fb4f3
commit 9514b4945e

View file

@ -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,