summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Faure <david.faure@kdab.com>2012-10-23 22:25:10 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-11-23 15:18:55 +0100
commit7120cf16d21923ecbae37c17c071eca2e7f891ab (patch)
treec950e07cce1e2394996b1590efbb07311a63d087
parent27aa41cbba6c0bd76148fde63863cfbba0ec2456 (diff)
Fix race condition on d->state, by locking the mutex first.
Detected by helgrind ./tst_qurl testThreads Change-Id: I0fe01153cd119741ce8a2bfe7dddead7c6ebf0b0 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Morten Johan Sørvig <morten.sorvig@digia.com>
-rw-r--r--src/corelib/thread/qfutureinterface.cpp12
1 files changed, 9 insertions, 3 deletions
diff --git a/src/corelib/thread/qfutureinterface.cpp b/src/corelib/thread/qfutureinterface.cpp
index bad55811fe..a293c711cd 100644
--- a/src/corelib/thread/qfutureinterface.cpp
+++ b/src/corelib/thread/qfutureinterface.cpp
@@ -283,14 +283,16 @@ void QFutureInterfaceBase::waitForResult(int resultIndex)
{
d->m_exceptionStore.throwPossibleException();
+ QMutexLocker lock(&d->m_mutex);
if (!(d->state & Running))
return;
+ lock.unlock();
// To avoid deadlocks and reduce the number of threads used, try to
// run the runnable in the current thread.
QThreadPool::globalInstance()->d_func()->stealRunnable(d->runnable);
- QMutexLocker lock(&d->m_mutex);
+ lock.relock();
if (!(d->state & Running))
return;
@@ -304,10 +306,14 @@ void QFutureInterfaceBase::waitForResult(int resultIndex)
void QFutureInterfaceBase::waitForFinished()
{
- if (d->state & Running) {
+ QMutexLocker lock(&d->m_mutex);
+ const bool alreadyFinished = !(d->state & Running);
+ lock.unlock();
+
+ if (!alreadyFinished) {
QThreadPool::globalInstance()->d_func()->stealRunnable(d->runnable);
- QMutexLocker lock(&d->m_mutex);
+ lock.relock();
while (d->state & Running)
d->waitCondition.wait(&d->m_mutex);