diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2016-07-25 16:07:16 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2016-08-05 18:55:39 +0000 |
commit | 68bfc9332cd65c1eb88d1ec87164447b0db43237 (patch) | |
tree | c668872cf02f9671fd25c64e916733e8b9ccb93d /src | |
parent | ff645deb25c18eeae3d248a6a60bc2954129ee28 (diff) |
Fix crash with Component.onDestruction
A call to a handler of Component.onDestruction may end up causing WeakValues
such as QQmlData::jsWrapper to be set again, even though they've been set to
undefined in an earlier iteration of the loop that walks through the weak
references. That in turn may result in invalid object references to objects
that are scheduled for destruction by the collector.
So after calling all destroy handlers for QObjects, reset all of the weak
values again.
Task-number: QTBUG-54939
Change-Id: I00ebabb76274e296fb1bd90d8d3e21dbbb920b57
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/memory/qv4mm.cpp | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 7ab6d15041..4592dd5c9b 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -428,7 +428,7 @@ void MemoryManager::sweep(bool lastSweep) Managed *m = (*it).as<Managed>(); if (m->markBit()) continue; - // we need to call detroyObject on qobjectwrappers now, so that they can emit the destroyed + // we need to call destroyObject on qobjectwrappers now, so that they can emit the destroyed // signal before we start sweeping the heap if (QObjectWrapper *qobjectWrapper = (*it).as<QObjectWrapper>()) qobjectWrapper->destroyObject(lastSweep); @@ -436,6 +436,17 @@ void MemoryManager::sweep(bool lastSweep) (*it) = Primitive::undefinedValue(); } + // onDestruction handlers may have accessed other QObject wrappers and reset their value, so ensure + // that they are all set to undefined. + for (PersistentValueStorage::Iterator it = m_weakValues->begin(); it != m_weakValues->end(); ++it) { + if (!(*it).isManaged()) + continue; + Managed *m = (*it).as<Managed>(); + if (m->markBit()) + continue; + (*it) = Primitive::undefinedValue(); + } + // Now it is time to free QV4::QObjectWrapper Value, we must check the Value's tag to make sure its object has been destroyed const int pendingCount = m_pendingFreedObjectWrapperValue.count(); if (pendingCount) { |