From 6650275e764df8fe5c623e73881b188ea603dc1e Mon Sep 17 00:00:00 2001
From: Friedemann Kleint <Friedemann.Kleint@nokia.com>
Date: Thu, 2 Sep 2010 13:39:19 +0200
Subject: [PATCH] Debugger/Console stub: Pass on main thread id on Windows.

Introduce private class to utils/ConsoloProcess as not to expose
<windows.h> from its header.

Task-number: QTCREATORBUG-1020
---
 src/libs/utils/consoleprocess.cpp      |   4 +-
 src/libs/utils/consoleprocess.h        |  51 ++----
 src/libs/utils/consoleprocess_unix.cpp | 180 ++++++++++++++--------
 src/libs/utils/consoleprocess_win.cpp  | 205 ++++++++++++++++---------
 src/libs/utils/process_stub_win.c      |   1 +
 5 files changed, 265 insertions(+), 176 deletions(-)

diff --git a/src/libs/utils/consoleprocess.cpp b/src/libs/utils/consoleprocess.cpp
index 9c7ef9b4ba5..c721cba3cc6 100644
--- a/src/libs/utils/consoleprocess.cpp
+++ b/src/libs/utils/consoleprocess.cpp
@@ -66,9 +66,9 @@ QString ConsoleProcess::msgCannotCreateTempDir(const QString & dir, const QStrin
     return tr("Cannot create temporary directory '%1': %2").arg(dir, why);
 }
 
-QString ConsoleProcess::msgUnexpectedOutput()
+QString ConsoleProcess::msgUnexpectedOutput(const QByteArray &what)
 {
-    return tr("Unexpected output from helper program.");
+    return tr("Unexpected output from helper program (%1).").arg(QString::fromAscii(what));
 }
 
 QString ConsoleProcess::msgCannotChangeToWorkDir(const QString & dir, const QString &why)
diff --git a/src/libs/utils/consoleprocess.h b/src/libs/utils/consoleprocess.h
index a4b2fd902db..ced9aa352ec 100644
--- a/src/libs/utils/consoleprocess.h
+++ b/src/libs/utils/consoleprocess.h
@@ -36,22 +36,14 @@
 #include <QtCore/QString>
 #include <QtCore/QStringList>
 #include <QtCore/QProcess>
-
-#include <QtNetwork/QLocalServer>
-
-#ifdef Q_OS_WIN
-#include <windows.h>
-QT_BEGIN_NAMESPACE
-class QWinEventNotifier;
-QT_END_NAMESPACE
-#endif
+#include <QtCore/QScopedPointer>
 
 QT_BEGIN_NAMESPACE
 class QSettings;
-class QTemporaryFile;
 QT_END_NAMESPACE
 
 namespace Utils {
+struct ConsoleProcessPrivate;
 
 class QTCREATOR_UTILS_EXPORT ConsoleProcess : public QObject, public AbstractProcess
 {
@@ -65,16 +57,21 @@ public:
     bool start(const QString &program, const QStringList &args);
     void stop();
 
-    void setMode(Mode m) { m_mode = m; }
-    Mode mode() const { return m_mode; }
+    void setMode(Mode m);
+    Mode mode() const;
 
     bool isRunning() const; // This reflects the state of the console+stub
-    qint64 applicationPID() const { return m_appPid; }
-    int exitCode() const { return m_appCode; } // This will be the signal number if exitStatus == CrashExit
-    QProcess::ExitStatus exitStatus() const { return m_appStatus; }
+    qint64 applicationPID() const;
+
+#ifdef Q_OS_WIN
+    qint64 applicationMainThreadID() const;
+#endif
+
+    int exitCode() const;
+    QProcess::ExitStatus exitStatus() const;
 
 #ifdef Q_OS_UNIX
-    void setSettings(QSettings *settings) { m_settings = settings; }
+    void setSettings(QSettings *settings);
     static QString defaultTerminalEmulator();
     static QString terminalEmulator(const QSettings *settings);
     static void setTerminalEmulator(QSettings *settings, const QString &term);
@@ -104,7 +101,7 @@ private:
     static QString msgPromptToClose();
     static QString msgCannotCreateTempFile(const QString &why);
     static QString msgCannotCreateTempDir(const QString & dir, const QString &why);
-    static QString msgUnexpectedOutput();
+    static QString msgUnexpectedOutput(const QByteArray &what);
     static QString msgCannotChangeToWorkDir(const QString & dir, const QString &why);
     static QString msgCannotExecute(const QString & p, const QString &why);
 
@@ -115,25 +112,7 @@ private:
     void cleanupInferior();
 #endif
 
-    Mode m_mode;
-    qint64 m_appPid;
-    int m_appCode;
-    QString m_executable;
-    QProcess::ExitStatus m_appStatus;
-    QLocalServer m_stubServer;
-    QLocalSocket *m_stubSocket;
-    QTemporaryFile *m_tempFile;
-#ifdef Q_OS_WIN
-    PROCESS_INFORMATION *m_pid;
-    HANDLE m_hInferior;
-    QWinEventNotifier *inferiorFinishedNotifier;
-    QWinEventNotifier *processFinishedNotifier;
-#else
-    QProcess m_process;
-    QByteArray m_stubServerDir;
-    QSettings *m_settings;
-#endif
-
+    QScopedPointer<ConsoleProcessPrivate> d;
 };
 
 } //namespace Utils
