forked from qt-creator/qt-creator
Utils: Allow graceful termination of reaped processes
Utils::Internal::Reaper class is doing graceful termination of
process. It tries in a loop to first terminate() then kill()
the process and at the end delete the object.
Utils::ProcessReapder::reap should not kill the process directly,
and now that the function works with a QProcess, the special
handling of QtcProcess::terminat() of qtcreator_ctrlc_stub.exe
processes needs to be handled explicitly.
Amends ace765c199
Fixes: QTCREATORBUG-26612
Change-Id: Ia109ec0737a8c605a84e93b6ee3691d843ed5da8
Reviewed-by: David Schulz <david.schulz@qt.io>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -31,6 +31,13 @@
|
|||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#ifdef QTCREATOR_PCH_H
|
||||||
|
#define CALLBACK WINAPI
|
||||||
|
#endif
|
||||||
|
#include <qt_windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
@@ -83,6 +90,26 @@ bool Reaper::isFinished() const
|
|||||||
return !m_process;
|
return !m_process;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
static BOOL sendMessage(UINT message, HWND hwnd, LPARAM lParam)
|
||||||
|
{
|
||||||
|
DWORD dwProcessID;
|
||||||
|
GetWindowThreadProcessId(hwnd, &dwProcessID);
|
||||||
|
if ((DWORD)lParam == dwProcessID) {
|
||||||
|
SendNotifyMessage(hwnd, message, 0, 0);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL CALLBACK sendShutDownMessageToAllWindowsOfProcess_enumWnd(HWND hwnd, LPARAM lParam)
|
||||||
|
{
|
||||||
|
static UINT uiShutDownMessage = RegisterWindowMessage(L"qtcctrlcstub_shutdown");
|
||||||
|
return sendMessage(uiShutDownMessage, hwnd, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
void Reaper::nextIteration()
|
void Reaper::nextIteration()
|
||||||
{
|
{
|
||||||
QProcess::ProcessState state = m_process ? m_process->state() : QProcess::NotRunning;
|
QProcess::ProcessState state = m_process ? m_process->state() : QProcess::NotRunning;
|
||||||
@@ -96,10 +123,15 @@ void Reaper::nextIteration()
|
|||||||
if (m_lastState == QProcess::Starting)
|
if (m_lastState == QProcess::Starting)
|
||||||
m_process->kill();
|
m_process->kill();
|
||||||
} else if (state == QProcess::Running) {
|
} else if (state == QProcess::Running) {
|
||||||
if (m_lastState == QProcess::Running)
|
if (m_lastState == QProcess::Running) {
|
||||||
m_process->kill();
|
m_process->kill();
|
||||||
else
|
} else if (m_process->program().endsWith(QLatin1String("qtcreator_ctrlc_stub.exe"))) {
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
EnumWindows(sendShutDownMessageToAllWindowsOfProcess_enumWnd, m_process->processId());
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
m_process->terminate();
|
m_process->terminate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lastState = state;
|
m_lastState = state;
|
||||||
@@ -149,10 +181,7 @@ void ProcessReaper::reap(QProcess *process, int timeoutMs)
|
|||||||
if (process->state() == QProcess::NotRunning) {
|
if (process->state() == QProcess::NotRunning) {
|
||||||
process->deleteLater();
|
process->deleteLater();
|
||||||
return;
|
return;
|
||||||
} else {
|
|
||||||
process->kill();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Neither can move object with a parent into a different thread
|
// Neither can move object with a parent into a different thread
|
||||||
// nor reaping the process with a parent makes any sense.
|
// nor reaping the process with a parent makes any sense.
|
||||||
process->setParent(nullptr);
|
process->setParent(nullptr);
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ QtcTool {
|
|||||||
|
|
||||||
cpp.defines: base.concat("QTCREATOR_UTILS_STATIC_LIB")
|
cpp.defines: base.concat("QTCREATOR_UTILS_STATIC_LIB")
|
||||||
cpp.includePaths: base.concat(pathToUtils)
|
cpp.includePaths: base.concat(pathToUtils)
|
||||||
|
cpp.dynamicLibraries: [
|
||||||
|
"user32",
|
||||||
|
]
|
||||||
|
|
||||||
files: [
|
files: [
|
||||||
"launcherlogging.cpp",
|
"launcherlogging.cpp",
|
||||||
|
|||||||
Reference in New Issue
Block a user