forked from qt-creator/qt-creator
Clang: Do not use Core::MessageManager from worker thread
...since that's not thread-safe and thus leads to crashes from time to time. Change-Id: I907ae8b5c4d60bfc82bc97b55cc5d62d8bbeae04 Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
This commit is contained in:
@@ -34,6 +34,7 @@
|
|||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/progressmanager/progressmanager.h>
|
#include <coreplugin/progressmanager/progressmanager.h>
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/runextensions.h>
|
#include <utils/runextensions.h>
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
@@ -153,14 +154,36 @@ void PchManager::updatePchInfo(ClangProjectSettings *cps,
|
|||||||
const QList<ProjectPart::Ptr> &projectParts)
|
const QList<ProjectPart::Ptr> &projectParts)
|
||||||
{
|
{
|
||||||
if (m_pchGenerationWatcher.isRunning()) {
|
if (m_pchGenerationWatcher.isRunning()) {
|
||||||
// m_pchGenerationWatcher.cancel();
|
|
||||||
m_pchGenerationWatcher.waitForFinished();
|
m_pchGenerationWatcher.waitForFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
QFuture<void> future = QtConcurrent::run(&PchManager::doPchInfoUpdate,
|
const QString customPchFile = cps->customPchFile();
|
||||||
cps->pchUsage(),
|
const ClangProjectSettings::PchUsage pchUsage = cps->pchUsage();
|
||||||
cps->customPchFile(),
|
|
||||||
projectParts);
|
void (*updateFunction)(QFutureInterface<void> &future,
|
||||||
|
const PchManager::UpdateParams ¶ms) = 0;
|
||||||
|
QString message;
|
||||||
|
if (pchUsage == ClangProjectSettings::PchUse_None
|
||||||
|
|| (pchUsage == ClangProjectSettings::PchUse_Custom && customPchFile.isEmpty())) {
|
||||||
|
updateFunction = &PchManager::doPchInfoUpdateNone;
|
||||||
|
message = QLatin1String("updatePchInfo: switching to none");
|
||||||
|
} else if (pchUsage == ClangProjectSettings::PchUse_BuildSystem_Fuzzy) {
|
||||||
|
updateFunction = &PchManager::doPchInfoUpdateFuzzy;
|
||||||
|
message = QLatin1String("updatePchInfo: switching to build system (fuzzy)");
|
||||||
|
} else if (pchUsage == ClangProjectSettings::PchUse_BuildSystem_Exact) {
|
||||||
|
updateFunction = &PchManager::doPchInfoUpdateExact;
|
||||||
|
message = QLatin1String("updatePchInfo: switching to build system (exact)");
|
||||||
|
} else if (pchUsage == ClangProjectSettings::PchUse_Custom) {
|
||||||
|
updateFunction = &PchManager::doPchInfoUpdateCustom;
|
||||||
|
message = QLatin1String("updatePchInfo: switching to custom") + customPchFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTC_ASSERT(updateFunction && !message.isEmpty(), return);
|
||||||
|
|
||||||
|
Core::MessageManager::write(message, Core::MessageManager::Silent);
|
||||||
|
const UpdateParams updateParams = UpdateParams(customPchFile, projectParts);
|
||||||
|
QFuture<void> future
|
||||||
|
= QtConcurrent::run<void, const UpdateParams &>(updateFunction, updateParams);
|
||||||
m_pchGenerationWatcher.setFuture(future);
|
m_pchGenerationWatcher.setFuture(future);
|
||||||
Core::ProgressManager::addTask(future, tr("Precompiling..."), "Key.Tmp.Precompiling");
|
Core::ProgressManager::addTask(future, tr("Precompiling..."), "Key.Tmp.Precompiling");
|
||||||
}
|
}
|
||||||
@@ -214,27 +237,17 @@ CppTools::ProjectFile::Kind getPrefixFileKind(bool hasObjectiveC, bool hasCPlusP
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PchManager::doPchInfoUpdate(QFutureInterface<void> &future,
|
void PchManager::doPchInfoUpdateNone(QFutureInterface<void> &future, const PchManager::UpdateParams ¶ms)
|
||||||
ClangProjectSettings::PchUsage pchUsage,
|
|
||||||
const QString customPchFile,
|
|
||||||
const QList<ProjectPart::Ptr> projectParts)
|
|
||||||
{
|
{
|
||||||
PchManager *pchManager = PchManager::instance();
|
future.setProgressRange(0, 1);
|
||||||
|
|
||||||
// qDebug() << "switching to" << pchUsage;
|
|
||||||
|
|
||||||
if (pchUsage == ClangProjectSettings::PchUse_None
|
|
||||||
|| (pchUsage == ClangProjectSettings::PchUse_Custom && customPchFile.isEmpty())) {
|
|
||||||
future.setProgressRange(0, 2);
|
|
||||||
Core::MessageManager::write(QLatin1String("updatePchInfo: switching to none"),
|
|
||||||
Core::MessageManager::Silent);
|
|
||||||
PchInfo::Ptr emptyPch = PchInfo::createEmpty();
|
PchInfo::Ptr emptyPch = PchInfo::createEmpty();
|
||||||
pchManager->setPCHInfo(projectParts, emptyPch, qMakePair(true, QStringList()));
|
PchManager::instance()->setPCHInfo(params.projectParts, emptyPch,
|
||||||
|
qMakePair(true, QStringList()));
|
||||||
future.setProgressValue(1);
|
future.setProgressValue(1);
|
||||||
} else if (pchUsage == ClangProjectSettings::PchUse_BuildSystem_Fuzzy) {
|
}
|
||||||
Core::MessageManager::write(
|
|
||||||
QLatin1String("updatePchInfo: switching to build system (fuzzy)"),
|
void PchManager::doPchInfoUpdateFuzzy(QFutureInterface<void> &future, const PchManager::UpdateParams ¶ms)
|
||||||
Core::MessageManager::Silent);
|
{
|
||||||
QHash<QString, QSet<QString> > includes, frameworks;
|
QHash<QString, QSet<QString> > includes, frameworks;
|
||||||
QHash<QString, QSet<QByteArray> > definesPerPCH;
|
QHash<QString, QSet<QByteArray> > definesPerPCH;
|
||||||
QHash<QString, bool> objc;
|
QHash<QString, bool> objc;
|
||||||
@@ -244,7 +257,7 @@ void PchManager::doPchInfoUpdate(QFutureInterface<void> &future,
|
|||||||
QHash<QString, ProjectPart::CXXVersion> cxxVersions;
|
QHash<QString, ProjectPart::CXXVersion> cxxVersions;
|
||||||
QHash<QString, ProjectPart::CXXExtensions> cxxExtensionsMap;
|
QHash<QString, ProjectPart::CXXExtensions> cxxExtensionsMap;
|
||||||
QHash<QString, QList<ProjectPart::Ptr> > inputToParts;
|
QHash<QString, QList<ProjectPart::Ptr> > inputToParts;
|
||||||
foreach (const ProjectPart::Ptr &projectPart, projectParts) {
|
foreach (const ProjectPart::Ptr &projectPart, params.projectParts) {
|
||||||
if (projectPart->precompiledHeaders.isEmpty())
|
if (projectPart->precompiledHeaders.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
const QString &pch = projectPart->precompiledHeaders.first(); // TODO: support more than 1 PCH file.
|
const QString &pch = projectPart->precompiledHeaders.first(); // TODO: support more than 1 PCH file.
|
||||||
@@ -310,6 +323,7 @@ void PchManager::doPchInfoUpdate(QFutureInterface<void> &future,
|
|||||||
QStringList options = Utils::createClangOptions(projectPart, prefixFileKind);
|
QStringList options = Utils::createClangOptions(projectPart, prefixFileKind);
|
||||||
projectPart.reset();
|
projectPart.reset();
|
||||||
|
|
||||||
|
PchManager *pchManager = PchManager::instance();
|
||||||
PchInfo::Ptr pchInfo = pchManager->findMatchingPCH(pch, options, true);
|
PchInfo::Ptr pchInfo = pchManager->findMatchingPCH(pch, options, true);
|
||||||
QPair<bool, QStringList> msgs = qMakePair(true, QStringList());
|
QPair<bool, QStringList> msgs = qMakePair(true, QStringList());
|
||||||
if (pchInfo.isNull()) {
|
if (pchInfo.isNull()) {
|
||||||
@@ -320,13 +334,15 @@ void PchManager::doPchInfoUpdate(QFutureInterface<void> &future,
|
|||||||
pchManager->setPCHInfo(inputToParts[pch], pchInfo, msgs);
|
pchManager->setPCHInfo(inputToParts[pch], pchInfo, msgs);
|
||||||
future.setProgressValue(future.progressValue() + 1);
|
future.setProgressValue(future.progressValue() + 1);
|
||||||
}
|
}
|
||||||
} else if (pchUsage == ClangProjectSettings::PchUse_BuildSystem_Exact) {
|
|
||||||
future.setProgressRange(0, projectParts.size() + 1);
|
future.setProgressValue(future.progressValue() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PchManager::doPchInfoUpdateExact(QFutureInterface<void> &future, const PchManager::UpdateParams ¶ms)
|
||||||
|
{
|
||||||
|
future.setProgressRange(0, params.projectParts.size() + 1);
|
||||||
future.setProgressValue(0);
|
future.setProgressValue(0);
|
||||||
Core::MessageManager::write(
|
foreach (const ProjectPart::Ptr &projectPart, params.projectParts) {
|
||||||
QLatin1String("updatePchInfo: switching to build system (exact)"),
|
|
||||||
Core::MessageManager::Silent);
|
|
||||||
foreach (const ProjectPart::Ptr &projectPart, projectParts) {
|
|
||||||
if (future.isCanceled())
|
if (future.isCanceled())
|
||||||
return;
|
return;
|
||||||
if (projectPart->precompiledHeaders.isEmpty())
|
if (projectPart->precompiledHeaders.isEmpty())
|
||||||
@@ -339,6 +355,7 @@ void PchManager::doPchInfoUpdate(QFutureInterface<void> &future,
|
|||||||
QStringList options = Utils::createClangOptions(
|
QStringList options = Utils::createClangOptions(
|
||||||
projectPart, getPrefixFileKind(hasObjC, hasCppFiles(projectPart)));
|
projectPart, getPrefixFileKind(hasObjC, hasCppFiles(projectPart)));
|
||||||
|
|
||||||
|
PchManager *pchManager = PchManager::instance();
|
||||||
PchInfo::Ptr pchInfo = pchManager->findMatchingPCH(pch, options, false);
|
PchInfo::Ptr pchInfo = pchManager->findMatchingPCH(pch, options, false);
|
||||||
QPair<bool, QStringList> msgs = qMakePair(true, QStringList());
|
QPair<bool, QStringList> msgs = qMakePair(true, QStringList());
|
||||||
if (pchInfo.isNull()) {
|
if (pchInfo.isNull()) {
|
||||||
@@ -349,19 +366,21 @@ void PchManager::doPchInfoUpdate(QFutureInterface<void> &future,
|
|||||||
pchInfo, msgs);
|
pchInfo, msgs);
|
||||||
future.setProgressValue(future.progressValue() + 1);
|
future.setProgressValue(future.progressValue() + 1);
|
||||||
}
|
}
|
||||||
} else if (pchUsage == ClangProjectSettings::PchUse_Custom) {
|
|
||||||
future.setProgressRange(0, 2);
|
future.setProgressValue(future.progressValue() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PchManager::doPchInfoUpdateCustom(QFutureInterface<void> &future, const PchManager::UpdateParams ¶ms)
|
||||||
|
{
|
||||||
|
future.setProgressRange(0, 1);
|
||||||
future.setProgressValue(0);
|
future.setProgressValue(0);
|
||||||
Core::MessageManager::write(
|
|
||||||
QLatin1String("updatePchInfo: switching to custom") + customPchFile,
|
|
||||||
Core::MessageManager::Silent);
|
|
||||||
|
|
||||||
QSet<QString> includes, frameworks;
|
QSet<QString> includes, frameworks;
|
||||||
bool objc = false;
|
bool objc = false;
|
||||||
bool cplusplus = false;
|
bool cplusplus = false;
|
||||||
ProjectPart::Ptr united(new ProjectPart());
|
ProjectPart::Ptr united(new ProjectPart());
|
||||||
united->cxxVersion = ProjectPart::CXX98;
|
united->cxxVersion = ProjectPart::CXX98;
|
||||||
foreach (const ProjectPart::Ptr &projectPart, projectParts) {
|
foreach (const ProjectPart::Ptr &projectPart, params.projectParts) {
|
||||||
includes.unite(QSet<QString>::fromList(projectPart->includePaths));
|
includes.unite(QSet<QString>::fromList(projectPart->includePaths));
|
||||||
frameworks.unite(QSet<QString>::fromList(projectPart->frameworkPaths));
|
frameworks.unite(QSet<QString>::fromList(projectPart->frameworkPaths));
|
||||||
united->cVersion = std::max(united->cVersion, projectPart->cVersion);
|
united->cVersion = std::max(united->cVersion, projectPart->cVersion);
|
||||||
@@ -376,21 +395,19 @@ void PchManager::doPchInfoUpdate(QFutureInterface<void> &future,
|
|||||||
united, getPrefixFileKind(objc, cplusplus));
|
united, getPrefixFileKind(objc, cplusplus));
|
||||||
united.clear();
|
united.clear();
|
||||||
|
|
||||||
PchInfo::Ptr pchInfo = pchManager->findMatchingPCH(customPchFile, opts, true);
|
PchManager *pchManager = PchManager::instance();
|
||||||
|
PchInfo::Ptr pchInfo = pchManager->findMatchingPCH(params.customPchFile, opts, true);
|
||||||
QPair<bool, QStringList> msgs = qMakePair(true, QStringList());;
|
QPair<bool, QStringList> msgs = qMakePair(true, QStringList());;
|
||||||
if (future.isCanceled())
|
if (future.isCanceled())
|
||||||
return;
|
return;
|
||||||
if (pchInfo.isNull()) {
|
if (pchInfo.isNull()) {
|
||||||
pchInfo = PchInfo::createWithFileName(customPchFile, opts, objc);
|
pchInfo = PchInfo::createWithFileName(params.customPchFile, opts, objc);
|
||||||
msgs = precompile(pchInfo);
|
msgs = precompile(pchInfo);
|
||||||
}
|
}
|
||||||
pchManager->setPCHInfo(projectParts, pchInfo, msgs);
|
pchManager->setPCHInfo(params.projectParts, pchInfo, msgs);
|
||||||
future.setProgressValue(1);
|
future.setProgressValue(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
future.setProgressValue(future.progressValue() + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
PchInfo::Ptr PchManager::findMatchingPCH(const QString &inputFileName,
|
PchInfo::Ptr PchManager::findMatchingPCH(const QString &inputFileName,
|
||||||
const QStringList &options,
|
const QStringList &options,
|
||||||
bool fuzzyMatching) const
|
bool fuzzyMatching) const
|
||||||
|
@@ -75,12 +75,21 @@ private slots:
|
|||||||
void updateActivePchFiles();
|
void updateActivePchFiles();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct UpdateParams {
|
||||||
|
UpdateParams(const QString &customPchFile, const QList<ProjectPart::Ptr> &projectParts)
|
||||||
|
: customPchFile(customPchFile) , projectParts(projectParts) {}
|
||||||
|
const QString customPchFile;
|
||||||
|
const QList<ProjectPart::Ptr> projectParts;
|
||||||
|
};
|
||||||
|
|
||||||
void updatePchInfo(ClangProjectSettings *cps,
|
void updatePchInfo(ClangProjectSettings *cps,
|
||||||
const QList<ProjectPart::Ptr> &projectParts);
|
const QList<ProjectPart::Ptr> &projectParts);
|
||||||
static void doPchInfoUpdate(QFutureInterface<void> &future,
|
|
||||||
ClangProjectSettings::PchUsage pchUsage,
|
static void doPchInfoUpdateNone(QFutureInterface<void> &future, const UpdateParams ¶ms);
|
||||||
const QString customPchFile,
|
static void doPchInfoUpdateFuzzy(QFutureInterface<void> &future, const UpdateParams ¶ms);
|
||||||
const QList<ProjectPart::Ptr> projectParts);
|
static void doPchInfoUpdateExact(QFutureInterface<void> &future, const UpdateParams ¶ms);
|
||||||
|
static void doPchInfoUpdateCustom(QFutureInterface<void> &future, const UpdateParams ¶ms);
|
||||||
|
|
||||||
void setPCHInfo(const QList<ProjectPart::Ptr> &projectParts,
|
void setPCHInfo(const QList<ProjectPart::Ptr> &projectParts,
|
||||||
const PchInfo::Ptr &pchInfo,
|
const PchInfo::Ptr &pchInfo,
|
||||||
const QPair<bool, QStringList> &msgs);
|
const QPair<bool, QStringList> &msgs);
|
||||||
|
Reference in New Issue
Block a user