diff --git a/src/libs/utils/consoleprocess_unix.cpp b/src/libs/utils/consoleprocess_unix.cpp
index 207ead5891a..32528d44af0 100644
--- a/src/libs/utils/consoleprocess_unix.cpp
+++ b/src/libs/utils/consoleprocess_unix.cpp
@@ -35,6 +35,7 @@
 #include <QtCore/QTemporaryFile>
 
 #include <QtNetwork/QLocalSocket>
+#include <QtNetwork/QLocalServer>
 
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -42,19 +43,39 @@
 #include <string.h>
 #include <unistd.h>
 
-using namespace Utils;
+namespace Utils {
+struct ConsoleProcessPrivate {
+    ConsoleProcessPrivate();
 
-ConsoleProcess::ConsoleProcess(QObject *parent)  :
-    QObject(parent),
-    m_mode(Run),
+    ConsoleProcess::Mode m_mode;
+    qint64 m_appPid;
+    qint64 m_appMainThreadId;
+    int m_appCode;
+    QString m_executable;
+    QProcess::ExitStatus m_appStatus;
+    QLocalServer m_stubServer;
+    QLocalSocket *m_stubSocket;
+    QTemporaryFile *m_tempFile;
+
+    QProcess m_process;
+    QByteArray m_stubServerDir;
+    QSettings *m_settings;
+};
+
+ConsoleProcessPrivate::ConsoleProcessPrivate() :
+    m_mode(ConsoleProcess::Run),
     m_appPid(0),
     m_stubSocket(0),
     m_settings(0)
 {
-    connect(&m_stubServer, SIGNAL(newConnection()), SLOT(stubConnectionAvailable()));
+}
+ConsoleProcess::ConsoleProcess(QObject *parent)  :
+    QObject(parent), d(new ConsoleProcessPrivate)
+{
+    connect(&d->m_stubServer, SIGNAL(newConnection()), SLOT(stubConnectionAvailable()));
 
-    m_process.setProcessChannelMode(QProcess::ForwardedChannels);
-    connect(&m_process, SIGNAL(finished(int, QProcess::ExitStatus)),
+    d->m_process.setProcessChannelMode(QProcess::ForwardedChannels);
+    connect(&d->m_process, SIGNAL(finished(int, QProcess::ExitStatus)),
             SLOT(stubExited()));
 }
 
@@ -63,6 +84,36 @@ ConsoleProcess::~ConsoleProcess()
     stop();
 }
 
+void ConsoleProcess::setMode(Mode m)
+{
+    d->m_mode = m;
+}
+
+ConsoleProcess::Mode ConsoleProcess::mode() const
+{
+    return d->m_mode;
+}
+
+qint64 ConsoleProcess::applicationPID() const
+{
+    return d->m_appPid;
+}
+
+int ConsoleProcess::exitCode() const
+{
+    return d->m_appCode;
+} // This will be the signal number if exitStatus == CrashExit
+
+QProcess::ExitStatus ConsoleProcess::exitStatus() const
+{
+    return d->m_appStatus;
+}
+
+void ConsoleProcess::setSettings(QSettings *settings)
+{
+    d->m_settings = settings;
+}
+
 bool ConsoleProcess::start(const QString &program, const QStringList &args)
 {
     if (isRunning())
@@ -75,45 +126,45 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
     }
 
     if (!environment().isEmpty()) {
-        m_tempFile = new QTemporaryFile();
-        if (!m_tempFile->open()) {
+        d->m_tempFile = new QTemporaryFile();
+        if (!d->m_tempFile->open()) {
             stubServerShutdown();
-            emit processMessage(msgCannotCreateTempFile(m_tempFile->errorString()), true);
-            delete m_tempFile;
-            m_tempFile = 0;
+            emit processMessage(msgCannotCreateTempFile(d->m_tempFile->errorString()), true);
+            delete d->m_tempFile;
+            d->m_tempFile = 0;
             return false;
         }
         foreach (const QString &var, environment()) {
-            m_tempFile->write(var.toLocal8Bit());
-            m_tempFile->write("", 1);
+            d->m_tempFile->write(var.toLocal8Bit());
+            d->m_tempFile->write("", 1);
         }
-        m_tempFile->flush();
+        d->m_tempFile->flush();
     }
 
-    QStringList xtermArgs = terminalEmulator(m_settings).split(QLatin1Char(' ')); // FIXME: quoting
+    QStringList xtermArgs = terminalEmulator(d->m_settings).split(QLatin1Char(' ')); // FIXME: quoting
     xtermArgs
 #ifdef Q_OS_MAC
               << (QCoreApplication::applicationDirPath() + QLatin1String("/../Resources/qtcreator_process_stub"))
 #else
               << (QCoreApplication::applicationDirPath() + QLatin1String("/qtcreator_process_stub"))
 #endif
-              << modeOption(m_mode)
-              << m_stubServer.fullServerName()
+              << modeOption(d->m_mode)
+              << d->m_stubServer.fullServerName()
               << msgPromptToClose()
               << workingDirectory()
-              << (m_tempFile ? m_tempFile->fileName() : QString())
+              << (d->m_tempFile ? d->m_tempFile->fileName() : QString())
               << program << args;
 
     QString xterm = xtermArgs.takeFirst();
-    m_process.start(xterm, xtermArgs);
-    if (!m_process.waitForStarted()) {
+    d->m_process.start(xterm, xtermArgs);
+    if (!d->m_process.waitForStarted()) {
         stubServerShutdown();
         emit processMessage(tr("Cannot start the terminal emulator '%1'.").arg(xterm), true);
-        delete m_tempFile;
-        m_tempFile = 0;
+        delete d->m_tempFile;
+        d->m_tempFile = 0;
         return false;
     }
-    m_executable = program;
+    d->m_executable = program;
     emit wrapperStarted();
     return true;
 }
@@ -123,16 +174,16 @@ void ConsoleProcess::stop()
     if (!isRunning())
         return;
     stubServerShutdown();
-    m_appPid = 0;
-    m_process.terminate();
-    if (!m_process.waitForFinished(1000))
-        m_process.kill();
-    m_process.waitForFinished();
+    d->m_appPid = 0;
+    d->m_process.terminate();
+    if (!d->m_process.waitForFinished(1000))
+        d->m_process.kill();
+    d->m_process.waitForFinished();
 }
 
 bool ConsoleProcess::isRunning() const
 {
-    return m_process.state() != QProcess::NotRunning;
+    return d->m_process.state() != QProcess::NotRunning;
 }
 
 QString ConsoleProcess::stubServerListen()
@@ -148,34 +199,34 @@ QString ConsoleProcess::stubServerListen()
             stubFifoDir = QFile::encodeName(tf.fileName());
         }
         // By now the temp file was deleted again
