From 00298ab24823a8cf922b693492929eac4ea71180 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint <Friedemann.Kleint@nokia.com> Date: Wed, 4 Nov 2009 15:19:02 +0100 Subject: [PATCH] WinGuiProcess: Fix hang if binary cannot be found. ..occurring in conjunction with custom run configuration and S60 emulator. Ensure all handles are closed even if start attempt failed. Reviewed-by: con <qtc-committer@nokia.com> --- src/plugins/projectexplorer/winguiprocess.cpp | 123 ++++++++++-------- src/plugins/projectexplorer/winguiprocess.h | 3 + 2 files changed, 69 insertions(+), 57 deletions(-) diff --git a/src/plugins/projectexplorer/winguiprocess.cpp b/src/plugins/projectexplorer/winguiprocess.cpp index 961a352dbe6..71ea57a749f 100644 --- a/src/plugins/projectexplorer/winguiprocess.cpp +++ b/src/plugins/projectexplorer/winguiprocess.cpp @@ -101,72 +101,81 @@ void WinGuiProcess::run() ZeroMemory(m_pid, sizeof(PROCESS_INFORMATION)); m_exitCode = 0; + bool started = false; HANDLE bufferReadyEvent = NULL; HANDLE dataReadyEvent = NULL; HANDLE sharedFile = NULL; - LPVOID sharedMem = NULL; - - bool dbgInterface = setupDebugInterface(bufferReadyEvent, dataReadyEvent, sharedFile, sharedMem); - - QString cmdLine = createWinCommandline(m_program, m_args); - bool success = CreateProcessW(0, (WCHAR*)cmdLine.utf16(), - 0, 0, TRUE, CREATE_UNICODE_ENVIRONMENT, - environment().isEmpty() ? 0 - : createWinEnvironment(fixWinEnvironment(environment())).data(), - workingDirectory().isEmpty() ? 0 - : (WCHAR*)QDir::convertSeparators(workingDirectory()).utf16(), - &si, m_pid); - - if (!success) { - emit processError(tr("The process could not be started!")); - delete m_pid; - m_pid = 0; - return; - } + LPVOID sharedMem = 0; - if (!dbgInterface) { - emit receivedDebugOutput(tr("Cannot retrieve debugging output!")); - WaitForSingleObject(m_pid->hProcess, INFINITE); - } else { - LPSTR message; - LPDWORD processId; - HANDLE toWaitFor[2]; - - message = reinterpret_cast<LPSTR>(sharedMem) + sizeof(DWORD); - processId = reinterpret_cast<LPDWORD>(sharedMem); - - SetEvent(bufferReadyEvent); - - toWaitFor[0] = dataReadyEvent; - toWaitFor[1] = m_pid->hProcess; - - for (bool stop = false; !stop;) { - DWORD ret = WaitForMultipleObjects(2, toWaitFor, FALSE, INFINITE); - - switch (ret) { - case WAIT_OBJECT_0 + 0: - if (*processId == m_pid->dwProcessId) - emit receivedDebugOutput(QString::fromLocal8Bit(message)); - SetEvent(bufferReadyEvent); - break; - case WAIT_OBJECT_0 + 1: - stop = true; - break; - } + do { + + const bool dbgInterface = setupDebugInterface(bufferReadyEvent, dataReadyEvent, sharedFile, sharedMem); + + const QString cmdLine = createWinCommandline(m_program, m_args); + started = CreateProcessW(0, (WCHAR*)cmdLine.utf16(), + 0, 0, TRUE, CREATE_UNICODE_ENVIRONMENT, + environment().isEmpty() ? 0 + : createWinEnvironment(fixWinEnvironment(environment())).data(), + workingDirectory().isEmpty() ? 0 + : (WCHAR*)QDir::convertSeparators(workingDirectory()).utf16(), + &si, m_pid); + + if (!started) { + emit processError(tr("The process could not be started!")); + break; } - } - GetExitCodeProcess(m_pid->hProcess, &m_exitCode); - emit processFinished(static_cast<int>(m_exitCode)); + if (!dbgInterface) { + emit receivedDebugOutput(tr("Cannot retrieve debugging output!")); + WaitForSingleObject(m_pid->hProcess, INFINITE); + } else { + LPSTR message; + LPDWORD processId; + HANDLE toWaitFor[2]; + + message = reinterpret_cast<LPSTR>(sharedMem) + sizeof(DWORD); + processId = reinterpret_cast<LPDWORD>(sharedMem); + + SetEvent(bufferReadyEvent); + + toWaitFor[0] = dataReadyEvent; + toWaitFor[1] = m_pid->hProcess; + + for (bool stop = false; !stop;) { + DWORD ret = WaitForMultipleObjects(2, toWaitFor, FALSE, INFINITE); + + switch (ret) { + case WAIT_OBJECT_0 + 0: + if (*processId == m_pid->dwProcessId) + emit receivedDebugOutput(QString::fromLocal8Bit(message)); + SetEvent(bufferReadyEvent); + break; + case WAIT_OBJECT_0 + 1: + stop = true; + break; + } + } + } + } while (false); - UnmapViewOfFile(sharedMem); - CloseHandle(sharedFile); - CloseHandle(bufferReadyEvent); - CloseHandle(dataReadyEvent); - CloseHandle(m_pid->hProcess); - CloseHandle(m_pid->hThread); + if (started) { + GetExitCodeProcess(m_pid->hProcess, &m_exitCode); + emit processFinished(static_cast<int>(m_exitCode)); + } + if (sharedMem) + UnmapViewOfFile(sharedMem); + if (sharedFile != NULL) + CloseHandle(sharedFile); + if (bufferReadyEvent != NULL) + CloseHandle(bufferReadyEvent); + if (dataReadyEvent != NULL) + CloseHandle(dataReadyEvent); + if (m_pid->hProcess != NULL) + CloseHandle(m_pid->hProcess); + if (m_pid->hThread != NULL) + CloseHandle(m_pid->hThread); delete m_pid; m_pid = 0; } diff --git a/src/plugins/projectexplorer/winguiprocess.h b/src/plugins/projectexplorer/winguiprocess.h index 460651ff12c..c3ffee1e772 100644 --- a/src/plugins/projectexplorer/winguiprocess.h +++ b/src/plugins/projectexplorer/winguiprocess.h @@ -42,6 +42,9 @@ using namespace Utils; namespace ProjectExplorer { namespace Internal { +/* Captures the debug output of a Windows GUI application (which + * would otherwise not be visible) using the debug interface and + * emits via a signal. */ class WinGuiProcess : public QThread, public AbstractProcess { Q_OBJECT -- GitLab