The symptom, and the wrong first assumption

Every so often my desktop would vanish. Not freeze — vanish. Screen goes black, SDDM's login prompt appears, and everything I had open is gone. Konsole sessions, the editor, mail, the browser tabs I had not got round to reading. A full session teardown with no warning and no prompt.

The obvious conclusion is the one I reached: Plasma is crashing. That is certainly what it looks like from the chair. It is also what the search results tell you if you type the symptom into a search engine — there is an enormous amount of writing about Plasma instability, and it is very easy to spend an evening reading about plasmashell restarts and QML errors.

I had one advantage over my own instinct, which is that I had just come off a project where I got the framing wrong for an entire day and only escaped by running a diagnostic command I should have run first. So this time I went to the logs before I went to the search engine.


Reading the logs in the right order

The first thing worth knowing is that when a session dies, everything in it dies at once, and they all say so. Here is what the journal looked like at the moment of a crash:

11:33:37 kactivitymanagerd: The X11 connection broke (error 1). Did the X11 server die?
11:33:37 org_kde_powerdevil: The X11 connection broke (error 1). Did the X11 server die?
11:33:37 ksmserver:         The X11 connection broke (error 1). Did the X11 server die?
11:33:37 kmail:             The X11 connection broke (error 1). Did the X11 server die?
11:33:37 plasmashell:       The X11 connection broke (error 1). Did the X11 server die?
11:33:37 kwin_x11:          The X11 connection broke: I/O error (code 1)
11:33:37 konsole:           The X11 connection broke (error 1). Did the X11 server die?
11:33:37 plasmashell:       ICE default IO error handler doing an exit(), pid = 106376, errno = 32

Fourteen processes, one second, all reporting the same thing. That pattern is the tell. If plasmashell had crashed, plasmashell would be the one dying and kwin_x11 would still be up. Instead every X client in the session hits an I/O error on its connection simultaneously, which only happens when the thing on the other end of the socket — the X server — goes away.

The message even asks the question outright: Did the X11 server die? Yes. It did.

This is also why nothing useful shows up in coredumpctl for Plasma. I checked — plenty of dumps from my own .NET builds, from kmail, from ksecretd, but nothing from plasmashell or kwin. They did not crash. They exited, cleanly and deliberately, because their display went away. ICE default IO error handler doing an exit() is an orderly shutdown, not a fault.

So: wrong log file. The X server writes its own.


The actual crash

/var/log/Xorg.0.log.old — the .old matters, because a crash means a restart and a restart rotates the log:

[ 4554.012] (WW) modeset(0): flip queue retry
[ 4554.012] (EE)
[ 4554.012] (EE) Backtrace:
[ 4554.013] (EE) 0: /usr/libexec/Xorg (?+0x0)
[ 4554.014] (EE) 1: /lib64/libc.so.6 (?+0x0)
[ 4554.015] (EE) 2: /usr/lib64/xorg/modules/drivers/modesetting_drv.so (?+0x0)
[ 4554.015] (EE) 3: /lib64/libdrm.so.2 (drmHandleEvent+0xba)
[ 4554.016] (EE) 4: /usr/libexec/Xorg (?+0x0)
[ 4554.016] (EE) 5: /usr/libexec/Xorg (WaitForSomething+0x18c)
[ 4554.018] (EE) Segmentation fault at address 0x562aacbcc9f3
[ 4554.018] (EE) Caught signal 11 (Segmentation fault). Server aborting

Three things in there are worth more than the rest.

The timestamps. flip queue retry and the start of the backtrace are both at 4554.012. Same millisecond. That warning is not background noise that happened to precede a crash — the crash is inside the code path that emitted it.

Frames 5 → 3 → 2. Read them bottom-up as a call chain: the X server is in WaitForSomething, its main event loop, waiting on file descriptors. Something arrives on the DRM fd, so it calls into libdrm's drmHandleEvent, whose entire job is to read kernel events and dispatch them to callbacks the driver registered earlier. It dispatches into modesetting_drv.so, and that callback segfaults.

A callback invoked from an event queue, crashing on a pointer — that shape says use-after-free before you know anything else about the code. Something was queued, something freed the thing it pointed at, and the event arrived anyway.

No (EE) from the kernel. I checked journalctl -k around the crash for i915 or DRM complaints. Nothing. The kernel was perfectly happy. This is a userspace bug in the X driver.

And it was reproducible. I had two crashes logged, a day apart, with byte-for-byte identical structure — same warning, same frames, same signal.


What actually triggers it

Two data points were not enough to see the pattern. The third one was, because I caused it myself and noticed what I had done.

The machine had been idle for a few minutes. Plasma's idle configuration had done its thing: lock the session, blank the monitor. I came back and touched the touchpad to wake it up, expecting the unlock prompt.

I got SDDM instead.

