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

Alexis Murzeau <amub...@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |amub...@gmail.com

--- Comment #87 from Alexis Murzeau <amub...@gmail.com> ---
Hi,

I get this too on my laptop on Debian which is easily found as the fan goes up
when locked.
My configuration is: laptop lid closed, external screen plugged in as main and
only enabled screen.


I found that a loop of events is causing the high CPU usage.
But I don't really know what component is wrong and what is the path forward.

Here is the loop :
- The screenlocker (code in ksmserver) which wants to be above all other
windows
  - On a XCB_MAP_NOTIFY (0x13) event on the root window, it will call
XRaiseWindow/XRestackWindows to ensure it is above others.
   
https://sources.debian.org/src/kscreenlocker/6.3.5-1/x11locker.cpp/#L362-L391
  - This will cause XCB_CONFIGURE_NOTIFY like this (from xev -root):

ConfigureNotify event, serial 24, synthetic NO, window 0x251,
    event 0x251, window 0x3800022, (0,0), width 1920, height 1080,
    border_width 0, above 0x1228514, override YES

ConfigureNotify event, serial 24, synthetic NO, window 0x251,
    event 0x251, window 0x1000031, (0,0), width 1920, height 1080,
    border_width 0, above 0x1228514, override YES

  - At this stage (before kwin try something), xwininfo -tree -root gives this:
```
xwininfo: Window id: 0x251 (the root window) (has no name)

  Root window id: 0x251 (the root window) (has no name)
  Parent window id: 0x0 (none)
     91 children:
     0x3400022 "kscreenlocker_greet": ("kscreenlocker_greet"
"kscreenlocker_greet")  1920x1080+0+0  +0+0
     0x1000090 "ksmserver": ("ksmserver" "ksmserver")  1920x1080+0+0  +0+0
     0x12737b6 (has no name): ()  36x36+0+0  +0+0
     0x12737b5 (has no name): ()  8x8+0+0  +0+0
     0x3400041 "Qt Clipboard Requestor Window": ()  3x3+0+0  +0+0
     0x3400024 "kscreenlocker_greet": ()  1x1+0+0  +0+0
[...]
```


- KWin is listening XCB_CONFIGURE_NOTIFY on the root window:
  - On a XCB_CONFIGURE_NOTIFY event on the root window, it will restack windows
    https://sources.debian.org/src/kwin/4:6.3.5-1/src/events.cpp/#L273-L280
  - This doesn't seem to cause a conflict with the screenlocker (no X11 event
triggered except a QueryTree).

- Qt's XCB implementation (libQt6XcbQpa.so) listening for screen changes by
itself within kwin_x11 process. KWin code doesn't seem to be involved here,
maybe just the fact that it listen for events on the root window too.
  - On a XCB_CONFIGURE_NOTIFY event on the root window, it will rescan screens
   
https://sources.debian.org/src/qt6-base/6.8.2+dfsg-8/src/plugins/platforms/xcb/qxcbconnection.cpp/?hl=532#L585-L591
  - During that processing, it will send a XRANDR XRRSelectInput request.
   
https://sources.debian.org/src/qt6-base/6.8.2+dfsg-8/src/plugins/platforms/xcb/qxcbconnection_screens.cpp/?hl=273#L483
   
https://sources.debian.org/src/qt6-base/6.8.2+dfsg-8/src/plugins/platforms/xcb/qxcbscreen.cpp/?hl=589#L608
  - On Xorg side, XRRSelectInput cause a XRRScreenChangeNotify event (this
might not always be the case, but this is the case here):
   
https://sources.debian.org/src/xorg-server/2:21.1.16-1.3/randr/rrdispatch.c/?hl=91#L156

- KWin is also listening on XRANDR events (caused by Qt's XCB doing
XRRSelectInput)
  - On XRRScreenChangeNotify event, KWin update its internal state about
screens after some delay to avoid doing too often.
   
https://sources.debian.org/src/kwin/4%3A6.3.5-1/src/backends/x11/standalone/x11_standalone_backend.cpp/#L72
   
https://sources.debian.org/src/kwin/4%3A6.3.5-1/src/backends/x11/standalone/x11_standalone_backend.cpp/#L276
  - While doing this outputUpdate, it will `KWin::ScreenEdges::recreateEdges`,
which destroy and recreate small windows which are used to detect mouse at
screen edge.
  - This will cause a XCB_MAP_NOTIFY to be send on the root window.


  - At this stage (before the screenlocker try something), xwininfo -tree -root
gives this:
```
xwininfo: Window id: 0x251 (the root window) (has no name)

  Root window id: 0x251 (the root window) (has no name)
  Parent window id: 0x0 (none)
     91 children:
     0x126e2f1 (has no name): ()  36x36+0+0  +0+0
     0x126e2f0 (has no name): ()  8x8+0+0  +0+0
     0x3400022 "kscreenlocker_greet": ("kscreenlocker_greet"
"kscreenlocker_greet")  1920x1080+0+0  +0+0
     0x1000090 "ksmserver": ("ksmserver" "ksmserver")  1920x1080+0+0  +0+0
     0x3400041 "Qt Clipboard Requestor Window": ()  3x3+0+0  +0+0
     0x3400024 "kscreenlocker_greet": ()  1x1+0+0  +0+0
[...]
```
  Note: the 2 first windows (0x126e2f0 and 0x126e2f1) are the ones just created
