diff options
author | Zsolt Simon <zsolt.simon@nokia.com> | 2010-11-18 14:13:26 +1000 |
---|---|---|
committer | Zsolt Simon <zsolt.simon@nokia.com> | 2010-11-18 14:13:26 +1000 |
commit | fec3e7bc6a7cd4e2968aa6638889611096425fb7 (patch) | |
tree | fff2a9450ebb987244bdcae364e3b3c343c90d9a | |
parent | 85f1384e199aef194eee3c8b7cc37e54da4becc3 (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.cpp | 32 | ||||
-rw-r--r-- | plugins/organizer/mkcal/qorganizerasynchmanager.h | 3 |
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; |