Bug 523001 - Interrupted DPMS-off leaks sleep inhibitor, delaying subsequent suspends by timeout
Summary: Interrupted DPMS-off leaks sleep inhibitor, delaying subsequent suspends by t...
Status: RESOLVED FIXED
Alias: None
Product: kwin
Classification: Plasma
Component: wayland-generic (other bugs)
Version First Reported In: 6.7.2
Platform: CachyOS Linux
: NOR normal
Target Milestone: ---
Assignee: KWin default assignee
URL: https://invent.kde.org/plasma/kwin/-/...
Keywords:
Depends on:
Blocks:
 
Reported: 2026-07-13 02:02 UTC by ameenalasady
Modified: 2026-07-14 00:57 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed/Implemented In: 6.7.3
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description ameenalasady 2026-07-13 02:02:55 UTC
On Plasma Wayland, interrupting the monitor power-off sequence (DPMS) by waking the screens mid-transition (e.g., jiggling the mouse right as the screen fades to black) leaks a delay-sleep inhibitor reference in KWin. This causes subsequent system suspends to hang on the visible lock screen for the full systemd inhibitor timeout duration (default 5 seconds, or whatever InhibitDelayMaxSec is set to) before the machine actually goes to sleep.

Detailed Root Cause:
LogindSession::delaySleep() (src/core/session_logind.cpp) caches the logind inhibitor file descriptor in a weak_ptr (m_suspendLock) and hands the exact same shared fd to all internal callers. Its two primary callers are the kscreenlocker integration (wayland_server.cpp) and the "dpms animation" inhibitor in Workspace::requestDpmsState() (workspace.cpp).

When displays are commanded to turn off, Workspace::requestDpmsState() acquires this shared inhibitor. However, the DpmsState::On code path completely forgets to reset m_sleepInhibitor. The reference is only normally released in maybeUpdateDpmsState() once all outputs successfully report that they have fully reached the Off state. 

If a user wakes the displays mid-transition, Workspace permanently leaks its reference to that shared fd cache. On the next system suspend, KSldApp successfully locks the screen and drops its own reference to the inhibitor, but the underlying file descriptor stays open because of KWin's stale Workspace reference. As a result, systemd-logind waits out the entire safety timeout, throwing this log into the journal:
systemd-logind: Delay lock is active (PID .../kwin_wayland) but inhibitor timeout is reached.

The leak temporarily self-heals the next time the monitor is allowed to complete a full, uninterrupted screen-off cycle.


STEPS TO REPRODUCE
1. Open a terminal in a Plasma Wayland session.
2. Simulate an interrupted screen-off transition by running: 
   kscreen-doctor --dpms off; sleep 0.1; kscreen-doctor --dpms on; sleep 1
3. Lock the session: loginctl lock-session
4. Check if the screen-lock sleep inhibitor was correctly released by running:
   systemd-inhibit --list | grep -c "screen gets locked"


OBSERVED RESULT
The command returns 1, proving the inhibitor is leaked and still actively held while the session is locked. When you next attempt to suspend the machine, it will sit on the lock screen for 5 seconds before sleeping.


EXPECTED RESULT
The command should return 0. Waking the displays should immediately clear the DPMS animation sleep inhibitor, allowing the system to suspend instantly.


SOFTWARE/OS VERSIONS
Operating System: CachyOS Linux
KDE Plasma Version: 6.7.2
KDE Frameworks Version: 6.27.0
Qt Version: 6.11.1


ADDITIONAL INFORMATION
I have already submitted a tested, one-line merge request fixing this issue on GitLab by explicitly resetting the inhibitor when switching the DPMS state back to On.

Merge Request Link: https://invent.kde.org/plasma/kwin/-/merge_requests/9572

Proposed Fix:
--- a/src/workspace.cpp
+++ b/src/workspace.cpp
@@ -572,6 +572,7 @@ void Workspace::requestDpmsState(DpmsState state)
     if (m_dpms == DpmsState::On) {
         applyOutputConfiguration(cfg);
         m_dpmsFilter.reset();
         m_dpmsTimer.stop();
+        m_sleepInhibitor.reset();
     } else {
         applyOutputConfiguration(cfg);
         m_dpmsFilter = std::make_unique<DpmsInputEventFilter>();
Comment 1 Zamundaaa 2026-07-14 00:32:27 UTC
Git commit 1e702e03edf8b0b0212a9d371901c901322f4feb by Xaver Hugl, on behalf of Ameen Al-Asady.
Committed on 14/07/2026 at 00:32.
Pushed by zamundaaa into branch 'master'.

workspace: remove sleep inhibitor if the dpms animation is canceled

M  +1    -0    src/workspace.cpp

https://invent.kde.org/plasma/kwin/-/commit/1e702e03edf8b0b0212a9d371901c901322f4feb
Comment 2 Zamundaaa 2026-07-14 00:56:57 UTC
Git commit cdd6a9c8ed751e4540e8391045b8440369c36458 by Xaver Hugl.
Committed on 14/07/2026 at 00:56.
Pushed by zamundaaa into branch 'Plasma/6.7'.

workspace: remove sleep inhibitor if the dpms animation is canceled

(cherry picked from commit 1e702e03edf8b0b0212a9d371901c901322f4feb)

Co-authored-by: Ameen Al-Asady <ameenaladdin@gmail.com>

M  +1    -0    src/workspace.cpp

https://invent.kde.org/plasma/kwin/-/commit/cdd6a9c8ed751e4540e8391045b8440369c36458