From f55ecc080d0c5eca4e65a235c63ab13867c86874 Mon Sep 17 00:00:00 2001
From: Bea Lam <bea.lam@nokia.com>
Date: Thu, 11 Aug 2011 13:11:52 +1000
Subject: Fix race condition in processJobs()

Don't modify list of running jobs when a job is aborted since the job
may have just started. Wait till the next time processJobs() is invoked
for a new job and discard the aborted job at that time.

Regression from 422f4e8ec53b917fad09a3e671fd93048dde72ed

Task-number: QTBUG-20841
---
 src/declarative/util/qdeclarativexmllistmodel.cpp | 31 ++++++++---------------
 1 file changed, 11 insertions(+), 20 deletions(-)

diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp
index 5236757..77fc7de 100644
--- a/src/declarative/util/qdeclarativexmllistmodel.cpp
+++ b/src/declarative/util/qdeclarativexmllistmodel.cpp
@@ -289,11 +289,8 @@ int QDeclarativeXmlQueryEngine::doQuery(QString query, QString namespaces, QByte
 void QDeclarativeXmlQueryEngine::abort(int id)
 {
     QMutexLocker ml(&m_mutex);
-    if (id != -1) {
+    if (id != -1)
         m_cancelledJobs.insert(id);
-        if (m_threadObject)
-            m_threadObject->processJobs();
-    }
 }
 
 void QDeclarativeXmlQueryEngine::run()
@@ -314,25 +311,19 @@ void QDeclarativeXmlQueryEngine::processJobs()
     QMutexLocker locker(&m_mutex);
 
     while (true) {
-        if (m_cancelledJobs.isEmpty() && m_jobs.isEmpty())
+        if (m_jobs.isEmpty())
             return;
 
-        if (!m_cancelledJobs.isEmpty()) {
-            for (QList<XmlQueryJob>::Iterator it = m_jobs.begin(); it != m_jobs.end(); ++it) {
-                int queryId = (*it).queryId;
-                if (m_cancelledJobs.remove(queryId))
-                    it = m_jobs.erase(it);
-            }
-            m_cancelledJobs.clear();
-        }
-
-        if (!m_jobs.isEmpty()) {
-            XmlQueryJob currentJob = m_jobs.takeLast();
-
-            locker.unlock();
-            processQuery(&currentJob);
-            locker.relock();
+        XmlQueryJob currentJob = m_jobs.takeLast();
+        while (m_cancelledJobs.remove(currentJob.queryId)) {
+            if (m_jobs.isEmpty())
+              return;
+            currentJob = m_jobs.takeLast();
         }
+        
+        locker.unlock();
+        processQuery(&currentJob);
+        locker.relock();
     }
 }
 
-- 
cgit v0.12