Bug 443317

Summary: plasmashell crashes after toggle the "Show Background" on applet
Product: [Plasma] plasmashell Reporter: Slava Aseev <nullptrnine>
Component: generic-multiscreenAssignee: Aleix Pol <aleixpol>
Status: RESOLVED WORKSFORME    
Severity: crash CC: nate, nullptrnine, plasma-bugs-null
Priority: NOR    
Version First Reported In: 5.22.4   
Target Milestone: 1.0   
Platform: unspecified   
OS: Linux   
Latest Commit: Version Fixed/Implemented In:
Sentry Crash Report:
Attachments: plasmashell segfault

Description Slava Aseev 2021-10-04 18:31:00 UTC
SUMMARY
Reproduces with any applet which have the `PlasmaCore.Types.ShadowBackground` in `backgroundHints` at least one time after launch.

STEPS TO REPRODUCE
1. Add a second display
2. Add an applet which can have the `ShadowBackground` in `backgroundHints` of the root `Item` (possibly any applet with the `PlasmaCore.Types.ConfigurableBackground` background hint, e.g. digital-clock, fuzzy-clock, timer, weather, etc.)
3. Turn off the "Show Background" toggle (if it is enabled) and move the applet to another display
(pay attention for glitches/garbage in place of an applet's appearance).
4. Toggle the "Show Background" again (maybe many times) and enjoy the plasmashell crash.

OBSERVED RESULT
The crash.

EXPECTED RESULT
No crash.

SOFTWARE/OS VERSIONS
Tested on X11
KDE Plasma Version: 5.11.4/5.22.4
Qt Version: 5.15.2


The crash occurs due to some asserts in `qtdeclarative/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp`
or due to segfault (if asserts are not included into lib). Backtrace/debugging scenegraph's sources cannot say anything about a real conditions of the crash (only say that something in the scenegraph definitely broken at the moment of the crash).

After the third step (in "Steps to reproduce") plasmashell prints something interesting to stderr/stdout: 

> QQuickItem: Cannot use same item on different windows at the same time.
> ShaderEffectSource: sourceItem and ShaderEffectSource must both be children of the same window.

The first warning may be found in the qtdeclarative/src/quick/items/qquickitem.cpp:

void QQuickItemPrivate::refWindow(QQuickWindow *c)
{
    // An item needs a window if it is referenced by another item which has a window.
    // Typically the item is referenced by a parent, but can also be referenced by a
    // ShaderEffect or ShaderEffectSource. 'windowRefCount' counts how many items with
    // a window is referencing this item. When the reference count goes from zero to one,
    // or one to zero, the window of this item is updated and propagated to the children.
    // As long as the reference count stays above zero, the window is unchanged.
    // refWindow() increments the reference count.
    // derefWindow() decrements the reference count.

    Q_Q(QQuickItem);
    Q_ASSERT((window != nullptr) == (windowRefCount > 0));
    Q_ASSERT(c);
    if (++windowRefCount > 1) {
        if (c != window)
            qWarning("QQuickItem: Cannot use same item on different windows at the same time.");
        return; // Window already set.
    }


The possible reason of the crash becomes clear with help of this comment. While the applet is moving to another display, it removes the reference to the old `parentItem` (and its window) and starts to reference the other `parentItem`/window (so the applet's item do `unrefWindow(); refWindow(newWindow);`). It works while the applet's item is referenced only by `parentItem`, but fails in case of `ShaderEffect`/`ShaderEffectSource` which may also referencing this item (this is our case, we got item with `ShadowBackground` hint). The early return under these circumstances leads to buggy behavior: glitches instead of applet's elements and eventually the crash (somewhere in `qsgbatchrenderer.cpp`).

This patch proves the assumptions:

diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 67c4611d9e..f42484912b 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -2696,8 +2696,14 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
                 QQuickWindowPrivate::get(d->window)->parentlessItems.remove(this);
             }
         }
-        if (parentWindow)
+        if (parentWindow) {
+            if (d->windowRefCount > 0 && d->window != parentWindow) {
+                qWarning() << "WORKAROUND";
+                d->windowRefCount = 1;
+                d->derefWindow();
+            }
             d->refWindow(parentWindow);
+        }
     }
 
     d->dirty(QQuickItemPrivate::ParentChanged);

This handles the problem situation and calls derefWindow() before refWindow(). There will be no more crashes after this patch, but I doubt this solves the problem correctly.

I don't know exactly what is to blame for this bug (is this the QtQuick flaw or is Plasma doing something wrong?).
Comment 1 Slava Aseev 2021-10-04 18:37:42 UTC
> KDE Plasma Version: 5.11.4/5.22.4
5.21.4/5.22.4 (typo)
Comment 2 Nate Graham 2021-10-04 22:34:14 UTC
Nice investigation!
Comment 3 Nate Graham 2023-04-21 14:53:55 UTC
A lot of multimonitor fixes went into Plasma 5.27; any chance you could check to see if this is still an issue in Plasma 5.27.4 or newer?
Comment 4 Nate Graham 2023-04-27 16:36:40 UTC
Gentle ping.
Comment 5 ptrnine 2023-05-10 15:19:16 UTC
(In reply to Nate Graham from comment #3)
> A lot of multimonitor fixes went into Plasma 5.27; any chance you could
> check to see if this is still an issue in Plasma 5.27.4 or newer?

Sorry for delay.

This is still reproduced on neon-testing-20230509-0250.iso md5: 5262331597cbabf875d42b29a11f8ccb.
Comment 6 ptrnine 2023-05-10 15:20:02 UTC
Created attachment 158831 [details]
plasmashell segfault
Comment 7 ptrnine 2023-05-10 15:42:46 UTC
Also that patch seems to work fine: https://git.altlinux.org/gears/q/qt5-declarative.git?p=qt5-declarative.git;a=blob;f=alt-multiscreen-applet-sigsegv-fix.patch;h=f62b0a5c11bd7d79dfd73dab24322fbf7f738241;hb=7f7947e0845050d1715d140f5186bc7dd453cfe6

Except that the text on the applet is sometimes missing after moving the applet :D
But this is better than segfault IMO.
Comment 8 Nate Graham 2023-05-13 22:43:06 UTC
Was this ever submitted upstream?
Comment 9 Bug Janitor Service 2023-05-28 03:45:19 UTC
Dear Bug Submitter,

This bug has been in NEEDSINFO status with no change for at least
15 days. Please provide the requested information as soon as
possible and set the bug status as REPORTED. Due to regular bug
tracker maintenance, if the bug is still in NEEDSINFO status with
no change in 30 days the bug will be closed as RESOLVED > WORKSFORME
due to lack of needed information.

For more information about our bug triaging procedures please read the
wiki located here:
https://community.kde.org/Guidelines_and_HOWTOs/Bug_triaging

If you have already provided the requested information, please
mark the bug as REPORTED so that the KDE team knows that the bug is
ready to be confirmed.

Thank you for helping us make KDE software even better for everyone!
Comment 10 Bug Janitor Service 2023-06-12 03:45:27 UTC
This bug has been in NEEDSINFO status with no change for at least
30 days. The bug is now closed as RESOLVED > WORKSFORME
due to lack of needed information.

For more information about our bug triaging procedures please read the
wiki located here:
https://community.kde.org/Guidelines_and_HOWTOs/Bug_triaging

Thank you for helping us make KDE software even better for everyone!