by kwin_x11 by KWin::ScreenEdges::recreateEdges.

- The screenlocker (code in ksmserver) which wants to be above all other
windows (this is where the loop restart)
  - On a XCB_MAP_NOTIFY (0x13) event on the root window, it will call
XRaiseWindow/XRestackWindows to ensure it is above others.
   
https://sources.debian.org/src/kscreenlocker/6.3.5-1/x11locker.cpp/#L362-L391


When I run `kwin_x11 --replace` once, then locking the desktop won't trigger
the issue anymore.
As a comparison, the `xwininfo -tree -root` output when the issue does not
occur is:
```
xwininfo: Window id: 0x251 (the root window) (has no name)

  Root window id: 0x251 (the root window) (has no name)
  Parent window id: 0x0 (none)
     89 children:
     0x1800041 "Qt Clipboard Requestor Window": ()  3x3+0+0  +0+0
     0x1800022 "kscreenlocker_greet": ("kscreenlocker_greet"
"kscreenlocker_greet")  1920x1080+0+0  +0+0
     0x1000095 "ksmserver": ("ksmserver" "ksmserver")  1920x1080+0+0  +0+0
     0x1800024 "kscreenlocker_greet": ()  1x1+0+0  +0+0
     0x1800016 (has no name): ()  1x1+0+0  +0+0
     0x1800005 "Qt Selection Owner for kscreenlocker_greet": ()  3x3+0+0  +0+0

[... far under many other windows]
     0x3400044 (has no name): ()  8x8+0+0  +0+0
     0x3400045 (has no name): ()  36x36+0+0  +0+0
[...]
```

It seems that both KWin and the screenlocker didn't restack windows.
If I unplug and plug back again my external screen, the infinite high CPU loop
is back again at each lock until the kwin_x11 is replaced again.

-------

To find this, I've used this setup:

I've investigated what's happening using the linux perf tool and custom probes.
Here is my setup:
```sh
# Create probes to have clues about which program does what with X11.
# Monitor programs sending X11 requests without using XCB (ksmserver):
perf probe -x /usr/lib/x86_64-linux-gnu/libX11.so.6.4.0 _XGetRequest
# Monitor programs sending X11 requests using XCB (kwin_x11):
perf probe -x /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0 xcb_send_request
# Monitor Xorg sending replies or events:
perf probe -x /usr/lib/xorg/Xorg WriteToClient
# Monitor received events by the screenlocker stored in responseType:
perf probe -x /usr/lib/x86_64-linux-gnu/libKScreenLocker.so.6
'X11Locker=_ZN12ScreenLocker9X11Locker17nativeEventFilterERK10QByteArrayPvPx:13
responseType'
# Monitor kwin_x11 receiving the XRANDR event
probe -x /usr/bin/kwin_x11
_ZN4KWin17XrandrEventFilter5eventEP19xcb_generic_event_t
```

Then reproduce the problem by locking the desktop.
In parallel, use a secondary device to SSH into your locked computer and open 2
consoles:
- On the first:
  - Run GDB against ksmserver using its pid
  - Put a breakpoint on XRaiseWindow (break XRaiseWindow)
  - Continue execution to read the breakpoint
- On the second console:
  - Run this command:
perf record \
    -e probe_libxcb:xcb_send_request \
    -e probe_libX11:_XGetRequest \
    -e probe_Xorg:WriteToClient \
    -e probe_kwin_x11:_ZN4KWin17XrandrEventFilter5eventEP19xcb_generic_event_t
\
    -e probe_libKScreenLocker:X11Locker \
    --exclude-perf \
    --call-graph dwarf,4096 \
    --user-callchains

- Back on the first command, continue th eexecution once which will break again
on the breakpoint (effectively doing a single "loop" of the issue)
- On the second console, use CTRL+C to stop the recording
- Close GDB and SSH and unlock the locked computer to go back on it
- Generate a text trace file of the recording using `perf script > perf.trace`

-------


Software versions:
```
Operating System: Debian GNU/Linux 13
KDE Plasma Version: 6.3.5
KDE Frameworks Version: 6.13.0
Qt Version: 6.8.2
Kernel Version: 6.12.37+deb13-amd64 (64-bit)
Graphics Platform: X11
Processors: 4 × Intel® Core™ i5-3230M CPU @ 2.60GHz
Memory: 7.6 Gio of RAM
Graphics Processor: Intel® HD Graphics 4000
Manufacturer: Sony Corporation
Product Name: SVE1513Q1EB
System Version: C10GMJY7
```

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

Reply via email to