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

            Bug ID: 527823
           Summary: SIGSEGV at address 1 in EglContext::popFramebuffer
                    while screencasting (cursor metadata, nested
                    ItemTreeView::paint)
    Classification: Plasma
           Product: kwin
      Version First 6.8.1
       Reported In:
          Platform: EndeavourOS
                OS: Linux
            Status: REPORTED
          Keywords: regression, wayland-only
          Severity: crash
          Priority: NOR
         Component: compositing
          Assignee: [email protected]
          Reporter: [email protected]
  Target Milestone: ---
             Flags: Intel+

SUMMARY

kwin_wayland crashes with SIGSEGV at address 0x1 in EglContext::popFramebuffer
while a PipeWire screencast (OBS) is running and cursor metadata is requested.
Both OBS and Firebot die right after, because the display connection dies with
the compositor.

STEPS TO REPRODUCE

1. Plasma 6.8.x on Wayland, single Intel Iris Xe (TGL GT2), Mesa 26.2.x.
2. Start OBS with the "Screen Capture (PipeWire)" source. The portal asks for
   cursor metadata (OBS always requests PORTAL_CURSOR_MODE_METADATA; the
   "Show Cursor" UI switch does not change the request).
3. Record/stream for an hour or two. It is race-like, not instant.
4. At some point kwin_wayland segfaults; OBS logs
   "The X11 connection broke (error 1)" / "Error reading events from display:
   Broken pipe" and exits.

EXPECTED RESULT

Compositor keeps running while screencasting.

OBSERVED RESULT

kwin_wayland segfaults:

  kwin_wayland[1659]: segfault at 1 ip 00007f4cf811a704 ... error 4
  in libkwin.so.6.8.1[31a704,...]

Crash happens with 6.8.0 (1 crash in ~3 days of streaming) and 6.8.1
(2 crashes in ~1.5 days). Never with 6.7.5 (0 crashes in ~1 month, same
workload).

Call chain from the core dump / disassembly:

  VsyncSource::vblankOccurred
    -> ScreenCastStream::record
      -> addCursorMetadata
        -> Application::cursorImage
          -> grabCursorOpenGL
            -> ItemTreeView::paint   (nested paint inside a screencast frame)
              -> ItemRendererOpenGL::endFrame
                -> GLFramebuffer::popFramebuffer
                  -> EglContext::popFramebuffer   <-- SIGSEGV

The faulting instruction in libkwin.so.6.8.1 is at ip 0x31a704
(EglContext::popFramebuffer, 0x31a690) and dereferences rax == 0x1:

  mov (%rax),%esi

SUSPECTED MECHANISM

ItemRenderer::beginFrame() pushes the framebuffer onto EglContext::m_fbos,
ItemRenderer::endFrame() pops it. ItemTreeView::paint() returns early when
renderItem() fails:

  renderer->beginFrame(renderTarget, renderViewport);
  renderer->renderBackground(renderTarget, renderViewport, deviceRegion);
  WindowPaintData data;
  if (!renderer->renderItem(renderTarget, renderViewport, m_item, 0,
                            deviceRegion, data, {}, {})) {
      return;                    // no endFrame()
  }
  renderer->endFrame();

(b457dd894, "fix some cases where the return value of renderItem was
ignored", plus the per-RenderDevice item renderer work.) If push and pop then
end up on different EglContext instances (context changed or lost during the
nested cursor paint), popFramebuffer() runs on an empty QStack:

  const auto ret = m_fbos.pop();          // QList::takeLast() on empty list
  if (const auto fbo = currentFramebuffer(); fbo != ret) {

m_fbos.pop() reads data()[-1] and leaves the list size at -1. The next
push_back() writes to data()[-1] and corrupts the QArrayData header;
currentFramebuffer() then returns a garbage GLFramebuffer* whose handle is
the value 1 (the QArrayData ref_/flags of a real allocation), and
fbo->handle() dereferences address 1.

Disassembly used to confirm (libkwin.so.6.8.1, Arch package):
  EglContext::pushFramebuffer    @ 0x31a670
  EglContext::popFramebuffer     @ 0x31a690
  EglContext::currentFramebuffer @ 0x31a370

NOT memory pressure

  * systemd-oomd is inactive
  * no oom-kill entries in the kernel log
  * no memory pressure at the time of the crash
  * earlyoom is running, but its regex would have logged a kill

ADDITIONAL INFORMATION

  Plasma:            6.8.1 (also reproduced on 6.8.0)
  KWin:              kwin 6.8.1-1 / 6.8.1-2 (Arch)
  Qt:                6.12.0-3
  KF6:               6.31.0
  Mesa:              1:26.2.5-1
  Kernel:            7.2.11-zen1-1-zen
  Distro:            Arch Linux
  GPU:               Intel Iris Xe Graphics (TGL GT2), 8086:9a49
  Session:           Wayland, single output
  Screencast client: OBS Studio (PipeWire via xdg-desktop-portal-kde)

Workaround for users: stay on Plasma 6.7.5. Rolling back only kwin does not
work, because kwin 6.7.5 needs the private Qt symbol
_ZN22QWindowSystemInterface36handleTabletEnterLeaveProximityEventEP7QWindowPK15QPointingDeviceb...
which Qt 6.12 renamed (extra QPointer), so the whole Plasma/KF6/Qt stack has
to be rolled back together.

Possibly relevant commits (checked in the 6.8 branch):
  * b457dd894 "fix some cases where the return value of renderItem was
    ignored" (already in 6.8.1, does not prevent the crash)
  * 729d68334 / d075c0c5e "opengl/eglcontext: fail makeCurrent if the
    context is failed" (only in Plasma/6.8 after the 6.8.1 tag)

EglContext::popFramebuffer() still has no guard against an empty m_fbos stack
in current master, so the mechanism above is still reachable.

Attached: journal excerpt, full backtrace with debug symbols, drm_info,
KWin support information.

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

Reply via email to