From 7e7b6a52f9bbe105e08b7860ae993a1faa45d636 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Fri, 1 Oct 2021 10:56:52 +0200 Subject: [PATCH] Don't kill the QProcess instance which is running in other thread The main thread doesn't kill processes directly, but sets just the cancel flag. Instead of waiting infinitely long for a process to finish we poll periodically (every 100ms) for the canceled flag inside the thread that started the process. Amends: a30aa4421a0257b048197b51330e6bf5c2732af5 Task-number: QTCREATORBUG-26333 Change-Id: I599d5c6cd69381cadc4a01c65f6a79f9a9bbd3fb Reviewed-by: Eike Ziller Reviewed-by: Qt CI Bot Reviewed-by: Christian Kandeler --- .../qmakeprojectmanager/qmakeproject.cpp | 3 ++- src/shared/proparser/qmakebuiltins.cpp | 27 +++++++++++-------- src/shared/proparser/qmakeglobals.cpp | 4 --- src/shared/proparser/qmakeglobals.h | 3 +-- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index 793ec73ba86..54395bfc37b 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -674,8 +674,9 @@ void QmakeBuildSystem::asyncUpdate() connect(watcher, &QFutureWatcher::canceled, this, [this, watcher] { if (!m_qmakeGlobals) return; - watcher->disconnect(); m_qmakeGlobals->killProcesses(); + watcher->disconnect(); + watcher->deleteLater(); }); connect(watcher, &QFutureWatcher::finished, this, [watcher] { watcher->disconnect(); diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index a697133896f..c47bc1b2e72 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -474,12 +474,8 @@ void QMakeEvaluator::runProcess(QProcess *proc, const QString &command) const } # endif # ifdef PROEVALUATOR_THREAD_SAFE - m_option->mutex.lock(); - if (m_option->canceled) { - m_option->mutex.unlock(); + if (m_option->canceled) return; - } - m_option->runningProcs << proc; # endif # ifdef Q_OS_WIN proc->setNativeArguments(QLatin1String("/v:off /s /c \"") + command + QLatin1Char('"')); @@ -488,12 +484,21 @@ void QMakeEvaluator::runProcess(QProcess *proc, const QString &command) const 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); + while (true) { + if (proc->waitForFinished(100)) + break; + if (m_option->canceled) { + proc->terminate(); + if (proc->waitForFinished(1000)) + break; + proc->kill(); + proc->waitForFinished(1000); + break; + } + } +# else + proc->waitForFinished(-1); // If have have single thread we can't cancel it using + // synchronous API of QProcess # endif } #endif diff --git a/src/shared/proparser/qmakeglobals.cpp b/src/shared/proparser/qmakeglobals.cpp index ea429145e3c..ca22bdde8b7 100644 --- a/src/shared/proparser/qmakeglobals.cpp +++ b/src/shared/proparser/qmakeglobals.cpp @@ -92,11 +92,7 @@ QMakeGlobals::~QMakeGlobals() void QMakeGlobals::killProcesses() { #ifdef PROEVALUATOR_THREAD_SAFE - QMutexLocker lock(&mutex); canceled = true; - for (QProcess * const proc : runningProcs) - proc->kill(); - runningProcs.clear(); #endif } diff --git a/src/shared/proparser/qmakeglobals.h b/src/shared/proparser/qmakeglobals.h index 2fa9a332135..2baeab4bf58 100644 --- a/src/shared/proparser/qmakeglobals.h +++ b/src/shared/proparser/qmakeglobals.h @@ -159,8 +159,7 @@ private: #ifdef PROEVALUATOR_THREAD_SAFE QMutex mutex; - bool canceled = false; - QList runningProcs; + std::atomic_bool canceled = false; #endif QHash baseEnvs;