diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2014-06-24 16:09:29 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2014-06-24 17:09:35 +0200 |
commit | 9f22767784dc859283b321c47636ea708eef3bfe (patch) | |
tree | e47f68fb1943d913c124da2c48f0195e38345649 /tests/auto | |
parent | cf93acbee66db96a6f7fab8607432b70ec5c0437 (diff) |
Fix crash in QQmlDelegateModel during destruction phase
It has been reported multiple times (with different back traces) that
the QQmlDelegateModel tries to access a dangling QQmlContext pointer.
The scenarios for reaching this point differ slightly, one such scenario
is very late model activity during the scene destruction. The provided
test-case simulates that and the provided patch guards the QQmlContext
in a QPointer.
Task-number: QTBUG-39780
Change-Id: I594ee4918cd1b78c5db5c164314e85e9eea99fbd
Reviewed-by: Alan Alpert (Personal) <416365416c@gmail.com>
Diffstat (limited to 'tests/auto')
-rw-r--r-- | tests/auto/quick/qquickrepeater/data/invalidContextCrash.qml | 7 | ||||
-rw-r--r-- | tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp | 43 |
2 files changed, 50 insertions, 0 deletions
diff --git a/tests/auto/quick/qquickrepeater/data/invalidContextCrash.qml b/tests/auto/quick/qquickrepeater/data/invalidContextCrash.qml new file mode 100644 index 0000000000..4a822cf25a --- /dev/null +++ b/tests/auto/quick/qquickrepeater/data/invalidContextCrash.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 +Item { + Repeater { + model: badModel + delegate: Item {} + } +} diff --git a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp index 9fb76f9584..2dc5a65d7d 100644 --- a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp +++ b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp @@ -79,6 +79,7 @@ private slots: void initParent(); void dynamicModelCrash(); void visualItemModelCrash(); + void invalidContextCrash(); }; class TestObject : public QObject @@ -744,6 +745,48 @@ void tst_QQuickRepeater::visualItemModelCrash() delete window; } +class BadModel : public QAbstractListModel +{ +public: + ~BadModel() + { + beginResetModel(); + endResetModel(); + } + + QVariant data(const QModelIndex &, int) const { return QVariant(); } + int rowCount(const QModelIndex &) const { return 0; } +}; + + +void tst_QQuickRepeater::invalidContextCrash() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("invalidContextCrash.qml")); + + BadModel* model = new BadModel; + engine.rootContext()->setContextProperty("badModel", model); + + QScopedPointer<QObject> root(component.create()); + QCOMPARE(root->children().count(), 1); + QObject *repeater = root->children().first(); + + // Make sure the model comes first in the child list, so it will be + // deleted first and then the repeater. During deletion the QML context + // has been deleted already and is invalid. + model->setParent(root.data()); + repeater->setParent(0); + repeater->setParent(root.data()); + + QCOMPARE(root->children().count(), 2); + QVERIFY(root->children().at(0) == model); + QVERIFY(root->children().at(1) == repeater); + + // Delete the root object, which will invalidate/delete the QML context + // and then delete the child QObjects, which may try to access the context. + root.reset(0); +} + QTEST_MAIN(tst_QQuickRepeater) #include "tst_qquickrepeater.moc" |