diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index 5d1d848e4d2..cbaa22c7881 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -666,6 +666,18 @@ void QmakeBuildSystem::asyncUpdate() Constants::PROFILE_EVALUATE); m_asyncUpdateFutureInterface.reportStarted(); + const auto watcher = new QFutureWatcher(this); + connect(watcher, &QFutureWatcher::canceled, this, [this, watcher] { + if (!m_qmakeGlobals) + return; + watcher->disconnect(); + m_qmakeGlobals->killProcesses(); + }); + connect(watcher, &QFutureWatcher::finished, this, [watcher] { + watcher->disconnect(); + watcher->deleteLater(); + }); + watcher->setFuture(m_asyncUpdateFutureInterface.future()); const Kit *const k = kit(); QtSupport::BaseQtVersion *const qtVersion = QtSupport::QtKitAspect::qtVersion(k); diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index fe12f2d32e5..a697133896f 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -473,13 +473,28 @@ void QMakeEvaluator::runProcess(QProcess *proc, const QString &command) const proc->setProcessEnvironment(env); } # endif +# ifdef PROEVALUATOR_THREAD_SAFE + m_option->mutex.lock(); + if (m_option->canceled) { + m_option->mutex.unlock(); + return; + } + m_option->runningProcs << proc; +# endif # ifdef Q_OS_WIN proc->setNativeArguments(QLatin1String("/v:off /s /c \"") + command + QLatin1Char('"')); proc->start(m_option->getEnv(QLatin1String("COMSPEC")), QStringList()); # else proc->start(QLatin1String("/bin/sh"), QStringList() << QLatin1String("-c") << command); +# endif +# ifdef PROEVALUATOR_THREAD_SAFE + m_option->mutex.unlock(); # endif proc->waitForFinished(-1); +# ifdef PROEVALUATOR_THREAD_SAFE + QMutexLocker(&m_option->mutex); + m_option->runningProcs.removeOne(proc); +# endif } #endif @@ -490,7 +505,7 @@ QByteArray QMakeEvaluator::getCommandOutput(const QString &args, int *exitCode) QProcess proc; runProcess(&proc, args); *exitCode = (proc.exitStatus() == QProcess::NormalExit) ? proc.exitCode() : -1; - QByteArray errout = proc.readAllStandardError(); + QByteArray errout = proc.isReadable() ? proc.readAllStandardError() : QByteArray(); # ifdef PROEVALUATOR_FULL // FIXME: Qt really should have the option to set forwarding per channel fputs(errout.constData(), stderr); @@ -503,7 +518,7 @@ QByteArray QMakeEvaluator::getCommandOutput(const QString &args, int *exitCode) QString::fromLocal8Bit(errout)); } # endif - out = proc.readAllStandardOutput(); + out = proc.isReadable() ? proc.readAllStandardOutput() : QByteArray(); # ifdef Q_OS_WIN // FIXME: Qt's line end conversion on sequential files should really be fixed out.replace("\r\n", "\n"); diff --git a/src/shared/proparser/qmakeglobals.cpp b/src/shared/proparser/qmakeglobals.cpp index 07cb8be258f..ea429145e3c 100644 --- a/src/shared/proparser/qmakeglobals.cpp +++ b/src/shared/proparser/qmakeglobals.cpp @@ -89,6 +89,17 @@ QMakeGlobals::~QMakeGlobals() qDeleteAll(baseEnvs); } +void QMakeGlobals::killProcesses() +{ +#ifdef PROEVALUATOR_THREAD_SAFE + QMutexLocker lock(&mutex); + canceled = true; + for (QProcess * const proc : runningProcs) + proc->kill(); + runningProcs.clear(); +#endif +} + QString QMakeGlobals::cleanSpec(QMakeCmdLineParserState &state, const QString &spec) { QString ret = QDir::cleanPath(spec); diff --git a/src/shared/proparser/qmakeglobals.h b/src/shared/proparser/qmakeglobals.h index c8efbb22529..2fa9a332135 100644 --- a/src/shared/proparser/qmakeglobals.h +++ b/src/shared/proparser/qmakeglobals.h @@ -112,6 +112,8 @@ public: QString extra_cmds[4]; bool runSystemFunction = false; + void killProcesses(); + #ifdef PROEVALUATOR_DEBUG int debugLevel; #endif @@ -157,6 +159,8 @@ private: #ifdef PROEVALUATOR_THREAD_SAFE QMutex mutex; + bool canceled = false; + QList runningProcs; #endif QHash baseEnvs;