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

            Bug ID: 443317
           Summary: plasmashell crashes after toggle the "Show Background"
                    on applet
           Product: plasmashell
           Version: 5.22.4
          Platform: unspecified
                OS: Linux
            Status: REPORTED
          Severity: normal
          Priority: NOR
         Component: Multi-screen support
          Assignee: aleix...@kde.org
          Reporter: nullptrn...@basealt.ru
                CC: plasma-b...@kde.org
  Target Milestone: 1.0

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?).

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

Reply via email to