That is the reproducer: the crash fires on DPMS wake-up. Not on lock, not on blank — on the transition back. The display comes out of power-save, the driver starts pushing frames again, and the page-flip machinery falls over.

It is worth noting how much this narrows the problem. "Plasma crashes randomly" is not something you can investigate. "The X server segfaults in the page-flip completion callback when the display returns from DPMS off" is a sentence with maybe two possible causes in it.


Why this code exists on my machine at all

Here is where it got interesting, and where the answer turned out to be about packaging rather than about graphics.

flip queue retry is a distinctive string, so I went looking for it in the X server source. It lives in hw/xfree86/drivers/modesetting/pageflip.c, in the retry loop of do_queue_flip_on_crtc(). My machine runs x11-server-xorg-21.1.24, so I fetched that file from the stable branch and from the development branch to compare:

$ grep -c -i tearfree pageflip.c          # server-21.1-branch
0
$ grep -c -i tearfree drmmode_display.c   # server-21.1-branch
0

$ grep -c -i tearfree pageflip.c          # master
39
$ grep -c -i tearfree drmmode_display.c   # master
13

Upstream's 21.1 stable branch has no TearFree code whatsoever. Not a reduced version, not a disabled version — it does not exist there. TearFree is a development-branch feature.

My Xorg log, however, says this:

[ 4554.667] (II) modeset(0): Atomic modesetting disabled
[ 4554.667] (II) modeset(0): TearFree: enabled

And the installed driver binary is full of it:

$ strings /usr/lib64/xorg/modules/drivers/modesetting_drv.so | grep -i tearfree
TearFree cannot synchronize PRIME; use 'PRIME Synchronization' instead
TearFree requires either universal planes, or setting 'Option "PageFlip" "off"'
TearFree requires Glamor acceleration
TearFree flip failed, rendering frame without TearFree
TearFree: enabled

So the feature is present in a release that upstream does not ship it in. The package changelog explains itself in one line:

$ rpm -q --changelog x11-server-xorg | grep -i tearfree
- Merge patchset from master upstream to enable screen Tearfree.

From 21.1.20-2.mga10, last October. Mageia backported the TearFree patchset from the development branch onto the stable branch, and enabled it by default.

I want to be careful about the tone here, because this is a genuinely reasonable thing for a distribution to do and I am not interested in dunking on a volunteer maintainer. TearFree eliminates tearing without a compositor, it is a real improvement, and it had presumably been soaking upstream for a while. The xorg-server 21.1 branch is in deep maintenance and gets essentially nothing but security fixes, so if you want any display improvement at all on X11 in 2026, backporting is the only mechanism available. That is the actual situation X11 is in.

But a backport takes code written against one set of surrounding assumptions and drops it into a different one, and the bugs that produces are exactly the kind that do not show up in testing: timing-dependent, hardware-dependent, and triggered by a transition — DPMS wake — that nobody thinks to exercise deliberately.

You can see the shape of what goes wrong by reading the retry loop in the development branch, which is TearFree-aware:

while (drmmode_crtc_flip(crtc, fb_id, x, y, flags, (void *)(long)seq)) {
    if (ms_flush_drm_events(screen) <= 0) {
        /* The failure could be caused by a pending TearFree flip, in which
         * case we should wait until there's a new event and try again. */
        if (!trf->flip_seq || ms_flush_drm_events_timeout(screen, -1) < 0) {
            ms_drm_abort_seq(crtc->scrn, seq);
            return TRUE;
        }
    }
    xf86DrvMsg(crtc->scrn->scrnIndex, X_WARNING, "flip queue retry\n");
}

That code knows about trf->flip_seq — a TearFree flip that is already in flight — and treats a flush failure differently depending on whether one exists. The bookkeeping around which flips are outstanding, and who owns the data structure each queued flip points at, is precisely the part that has to be right when the display is being torn down and brought back by DPMS. Get the ordering wrong and a queued flip's flipdata is freed while the kernel still has an event for it in the pipe. The event arrives, drmHandleEvent dispatches it, the callback reads through a dangling pointer, and you are looking at my backtrace.

One more thing from the log matters:

(II) modeset(0): Atomic modesetting disabled

That is upstream's default — the Atomic option is off unless you ask for it. With atomic off, flips go through the legacy drmModePageFlip path rather than drmModeAtomicCommit. So TearFree, backported onto a stable branch, running on the legacy flip path, on a hybrid-GPU laptop, across a DPMS transition. Four conditions, all of them true on this machine, and probably not all true on the machine where the backport was tested.


Somebody else already found it

Before deciding what to do I wanted to know whether this was known. That turned out to be harder than it should be: the freedesktop GitLab is behind proof-of-work bot protection, which blocks scripted access to both the web UI and the REST API. The Mageia bug tracker has a browser check of its own. Neither is unreasonable given what crawler traffic looks like now, but it does mean the old habit of grepping bug trackers from a terminal no longer works, and I ended up searching through a mirror of the same code base instead.

