summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZsolt Simon <zsolt.simon@nokia.com>2010-11-18 14:13:26 +1000
committerZsolt Simon <zsolt.simon@nokia.com>2010-11-18 14:13:26 +1000
commitfec3e7bc6a7cd4e2968aa6638889611096425fb7 (patch)
treefff2a9450ebb987244bdcae364e3b3c343c90d9a
parent85f1384e199aef194eee3c8b7cc37e54da4becc3 (diff)
mkCal: fixed deadlock in async manager destructor
The deadlock occurred when the async manager wanted to destroy while a workerDone function call was in progress
-rw-r--r--plugins/organizer/mkcal/qorganizerasynchmanager.cpp32
-rw-r--r--plugins/organizer/mkcal/qorganizerasynchmanager.h3
2 files changed, 21 insertions, 14 deletions
diff --git a/plugins/organizer/mkcal/qorganizerasynchmanager.cpp b/plugins/organizer/mkcal/qorganizerasynchmanager.cpp
index aeadaa990b..51e92e2ce5 100644
--- a/plugins/organizer/mkcal/qorganizerasynchmanager.cpp
+++ b/plugins/organizer/mkcal/qorganizerasynchmanager.cpp
@@ -50,6 +50,7 @@ class AsyncWorker: public QThread
{
public:
AsyncWorker(OrganizerAsynchManager* manager): m_manager(manager), m_req(0), m_kill(false) {};
+ ~AsyncWorker() {kill();}
void assignRequest(QOrganizerAbstractRequest* r);
void kill();
@@ -93,9 +94,13 @@ void AsyncWorker::assignRequest(QOrganizerAbstractRequest* r)
void AsyncWorker::kill()
{
- //mark the exit flag and wake up the thread if is sleeping
- m_kill = true;
- m_wait.wakeAll();
+ {
+ QMutexLocker locker(&m_lock);
+
+ //mark the exit flag and wake up the thread if is sleeping
+ m_kill = true;
+ m_wait.wakeAll();
+ }
//wait the thread to finish
wait();
@@ -112,9 +117,9 @@ void AsyncWorker::run()
m_req = 0;
//if there are no requests sleep
- if (!r)
+ if (!r) {
m_wait.wait(&m_lock);
- else {
+ } else {
locker.unlock();
//process the request
processRequest(r);
@@ -328,7 +333,7 @@ void AsyncWorker::handleCollectionSaveRequest(QOrganizerCollectionSaveRequest *r
}
OrganizerAsynchManager::OrganizerAsynchManager(QOrganizerManagerEngine* engine, int maxWorkers)
- : m_engine(engine), m_maxWorkers(maxWorkers)
+ : m_engine(engine), m_maxWorkers(maxWorkers), m_destroying(false)
{
}
@@ -336,13 +341,9 @@ OrganizerAsynchManager::~OrganizerAsynchManager()
{
QMutexLocker locker(&m_mutex);
- //kill all idle workers
- foreach(AsyncWorker* worker, m_idleWorkers)
- worker->kill();
-
- //kill all active workers
- foreach(AsyncWorker* worker, m_activeWorkers)
- worker->kill();
+ m_destroying = true;
+ while (!m_activeWorkers.isEmpty())
+ m_destroyWait.wait(&m_mutex);
//delete all workers
foreach(AsyncWorker* worker, m_idleWorkers) {
@@ -475,7 +476,7 @@ void OrganizerAsynchManager::workerDone(AsyncWorker *worker, QOrganizerAbstractR
m_activeRequests.remove(req);
//check if there is more job for this worker
- if (m_queuedRequests.count() > 0) {
+ if (!m_destroying && m_queuedRequests.count() > 0) {
req = m_queuedRequests.dequeue();
m_activeRequests.insert(req);
worker->assignRequest(req);
@@ -483,6 +484,9 @@ void OrganizerAsynchManager::workerDone(AsyncWorker *worker, QOrganizerAbstractR
//remove from the active workers list and add it to the idle one
m_activeWorkers.removeOne(worker);
m_idleWorkers.enqueue(worker);
+
+ if (m_destroying)
+ m_destroyWait.wakeAll();
}
}
diff --git a/plugins/organizer/mkcal/qorganizerasynchmanager.h b/plugins/organizer/mkcal/qorganizerasynchmanager.h
index f2e3fe98d2..8f85db9527 100644
--- a/plugins/organizer/mkcal/qorganizerasynchmanager.h
+++ b/plugins/organizer/mkcal/qorganizerasynchmanager.h
@@ -92,6 +92,9 @@ private:
QMutex m_mutex;
+ bool m_destroying;
+ QWaitCondition m_destroyWait;
+
void workerDone(AsyncWorker *worker, QOrganizerAbstractRequest *req);
friend class AsyncWorker;