Bug 506782

Summary: Flushing buffers with screen locked under Wayland causes high CPU usage due to Mesa waiting for a surface
Product: [Plasma] kwin Reporter: jackmacwindowslinux
Component: performanceAssignee: KWin default assignee <kwin-bugs-null>
Status: RESOLVED UPSTREAM    
Severity: normal CC: julien.dlq, linx.system.adm, nate, xaver.hugl
Priority: NOR    
Version First Reported In: 6.4.2   
Target Milestone: ---   
Platform: Arch Linux   
OS: Linux   
Latest Commit: Version Fixed/Implemented In:
Sentry Crash Report:

Description jackmacwindowslinux 2025-07-09 07:06:04 UTC
SUMMARY
When I lock my system and the screen turns off*, CPU usage spikes in plasmashell, as well as kwin_wayland to an extent. The backtrace indicates that the QSGRenderThread gets stuck in a loop while swapping buffers, with the loop happening inside Mesa while waiting for a free buffer. Frame 10 in the backtrace below is the function that doesn't return. From what I can tell, plasmashell is constantly sending events to kwin_wayland and expects it to free a buffer, and kwin_wayland processes them but never frees any buffer.

*The primary monitor turns back on after a second, which I believe is related to #493974.

I'm not sure where to tag this, as the issue is spread across multiple projects, but it seems that plasmashell is the source of the issue and it doesn't affect any other programs, so I put it here. Please move it if it's more relevant to kwin_wayland or something else instead.

STEPS TO REPRODUCE
1. Lock the screen and let the system turn off the monitor
2. SSH into the machine from another system and check CPU usage
3. Observe high CPU usage in plasmashell

OBSERVED RESULT
I see plasmashell constantly using about 75% CPU, and kwin_wayland using about 50% CPU. My fans ramp up because of this.

EXPECTED RESULT
plasmashell and kwin_wayland remain dormant while the screen is off.

SOFTWARE/OS VERSIONS
Linux/KDE Plasma: Arch Linux 6.15.5-arch1-1
KDE Plasma Version: 6.4.2
KDE Frameworks Version: 6.15.0
Qt Version: 6.9.1
Mesa version: 25.1.5
CPU: AMD Ryzen 9 5950X
GPU: AMD Radeon RX 7900 GRE

ADDITIONAL INFORMATION
#0  __syscall_cancel_arch ()
    at ../sysdeps/unix/sysv/linux/x86_64/syscall_cancel.S:56
#1  0x00007fceb9ca1fda in __internal_syscall_cancel
    (a1=<optimized out>, a2=<optimized out>, a3=<optimized out>, a4=<optimized out>, a5=a5@entry=0, a6=a6@entry=4294967295, nr=202) at cancellation.c:49
#2  0x00007fceb9ca264c in __futex_abstimed_wait_common64
    (private=0, futex_word=0x556868a4025c, expected=<optimized out>, op=<optimized out>, abstime=0x0, cancel=true) at futex-internal.c:57
#3  __futex_abstimed_wait_common
    (futex_word=futex_word@entry=0x556868a4025c, expected=<optimized out>, clockid=clockid@entry=0, abstime=abstime@entry=0x0, private=private@entry=0, cancel=cancel@entry=true) at futex-internal.c:87
#4  0x00007fceb9ca26af in __GI___futex_abstimed_wait_cancelable64
    (futex_word=futex_word@entry=0x556868a4025c, expected=<optimized out>, clockid=clockid@entry=0, abstime=abstime@entry=0x0, private=private@entry=0)
    at futex-internal.c:139
#5  0x00007fceb9ca4d1e in __pthread_cond_wait_common
    (cond=0x556868a40238, mutex=0x556868a40208, clockid=0, abstime=0x0)
    at pthread_cond_wait.c:426
#6  ___pthread_cond_wait (cond=0x556868a40238, mutex=0x556868a40208)
    at pthread_cond_wait.c:458
#7  0x00007fcebcff8c2c in wl_display_read_events ()
    at /usr/lib/libwayland-client.so.0
#8  0x00007fcebcffa1a4 in wl_display_dispatch_queue ()
    at /usr/lib/libwayland-client.so.0
#9  0x00007fcebcffb4dc in wl_display_roundtrip_queue ()
    at /usr/lib/libwayland-client.so.0
* #10 0x00007fceb25a70ba in get_back_bo ()
    at ../mesa-25.1.5/src/egl/drivers/dri2/platform_wayland.c:1201
#11 update_buffers ()
    at ../mesa-25.1.5/src/egl/drivers/dri2/platform_wayland.c:1401
#12 0x00007fceb25a7870 in update_buffers_if_needed ()
    at ../mesa-25.1.5/src/egl/drivers/dri2/platform_wayland.c:1436
#13 image_get_buffers ()
    at ../mesa-25.1.5/src/egl/drivers/dri2/platform_wayland.c:1446
