forked from qt-creator/qt-creator
WinDebugInterface: Remove windows.h from header, resource cleanup.
Proper termination.
This commit is contained in:
@@ -32,6 +32,20 @@
|
|||||||
|
|
||||||
#include "windebuginterface.h"
|
#include "windebuginterface.h"
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class ProjectExplorer::Internal::WinDebugInterface
|
||||||
|
\brief Windows: Captures output of the Windows API OutputDebugString() function.
|
||||||
|
|
||||||
|
Emits output by process id.
|
||||||
|
|
||||||
|
OutputDebugString puts its data into a shared memory segment named
|
||||||
|
\c DBWIN_BUFFER which can be accessed via file mapping.
|
||||||
|
|
||||||
|
\sa ProjectExplorer::Internal::WinGuiProcess
|
||||||
|
*/
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -42,58 +56,80 @@ WinDebugInterface *WinDebugInterface::instance()
|
|||||||
return m_instance;
|
return m_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
WinDebugInterface::WinDebugInterface(QObject *parent) :
|
WinDebugInterface::WinDebugInterface(QObject *parent) :
|
||||||
QThread(parent)
|
QThread(parent)
|
||||||
{
|
{
|
||||||
m_instance = this;
|
m_instance = this;
|
||||||
|
setObjectName(QLatin1String("WinDebugInterfaceThread"));
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
WinDebugInterface::~WinDebugInterface()
|
WinDebugInterface::~WinDebugInterface()
|
||||||
{
|
{
|
||||||
terminate(); // Creator is shutting down anyway, no need to clean up.
|
if (m_waitHandles[TerminateEventHandle]) {
|
||||||
wait(500);
|
SetEvent(m_waitHandles[TerminateEventHandle]);
|
||||||
|
wait(500);
|
||||||
|
}
|
||||||
|
m_instance = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WinDebugInterface::run()
|
void WinDebugInterface::run()
|
||||||
{
|
{
|
||||||
HANDLE bufferReadyEvent = CreateEvent(NULL, FALSE, FALSE, L"DBWIN_BUFFER_READY");
|
m_waitHandles[DataReadyEventHandle] = m_waitHandles[TerminateEventHandle] = 0;
|
||||||
if (!bufferReadyEvent)
|
m_bufferReadyEvent = 0;
|
||||||
return;
|
m_sharedFile = 0;
|
||||||
HANDLE dataReadyEvent = CreateEvent(NULL, FALSE, FALSE, L"DBWIN_DATA_READY");
|
m_sharedMem = 0;
|
||||||
if (!dataReadyEvent) {
|
runLoop();
|
||||||
CloseHandle(bufferReadyEvent);
|
if (m_sharedMem) {
|
||||||
return;
|
UnmapViewOfFile(m_sharedMem);
|
||||||
|
m_sharedMem = 0;
|
||||||
}
|
}
|
||||||
HANDLE sharedFile = CreateFileMapping((HANDLE)-1, NULL, PAGE_READWRITE, 0, 4096, L"DBWIN_BUFFER");
|
if (m_sharedFile) {
|
||||||
if (!sharedFile) {
|
CloseHandle(m_sharedFile);
|
||||||
CloseHandle(dataReadyEvent);
|
m_sharedFile = 0;
|
||||||
CloseHandle(bufferReadyEvent);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
LPVOID sharedMem = MapViewOfFile(sharedFile, FILE_MAP_READ, 0, 0, 512);
|
if (m_waitHandles[TerminateEventHandle]) {
|
||||||
if (!sharedMem) {
|
CloseHandle(m_waitHandles[TerminateEventHandle]);
|
||||||
CloseHandle(sharedFile);
|
m_waitHandles[TerminateEventHandle] = 0;
|
||||||
CloseHandle(dataReadyEvent);
|
|
||||||
CloseHandle(bufferReadyEvent);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
if (m_waitHandles[DataReadyEventHandle]) {
|
||||||
|
CloseHandle(m_waitHandles[DataReadyEventHandle]);
|
||||||
|
m_waitHandles[DataReadyEventHandle] = 0;
|
||||||
|
}
|
||||||
|
if (m_bufferReadyEvent) {
|
||||||
|
CloseHandle(m_bufferReadyEvent);
|
||||||
|
m_bufferReadyEvent = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LPSTR message;
|
void WinDebugInterface::runLoop()
|
||||||
LPDWORD processId;
|
{
|
||||||
|
m_waitHandles[TerminateEventHandle] = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
m_waitHandles[DataReadyEventHandle] = CreateEvent(NULL, FALSE, FALSE, L"DBWIN_DATA_READY");
|
||||||
|
if (!m_waitHandles[TerminateEventHandle] || !m_waitHandles[DataReadyEventHandle])
|
||||||
|
return;
|
||||||
|
m_bufferReadyEvent = CreateEvent(NULL, FALSE, FALSE, L"DBWIN_BUFFER_READY");
|
||||||
|
if (!m_bufferReadyEvent)
|
||||||
|
return;
|
||||||
|
m_sharedFile = CreateFileMapping((HANDLE)-1, NULL, PAGE_READWRITE, 0, 4096, L"DBWIN_BUFFER");
|
||||||
|
if (!m_sharedFile)
|
||||||
|
return;
|
||||||
|
m_sharedMem = MapViewOfFile(m_sharedFile, FILE_MAP_READ, 0, 0, 512);
|
||||||
|
if (!m_sharedMem)
|
||||||
|
return;
|
||||||
|
|
||||||
message = reinterpret_cast<LPSTR>(sharedMem) + sizeof(DWORD);
|
LPSTR message = reinterpret_cast<LPSTR>(m_sharedMem) + sizeof(DWORD);
|
||||||
processId = reinterpret_cast<LPDWORD>(sharedMem);
|
LPDWORD processId = reinterpret_cast<LPDWORD>(m_sharedMem);
|
||||||
|
|
||||||
SetEvent(bufferReadyEvent);
|
SetEvent(m_bufferReadyEvent);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
DWORD ret = WaitForSingleObject(dataReadyEvent, INFINITE);
|
const DWORD ret = WaitForMultipleObjects(HandleCount, m_waitHandles, FALSE, INFINITE);
|
||||||
|
if (ret == WAIT_FAILED || ret - WAIT_OBJECT_0 == TerminateEventHandle)
|
||||||
if (ret == WAIT_OBJECT_0) {
|
break;
|
||||||
|
if (ret - WAIT_OBJECT_0 == DataReadyEventHandle) {
|
||||||
emit debugOutput(*processId, QString::fromLocal8Bit(message));
|
emit debugOutput(*processId, QString::fromLocal8Bit(message));
|
||||||
SetEvent(bufferReadyEvent);
|
SetEvent(m_bufferReadyEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,8 +35,6 @@
|
|||||||
|
|
||||||
#include <QtCore/QThread>
|
#include <QtCore/QThread>
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -54,9 +52,17 @@ signals:
|
|||||||
void debugOutput(qint64 pid, const QString &message);
|
void debugOutput(qint64 pid, const QString &message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum Handles { DataReadyEventHandle, TerminateEventHandle, HandleCount };
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
|
void runLoop();
|
||||||
|
|
||||||
static WinDebugInterface *m_instance;
|
static WinDebugInterface *m_instance;
|
||||||
|
|
||||||
|
Qt::HANDLE m_waitHandles[HandleCount];
|
||||||
|
Qt::HANDLE m_bufferReadyEvent;
|
||||||
|
Qt::HANDLE m_sharedFile;
|
||||||
|
void *m_sharedMem;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ using namespace ProjectExplorer::Internal;
|
|||||||
|
|
||||||
The output of a Windows GUI application would otherwise not be
|
The output of a Windows GUI application would otherwise not be
|
||||||
visible. Uses the debug interface and emits via a signal.
|
visible. Uses the debug interface and emits via a signal.
|
||||||
|
|
||||||
|
\sa ProjectExplorer::Internal::WinDebugInterface
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WinGuiProcess::WinGuiProcess(QObject *parent) :
|
WinGuiProcess::WinGuiProcess(QObject *parent) :
|
||||||
|
|||||||
Reference in New Issue
Block a user