CMakeProcess: Don't use QTimer for checking the canceled state

Create a QFutureWatcher instead and connect to its canceled()
signal.

Replace some includes with forward declarations.

Change-Id: Ie82bf8902ef8c8d87011809bd14b7db3d4f52179
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Cristian Adam <cristian.adam@qt.io>
This commit is contained in:
Jarek Kobus
2022-05-14 02:27:28 +02:00
parent 52770b746e
commit 9a4164a4de
4 changed files with 32 additions and 51 deletions

View File

@@ -25,6 +25,7 @@
#include "cmakeprocess.h"
#include "builddirparameters.h"
#include "cmakeparser.h"
#include <coreplugin/progressmanager/progressmanager.h>
@@ -36,7 +37,7 @@
#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
#include <QFutureInterface>
#include <QFutureWatcher>
using namespace Utils;
@@ -52,27 +53,22 @@ static QString stripTrailingNewline(QString str)
return str;
}
CMakeProcess::CMakeProcess()
{
connect(&m_cancelTimer, &QTimer::timeout, this, &CMakeProcess::checkForCancelled);
m_cancelTimer.setInterval(50);
}
CMakeProcess::CMakeProcess() = default;
CMakeProcess::~CMakeProcess()
{
m_process.reset();
m_parser.flush();
if (m_future) {
if (m_futureWatcher) {
// None of the progress related functions will work after this!
m_future->reportCanceled();
m_future->reportFinished();
m_futureInterface.reportCanceled();
m_futureInterface.reportFinished();
}
}
void CMakeProcess::run(const BuildDirParameters &parameters, const QStringList &arguments)
{
QTC_ASSERT(!m_process && !m_future, return);
QTC_ASSERT(!m_process && !m_futureWatcher, return);
CMakeTool *cmake = parameters.cmakeTool();
QTC_ASSERT(parameters.isValid() && cmake, return);
@@ -109,9 +105,6 @@ void CMakeProcess::run(const BuildDirParameters &parameters, const QStringList &
// then we are racing against CMakeCache.txt also getting deleted.
m_process.reset(new QtcProcess);
m_processWasCanceled = false;
m_cancelTimer.start();
m_process->setWorkingDirectory(buildDirectory);
m_process->setEnvironment(parameters.environment);
@@ -136,14 +129,17 @@ void CMakeProcess::run(const BuildDirParameters &parameters, const QStringList &
TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
BuildSystem::startNewBuildSystemOutput(
tr("Running %1 in %2.").arg(commandLine.toUserOutput()).arg(buildDirectory.toUserOutput()));
tr("Running %1 in %2.").arg(commandLine.toUserOutput(), buildDirectory.toUserOutput()));
m_future.reset(new QFutureInterface<void>);
m_future->setProgressRange(0, 1);
Core::ProgressManager::addTimedTask(*m_future.get(),
m_futureInterface = QFutureInterface<void>();
m_futureInterface.setProgressRange(0, 1);
Core::ProgressManager::addTimedTask(m_futureInterface,
tr("Configuring \"%1\"").arg(parameters.projectName),
"CMake.Configure",
10);
m_futureWatcher.reset(new QFutureWatcher<void>);
connect(m_futureWatcher.get(), &QFutureWatcher<void>::canceled, this, &CMakeProcess::stop);
m_futureWatcher->setFuture(m_futureInterface.future());
m_process->setCommand(commandLine);
emit started();
@@ -153,26 +149,22 @@ void CMakeProcess::run(const BuildDirParameters &parameters, const QStringList &
void CMakeProcess::stop()
{
if (m_process) {
m_processWasCanceled = true;
if (!m_process)
return;
m_process->close();
m_futureWatcher->disconnect();
handleProcessDone({15, QProcess::CrashExit, QProcess::Crashed, {}});
}
}
void CMakeProcess::handleProcessDone(const Utils::ProcessResultData &resultData)
{
QTC_ASSERT(m_future, return);
m_cancelTimer.stop();
const int code = resultData.m_exitCode;
QString msg;
if (resultData.m_error == QProcess::FailedToStart) {
msg = tr("CMake process failed to start.");
} else if (resultData.m_exitStatus != QProcess::NormalExit) {
if (m_processWasCanceled)
if (m_futureInterface.isCanceled())
msg = tr("CMake process was canceled by the user.");
else
msg = tr("CMake process crashed.");
@@ -184,12 +176,12 @@ void CMakeProcess::handleProcessDone(const Utils::ProcessResultData &resultData)
if (!msg.isEmpty()) {
BuildSystem::appendBuildSystemOutput(msg + '\n');
TaskHub::addTask(BuildSystemTask(Task::Error, msg));
m_future->reportCanceled();
m_futureInterface.reportCanceled();
} else {
m_future->setProgressValue(1);
m_futureInterface.setProgressValue(1);
}
m_future->reportFinished();
m_futureInterface.reportFinished();
emit finished();
@@ -197,16 +189,5 @@ void CMakeProcess::handleProcessDone(const Utils::ProcessResultData &resultData)
BuildSystem::appendBuildSystemOutput(elapsedTime + '\n');
}
void CMakeProcess::checkForCancelled()
{
if (!m_process || !m_future)
return;
if (m_future->isCanceled()) {
m_cancelTimer.stop();
stop();
}
}
} // namespace Internal
} // namespace CMakeProjectManager

View File

@@ -25,20 +25,18 @@
#pragma once
#include "builddirparameters.h"
#include <utils/outputformatter.h>
#include <QElapsedTimer>
#include <QFutureInterface>
#include <QObject>
#include <QStringList>
#include <QTimer>
#include <memory>
QT_BEGIN_NAMESPACE
template<class T>
class QFutureInterface;
class QFutureWatcher;
QT_END_NAMESPACE
namespace Utils {
@@ -49,6 +47,8 @@ class QtcProcess;
namespace CMakeProjectManager {
namespace Internal {
class BuildDirParameters;
class CMakeProcess : public QObject
{
Q_OBJECT
@@ -68,13 +68,11 @@ signals:
private:
void handleProcessDone(const Utils::ProcessResultData &resultData);
void checkForCancelled();
std::unique_ptr<Utils::QtcProcess> m_process;
Utils::OutputFormatter m_parser;
std::unique_ptr<QFutureInterface<void>> m_future;
bool m_processWasCanceled = false;
QTimer m_cancelTimer;
QFutureInterface<void> m_futureInterface;
std::unique_ptr<QFutureWatcher<void>> m_futureWatcher;
QElapsedTimer m_elapsed;
int m_lastExitCode = 0;
};

View File

@@ -25,6 +25,7 @@
#include "fileapireader.h"
#include "cmakeprocess.h"
#include "fileapidataextractor.h"
#include "fileapiparser.h"

View File

@@ -25,8 +25,8 @@
#pragma once
#include "builddirparameters.h"
#include "cmakebuildtarget.h"
#include "cmakeprocess.h"
#include "cmakeprojectnodes.h"
#include "fileapidataextractor.h"
@@ -49,6 +49,7 @@ class ProjectNode;
namespace CMakeProjectManager {
namespace Internal {
class CMakeProcess;
class FileApiQtcData;
class FileApiReader final : public QObject