lock baseEnv in cache()

as we modify the environment, it must be properly locked.
this implies that initFrom() also needs to be called with a lock.

Task-number: QTCREATORBUG-9835
Change-Id: I48bae9af9adaa0518e5a9db0ba08ff057ae14f9f
Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
This commit is contained in:
Oswald Buddenhagen
2013-07-23 17:57:44 +02:00
parent 759d0a69dd
commit d022a2d19c
2 changed files with 58 additions and 34 deletions

View File

@@ -44,6 +44,9 @@
#include <qset.h>
#include <qstringlist.h>
#include <qtextstream.h>
#ifdef PROEVALUATOR_THREAD_SAFE
# include <qthreadpool.h>
#endif
#ifdef Q_OS_UNIX
#include <time.h>
@@ -1526,8 +1529,31 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
ProStringList newval;
bool changed = false;
for (bool hostBuild = false; ; hostBuild = true) {
if (QMakeBaseEnv *baseEnv = m_option->baseEnvs.value(
QMakeBaseKey(m_buildRoot, hostBuild))) {
#ifdef PROEVALUATOR_THREAD_SAFE
m_option->mutex.lock();
#endif
QMakeBaseEnv *baseEnv =
m_option->baseEnvs.value(QMakeBaseKey(m_buildRoot, hostBuild));
#ifdef PROEVALUATOR_THREAD_SAFE
// It's ok to unlock this before locking baseEnv,
// as we have no intention to initialize the env.
m_option->mutex.unlock();
#endif
do {
if (!baseEnv)
break;
#ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&baseEnv->mutex);
if (baseEnv->inProgress) {
// The env is still in the works, but it may be already past the cache
// loading. So we need to wait for completion and amend it as usual.
QThreadPool::globalInstance()->releaseThread();
baseEnv->cond.wait(&baseEnv->mutex);
QThreadPool::globalInstance()->reserveThread();
}
if (!baseEnv->isOk)
break;
#endif
QMakeEvaluator *baseEval = baseEnv->evaluator;
const ProStringList &oldval = baseEval->values(dstvar);
if (mode == CacheSet) {
@@ -1558,7 +1584,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
}
changed = true;
}
}
} while (false);
if (hostBuild)
break;
}