CMake: Allow cancellation of CMake process

Allow cancellation of cmake runs in tea-leaf and fileapi modes.

At least in those modes cmake can now get stopped when it goes into
an infinite loop.

Change-Id: I4e9bd769292325b9837904cd391ff61dbc477898
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Tobias Hunger
2019-06-14 16:42:41 +02:00
parent fa57e933a9
commit 97392daaf3
2 changed files with 36 additions and 5 deletions

View File

@@ -38,6 +38,7 @@
#include <QDir> #include <QDir>
#include <QObject> #include <QObject>
#include <QTimer>
namespace CMakeProjectManager { namespace CMakeProjectManager {
namespace Internal { namespace Internal {
@@ -57,8 +58,11 @@ static QString lineSplit(const QString &rest, const QByteArray &array, std::func
return tmp.mid(start); return tmp.mid(start);
} }
CMakeProcess::CMakeProcess()
CMakeProcess::CMakeProcess() = default; {
connect(&m_cancelTimer, &QTimer::timeout, this, &CMakeProcess::checkForCancelled);
m_cancelTimer.setInterval(500);
}
CMakeProcess::~CMakeProcess() CMakeProcess::~CMakeProcess()
{ {
@@ -116,6 +120,10 @@ 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.
auto process = std::make_unique<Utils::QtcProcess>(); auto process = std::make_unique<Utils::QtcProcess>();
m_processWasCanceled = false;
m_cancelTimer.start();
process->setWorkingDirectory(workDirectory.toString()); process->setWorkingDirectory(workDirectory.toString());
process->setEnvironment(parameters.environment); process->setEnvironment(parameters.environment);
@@ -204,14 +212,21 @@ void CMakeProcess::handleProcessFinished(int code, QProcess::ExitStatus status)
{ {
QTC_ASSERT(m_process && m_future, return); QTC_ASSERT(m_process && m_future, return);
m_cancelTimer.stop();
processStandardOutput(); processStandardOutput();
processStandardError(); processStandardError();
QString msg; QString msg;
if (status != QProcess::NormalExit) if (status != QProcess::NormalExit) {
msg = tr("*** cmake process crashed."); if (m_processWasCanceled) {
else if (code != 0) msg = tr("*** cmake process was canceled by the user.");
} else {
msg = tr("*** cmake process crashed.");
}
} else if (code != 0) {
msg = tr("*** cmake process exited with exit code %1.").arg(code); msg = tr("*** cmake process exited with exit code %1.").arg(code);
}
if (!msg.isEmpty()) { if (!msg.isEmpty()) {
Core::MessageManager::write(msg); Core::MessageManager::write(msg);
@@ -226,5 +241,17 @@ void CMakeProcess::handleProcessFinished(int code, QProcess::ExitStatus status)
emit finished(code, status); emit finished(code, status);
} }
void CMakeProcess::checkForCancelled()
{
if (!m_process || !m_future)
return;
if (m_future->isCanceled()) {
m_cancelTimer.stop();
m_processWasCanceled = true;
m_process->close();
}
}
} // namespace Internal } // namespace Internal
} // namespace CMakeProjectManager } // namespace CMakeProjectManager

View File

@@ -32,6 +32,7 @@
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
#include <QFutureInterface> #include <QFutureInterface>
#include <QTimer>
#include <memory> #include <memory>
@@ -67,10 +68,13 @@ signals:
private: private:
void handleProcessFinished(int code, QProcess::ExitStatus status); void handleProcessFinished(int code, QProcess::ExitStatus status);
void checkForCancelled();
std::unique_ptr<Utils::QtcProcess> m_process; std::unique_ptr<Utils::QtcProcess> m_process;
std::unique_ptr<ProjectExplorer::IOutputParser> m_parser; std::unique_ptr<ProjectExplorer::IOutputParser> m_parser;
std::unique_ptr<QFutureInterface<void>> m_future; std::unique_ptr<QFutureInterface<void>> m_future;
bool m_processWasCanceled = false;
QTimer m_cancelTimer;
}; };
} // namespace Internal } // namespace Internal