#14 0x00007fcea16447b4 in dri_image_drawable_get_buffers ()
    at ../mesa-25.1.5/src/gallium/frontends/dri/dri2.c:270
#15 0x00007fcea164486c in dri2_allocate_textures ()
    at ../mesa-25.1.5/src/gallium/frontends/dri/dri2.c:326
#16 0x00007fcea163b236 in dri_st_framebuffer_validate ()
    at ../mesa-25.1.5/src/gallium/frontends/dri/dri_drawable.c:79
#17 0x00007fcea16eb0c8 in st_framebuffer_validate ()
    at ../mesa-25.1.5/src/mesa/state_tracker/st_manager.c:238
#18 0x00007fcea16ec088 in st_manager_validate_framebuffers ()
    at ../mesa-25.1.5/src/mesa/state_tracker/st_manager.c:1237
#19 0x00007fcea1965808 in st_update_framebuffer_state ()
    at ../mesa-25.1.5/src/mesa/state_tracker/st_atom_framebuffer.c:122
#20 0x00007fcea196b3d1 in st_validate_state ()
    at ../mesa-25.1.5/src/mesa/state_tracker/st_util.h:131
#21 st_Clear () at ../mesa-25.1.5/src/mesa/state_tracker/st_cb_clear.c:399
#22 0x00007fcea17b1008 in _mesa_unmarshal_Clear ()
    at src/mapi/glapi/gen/marshal_generated1.c:160
#23 0x00007fcea168cb71 in glthread_unmarshal_batch ()
    at ../mesa-25.1.5/src/mesa/main/glthread.c:141
#24 0x00007fcea168d26d in _mesa_glthread_finish ()
    at ../mesa-25.1.5/src/mesa/main/glthread.c:422
#25 0x00007fceb456467c in QtWaylandClient::QWaylandGLContext::swapBuffers(QPlatformSurface*) ()
    at /usr/lib/qt6/plugins/wayland-graphics-integration-client/../../../libQt6WaylandEglClientHwIntegration.so.6
#26 0x00007fcebafa5f0d in ??? () at /usr/lib/libQt6Gui.so.6
#27 0x00007fcebadf962c in QRhi::endFrame(QRhiSwapChain*, QFlags<QRhi::EndFrameFlag>) () at /usr/lib/libQt6Gui.so.6
#28 0x00007fcebc0ab5c8 in ??? () at /usr/lib/libQt6Quick.so.6
#29 0x00007fceba51ee69 in ??? () at /usr/lib/libQt6Core.so.6
#30 0x00007fceb9ca57eb in start_thread (arg=<optimized out>)
    at pthread_create.c:448
#31 0x00007fceb9d2918c in __GI___clone3 ()
    at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78
Comment 1 Nate Graham 2025-08-08 17:13:00 UTC
Thanks for the debugging!
Comment 2 Zamundaaa 2025-10-13 14:58:47 UTC
If KWin has high CPU usage as well, most likely plasmashell is presenting way more often than it should, and processing those commits just takes time.

There was an issue where Qt would attempt to run animations on hidden windows and go crazy because of that. This sounds like it could be a symptom of that same problem.
Do you have a panel set to auto-hide perhaps, or some non-default widgets?
Can you also reproduce the problem with a new user?
Comment 3 jackmacwindowslinux 2025-10-13 15:07:08 UTC
I do have a Latte-style dock set to auto-hide. I can try messing around later to see if that's the trigger - I do recall seeing icon updates from the dock in a stack trace at some point, though I'm not sure if that was the same issue.
Comment 4 Zamundaaa 2025-10-17 13:51:48 UTC
Okay, do try to set it to always visible. If you can check if it happens with a new user, that would be the most safe option.
Comment 5 jackmacwindowslinux 2025-10-21 22:46:04 UTC
Okay, bear with me here - I forgot what the original issue was until I just re-read it after experiencing a hang after unlock, which I got into my head as the issue. However, I think it may have some insight as to the source of this issue.

I disabled my auto-hiding panel, and today unlocked to find plasmashell hanging again. I already had GDB attached in anticipation of this issue, which I promptly used to break into plasmashell and see its stacktrace. I found that the global app menu I have on one of my panels appears to be taking a long time in the stack trace shown below:

