WinDebugInterface: Remove windows.h from header, resource cleanup.

Proper termination.
This commit is contained in:
Friedemann Kleint
2011-04-20 10:12:17 +02:00
parent a04997a630
commit e1f93aff18
3 changed files with 76 additions and 32 deletions

View File

@@ -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);
} }
} }
} }

View File

@@ -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

View File

@@ -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) :