https://bugs.kde.org/show_bug.cgi?id=523408

            Bug ID: 523408
           Summary: plasmashell deadlocks in
                    ShellCorona::removeDesktop()/QWaylandWindow::reset()
                    when handling kde_output_order_v1 output order change
    Classification: Plasma
           Product: plasmashell
      Version First 6.7.2
       Reported In:
          Platform: Bazzite
                OS: Linux
            Status: REPORTED
          Severity: normal
          Priority: NOR
         Component: generic-crash
          Assignee: [email protected]
          Reporter: [email protected]
  Target Milestone: 1.0

plasmashell (and sometimes kscreenlocker_greet) deadlocks completely as
soon as the number or order of active Wayland outputs changes while a
kde_output_order_v1 event is being processed. Root cause is a
re-entrancy deadlock: the main thread is inside
ScreenPool::handleOutputOrderChanged(), which synchronously triggers
ShellCorona::removeDesktop(). That destroys a ContainmentView, whose
QWaylandWindow destructor (reset()) tries to write-lock a QReadWriteLock
that the currently-running event dispatch already holds — the thread
waits on itself forever. A render thread then busy-loops at ~100% CPU
of one core with no further rendering. Reproducible at roughly 1 in 7
output changes — not deterministic on a single attempt, but reliable
over repeated attempts.

STEPS TO REPRODUCE
1. Have a running Plasma 6 Wayland session with at least two outputs
   (physical or virtual).
2. Repeatedly change the number/order of active outputs, e.g.:
   - hot-unplug/replug a monitor while the session is running, or
   - switch the input on a monitor (brief signal loss), or
   - toggle an output via `kscreen-doctor output.<N>.disable` followed
     by `kscreen-doctor output.<N>.enable` (e.g. a virtual display used
     for remote streaming).
3. Repeat several times (the deadlock hits roughly 1 in 7 toggles).
4. Check whether plasmashell (desktop, panels) still responds to input.
5. Optionally: trigger the same output change while the session is
   locked with kscreenlocker_greet.

OBSERVED RESULT
plasmashell hangs completely: the main thread sits forever in a
futex/QReadWriteLock wait (see backtrace below), and a render thread
then busy-loops at ~100% CPU of one core with no further rendering.
Desktop and panels freeze entirely and stop responding to any input
except globally registered KWin shortcuts. If the same deadlock hits
while the session is locked, kscreenlocker_greet freezes as a static
image with zero interactivity (no password-field feedback at all). The
only current recovery is manually restarting the affected process
(`systemctl --user restart plasma-plasmashell.service`, or killing and
letting kscreenlocker_greet respawn).

EXPECTED RESULT
plasmashell handles the output order/count change without blocking;
desktop views and panels are added/removed/rearranged accordingly. A
locked session's kscreenlocker_greet stays interactive throughout.

SOFTWARE/OS VERSIONS
Operating System: Bazzite (Fedora-based immutable/rpm-ostree), current image
KDE Plasma Version: 6.7.2 (also reproduced on 6.7.1)
KDE Frameworks Version: [please fill in from `kinfo` — not captured at time of
writing]
Qt Version: Qt 6 (exact point version not captured —
Qt6Core/Qt6Gui/Qt6WaylandClient involved per backtrace; please fill in from
`kinfo`)

ADDITIONAL INFORMATION

Backtrace (main thread):
#0  __syscall_cancel_arch (libc.so.6)
#1  __internal_syscall_cancel (libc.so.6)
#2  __GI___futex_abstimed_wait_cancelable64 (libc.so.6)
#3  pthread_cond_wait@@GLIBC_2.3.2 (libc.so.6)
#4  std::condition_variable::wait(std::unique_lock<std::mutex>&)
(libstdc++.so.6)
#5  QReadWriteLockPrivate::lockForWrite(std::unique_lock<std::mutex>&,
QDeadlineTimer) (libQt6Core.so.6)
#6  QReadWriteLockPrivate::recursiveLockForWrite(QDeadlineTimer)
(libQt6Core.so.6)
#7  QBasicReadWriteLock::contendedTryLockForWrite(QDeadlineTimer, void*)
(libQt6Core.so.6)
#8  QtWaylandClient::QWaylandWindow::reset() (libQt6WaylandClient.so.6)
#9  QtWaylandClient::QWaylandWindow::~QWaylandWindow()
(libQt6WaylandClient.so.6)
#10 QtWaylandClient::QWaylandVulkanWindow::~QWaylandVulkanWindow() [thunk]
(libQt6WaylandClient.so.6)
#11 QWindowPrivate::destroy() (libQt6Gui.so.6)
#12 PlasmaQuick::ContainmentView::destroy() (libPlasmaQuick.so.7)
#13 ShellCorona::removeDesktop(DesktopView*) (plasmashell)
#14 ShellCorona::handleScreenOrderChanged(QList<QScreen*>) (plasmashell)
#15 [Qt signal/slot dispatch] (libQt6Core.so.6)
#16 ScreenPool::handleOutputOrderChanged(QList<QString> const&) (plasmashell)
#17 [Qt signal/slot dispatch] (libQt6Core.so.6)
#18 OutputOrderWatcher::outputOrderChanged(QList<QString> const&)
(libkworkspace6.so.6)
#19 [Qt signal/slot dispatch] (libQt6Core.so.6)
#20 WaylandOutputOrder::kde_output_order_v1_done() [thunk]
(libkworkspace6.so.6)
#21 ffi_call_unix64 / ffi_call (libffi.so.8)
#22 wl_closure_invoke (libwayland-client.so.0)
#23 dispatch_event (libwayland-client.so.0)
#24 wl_display_dispatch_queue_pending (libwayland-client.so.0)
#25 QtWaylandClient::EventThread::readAndDispatchEvents()
(libQt6WaylandClient.so.6)
#26 [Qt event loop] (libQt6Core.so.6, QEventDispatcherGlib, QEventLoop::exec,
QCoreApplication::exec)
#27 main

Environment: NVIDIA proprietary driver 610.43.03, GeForce RTX 4070,
NVreg_PreserveVideoMemoryAllocations=1.

Trigger context: primarily observed in a headless-streaming setup
(Sunshine/Moonlight-like) with virtual displays managed dynamically via
DRM/KMS debugfs EDID overrides, toggled at runtime with
`kscreen-doctor output.X.enable`/`.disable`. Also reproduced with plain
physical monitor hotplug (unplug/replug, switching input) — not
specific to virtual displays, affects any Wayland output order/count
change.

Related bug: https://bugs.kde.org/show_bug.cgi?id=464377 ("Assert/crash
in ScreenPool::screenInvariants() after
ScreenPool::handleOutputOrderChanged() when waking up or re-plugging a
screen", CONFIRMED, 9 duplicates). Same trigger path
(WaylandOutputOrder -> OutputOrderWatcher ->
ScreenPool::handleOutputOrderChanged()), but ends in an assert-crash
there instead of a deadlock — likely the same underlying race in
ScreenPool with a different failure mode (possibly depending on whether
assertions are enabled in the build). The MR linked there (!4642,
"ScreenPool: add fake screens initially") targets the X11 case
primarily and likely does not fix this Wayland deadlock.

Frequency: with a script that toggles outputs via kscreen-doctor, the
deadlock hits roughly 1 in 7 output changes — not on every single
attempt, but reliably over repeated attempts.

Workaround: `systemctl --user restart plasma-plasmashell.service` (or
killing and letting kscreenlocker_greet respawn) restores desktop and
panels within seconds; running applications/streams are unaffected.

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to