#0  0x00007f4f04b3860d in syscall () at /usr/lib/libc.so.6
#1  0x00007f4f0555a9b1 in ??? () at /usr/lib/libQt6Core.so.6
#2  0x00007f4f05390f93 in QMetaObject::invokeMethodImpl(QObject*, QtPrivate::QSlotObjectBase*, Qt::ConnectionType, long long, void const* const*, char const* const*, QtPrivate::QMetaTypeInterface const* const*) () at /usr/lib/libQt6Core.so.6
#3  0x00007f4f063f5c34 in ??? () at /usr/lib/libQt6DBus.so.6
#4  0x00007f4f063f6817 in ??? () at /usr/lib/libQt6DBus.so.6
#5  0x00007f4f053e78bc in QObjectPrivate::connectImpl(QObject const*, int, QObject const*, void**, QtPrivate::QSlotObjectBase*, int, int const*, QMetaObject const*) () at /usr/lib/libQt6Core.so.6
#6  0x00007f4f053e7c44 in QObject::connectImpl(QObject const*, void**, QObject const*, void**, QtPrivate::QSlotObjectBase*, Qt::ConnectionType, int const*, QMetaObject const*) () at /usr/lib/libQt6Core.so.6
#7  0x00007f4e640cc1d1 in ??? () at /usr/lib/qt6/qml/org/kde/plasma/private/appmenu/libappmenuplugin.so
#8  0x00007f4f053e99d4 in ??? () at /usr/lib/libQt6Core.so.6
#9  0x00007f4ede05798b in ??? () at /usr/lib/libtaskmanager.so.6
#10 0x00007f4f053e99d4 in ??? () at /usr/lib/libQt6Core.so.6
#11 0x00007f4f056463b2 in QIdentityProxyModelPrivate::sourceDataChanged(QModelIndex const&, QModelIndex const&, QList<int> const&) () at /usr/lib/libQt6Core.so.6
#12 0x00007f4f053e99d4 in ??? () at /usr/lib/libQt6Core.so.6
#13 0x00007f4f0560fb84 in QAbstractItemModel::dataChanged(QModelIndex const&, QModelIndex const&, QList<int> const&) () at /usr/lib/libQt6Core.so.6
#14 0x00007f4ede075fe7 in ??? () at /usr/lib/libtaskmanager.so.6
#15 0x00007f4f053e99d4 in ??? () at /usr/lib/libQt6Core.so.6
#16 0x00007f4ede070951 in ??? () at /usr/lib/libtaskmanager.so.6
#17 0x00007f4f063a62ee in ??? () at /usr/lib/libffi.so.8
#18 0x00007f4f063a29f8 in ??? () at /usr/lib/libffi.so.8
#19 0x00007f4f063a56ce in ffi_call () at /usr/lib/libffi.so.8
#20 0x00007f4f0807547a in ??? () at /usr/lib/libwayland-client.so.0
#21 0x00007f4f080762e9 in ??? () at /usr/lib/libwayland-client.so.0
#22 0x00007f4f080766bb in wl_display_dispatch_queue_pending () at /usr/lib/libwayland-client.so.0
#23 0x00007f4f064d6f36 in ??? () at /usr/lib/libQt6WaylandClient.so.6
#24 0x00007f4f053ea001 in ??? () at /usr/lib/libQt6Core.so.6
#25 0x00007f4f05683109 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
    at /usr/lib/libQt6Core.so.6
#26 0x00007f4f05387d46 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) ()
    at /usr/lib/libQt6Core.so.6
#27 0x00007f4f0537db7c in QCoreApplication::exec() () at /usr/lib/libQt6Core.so.6
#28 0x000055f8fdb5ff78 in ??? ()
#29 0x00007f4f04a27b8b in __libc_start_call_main
    (main=main@entry=0x55f8fdb5cf30, argc=argc@entry=2, argv=argv@entry=0x7ffec59a0258)
    at ../sysdeps/nptl/libc_start_call_main.h:58
#30 0x00007f4f04a27c4b in __libc_start_main_impl
    (main=0x55f8fdb5cf30, argc=2, argv=0x7ffec59a0258, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffec59a0248) at ../csu/libc-start.c:360
#31 0x000055f8fdb60495 in ??? ()

This leads me to believe that the KWin hang may be tangentially related to the app menu constantly updating, and those updates getting stuck in a queue while KWin does... something. Now that I remember that I don't have to wait 24 hours for the plasmashell hang, I'll follow the reproduction steps I gave myself (:P), and see what's going on in a separate user. I'll also upgrade to Plasma 6.5 to see if the issue got fixed in the process.

By the way, the monitor turning back on issue has gone away since Plasma 6.4.4 or 6.4.5.
Comment 6 jackmacwindowslinux 2025-10-21 23:51:15 UTC
Disregard the above. I can confirm the issue goes away when I disable auto-hiding on the dock. I can also confirm that when the panel is set to Dodge Windows, the issue only appears when it is hiding, and doesn't happen when there are no windows to dodge. The dock panel only contains a standard Icons-Only Task Manager, with some spacers on the sides. I'm currently upgrading my system, and while I won't be on Plasma 6.5 yet (didn't realize it's still in Arch testing), I'll be able to test with Qt 6.10 in case that fixed the issue.
Comment 7 jackmacwindowslinux 2025-10-22 00:28:29 UTC
Qt 6.10 appears to have solved this issue for me. I'm closing it for now, but if I find it again in the future I'll reopen.