From 1b16b982142c6943bf239b481e588c75d41c4a9f Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Thu, 8 Aug 2024 21:39:34 +0200 Subject: [PATCH 1/2] surface: Don't crash due to weird state after resume --- src/backend/kms/surface/mod.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/backend/kms/surface/mod.rs b/src/backend/kms/surface/mod.rs index 8b866dad..51387731 100644 --- a/src/backend/kms/surface/mod.rs +++ b/src/backend/kms/surface/mod.rs @@ -673,8 +673,27 @@ impl SurfaceThreadState { let Some(compositor) = self.compositor.as_mut() else { return; }; + + // handle edge-cases right after resume + if !matches!( + self.state, + QueueState::WaitingForVBlank { .. } | QueueState::Idle + ) { + match mem::replace(&mut self.state, QueueState::Idle) { + QueueState::WaitingForVBlank { .. } | QueueState::Idle => unreachable!(), + QueueState::Queued(token) | QueueState::WaitingForEstimatedVBlank(token) => { + self.loop_handle.remove(token); + } + QueueState::WaitingForEstimatedVBlankAndQueued { + estimated_vblank, + queued_render, + } => { + self.loop_handle.remove(estimated_vblank); + self.loop_handle.remove(queued_render); + } + } + } if matches!(self.state, QueueState::Idle) { - // can happen right after resume return; } From f60499fd636e5aebfa6694000348fdd19edd3ab3 Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Wed, 21 Aug 2024 14:14:15 +0200 Subject: [PATCH 2/2] kms: Only pause device after all surfaces are successfully suspended --- src/backend/kms/mod.rs | 4 ++-- src/backend/kms/surface/mod.rs | 20 +++++++++++++++----- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/backend/kms/mod.rs b/src/backend/kms/mod.rs index 279cacb7..03eab9a1 100644 --- a/src/backend/kms/mod.rs +++ b/src/backend/kms/mod.rs @@ -325,13 +325,13 @@ impl State { let backend = self.backend.kms(); backend.libinput.suspend(); for device in backend.drm_devices.values_mut() { - device.drm.pause(); if let Some(lease_state) = device.leasing_global.as_mut() { lease_state.suspend(); } for surface in device.surfaces.values_mut() { - surface.suspend(); + let _ = surface.suspend(); } + device.drm.pause(); } } } diff --git a/src/backend/kms/surface/mod.rs b/src/backend/kms/surface/mod.rs index 51387731..b03403a2 100644 --- a/src/backend/kms/surface/mod.rs +++ b/src/backend/kms/surface/mod.rs @@ -217,7 +217,9 @@ impl Default for QueueState { #[derive(Debug)] pub enum ThreadCommand { - Suspend, + Suspend { + result: SyncSender>, + }, Resume { surface: DrmSurface, gbm: GbmDevice, @@ -389,8 +391,12 @@ impl Surface { rx.recv().context("Surface thread died")? } - pub fn suspend(&mut self) { - let _ = self.thread_command.send(ThreadCommand::Suspend); + pub fn suspend(&mut self) -> Result<()> { + let (tx, rx) = std::sync::mpsc::sync_channel(1); + let _ = self + .thread_command + .send(ThreadCommand::Suspend { result: tx }); + rx.recv().context("Surface thread died")? } pub fn resume( @@ -496,7 +502,9 @@ fn surface_thread( event_loop .handle() .insert_source(thread_receiver, move |command, _, state| match command { - Event::Msg(ThreadCommand::Suspend) => state.suspend(), + Event::Msg(ThreadCommand::Suspend { result }) => { + let _ = result.send(state.suspend()); + } Event::Msg(ThreadCommand::Resume { surface, gbm, @@ -546,7 +554,7 @@ fn surface_thread( } impl SurfaceThreadState { - fn suspend(&mut self) { + fn suspend(&mut self) -> Result<()> { self.active.store(false, Ordering::SeqCst); let _ = self.compositor.take(); @@ -564,6 +572,8 @@ impl SurfaceThreadState { self.loop_handle.remove(queued_render); } }; + + Ok(()) } fn resume(