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

            Bug ID: 527802
           Summary: kwin_x11: picture freezes for good when the
                    SGI_video_sync/OML_sync_control vsync monitor reports
                    no vblank
    Classification: Plasma
           Product: kwin
      Version First 6.3.6
       Reported In:
          Platform: Debian stable
                OS: Linux
            Status: REPORTED
          Severity: major
          Priority: NOR
         Component: platform-x11-standalone
          Assignee: [email protected]
          Reporter: [email protected]
  Target Milestone: ---

SUMMARY
With the GLX backend, when GLX_INTEL_swap_event is not used, a frame is
presented only after the SGI_video_sync (or OML_sync_control) vsync monitor
reports the next vblank. If that vblank never comes, the screen stops updating
for good: the cursor still moves and input still reaches the clients, but
nothing on screen changes until kwin_x11 is replaced. Replacing it can hang as
well, because the old instance waits for the blocked helper thread on exit.

This affects every X11 session on an Intel GPU, because KWin ignores
GLX_INTEL_swap_event on Intel (supportsSwapEvent = !glPlatform->isIntel(),
unless KWIN_USE_INTEL_SWAP_EVENT is set), even when the driver offers it.
With Mesa >= 25.2 there is no DRI2 any more, so this is the DRI3 path.

STEPS TO REPRODUCE
Seen in the wild once: Intel Arrow Lake laptop, X11 session (Deepin DDE shell
on
upstream KWin 6.3.6 as the window manager and compositor),
while a large language model benchmark filled RAM and swap. Shortly before,
the same kwin_x11 process had logged several hundred
"QRhiGles2: Failed to make context current. Expect bad things to happen."

Deterministic reproduction with a test shim (source at the end):
1. Build the shim:
   gcc -O2 -shared -fPIC -o vsync-stall.so vsync-stall.c -ldl
2. Start kwin_x11 with LD_PRELOAD=/path/to/vsync-stall.so (on an Intel GPU, or
   with KWIN_USE_INTEL_SWAP_EVENT=0 elsewhere, so that SGIVideoSyncVsyncMonitor
   is used).
3. touch /tmp/agino-vsync-stall
   From then on, the thread named "vsync event monitor" blocks for good in
   xcb_wait_for_special_event(), where Mesa's DRI3 code waits for Present
   events, i.e. the next vblank never arrives for it.

OBSERVED RESULT
- The screen stops updating immediately and stays frozen (checked 9 s later
  with a probe that draws alternating colours into a small override-redirect
  window and reads the pixel back from the root window; compositing still
  reported active).
- The helper thread sits in the blocked wait; the main thread is idle.
- SIGTERM does not end the frozen kwin_x11: its main thread waits on a futex
  in ~SGIVideoSyncVsyncMonitor() for the helper thread. It was still running
  16 s later; only SIGKILL helps.

EXPECTED RESULT
A missed vblank costs at most one late frame; the compositor keeps painting
and exits normally.

ANALYSIS (kwin 6.3.6, unchanged in kwin-x11 Plasma/6.7)
- GlxBackend::present() stores m_frame and calls m_vsyncMonitor->arm(). Only
  VsyncMonitor::vblankOccurred -> GlxBackend::vblank() presents the frame, and
  the render loop doesn't schedule another frame until then.
- SGIVideoSyncVsyncMonitorHelper::poll() calls glXMakeCurrent() and then
  glXWaitVideoSyncSGI(), which has no timeout (the OML helper with
  glXWaitForMscOML() is the same).
- When glXMakeCurrent() fails, the helper emits errorOccurred and returns.
  Nothing is connected to errorOccurred, and the failure is logged at debug
  level only, so this path freezes the picture just as silently.
- Every arm() while the helper is blocked queues one more poll() call in the
  helper thread.
- ~SGIVideoSyncVsyncMonitor() calls m_thread.quit() and m_thread.wait() with
  no timeout, hence the hang when kwin_x11 is replaced or terminated.

Probably few people hit this because Plasma 6 defaults to Wayland, but every
kwin_x11 on an Intel GPU runs this code.

SOFTWARE/OS VERSIONS
Linux/KDE Plasma: Debian 13 (trixie) based distribution, KWin 6.3.6,
  Linux 7.2
Qt Version: 6.8
Graphics: Intel Arrow Lake iGPU driving the internal panel (Mesa 26.2.5,
  Xorg 21.1.16, modesetting + glamor, DRI3). GLX_INTEL_swap_event,
  GLX_SGI_video_sync and GLX_OML_sync_control are all advertised.
  An NVIDIA dGPU is attached as a reverse PRIME sink; it is not used for
  compositing.

ADDITIONAL INFORMATION
A merge request will follow. With the fix, the same reproduction no longer
freezes the picture, KWin switches to software vsync after 5 seconds and logs
a warning, and the old instance exits within a second when replaced.

Test shim (vsync-stall.c):

/* Test shim: when /tmp/agino-vsync-stall exists, the thread named "vsync event
mon"
 * blocks for good in xcb_wait_for_special_event() (Mesa DRI3 waits for Present
MSC
 * events there), simulating a vblank that never arrives. */
#define _GNU_SOURCE
#include <dlfcn.h>
#include <string.h>
#include <sys/prctl.h>
#include <unistd.h>

typedef void *(*wait_fn)(void *c, void *se);

void *xcb_wait_for_special_event(void *c, void *se)
{
    static wait_fn real;
    if (!real)
        real = (wait_fn)dlsym(RTLD_NEXT, "xcb_wait_for_special_event");
    char name[17] = {0};
    prctl(PR_GET_NAME, name, 0, 0, 0);
    if (strncmp(name, "vsync event mon", 15) == 0 &&
access("/tmp/agino-vsync-stall", F_OK) == 0) {
        for (;;)
            pause();
    }
    return real(c, se);
}

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

Reply via email to