CMakePM: stop file api reader future on stop()

The future that would trigger the result of a cmake api file parsing
would not be removed if the stop parsing would be triggered.

This could be triggered by fast switching between build configurations.

It could also lead to forever parsing states having the project's
wheel always spinning.

Fixes: QTCREATORBUG-25588
Fixes: QTCREATORBUG-25287
Change-Id: I4f92806ebdb703b4910952cd8db1e52816daf9cf
Reviewed-by: Cristian Adam <cristian.adam@qt.io>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Eike Ziller
2021-05-31 13:38:41 +02:00
committed by Cristian Adam
parent 637a20c34c
commit fbeaa774b5
3 changed files with 35 additions and 24 deletions

View File

@@ -904,7 +904,8 @@ FilePath CMakeBuildSystem::workDirectory(const BuildDirParameters &parameters)
void CMakeBuildSystem::stopParsingAndClearState()
{
qCDebug(cmakeBuildSystemLog) << "stopping parsing run!";
qCDebug(cmakeBuildSystemLog) << cmakeBuildConfiguration()->displayName()
<< "stopping parsing run!";
m_reader.stop();
m_reader.resetData();
}

View File

@@ -165,6 +165,13 @@ void FileApiReader::stop()
if (m_cmakeProcess)
disconnect(m_cmakeProcess.get(), nullptr, this, nullptr);
m_cmakeProcess.reset();
if (m_future) {
m_future->cancel();
m_future->waitForFinished();
}
m_future = {};
m_isParsing = false;
}
bool FileApiReader::isParsing() const
@@ -259,7 +266,7 @@ void FileApiReader::endState(const QFileInfo &replyFi)
m_future = runAsync(ProjectExplorerPlugin::sharedThreadPool(),
[replyFi, sourceDirectory, buildDirectory, topCmakeFile, cmakeBuildType]() {
auto result = std::make_unique<FileApiQtcData>();
auto result = std::make_shared<FileApiQtcData>();
FileApiData data = FileApiParser::parseData(replyFi, cmakeBuildType, result->errorMessage);
if (!result->errorMessage.isEmpty()) {
qWarning() << result->errorMessage;
@@ -274,29 +281,30 @@ void FileApiReader::endState(const QFileInfo &replyFi)
qWarning() << result->errorMessage;
}
return result.release();
return result;
});
onFinished(m_future.value(), this, [this](const QFuture<FileApiQtcData *> &f) {
std::unique_ptr<FileApiQtcData> value(f.result()); // Adopt the pointer again:-)
onResultReady(m_future.value(),
this,
[this, topCmakeFile, sourceDirectory, buildDirectory](
const std::shared_ptr<FileApiQtcData> &value) {
m_isParsing = false;
m_cache = std::move(value->cache);
m_cmakeFiles = std::move(value->cmakeFiles);
m_buildTargets = std::move(value->buildTargets);
m_projectParts = std::move(value->projectParts);
m_rootProjectNode = std::move(value->rootProjectNode);
m_knownHeaders = std::move(value->knownHeaders);
m_ctestPath = std::move(value->ctestPath);
m_isMultiConfig = std::move(value->isMultiConfig);
m_usesAllCapsTargets = std::move(value->usesAllCapsTargets);
m_future = {};
m_isParsing = false;
m_cache = std::move(value->cache);
m_cmakeFiles = std::move(value->cmakeFiles);
m_buildTargets = std::move(value->buildTargets);
m_projectParts = std::move(value->projectParts);
m_rootProjectNode = std::move(value->rootProjectNode);
m_knownHeaders = std::move(value->knownHeaders);
m_ctestPath = std::move(value->ctestPath);
m_isMultiConfig = std::move(value->isMultiConfig);
m_usesAllCapsTargets = std::move(value->usesAllCapsTargets);
if (value->errorMessage.isEmpty()) {
emit this->dataAvailable();
} else {
emit this->errorOccurred(value->errorMessage);
}
});
if (value->errorMessage.isEmpty()) {
emit this->dataAvailable();
} else {
emit this->errorOccurred(value->errorMessage);
}
m_future = {};
});
}
void FileApiReader::makeBackupConfiguration(bool store)

View File

@@ -38,6 +38,8 @@
#include <QObject>
#include <QDateTime>
#include <memory>
namespace ProjectExplorer {
class ProjectNode;
}
@@ -105,7 +107,7 @@ private:
bool m_usesAllCapsTargets = false;
int m_lastCMakeExitCode = 0;
Utils::optional<QFuture<FileApiQtcData *>> m_future;
Utils::optional<QFuture<std::shared_ptr<FileApiQtcData>>> m_future;
// Update related:
bool m_isParsing = false;