Avoid race condition in QQmlEngine on shutdown.
authorGunnar Sletta <gunnar.sletta@jollamobile.com>
Tue, 1 Jul 2014 12:48:07 +0000 (14:48 +0200)
committerGunnar Sletta <gunnar.sletta@jollamobile.com>
Fri, 4 Jul 2014 06:44:06 +0000 (08:44 +0200)
The QQmlTypeLoader was deleted (and its thread shut down) when
the QQmlEnginePrivate was destroyed. However, the QQmlTypeLoader
runs a thread which would happiliy make calls on the engine and
its managed data. Fix this by stopping the QQmlTypeLoader's
thread right away in QQmlEngine.

Task-number: QTBUG-39905
Change-Id: Ida8e95d083f79237c74b036fd3521133a9fa4ac7
Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
src/qml/qml/qqmlengine.cpp
src/qml/qml/qqmltypeloader.cpp
src/qml/qml/qqmltypeloader_p.h

index 17e5c55..46fc329 100644 (file)
@@ -904,6 +904,8 @@ QQmlEngine::~QQmlEngine()
     if (d->isDebugging)
         QQmlDebugServer::instance()->removeEngine(this);
 
+    d->typeLoader.invalidate();
+
     // Emit onDestruction signals for the root context before
     // we destroy the contexts, engine, Singleton Types etc. that
     // may be required to handle the destruction signal.
index 1afc5bb..c5a4d65 100644 (file)
@@ -897,11 +897,20 @@ QQmlDataLoader::QQmlDataLoader(QQmlEngine *engine)
 /*! \internal */
 QQmlDataLoader::~QQmlDataLoader()
 {
+    invalidate();
+}
+
+void QQmlDataLoader::invalidate()
+{
     for (NetworkReplies::Iterator iter = m_networkReplies.begin(); iter != m_networkReplies.end(); ++iter)
         (*iter)->release();
+    m_networkReplies.clear();
 
-    shutdownThread();
-    delete m_thread;
+    if (m_thread) {
+        shutdownThread();
+        delete m_thread;
+        m_thread = 0;
+    }
 }
 
 void QQmlDataLoader::lock()
@@ -1228,7 +1237,7 @@ void QQmlDataLoader::setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::Cached
 
 void QQmlDataLoader::shutdownThread()
 {
-    if (!m_thread->isShutdown())
+    if (m_thread && !m_thread->isShutdown())
         m_thread->shutdown();
 }
 
index b09ac15..3d0b77e 100644 (file)
@@ -233,6 +233,7 @@ public:
 
     QQmlEngine *engine() const;
     void initializeEngine(QQmlExtensionInterface *, const char *);
+    void invalidate();
 
 protected:
     void shutdownThread();