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: a30aa4421a

Task-number: QTCREATORBUG-26333
Change-Id: I599d5c6cd69381cadc4a01c65f6a79f9a9bbd3fb
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
Jarek Kobus
2021-10-01 10:56:52 +02:00
parent 704a758f69
commit 7e7b6a52f9
4 changed files with 19 additions and 18 deletions

View File

@@ -674,8 +674,9 @@ void QmakeBuildSystem::asyncUpdate()
connect(watcher, &QFutureWatcher<void>::canceled, this, [this, watcher] { connect(watcher, &QFutureWatcher<void>::canceled, this, [this, watcher] {
if (!m_qmakeGlobals) if (!m_qmakeGlobals)
return; return;
watcher->disconnect();
m_qmakeGlobals->killProcesses(); m_qmakeGlobals->killProcesses();
watcher->disconnect();
watcher->deleteLater();
}); });
connect(watcher, &QFutureWatcher<void>::finished, this, [watcher] { connect(watcher, &QFutureWatcher<void>::finished, this, [watcher] {
watcher->disconnect(); watcher->disconnect();

View File

@@ -474,12 +474,8 @@ void QMakeEvaluator::runProcess(QProcess *proc, const QString &command) const
} }
# endif # endif
# ifdef PROEVALUATOR_THREAD_SAFE # ifdef PROEVALUATOR_THREAD_SAFE
m_option->mutex.lock(); if (m_option->canceled)
if (m_option->canceled) {
m_option->mutex.unlock();
return; return;
}
m_option->runningProcs << proc;
# endif # endif
# ifdef Q_OS_WIN # ifdef Q_OS_WIN
proc->setNativeArguments(QLatin1String("/v:off /s /c \"") + command + QLatin1Char('"')); 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); proc->start(QLatin1String("/bin/sh"), QStringList() << QLatin1String("-c") << command);
# endif # endif
# ifdef PROEVALUATOR_THREAD_SAFE # ifdef PROEVALUATOR_THREAD_SAFE
m_option->mutex.unlock(); while (true) {
# endif if (proc->waitForFinished(100))
proc->waitForFinished(-1); break;
# ifdef PROEVALUATOR_THREAD_SAFE if (m_option->canceled) {
QMutexLocker(&m_option->mutex); proc->terminate();
m_option->runningProcs.removeOne(proc); 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
} }
#endif #endif

View File

@@ -92,11 +92,7 @@ QMakeGlobals::~QMakeGlobals()
void QMakeGlobals::killProcesses() void QMakeGlobals::killProcesses()
{ {
#ifdef PROEVALUATOR_THREAD_SAFE #ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker lock(&mutex);
canceled = true; canceled = true;
for (QProcess * const proc : runningProcs)
proc->kill();
runningProcs.clear();
#endif #endif
} }

View File

@@ -159,8 +159,7 @@ private:
#ifdef PROEVALUATOR_THREAD_SAFE #ifdef PROEVALUATOR_THREAD_SAFE
QMutex mutex; QMutex mutex;
bool canceled = false; std::atomic_bool canceled = false;
QList<QProcess *> runningProcs;
#endif #endif
QHash<QMakeBaseKey, QMakeBaseEnv *> baseEnvs; QHash<QMakeBaseKey, QMakeBaseEnv *> baseEnvs;