forked from qt-creator/qt-creator
Terminal: Use QWinEventNotifier for shell process termination
Change-Id: I59ddcaa76714a0b15987b9e0912f4701a2951648 Reviewed-by: Cristian Adam <cristian.adam@qt.io>
This commit is contained in:
committed by
Marcus Tillmanns
parent
3287e14dd1
commit
007c47a2d4
35
src/libs/3rdparty/libptyqt/conptyprocess.cpp
vendored
35
src/libs/3rdparty/libptyqt/conptyprocess.cpp
vendored
@@ -6,6 +6,7 @@
|
|||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QMutexLocker>
|
#include <QMutexLocker>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
#include <QWinEventNotifier>
|
||||||
|
|
||||||
#include <qt_windows.h>
|
#include <qt_windows.h>
|
||||||
|
|
||||||
@@ -179,21 +180,19 @@ bool ConPtyProcess::startProcess(const QString &executable,
|
|||||||
m_pid = m_shellProcessInformation.dwProcessId;
|
m_pid = m_shellProcessInformation.dwProcessId;
|
||||||
|
|
||||||
// Notify when the shell process has been terminated
|
// Notify when the shell process has been terminated
|
||||||
RegisterWaitForSingleObject(
|
m_shellCloseWaitNotifier = new QWinEventNotifier(m_shellProcessInformation.hProcess, notifier());
|
||||||
&m_shellCloseWaitHandle,
|
QObject::connect(m_shellCloseWaitNotifier,
|
||||||
m_shellProcessInformation.hProcess,
|
&QWinEventNotifier::activated,
|
||||||
[](PVOID data, BOOLEAN) {
|
notifier(),
|
||||||
auto self = static_cast<ConPtyProcess *>(data);
|
[this](HANDLE hEvent) {
|
||||||
DWORD exitCode = 0;
|
DWORD exitCode = 0;
|
||||||
GetExitCodeProcess(self->m_shellProcessInformation.hProcess, &exitCode);
|
GetExitCodeProcess(hEvent, &exitCode);
|
||||||
self->m_exitCode = exitCode;
|
m_exitCode = exitCode;
|
||||||
// Do not respawn if the object is about to be destructed
|
// Do not respawn if the object is about to be destructed
|
||||||
if (!self->m_aboutToDestruct)
|
if (!m_aboutToDestruct)
|
||||||
emit self->notifier()->aboutToClose();
|
emit notifier()->aboutToClose();
|
||||||
},
|
m_shellCloseWaitNotifier->setEnabled(false);
|
||||||
this,
|
});
|
||||||
INFINITE,
|
|
||||||
WT_EXECUTEONLYONCE);
|
|
||||||
|
|
||||||
//this code runned in separate thread
|
//this code runned in separate thread
|
||||||
m_readThread = QThread::create([this]()
|
m_readThread = QThread::create([this]()
|
||||||
@@ -220,6 +219,8 @@ bool ConPtyProcess::startProcess(const QString &executable,
|
|||||||
if (QThread::currentThread()->isInterruptionRequested() || brokenPipe)
|
if (QThread::currentThread()->isInterruptionRequested() || brokenPipe)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CancelIoEx(m_hPipeIn, nullptr);
|
||||||
});
|
});
|
||||||
|
|
||||||
//start read thread
|
//start read thread
|
||||||
@@ -269,6 +270,9 @@ bool ConPtyProcess::kill()
|
|||||||
m_readThread->deleteLater();
|
m_readThread->deleteLater();
|
||||||
m_readThread = nullptr;
|
m_readThread = nullptr;
|
||||||
|
|
||||||
|
delete m_shellCloseWaitNotifier;
|
||||||
|
m_shellCloseWaitNotifier = nullptr;
|
||||||
|
|
||||||
m_pid = 0;
|
m_pid = 0;
|
||||||
m_ptyHandler = INVALID_HANDLE_VALUE;
|
m_ptyHandler = INVALID_HANDLE_VALUE;
|
||||||
m_hPipeIn = INVALID_HANDLE_VALUE;
|
m_hPipeIn = INVALID_HANDLE_VALUE;
|
||||||
@@ -276,7 +280,6 @@ bool ConPtyProcess::kill()
|
|||||||
|
|
||||||
CloseHandle(m_shellProcessInformation.hThread);
|
CloseHandle(m_shellProcessInformation.hThread);
|
||||||
CloseHandle(m_shellProcessInformation.hProcess);
|
CloseHandle(m_shellProcessInformation.hProcess);
|
||||||
UnregisterWait(m_shellCloseWaitHandle);
|
|
||||||
|
|
||||||
// Cleanup attribute list
|
// Cleanup attribute list
|
||||||
if (m_shellStartupInfo.lpAttributeList) {
|
if (m_shellStartupInfo.lpAttributeList) {
|
||||||
|
4
src/libs/3rdparty/libptyqt/conptyprocess.h
vendored
4
src/libs/3rdparty/libptyqt/conptyprocess.h
vendored
@@ -23,6 +23,8 @@ typedef VOID* HPCON;
|
|||||||
#define TOO_OLD_WINSDK
|
#define TOO_OLD_WINSDK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
class QWinEventNotifier;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::vector<T> vectorFromString(const std::basic_string<T> &str)
|
std::vector<T> vectorFromString(const std::basic_string<T> &str)
|
||||||
{
|
{
|
||||||
@@ -160,7 +162,7 @@ private:
|
|||||||
PtyBuffer m_buffer;
|
PtyBuffer m_buffer;
|
||||||
bool m_aboutToDestruct{false};
|
bool m_aboutToDestruct{false};
|
||||||
PROCESS_INFORMATION m_shellProcessInformation{};
|
PROCESS_INFORMATION m_shellProcessInformation{};
|
||||||
HANDLE m_shellCloseWaitHandle{INVALID_HANDLE_VALUE};
|
QWinEventNotifier* m_shellCloseWaitNotifier;
|
||||||
STARTUPINFOEX m_shellStartupInfo{};
|
STARTUPINFOEX m_shellStartupInfo{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
36
src/libs/3rdparty/libptyqt/winptyprocess.cpp
vendored
36
src/libs/3rdparty/libptyqt/winptyprocess.cpp
vendored
@@ -3,6 +3,8 @@
|
|||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
#include <QLocalSocket>
|
||||||
|
#include <QWinEventNotifier>
|
||||||
|
|
||||||
#define DEBUG_VAR_LEGACY "WINPTYDBG"
|
#define DEBUG_VAR_LEGACY "WINPTYDBG"
|
||||||
#define DEBUG_VAR_ACTUAL "WINPTY_DEBUG"
|
#define DEBUG_VAR_ACTUAL "WINPTY_DEBUG"
|
||||||
@@ -132,22 +134,22 @@ bool WinPtyProcess::startProcess(const QString &executable,
|
|||||||
|
|
||||||
m_pid = (int)GetProcessId(m_innerHandle);
|
m_pid = (int)GetProcessId(m_innerHandle);
|
||||||
|
|
||||||
|
m_outSocket = new QLocalSocket();
|
||||||
|
|
||||||
// Notify when the shell process has been terminated
|
// Notify when the shell process has been terminated
|
||||||
RegisterWaitForSingleObject(
|
m_shellCloseWaitNotifier = new QWinEventNotifier(m_innerHandle, notifier());
|
||||||
&m_shellCloseWaitHandle,
|
QObject::connect(m_shellCloseWaitNotifier,
|
||||||
m_innerHandle,
|
&QWinEventNotifier::activated,
|
||||||
[](PVOID data, BOOLEAN) {
|
notifier(),
|
||||||
auto self = static_cast<WinPtyProcess *>(data);
|
[this](HANDLE hEvent) {
|
||||||
// Do not respawn if the object is about to be destructed
|
DWORD exitCode = 0;
|
||||||
DWORD exitCode = 0;
|
GetExitCodeProcess(hEvent, &exitCode);
|
||||||
GetExitCodeProcess(self->m_innerHandle, &exitCode);
|
m_exitCode = exitCode;
|
||||||
self->m_exitCode = exitCode;
|
// Do not respawn if the object is about to be destructed
|
||||||
if (!self->m_aboutToDestruct)
|
if (!m_aboutToDestruct)
|
||||||
emit self->notifier()->aboutToClose();
|
emit notifier()->aboutToClose();
|
||||||
},
|
m_shellCloseWaitNotifier->setEnabled(false);
|
||||||
this,
|
});
|
||||||
INFINITE,
|
|
||||||
WT_EXECUTEONLYONCE);
|
|
||||||
|
|
||||||
//get pipe names
|
//get pipe names
|
||||||
LPCWSTR conInPipeName = winpty_conin_name(m_ptyHandler);
|
LPCWSTR conInPipeName = winpty_conin_name(m_ptyHandler);
|
||||||
@@ -158,7 +160,6 @@ bool WinPtyProcess::startProcess(const QString &executable,
|
|||||||
|
|
||||||
LPCWSTR conOutPipeName = winpty_conout_name(m_ptyHandler);
|
LPCWSTR conOutPipeName = winpty_conout_name(m_ptyHandler);
|
||||||
m_conOutName = QString::fromStdWString(std::wstring(conOutPipeName));
|
m_conOutName = QString::fromStdWString(std::wstring(conOutPipeName));
|
||||||
m_outSocket = new QLocalSocket();
|
|
||||||
m_outSocket->connectToServer(m_conOutName, QIODevice::ReadOnly);
|
m_outSocket->connectToServer(m_conOutName, QIODevice::ReadOnly);
|
||||||
m_outSocket->waitForConnected();
|
m_outSocket->waitForConnected();
|
||||||
|
|
||||||
@@ -214,7 +215,8 @@ bool WinPtyProcess::kill()
|
|||||||
winpty_free(m_ptyHandler);
|
winpty_free(m_ptyHandler);
|
||||||
exitCode = CloseHandle(m_innerHandle);
|
exitCode = CloseHandle(m_innerHandle);
|
||||||
|
|
||||||
UnregisterWait(m_shellCloseWaitHandle);
|
delete m_shellCloseWaitNotifier;
|
||||||
|
m_shellCloseWaitNotifier = nullptr;
|
||||||
|
|
||||||
m_ptyHandler = nullptr;
|
m_ptyHandler = nullptr;
|
||||||
m_innerHandle = nullptr;
|
m_innerHandle = nullptr;
|
||||||
|
5
src/libs/3rdparty/libptyqt/winptyprocess.h
vendored
5
src/libs/3rdparty/libptyqt/winptyprocess.h
vendored
@@ -4,7 +4,8 @@
|
|||||||
#include "iptyprocess.h"
|
#include "iptyprocess.h"
|
||||||
#include "winpty.h"
|
#include "winpty.h"
|
||||||
|
|
||||||
#include <QLocalSocket>
|
class QLocalSocket;
|
||||||
|
class QWinEventNotifier;
|
||||||
|
|
||||||
class WinPtyProcess : public IPtyProcess
|
class WinPtyProcess : public IPtyProcess
|
||||||
{
|
{
|
||||||
@@ -36,7 +37,7 @@ private:
|
|||||||
QLocalSocket *m_inSocket;
|
QLocalSocket *m_inSocket;
|
||||||
QLocalSocket *m_outSocket;
|
QLocalSocket *m_outSocket;
|
||||||
bool m_aboutToDestruct{false};
|
bool m_aboutToDestruct{false};
|
||||||
HANDLE m_shellCloseWaitHandle{INVALID_HANDLE_VALUE};
|
QWinEventNotifier* m_shellCloseWaitNotifier;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // WINPTYPROCESS_H
|
#endif // WINPTYPROCESS_H
|
||||||
|
Reference in New Issue
Block a user