commit:     aa184cc3e6b9f60fdfcc0ac5f412bf61bc4f4f97
Author:     Andreas Sturmlechner <asturm <AT> gentoo <DOT> org>
AuthorDate: Sat Nov 16 12:49:33 2019 +0000
Commit:     Andreas Sturmlechner <asturm <AT> gentoo <DOT> org>
CommitDate: Wed Nov 20 21:20:42 2019 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=aa184cc3

dev-qt/qtdeclarative: Fix application deadlocks on exit

Package-Manager: Portage-2.3.79, Repoman-2.3.17
Signed-off-by: Andreas Sturmlechner <asturm <AT> gentoo.org>

 ...qtdeclarative-5.13.2-fix-deadlock-on-exit.patch | 112 +++++++++++++++++++++
 .../qtdeclarative/qtdeclarative-5.13.2-r1.ebuild   |   1 +
 2 files changed, 113 insertions(+)

diff --git 
a/dev-qt/qtdeclarative/files/qtdeclarative-5.13.2-fix-deadlock-on-exit.patch 
b/dev-qt/qtdeclarative/files/qtdeclarative-5.13.2-fix-deadlock-on-exit.patch
new file mode 100644
index 00000000000..09c4ad831c5
--- /dev/null
+++ b/dev-qt/qtdeclarative/files/qtdeclarative-5.13.2-fix-deadlock-on-exit.patch
@@ -0,0 +1,112 @@
+From 73ad6e87bbeceea5830ab3a6b3dc66fa99e30f45 Mon Sep 17 00:00:00 2001
+From: Fabian Kosmale <fabian.kosm...@qt.io>
+Date: Mon, 28 Oct 2019 13:41:11 +0100
+Subject: [PATCH] QQuickItem::setParentItem: add child earlier
+
+Calling (de)refWindow can trigger QQuickItem::windowChanged, which in turn
+can call a user defined windowChanged handler. If that signal handler
+were to call setParentItem, we would encounter an inconsistent state:
+The item already has its parent set, but that parent would lack the item
+in its children list (as we would only call refWindow at a later point).
+
+Fixes: QTBUG-79573
+Fixes: QTBUG-73439
+Change-Id: I46adaa54a0521b5cd7f37810b3dd1a206e6a09c6
+Reviewed-by: Simon Hausmann <simon.hausm...@qt.io>
+---
+ src/quick/items/qquickitem.cpp                      | 21 +++++++++++++++++----
+ .../qquickitem/data/setParentInWindowChange.qml     | 12 ++++++++++++
+ tests/auto/quick/qquickitem/tst_qquickitem.cpp      |  8 ++++++++
+ 3 files changed, 37 insertions(+), 4 deletions(-)
+ create mode 100644 
tests/auto/quick/qquickitem/data/setParentInWindowChange.qml
+
+diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
+index 396012e1e67..26f02aeed7f 100644
+--- a/src/quick/items/qquickitem.cpp
++++ b/src/quick/items/qquickitem.cpp
+@@ -2748,22 +2748,35 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
+     }
+ 
+     QQuickWindow *parentWindow = parentItem ? 
QQuickItemPrivate::get(parentItem)->window : nullptr;
++    bool alreadyAddedChild = false;
+     if (d->window == parentWindow) {
+         // Avoid freeing and reallocating resources if the window stays the 
same.
+         d->parentItem = parentItem;
+     } else {
+-        if (d->window)
+-            d->derefWindow();
++        auto oldParentItem = d->parentItem;
+         d->parentItem = parentItem;
++        if (d->parentItem) {
++            QQuickItemPrivate::get(d->parentItem)->addChild(this);
++            alreadyAddedChild = true;
++        }
++        if (d->window) {
++            d->derefWindow();
++            // as we potentially changed d->parentWindow above
++            // the check in derefWindow could not work
++            // thus, we redo it here with the old parent
++            if (!oldParentItem) {
++                
QQuickWindowPrivate::get(d->window)->parentlessItems.remove(this);
++            }
++        }
+         if (parentWindow)
+             d->refWindow(parentWindow);
+     }
+ 
+     d->dirty(QQuickItemPrivate::ParentChanged);
+ 
+-    if (d->parentItem)
++    if (d->parentItem && !alreadyAddedChild)
+         QQuickItemPrivate::get(d->parentItem)->addChild(this);
+-    else if (d->window)
++    else if (d->window && !alreadyAddedChild)
+         QQuickWindowPrivate::get(d->window)->parentlessItems.insert(this);
+ 
+     d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
+diff --git a/tests/auto/quick/qquickitem/data/setParentInWindowChange.qml 
b/tests/auto/quick/qquickitem/data/setParentInWindowChange.qml
+new file mode 100644
+index 00000000000..d68b7adb72a
+--- /dev/null
++++ b/tests/auto/quick/qquickitem/data/setParentInWindowChange.qml
+@@ -0,0 +1,12 @@
++import QtQuick 2.12
++
++Rectangle {
++    width: 800
++    height: 600
++    Item {
++        id: it
++        onWindowChanged: () => it.parent = newParent
++    }
++
++    Item { id: newParent }
++}
+diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp 
b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
+index 7e132f97b67..9ce9766c925 100644
+--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
++++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
+@@ -197,6 +197,8 @@ private slots:
+     void qtBug60123();
+ #endif
+ 
++    void setParentCalledInOnWindowChanged();
++
+ private:
+ 
+     enum PaintOrderOp {
+@@ -2145,6 +2147,12 @@ void tst_qquickitem::qtBug60123()
+     activateWindowAndTestPress(&window);
+ }
+ #endif
++void tst_qquickitem::setParentCalledInOnWindowChanged()
++{
++    QQuickView view;
++    view.setSource(testFileUrl("setParentInWindowChange.qml"));
++    QVERIFY(ensureFocus(&view)); // should not crash
++}
+ 
+ QTEST_MAIN(tst_qquickitem)
+ 
+-- 
+2.16.3

diff --git a/dev-qt/qtdeclarative/qtdeclarative-5.13.2-r1.ebuild 
b/dev-qt/qtdeclarative/qtdeclarative-5.13.2-r1.ebuild
index 90abd95d64f..24def17bec0 100644
--- a/dev-qt/qtdeclarative/qtdeclarative-5.13.2-r1.ebuild
+++ b/dev-qt/qtdeclarative/qtdeclarative-5.13.2-r1.ebuild
@@ -29,6 +29,7 @@ RDEPEND="${DEPEND}
 
 PATCHES=(
        "${FILESDIR}/${P}-read-QQmlPropertyMap-correctly.patch" # QTBUG-79614
+       "${FILESDIR}/${P}-fix-deadlock-on-exit.patch" # QTBUG-79573
 )
 
 src_prepare() {

Reply via email to