In the X11Libre fork's tracker — same modesetting driver, same code — there is issue #3432, "Xorg Server crash at 'flip queue retry'". Labels: hybrid-gpu-setup, intel-gpu, nvidia-gpu. The reporter has an Intel + NVIDIA laptop where X is not running on the NVIDIA card, and describes the trigger as:

the second i try to move a mouse or do anything which for removing dpms xserver crashes and i get thrown to my dm

Same hardware class, same trigger, same crash, same outcome. It is open, with no maintainer response and no patch.

There is also #1200, where the same flip queue retry warning floods the log on another hybrid Intel+NVIDIA machine, causing rendering freezes rather than a crash. Closed as not planned. The reporter notes the problem does not occur under Wayland.

So: known, unfixed, and specific to roughly the configuration I have. There is no patch to cherry-pick. That leaves mitigation.

One near-miss worth being careful about

Searching Mageia's own tracker turns up bug 29405, "Can't record my desktop in KDE Plasma", which mentions TearFree and Plasma and is still open. It is not this bug, and I want to be explicit about that rather than quietly cite it: different driver (the intel DDX, not modesetting), different symptom (screen recording captures the wrong frames — nothing crashes at all), different hardware era, and there TearFree is proposed as a workaround rather than being the cause.

The reason I looked twice is one line in its comment 10. Having suggested Option "TearFree" "true" on the intel DDX as a fix for the recording problem, the reporter comes back with:

But it stuck on suspend and resume

Two different DDX drivers, two independently written TearFree implementations, and both of them turn out to have trouble across a display power-management transition. That is not evidence about my crash — it is a different codebase and I have not read it. But it does suggest that "what happens to the flip bookkeeping when the display is torn down and brought back" is a recurring soft spot in this kind of code, which makes it a reasonable first place to look rather than a surprising one.

I mention it mostly as a caution. When you are deep in an investigation and find an old bug with three of your keywords in it, the pull to declare it a match is strong, and matching on keywords rather than mechanism is how you end up filing a duplicate of something unrelated and wasting a maintainer's afternoon.


The fix

The bug is in a backported feature. The most targeted thing I can do is switch that feature off, which removes the entire code path from the picture without touching anything else:

# /etc/X11/xorg.conf.d/20-modesetting-tearfree.conf
Section "Device"
    Identifier "Intel Graphics"
    Driver     "modesetting"
    Option     "TearFree" "false"
EndSection

Log out and back in — this needs a fresh X server, not just a Plasma restart — and confirm it took:

$ grep TearFree /var/log/Xorg.0.log
(II) modeset(0): TearFree: disabled

The cost is that tearing may come back in video playback and fullscreen content. On a Plasma desktop, KWin composites by default and handles that itself, so in practice I expect to notice very little. I would rather have occasional tearing than lose a session.

Two other options I considered and did not take:

Switch to Wayland. Both upstream reports say the problem does not occur there, and it cannot occur there — KWin on Wayland never runs this code. Plasma 6.5.5 and kwin-wayland are already installed on this machine. This is probably where I end up eventually; I did not do it today because I wanted to verify the diagnosis by fixing the specific thing I had identified, and changing display servers changes too many variables at once to prove anything.

Turn on atomic modesetting (Option "Atomic" "on"), which routes flips through drmModeAtomicCommit instead of the legacy path. That might sidestep the race. It might also be a different set of bugs — atomic is off by default upstream for reasons I have not investigated. Worth testing separately, not together with the TearFree change, or I will not know which one did what.


What I take from it

The whole investigation was about forty minutes once I stopped reading about Plasma and started reading the X server's log. Everything I needed was in two files that were already on disk.

The thing I would generalise is about layer attribution. The crash presented as a desktop environment problem, and the desktop environment was the most visible thing involved, and it was completely innocent. Every symptom I could see — session gone, apps gone, back to the login screen — was Plasma correctly handling a catastrophe that happened underneath it. ICE default IO error handler doing an exit() is not a crash message. It is a well-behaved program saying my display is gone, there is nothing further I can do.

The second thing is that rpm -q --changelog deserves to be a reflex. I have spent years comparing installed versions against upstream release notes and assuming a version number tells me what code I am running. It does not. A distribution package is upstream plus a patch stack, and on a stable branch the patch stack is where the interesting divergence lives. The single most useful command in this whole investigation was the one that printed a line of changelog from last October explaining why my X server contained a feature that its own version number says it should not have.


Mageia 10 (Cauldron), kernel 6.18.44, Plasma 6.5.5 on X11, x11-server-xorg 21.1.24-1.mga10. MSI Stealth 15M B12UE — Intel Alder Lake-P Iris Xe driving the display, NVIDIA RTX 3060 Mobile present but not scanning out. Filed against x11-server as Mageia bug 36308, with the backport, both backtraces, and X11Libre#3432.