diff options
author | Albert Astals Cid <albert.astals@canonical.com> | 2013-04-30 14:03:03 -0700 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-05-03 19:11:18 +0200 |
commit | 9d6cd72353e4862592c016951810abf9a7ab8079 (patch) | |
tree | 76cf626c81756ff5e11694b2b636b7d8f67c765b | |
parent | e1a8762e9c39133cb3d1d9c2cdf51003f75d6c05 (diff) |
Fix crash in QQmlDelegateModel
It can happen that when the QQmlDelegateModel goes away some of the
QQmlDelegateModelItem from d->m_cache are still incubating, this
means that isReferenced() will return true and we will not delete them.
This also means that when these QQDMIncubationTask finish they may end
up calling QQDMIncubationTask::statusChanged which will try to access
the delegate model that is already gone.
This commit makes sure we set vdm to 0 in these orphaned
QQDMIncubationTask so in QQDMIncubationTask::statusChanged we know
no one cares about us anymore and don't reference the already gone
delegate model
Task-number: QTBUG-30928
Change-Id: Ief6176cec151d861dad09ca2498ca27e17ee6385
Reviewed-by: Andrew den Exter <andrew.den.exter@qinetic.com.au>
-rw-r--r-- | src/qml/types/qqmldelegatemodel.cpp | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 16572c44dd..5e36be1eca 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -230,6 +230,8 @@ QQmlDelegateModel::~QQmlDelegateModel() cacheItem->objectRef = 0; if (!cacheItem->isReferenced()) delete cacheItem; + else if (cacheItem->incubationTask) + cacheItem->incubationTask->vdm = 0; } } @@ -780,7 +782,21 @@ void QQmlDelegateModelPrivate::emitDestroyingPackage(QQuickPackage *package) void QQDMIncubationTask::statusChanged(Status status) { - vdm->incubatorStatusChanged(this, status); + if (vdm) { + vdm->incubatorStatusChanged(this, status); + } else if (status == QQmlIncubator::Ready || status == QQmlIncubator::Error) { + Q_ASSERT(incubating); + // The model was deleted from under our feet, cleanup ourselves + if (incubating->object) { + delete incubating->object; + + incubating->object = 0; + incubating->contextData->destroy(); + incubating->contextData = 0; + } + incubating->scriptRef = 0; + incubating->deleteLater(); + } } void QQmlDelegateModelPrivate::releaseIncubator(QQDMIncubationTask *incubationTask) @@ -1766,8 +1782,12 @@ QQmlDelegateModelItem::~QQmlDelegateModelItem() Q_ASSERT(objectRef == 0); Q_ASSERT(!object); - if (incubationTask && metaType->model) - QQmlDelegateModelPrivate::get(metaType->model)->releaseIncubator(incubationTask); + if (incubationTask) { + if (metaType->model) + QQmlDelegateModelPrivate::get(metaType->model)->releaseIncubator(incubationTask); + else + delete incubationTask; + } metaType->release(); |