[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#983597: Segfault in libqt5quick5.so: QQuickItemLayer::~QQuickItemLayer()



Control: tag -1 + patch

The attached patch fixed the crashes of Linphone for me.

Regards.
Description: Don't update visibility etc. recursively in setParentItem() when called within a dtor
 Debian bugs: 996910 983597
Last-Update: 2022-10-10
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -2330,13 +2330,13 @@
     if (d->windowRefCount > 1)
         d->windowRefCount = 1; // Make sure window is set to null in next call to derefWindow().
     if (d->parentItem)
-        setParentItem(nullptr);
+        _setParentItem(nullptr, true);
     else if (d->window)
         d->derefWindow();
 
     // XXX todo - optimize
     while (!d->childItems.isEmpty())
-        d->childItems.constFirst()->setParentItem(nullptr);
+        d->childItems.constFirst()->_setParentItem(nullptr, true);
 
     if (!d->changeListeners.isEmpty()) {
         const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732)
@@ -2643,6 +2643,11 @@
 
 void QQuickItem::setParentItem(QQuickItem *parentItem)
 {
+    _setParentItem(parentItem, false);
+}
+
+void QQuickItem::_setParentItem(QQuickItem *parentItem, bool in_dtor)
+{
     Q_D(QQuickItem);
     if (parentItem == d->parentItem)
         return;
@@ -2729,8 +2734,14 @@
     else if (d->window && !alreadyAddedChild)
         QQuickWindowPrivate::get(d->window)->parentlessItems.insert(this);
 
-    d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
-    d->setEffectiveEnableRecur(nullptr, d->calcEffectiveEnable());
+    // Updating recursively is superfluous if the object is being
+    // destroyed anyway, and also unsafe as doing it would involve
+    // virtual functions like accessibleRole() among maybe others
+    // (QTBUG 84858).
+    if (!in_dtor) {
+      d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
+      d->setEffectiveEnableRecur(nullptr, d->calcEffectiveEnable());
+    }
 
     if (d->parentItem) {
         if (!scopeFocusedItem) {
--- a/src/quick/items/qquickitem.h
+++ b/src/quick/items/qquickitem.h
@@ -458,6 +458,8 @@
     Q_PRIVATE_SLOT(d_func(), void _q_resourceObjectDeleted(QObject *))
     Q_PRIVATE_SLOT(d_func(), quint64 _q_createJSWrapper(QV4::ExecutionEngine *))
 
+    __attribute__((visibility("hidden"))) void _setParentItem(QQuickItem *parent, bool in_dtor);
+
     friend class QQuickEventPoint;
     friend class QQuickWindow;
     friend class QQuickWindowPrivate;

Reply to: