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: