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

View File

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

View File

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

View File

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