-        m_stubServerDir = QFile::encodeName(stubFifoDir);
-        if (!::mkdir(m_stubServerDir.constData(), 0700))
+        d->m_stubServerDir = QFile::encodeName(stubFifoDir);
+        if (!::mkdir(d->m_stubServerDir.constData(), 0700))
             break;
         if (errno != EEXIST)
             return msgCannotCreateTempDir(stubFifoDir, QString::fromLocal8Bit(strerror(errno)));
     }
     const QString stubServer  = stubFifoDir + "/stub-socket";
-    if (!m_stubServer.listen(stubServer)) {
-        ::rmdir(m_stubServerDir.constData());
-        return tr("Cannot create socket '%1': %2").arg(stubServer, m_stubServer.errorString());
+    if (!d->m_stubServer.listen(stubServer)) {
+        ::rmdir(d->m_stubServerDir.constData());
+        return tr("Cannot create socket '%1': %2").arg(stubServer, d->m_stubServer.errorString());
     }
     return QString();
 }
 
 void ConsoleProcess::stubServerShutdown()
 {
-    delete m_stubSocket;
-    m_stubSocket = 0;
-    if (m_stubServer.isListening()) {
-        m_stubServer.close();
-        ::rmdir(m_stubServerDir.constData());
+    delete d->m_stubSocket;
+    d->m_stubSocket = 0;
+    if (d->m_stubServer.isListening()) {
+        d->m_stubServer.close();
+        ::rmdir(d->m_stubServerDir.constData());
     }
 }
 
 void ConsoleProcess::stubConnectionAvailable()
 {
-    m_stubSocket = m_stubServer.nextPendingConnection();
-    connect(m_stubSocket, SIGNAL(readyRead()), SLOT(readStubOutput()));
+    d->m_stubSocket = d->m_stubServer.nextPendingConnection();
+    connect(d->m_stubSocket, SIGNAL(readyRead()), SLOT(readStubOutput()));
 }
 
 static QString errorMsg(int code)
@@ -185,33 +236,33 @@ static QString errorMsg(int code)
 
 void ConsoleProcess::readStubOutput()
 {
-    while (m_stubSocket->canReadLine()) {
-        QByteArray out = m_stubSocket->readLine();
+    while (d->m_stubSocket->canReadLine()) {
+        QByteArray out = d->m_stubSocket->readLine();
         out.chop(1); // \n
         if (out.startsWith("err:chdir ")) {
             emit processMessage(msgCannotChangeToWorkDir(workingDirectory(), errorMsg(out.mid(10).toInt())), true);
         } else if (out.startsWith("err:exec ")) {
-            emit processMessage(msgCannotExecute(m_executable, errorMsg(out.mid(9).toInt())), true);
+            emit processMessage(msgCannotExecute(d->m_executable, errorMsg(out.mid(9).toInt())), true);
         } else if (out.startsWith("pid ")) {
             // Will not need it any more
-            delete m_tempFile;
-            m_tempFile = 0;
+            delete d->m_tempFile;
+            d->m_tempFile = 0;
 
-            m_appPid = out.mid(4).toInt();
+            d->m_appPid = out.mid(4).toInt();
             emit processStarted();
         } else if (out.startsWith("exit ")) {
-            m_appStatus = QProcess::NormalExit;
-            m_appCode = out.mid(5).toInt();
-            m_appPid = 0;
+            d->m_appStatus = QProcess::NormalExit;
+            d->m_appCode = out.mid(5).toInt();
+            d->m_appPid = 0;
             emit processStopped();
         } else if (out.startsWith("crash ")) {
-            m_appStatus = QProcess::CrashExit;
-            m_appCode = out.mid(6).toInt();
-            m_appPid = 0;
+            d->m_appStatus = QProcess::CrashExit;
+            d->m_appCode = out.mid(6).toInt();
+            d->m_appPid = 0;
             emit processStopped();
         } else {
-            emit processMessage(msgUnexpectedOutput(), true);
-            m_process.terminate();
+            emit processMessage(msgUnexpectedOutput(out), true);
+            d->m_process.terminate();
             break;
         }
     }
@@ -220,15 +271,15 @@ void ConsoleProcess::readStubOutput()
 void ConsoleProcess::stubExited()
 {
     // The stub exit might get noticed before we read the error status.
-    if (m_stubSocket && m_stubSocket->state() == QLocalSocket::ConnectedState)
-        m_stubSocket->waitForDisconnected();
+    if (d->m_stubSocket && d->m_stubSocket->state() == QLocalSocket::ConnectedState)
+        d->m_stubSocket->waitForDisconnected();
     stubServerShutdown();
-    delete m_tempFile;
-    m_tempFile = 0;
-    if (m_appPid) {
-        m_appStatus = QProcess::CrashExit;
-        m_appCode = -1;
-        m_appPid = 0;
+    delete d->m_tempFile;
+    d->m_tempFile = 0;
+    if (d->m_appPid) {
+        d->m_appStatus = QProcess::CrashExit;
+        d->m_appCode = -1;
+        d->m_appPid = 0;
         emit processStopped(); // Maybe it actually did not, but keep state consistent
     }
     emit wrapperStopped();
@@ -257,3 +308,4 @@ void ConsoleProcess::setTerminalEmulator(QSettings *settings, const QString &ter
 {
     return settings->setValue(QLatin1String("General/TerminalEmulator"), term);
 }
+} // namespace Utils
diff --git a/src/libs/utils/consoleprocess_win.cpp b/src/libs/utils/consoleprocess_win.cpp
index a54a9e964ab..eeaa3336045 100644
--- a/src/libs/utils/consoleprocess_win.cpp
+++ b/src/libs/utils/consoleprocess_win.cpp
@@ -30,6 +30,8 @@
 #include "consoleprocess.h"
 #include "winutils.h"
 
+#include <windows.h>
+
 #include <QtCore/QCoreApplication>
 #include <QtCore/QDir>
 #include <QtCore/QTemporaryFile>
@@ -37,15 +39,32 @@
 #include <QtCore/private/qwineventnotifier_p.h>
 
 #include <QtNetwork/QLocalSocket>
+#include <QtNetwork/QLocalServer>
 
 #include <stdlib.h>
 
-using namespace Utils;
+namespace Utils {
+struct ConsoleProcessPrivate {
+    ConsoleProcessPrivate();
 
-ConsoleProcess::ConsoleProcess(QObject *parent) :
-    QObject(parent),
-    m_mode(Run),
-    m_appPid(0),
+    ConsoleProcess::Mode m_mode;
+    qint64 m_appPid;
+    qint64 m_appMainThreadId;
+    int m_appCode;
+    QString m_executable;
+    QProcess::ExitStatus m_appStatus;
+    QLocalServer m_stubServer;
+    QLocalSocket *m_stubSocket;
+    QTemporaryFile *m_tempFile;
+    PROCESS_INFORMATION *m_pid;
+    HANDLE m_hInferior;
+    QWinEventNotifier *inferiorFinishedNotifier;
+    QWinEventNotifier *processFinishedNotifier;
+};
+
+ConsoleProcessPrivate::ConsoleProcessPrivate() :
+    m_mode(ConsoleProcess::Run),
+    m_appPid(0),m_appMainThreadId(0),
     m_stubSocket(0),
     m_tempFile(0),
     m_pid(0),
@@ -53,7 +72,12 @@ ConsoleProcess::ConsoleProcess(QObject *parent) :
     inferiorFinishedNotifier(0),
     processFinishedNotifier(0)
 {
-    connect(&m_stubServer, SIGNAL(newConnection()), SLOT(stubConnectionAvailable()));
+}
+
+ConsoleProcess::ConsoleProcess(QObject *parent) :
+    QObject(parent), d(new ConsoleProcessPrivate)
+{
+    connect(&d->m_stubServer, SIGNAL(newConnection()), SLOT(stubConnectionAvailable()));
 }
 
 ConsoleProcess::~ConsoleProcess()
@@ -61,6 +85,36 @@ ConsoleProcess::~ConsoleProcess()
     stop();
 }
 
+void ConsoleProcess::setMode(Mode m)
+{
+    d->m_mode = m;
+}
+
+ConsoleProcess::Mode ConsoleProcess::mode() const
+{
+    return d->m_mode;
+}
+
+qint64 ConsoleProcess::applicationPID() const
+{
+    return d->m_appPid;
+}
+
+qint64 ConsoleProcess::applicationMainThreadID() const
+{
+    return d->m_appMainThreadId;
+}
+
+int ConsoleProcess::exitCode() const
+{
+    return d->m_appCode;
+} // This will be the signal number if exitStatus == CrashExit
+
+QProcess::ExitStatus ConsoleProcess::exitStatus() const
+{
+    return d->m_appStatus;
+}
+
 bool ConsoleProcess::start(const QString &program, const QStringList &args)
 {
     if (isRunning())
@@ -73,15 +127,15 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
     }
 
     if (!environment().isEmpty()) {
-        m_tempFile = new QTemporaryFile();
-        if (!m_tempFile->open()) {
+        d->m_tempFile = new QTemporaryFile();
+        if (!d->m_tempFile->open()) {
             stubServerShutdown();
-            emit processMessage(msgCannotCreateTempFile(m_tempFile->errorString()), true);
-            delete m_tempFile;
-            m_tempFile = 0;
+            emit processMessage(msgCannotCreateTempFile(d->m_tempFile->errorString()), true);
+            delete d->m_tempFile;
+            d->m_tempFile = 0;
             return false;
         }
-        QTextStream out(m_tempFile);
+        QTextStream out(d->m_tempFile);
         out.setCodec("UTF-16LE");
         out.setGenerateByteOrderMark(false);
         foreach (const QString &var, fixWinEnvironment(environment()))
@@ -93,18 +147,18 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
     ZeroMemory(&si, sizeof(si));
     si.cb = sizeof(si);
 
-    m_pid = new PROCESS_INFORMATION;
-    ZeroMemory(m_pid, sizeof(PROCESS_INFORMATION));
+    d->m_pid = new PROCESS_INFORMATION;
+    ZeroMemory(d->m_pid, sizeof(PROCESS_INFORMATION));
 
     QString workDir = QDir::toNativeSeparators(workingDirectory());
     if (!workDir.isEmpty() && !workDir.endsWith('\\'))
         workDir.append('\\');
 
     QStringList stubArgs;
-    stubArgs << modeOption(m_mode)
-             << m_stubServer.fullServerName()
+    stubArgs << modeOption(d->m_mode)
+             << d->m_stubServer.fullServerName()
              << workDir
-             << (m_tempFile ? m_tempFile->fileName() : 0)
+             << (d->m_tempFile ? d->m_tempFile->fileName() : 0)
              << createWinCommandline(program, args)
              << msgPromptToClose();
 
@@ -114,95 +168,97 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
     bool success = CreateProcessW(0, (WCHAR*)cmdLine.utf16(),
                                   0, 0, FALSE, CREATE_NEW_CONSOLE,
                                   0, 0,
-                                  &si, m_pid);
+                                  &si, d->m_pid);
 
     if (!success) {
-        delete m_pid;
-        m_pid = 0;
-        delete m_tempFile;
-        m_tempFile = 0;
+        delete d->m_pid;
+        d->m_pid = 0;
+        delete d->m_tempFile;
+        d->m_tempFile = 0;
         stubServerShutdown();
         emit processMessage(tr("The process '%1' could not be started: %2").arg(cmdLine, winErrorMessage(GetLastError())), true);
         return false;
     }
 
-    processFinishedNotifier = new QWinEventNotifier(m_pid->hProcess, this);
-    connect(processFinishedNotifier, SIGNAL(activated(HANDLE)), SLOT(stubExited()));
+    d->processFinishedNotifier = new QWinEventNotifier(d->m_pid->hProcess, this);
+    connect(d->processFinishedNotifier, SIGNAL(activated(HANDLE)), SLOT(stubExited()));
     emit wrapperStarted();
     return true;
 }
 
 void ConsoleProcess::stop()
 {
-    if (m_hInferior != NULL) {
-        TerminateProcess(m_hInferior, (unsigned)-1);
+    if (d->m_hInferior != NULL) {
+        TerminateProcess(d->m_hInferior, (unsigned)-1);
         cleanupInferior();
     }
-    if (m_pid) {
-        TerminateProcess(m_pid->hProcess, (unsigned)-1);
-        WaitForSingleObject(m_pid->hProcess, INFINITE);
+    if (d->m_pid) {
+        TerminateProcess(d->m_pid->hProcess, (unsigned)-1);
+        WaitForSingleObject(d->m_pid->hProcess, INFINITE);
         cleanupStub();
     }
 }
 
 bool ConsoleProcess::isRunning() const
 {
-    return m_pid != 0;
+    return d->m_pid != 0;
 }
 
 QString ConsoleProcess::stubServerListen()
 {
-    if (m_stubServer.listen(QString::fromLatin1("creator-%1-%2")
+    if (d->m_stubServer.listen(QString::fromLatin1("creator-%1-%2")
                             .arg(QCoreApplication::applicationPid())
                             .arg(rand())))
         return QString();
-    return m_stubServer.errorString();
+    return d->m_stubServer.errorString();
 }
 
 void ConsoleProcess::stubServerShutdown()
 {
-    delete m_stubSocket;
-    m_stubSocket = 0;
-    if (m_stubServer.isListening())
-        m_stubServer.close();
+    delete d->m_stubSocket;
+    d->m_stubSocket = 0;
+    if (d->m_stubServer.isListening())
+        d->m_stubServer.close();
 }
 
 void ConsoleProcess::stubConnectionAvailable()
 {
-    m_stubSocket = m_stubServer.nextPendingConnection();
-    connect(m_stubSocket, SIGNAL(readyRead()), SLOT(readStubOutput()));
+    d->m_stubSocket = d->m_stubServer.nextPendingConnection();
+    connect(d->m_stubSocket, SIGNAL(readyRead()), SLOT(readStubOutput()));
 }
 
 void ConsoleProcess::readStubOutput()
 {
-    while (m_stubSocket->canReadLine()) {
-        QByteArray out = m_stubSocket->readLine();
+    while (d->m_stubSocket->canReadLine()) {
+        QByteArray out = d->m_stubSocket->readLine();
         out.chop(2); // \r\n
         if (out.startsWith("err:chdir ")) {
             emit processMessage(msgCannotChangeToWorkDir(workingDirectory(), winErrorMessage(out.mid(10).toInt())), true);
         } else if (out.startsWith("err:exec ")) {
-            emit processMessage(msgCannotExecute(m_executable, winErrorMessage(out.mid(9).toInt())), true);
+            emit processMessage(msgCannotExecute(d->m_executable, winErrorMessage(out.mid(9).toInt())), true);
+        } else if (out.startsWith("thread ")) { // Windows only
+            d->m_appMainThreadId = out.mid(7).toLongLong();
         } else if (out.startsWith("pid ")) {
-            // Wil not need it any more
-            delete m_tempFile;
-            m_tempFile = 0;
+            // Will not need it any more
+            delete d->m_tempFile;
+            d->m_tempFile = 0;
+            d->m_appPid = out.mid(4).toLongLong();
 
-            m_appPid = out.mid(4).toInt();
-            m_hInferior = OpenProcess(
+            d->m_hInferior = OpenProcess(
                     SYNCHRONIZE | PROCESS_QUERY_INFORMATION | PROCESS_TERMINATE,
-                    FALSE, m_appPid);
-            if (m_hInferior == NULL) {
+                    FALSE, d->m_appPid);
+            if (d->m_hInferior == NULL) {
                 emit processMessage(tr("Cannot obtain a handle to the inferior: %1")
                                     .arg(winErrorMessage(GetLastError())), true);
                 // Uhm, and now what?
                 continue;
             }
-            inferiorFinishedNotifier = new QWinEventNotifier(m_hInferior, this);
-            connect(inferiorFinishedNotifier, SIGNAL(activated(HANDLE)), SLOT(inferiorExited()));
+            d->inferiorFinishedNotifier = new QWinEventNotifier(d->m_hInferior, this);
+            connect(d->inferiorFinishedNotifier, SIGNAL(activated(HANDLE)), SLOT(inferiorExited()));
             emit processStarted();
         } else {
-            emit processMessage(msgUnexpectedOutput(), true);
-            TerminateProcess(m_pid->hProcess, (unsigned)-1);
+            emit processMessage(msgUnexpectedOutput(out), true);
+            TerminateProcess(d->m_pid->hProcess, (unsigned)-1);
             break;
         }
     }
@@ -210,52 +266,53 @@ void ConsoleProcess::readStubOutput()
 
 void ConsoleProcess::cleanupInferior()
 {
-    delete inferiorFinishedNotifier;
-    inferiorFinishedNotifier = 0;
-    CloseHandle(m_hInferior);
-    m_hInferior = NULL;
-    m_appPid = 0;
+    delete d->inferiorFinishedNotifier;
+    d->inferiorFinishedNotifier = 0;
+    CloseHandle(d->m_hInferior);
+    d->m_hInferior = NULL;
+    d->m_appPid = 0;
 }
 
 void ConsoleProcess::inferiorExited()
 {
     DWORD chldStatus;
 
-    if (!GetExitCodeProcess(m_hInferior, &chldStatus))
+    if (!GetExitCodeProcess(d->m_hInferior, &chldStatus))
         emit processMessage(tr("Cannot obtain exit status from inferior: %1")
                             .arg(winErrorMessage(GetLastError())), true);
     cleanupInferior();
-    m_appStatus = QProcess::NormalExit;
-    m_appCode = chldStatus;
+    d->m_appStatus = QProcess::NormalExit;
+    d->m_appCode = chldStatus;
     emit processStopped();
 }
 
 void ConsoleProcess::cleanupStub()
 {
     stubServerShutdown();
-    delete processFinishedNotifier;
-    processFinishedNotifier = 0;
-    CloseHandle(m_pid->hThread);
-    CloseHandle(m_pid->hProcess);
-    delete m_pid;
-    m_pid = 0;
-    delete m_tempFile;
-    m_tempFile = 0;
+    delete d->processFinishedNotifier;
+    d->processFinishedNotifier = 0;
+    CloseHandle(d->m_pid->hThread);
+    CloseHandle(d->m_pid->hProcess);
+    delete d->m_pid;
+    d->m_pid = 0;
+    delete d->m_tempFile;
+    d->m_tempFile = 0;
 }
 
 void ConsoleProcess::stubExited()
 {
     // The stub exit might get noticed before we read the pid for the kill.
-    if (m_stubSocket && m_stubSocket->state() == QLocalSocket::ConnectedState)
-        m_stubSocket->waitForDisconnected();
+    if (d->m_stubSocket && d->m_stubSocket->state() == QLocalSocket::ConnectedState)
+        d->m_stubSocket->waitForDisconnected();
     cleanupStub();
-    if (m_hInferior != NULL) {
-        TerminateProcess(m_hInferior, (unsigned)-1);
+    if (d->m_hInferior != NULL) {
+        TerminateProcess(d->m_hInferior, (unsigned)-1);
         cleanupInferior();
-        m_appStatus = QProcess::CrashExit;
-        m_appCode = -1;
+        d->m_appStatus = QProcess::CrashExit;
+        d->m_appCode = -1;
         emit processStopped();
     }
     emit wrapperStopped();
 }
 
+} // namespace Utils
diff --git a/src/libs/utils/process_stub_win.c b/src/libs/utils/process_stub_win.c
index f27fe33da54..d54e0f0f131 100644
--- a/src/libs/utils/process_stub_win.c
+++ b/src/libs/utils/process_stub_win.c
@@ -208,6 +208,7 @@ int main()
 
     SetConsoleCtrlHandler(ctrlHandler, TRUE);
 
+    sendMsg("thread %d\n", pi.dwThreadId);
     sendMsg("pid %d\n", pi.dwProcessId);
 
     if (WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_FAILED)
-- 
GitLab