diff --git a/src/libs/libs.pro b/src/libs/libs.pro
index 0bb942edada6771ec698ad21d787f10fa63953cb..f87e023c1281875070d6b98c5e751283bc132d84 100644
--- a/src/libs/libs.pro
+++ b/src/libs/libs.pro
@@ -6,4 +6,5 @@ SUBDIRS   = \
     aggregation \
     extensionsystem \
     utils \
+    utils/process_stub.pro \
     cplusplus
diff --git a/src/libs/utils/consoleprocess.h b/src/libs/utils/consoleprocess.h
index 28ae4956e240a864311f4e4fd55f506fefc75ef8..ac8d4b3eb9de2093fb835d401308d6b05505837f 100644
--- a/src/libs/utils/consoleprocess.h
+++ b/src/libs/utils/consoleprocess.h
@@ -37,9 +37,12 @@
 #include <QtCore/QStringList>
 #include <QtCore/QProcess>
 
+#include <QtNetwork/QLocalServer>
+
 #ifdef Q_OS_WIN
 #include <windows.h>
 class QWinEventNotifier;
+class QTemporaryFile;
 #endif
 
 namespace Core {
@@ -50,41 +53,68 @@ class QWORKBENCH_UTILS_EXPORT ConsoleProcess : public QObject, public AbstractPr
     Q_OBJECT
 
 public:
-    ConsoleProcess(QObject *parent);
+    ConsoleProcess(QObject *parent = 0);
     ~ConsoleProcess();
 
     bool start(const QString &program, const QStringList &args);
     void stop();
 
-    bool isRunning() const;
-    qint64 applicationPID() const;
-    int exitCode() const;
+    void setDebug(bool on) { m_debug = on; }
+    bool isDebug() const { return m_debug; }
+
+    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; }
+
+#ifdef Q_OS_WIN
+    // These are public for WinGuiProcess. Should be in AbstractProcess, but it has no .cpp so far.
+    static QString createCommandline(const QString &program, const QStringList &args);
+    static QStringList fixEnvironment(const QStringList &env);
+#endif
 
 signals:
     void processError(const QString &error);
+    // These reflect the state of the actual client process
     void processStarted();
     void processStopped();
 
-private:
-    bool m_isRunning;
-
-#ifdef Q_OS_WIN
-public:
-    static QString createCommandline(const QString &program,
-                                     const QStringList &args);
-    static QByteArray createEnvironment(const QStringList &env);
+    // These reflect the state of the console+stub
+    void wrapperStarted();
+    void wrapperStopped();
 
 private slots:
-    void processDied();
+    void stubConnectionAvailable();
+    void readStubOutput();
+    void stubExited();
+#ifdef Q_OS_WIN
+    void inferiorExited();
+#endif
 
 private:
+    QString stubServerListen();
+    void stubServerShutdown();
+#ifdef Q_OS_WIN
+    void cleanupStub();
+    void cleanupInferior();
+#endif
+
+    bool m_debug;
+    qint64 m_appPid;
+    int m_appCode;
+    QString m_executable;
+    QProcess::ExitStatus m_appStatus;
+    QLocalServer m_stubServer;
+    QLocalSocket *m_stubSocket;
+#ifdef Q_OS_WIN
     PROCESS_INFORMATION *m_pid;
+    HANDLE m_hInferior;
+    QWinEventNotifier *inferiorFinishedNotifier;
     QWinEventNotifier *processFinishedNotifier;
+    QTemporaryFile *m_tempFile;
 #else
-private:
     QProcess m_process;
-private slots:
-    void processFinished(int, QProcess::ExitStatus);
+    QByteArray m_stubServerDir;
 #endif
 
 };
diff --git a/src/libs/utils/consoleprocess_unix.cpp b/src/libs/utils/consoleprocess_unix.cpp
index 34709253764668e4baf078a602042c0e8ecb36c0..610082377852150b6adad7a1bd7f3d6c3b103d07 100644
--- a/src/libs/utils/consoleprocess_unix.cpp
+++ b/src/libs/utils/consoleprocess_unix.cpp
@@ -29,57 +29,78 @@
 
 #include "consoleprocess.h"
 
+#include <QtCore/QCoreApplication>
+#include <QtCore/QTemporaryFile>
+
+#include <QtNetwork/QLocalSocket>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
 using namespace Core::Utils;
 
 ConsoleProcess::ConsoleProcess(QObject *parent)
     : QObject(parent)
 {
-    m_isRunning = false;
-}
+    m_debug = false;
+    m_appPid = 0;
+    m_stubSocket = 0;
 
-ConsoleProcess::~ConsoleProcess()
-{
+    connect(&m_stubServer, SIGNAL(newConnection()), SLOT(stubConnectionAvailable()));
+
+    m_process.setProcessChannelMode(QProcess::ForwardedChannels);
+    connect(&m_process, SIGNAL(finished(int, QProcess::ExitStatus)),
+            SLOT(stubExited()));
 }
 
-static QString shellEscape(const QString &in)
+ConsoleProcess::~ConsoleProcess()
 {
-    QString out = in;
-    out.replace('\'', "'\''");
-    out.prepend('\'');
-    out.append('\'');
-    return out;
+    stop();
 }
 
 bool ConsoleProcess::start(const QString &program, const QStringList &args)
 {
-    if (m_process.state() != QProcess::NotRunning)
+    if (isRunning())
         return false;
-    QString shellArgs;
-    shellArgs += QLatin1String("cd ");
-    shellArgs += shellEscape(workingDirectory());
-    shellArgs += QLatin1Char(';');
-    shellArgs += shellEscape(program);
-    foreach (const QString &arg, args) {
-        shellArgs += QLatin1Char(' ');
-        shellArgs += shellEscape(arg);
-    }
-    shellArgs += QLatin1String("; echo; echo \"Press enter to close this window\"; read DUMMY");
 
-    m_process.setEnvironment(environment());
+    QString err = stubServerListen();
+    if (!err.isEmpty()) {
+        emit processError(tr("Cannot set up comm channel: %1").arg(err));
+        return false;
+    }
 
-    connect(&m_process, SIGNAL(finished(int, QProcess::ExitStatus)),
-            this, SLOT(processFinished(int, QProcess::ExitStatus)));
+    QStringList xtermArgs;
+    xtermArgs << "-e" << (QCoreApplication::applicationDirPath() + "/qtcreator_process_stub")
+              << (m_debug ? "debug" : "exec")
+              << m_stubServer.fullServerName()
+              << tr("Press <RETURN> to close this window...")
+              << workingDirectory() << environment() << ""
+              << program << args;
 
-    m_process.start(QLatin1String("xterm"), QStringList() << QLatin1String("-e") << "/bin/sh" << "-c" << shellArgs);
-    if (!m_process.waitForStarted())
+    m_process.start(QLatin1String("xterm"), xtermArgs);
+    if (!m_process.waitForStarted()) {
+        stubServerShutdown();
+        emit processError(tr("Cannot start console emulator xterm."));
         return false;
-    emit processStarted();
+    }
+    m_executable = program;
+    emit wrapperStarted();
     return true;
 }
 
-void ConsoleProcess::processFinished(int, QProcess::ExitStatus)
+void ConsoleProcess::stop()
 {
-    emit processStopped();
+    if (!isRunning())
+        return;
+    stubServerShutdown();
+    m_appPid = 0;
+    m_process.terminate();
+    if (!m_process.waitForFinished(1000))
+        m_process.kill();
+    m_process.waitForFinished();
 }
 
 bool ConsoleProcess::isRunning() const
@@ -87,19 +108,97 @@ bool ConsoleProcess::isRunning() const
     return m_process.state() != QProcess::NotRunning;
 }
 
-void ConsoleProcess::stop()
+QString ConsoleProcess::stubServerListen()
 {
-    m_process.terminate();
-    m_process.waitForFinished();
+    // We need to put the socket in a private directory, as some systems simply do not
+    // check the file permissions of sockets.
+    QString stubFifoDir;
+    forever {
+        {
+            QTemporaryFile tf;
+            if (!tf.open())
+                return tr("Cannot create temporary file: %2").arg(tf.errorString());
+            stubFifoDir = QFile::encodeName(tf.fileName());
+        }
+        // By now the temp file was deleted again
+        m_stubServerDir = QFile::encodeName(stubFifoDir);
+        if (!::mkdir(m_stubServerDir.constData(), 0700))
+            break;
+        if (errno != EEXIST)
+            return tr("Cannot create temporary directory %1: %2").arg(stubFifoDir, strerror(errno));
+    }
+    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());
+    }
+    return QString();
+}
+
+void ConsoleProcess::stubServerShutdown()
+{
+    delete m_stubSocket;
+    m_stubSocket = 0;
+    if (m_stubServer.isListening()) {
+        m_stubServer.close();
+        ::rmdir(m_stubServerDir.constData());
+    }
+}
+
+void ConsoleProcess::stubConnectionAvailable()
+{
+    m_stubSocket = m_stubServer.nextPendingConnection();
+    connect(m_stubSocket, SIGNAL(readyRead()), SLOT(readStubOutput()));
 }
 
-qint64 ConsoleProcess::applicationPID() const
+static QString errorMsg(int code)
 {
-    return m_process.pid();
+    return QString::fromLocal8Bit(strerror(code));
 }
 
-int ConsoleProcess::exitCode() const
+void ConsoleProcess::readStubOutput()
 {
-    return m_process.exitCode();
+    while (m_stubSocket->canReadLine()) {
+        QByteArray out = m_stubSocket->readLine();
+        out.chop(1); // \n
+        if (out.startsWith("err:chdir ")) {
+            emit processError(tr("Cannot change to working directory %1: %2")
+                              .arg(workingDirectory(), errorMsg(out.mid(10).toInt())));
+        } else if (out.startsWith("err:exec ")) {
+            emit processError(tr("Cannot execute %1: %2")
+                              .arg(m_executable, errorMsg(out.mid(9).toInt())));
+        } else if (out.startsWith("pid ")) {
+            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;
+            emit processStopped();
+        } else if (out.startsWith("crash ")) {
+            m_appStatus = QProcess::CrashExit;
+            m_appCode = out.mid(6).toInt();
+            m_appPid = 0;
+            emit processStopped();
+        } else {
+            emit processError(tr("Unexpected output from helper program."));
+            m_process.terminate();
+            break;
+        }
+    }
 }
 
+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();
+    stubServerShutdown();
+    if (m_appPid) {
+        m_appStatus = QProcess::CrashExit;
+        m_appCode = -1;
+        m_appPid = 0;
+        emit processStopped(); // Maybe it actually did not, but keep state consistent
+    }
+    emit wrapperStopped();
+}
diff --git a/src/libs/utils/consoleprocess_win.cpp b/src/libs/utils/consoleprocess_win.cpp
index 94409bee1be00047a55ceec0c7c5fe7e9e0fc2fe..969823c582b54f166e5e499677e84f1aeee6d16b 100644
--- a/src/libs/utils/consoleprocess_win.cpp
+++ b/src/libs/utils/consoleprocess_win.cpp
@@ -29,19 +29,31 @@
 
 #include "consoleprocess.h"
 
+#include <QtCore/QCoreApplication>
 #include <QtCore/QDir>
-#include <QtCore/private/qwineventnotifier_p.h>
+#include <QtCore/QTemporaryFile>
 #include <QtCore/QAbstractEventDispatcher>
+#include <QtCore/private/qwineventnotifier_p.h>
+
+#include <QtNetwork/QLocalSocket>
 
-#include <Tlhelp32.h>
+#include <stdlib.h>
 
 using namespace Core::Utils;
 
 ConsoleProcess::ConsoleProcess(QObject *parent)
     : QObject(parent)
 {
-    m_isRunning = false;
+    m_debug = false;
+    m_appPid = 0;
     m_pid = 0;
+    m_hInferior = NULL;
+    m_tempFile = 0;
+    m_stubSocket = 0;
+    processFinishedNotifier = 0;
+    inferiorFinishedNotifier = 0;
+
+    connect(&m_stubServer, SIGNAL(newConnection()), SLOT(stubConnectionAvailable()));
 }
 
 ConsoleProcess::~ConsoleProcess()
@@ -49,156 +61,234 @@ ConsoleProcess::~ConsoleProcess()
     stop();
 }
 
-void ConsoleProcess::stop()
-{
-    if (m_pid)
-        TerminateProcess(m_pid->hProcess, -1);
-    m_isRunning = false;
-}
-
 bool ConsoleProcess::start(const QString &program, const QStringList &args)
 {
-    if (m_isRunning)
+    if (isRunning())
         return false;
 
+    QString err = stubServerListen();
+    if (!err.isEmpty()) {
+        emit processError(tr("Cannot set up comm channel: %1").arg(err));
+        return false;
+    }
+
+    if (!environment().isEmpty()) {
+        m_tempFile = new QTemporaryFile();
+        if (!m_tempFile->open()) {
+            stubServerShutdown();
+            emit processError(tr("Cannot create temp file: %1").arg(m_tempFile->errorString()));
+            delete m_tempFile;
+            m_tempFile = 0;
+            return false;
+        }
+        QTextStream out(m_tempFile);
+        out.setCodec("UTF-16LE");
+        out.setGenerateByteOrderMark(false);
+        foreach (const QString &var, fixEnvironment(environment()))
+            out << var << QChar(0);
+        out << QChar(0);
+    }
+
     STARTUPINFO si;
     ZeroMemory(&si, sizeof(si));
     si.cb = sizeof(si);
 
-    if (m_pid) {
-        CloseHandle(m_pid->hThread);
-        CloseHandle(m_pid->hProcess);
-        delete m_pid;
-        m_pid = 0;
-    }
     m_pid = new PROCESS_INFORMATION;
     ZeroMemory(m_pid, sizeof(PROCESS_INFORMATION));
 
-    QString cmdLine = QLatin1String("cmd /k ")
-                      + createCommandline(program, args)
-                      + QLatin1String(" & pause & exit");
+    QString workDir = QDir::toNativeSeparators(workingDirectory());
+    if (!workDir.isEmpty() && !workDir.endsWith('\\'))
+        workDir.append('\\');
+
+    QStringList stubArgs;
+    stubArgs << (m_debug ? "debug" : "exec")
+             << m_stubServer.fullServerName()
+             << workDir
+             << (m_tempFile ? m_tempFile->fileName() : 0)
+             << createCommandline(program, args)
+             << tr("Press <RETURN> to close this window...");
+
+    QString cmdLine = createCommandline(
+            QCoreApplication::applicationDirPath() + "/qtcreator_process_stub.exe", stubArgs);
 
     bool success = CreateProcessW(0, (WCHAR*)cmdLine.utf16(),
-                                  0, 0, TRUE, CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,
-                                  environment().isEmpty() ? 0
-                                  : createEnvironment(environment()).data(),
-                                  workingDirectory().isEmpty() ? 0
-                                  : (WCHAR*)QDir::convertSeparators(workingDirectory()).utf16(),
+                                  0, 0, FALSE, CREATE_NEW_CONSOLE,
+                                  0, 0,
                                   &si, m_pid);
 
     if (!success) {
+        delete m_pid;
+        m_pid = 0;
+        delete m_tempFile;
+        m_tempFile = 0;
+        stubServerShutdown();
         emit processError(tr("The process could not be started!"));
         return false;
     }
 
-    if (QAbstractEventDispatcher::instance(thread())) {
-        processFinishedNotifier = new QWinEventNotifier(m_pid->hProcess, this);
-        QObject::connect(processFinishedNotifier, SIGNAL(activated(HANDLE)), this, SLOT(processDied()));
-        processFinishedNotifier->setEnabled(true);
+    processFinishedNotifier = new QWinEventNotifier(m_pid->hProcess, this);
+    connect(processFinishedNotifier, SIGNAL(activated(HANDLE)), SLOT(stubExited()));
+    emit wrapperStarted();
+    return true;
+}
+
+void ConsoleProcess::stop()
+{
+    if (m_hInferior != NULL) {
+        TerminateProcess(m_hInferior, (unsigned)-1);
+        cleanupInferior();
+    }
+    if (m_pid) {
+        TerminateProcess(m_pid->hProcess, (unsigned)-1);
+        WaitForSingleObject(m_pid->hProcess, INFINITE);
+        cleanupStub();
     }
-    m_isRunning = true;
-    emit processStarted();
-    return success;
 }
 
 bool ConsoleProcess::isRunning() const
 {
-    return m_isRunning;
+    return m_pid != 0;
 }
 
-void ConsoleProcess::processDied()
+QString ConsoleProcess::stubServerListen()
 {
-    if (processFinishedNotifier) {
-        processFinishedNotifier->setEnabled(false);
-        delete processFinishedNotifier;
-        processFinishedNotifier = 0;
-    }
-    delete m_pid;
-    m_pid = 0;
-    m_isRunning = false;
-    emit processStopped();
+    if (m_stubServer.listen(QString::fromLatin1("creator-%1-%2")
+                            .arg(QCoreApplication::applicationPid())
+                            .arg(rand())))
+        return QString();
+    return m_stubServer.errorString();
 }
 
-qint64 ConsoleProcess::applicationPID() const
+void ConsoleProcess::stubServerShutdown()
 {
-    if (m_pid) {
-        HANDLE hProcList = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
-        PROCESSENTRY32 procEntry;
-        procEntry.dwSize = sizeof(PROCESSENTRY32);
-        DWORD procId = 0;
-        BOOL moreProc = Process32First(hProcList, &procEntry);
-        while (moreProc) {
-            if (procEntry.th32ParentProcessID == m_pid->dwProcessId) {
-                procId = procEntry.th32ProcessID;
-                break;
-            }
-            moreProc = Process32Next(hProcList, &procEntry);
-        }
+    delete m_stubSocket;
+    m_stubSocket = 0;
+    if (m_stubServer.isListening())
+        m_stubServer.close();
+}
 
-        CloseHandle(hProcList);
-        return procId;
-    }
-    return 0;
+void ConsoleProcess::stubConnectionAvailable()
+{
+    m_stubSocket = m_stubServer.nextPendingConnection();
+    connect(m_stubSocket, SIGNAL(readyRead()), SLOT(readStubOutput()));
 }
 
-int ConsoleProcess::exitCode() const
+static QString errorMsg(int code)
 {
-    DWORD exitCode;
-    if (GetExitCodeProcess(m_pid->hProcess, &exitCode))
-        return exitCode;
-    return -1;
+    LPVOID lpMsgBuf;
+
+    int len = FormatMessage(
+        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+        NULL, (DWORD)code, 0, (LPTSTR)&lpMsgBuf, 0, NULL);
+    QString ret = QString::fromUtf16((ushort *)lpMsgBuf, len);
+    LocalFree(lpMsgBuf);
+    return ret;
 }
 
-QByteArray ConsoleProcess::createEnvironment(const QStringList &env)
+void ConsoleProcess::readStubOutput()
 {
-    QByteArray envlist;
-    if (!env.isEmpty()) {
-        QStringList envStrings = env;
-        int pos = 0;
-        // add PATH if necessary (for DLL loading)
-        if (envStrings.filter(QRegExp("^PATH=",Qt::CaseInsensitive)).isEmpty()) {
-            QByteArray path = qgetenv("PATH");
-            if (!path.isEmpty())
-                envStrings.prepend(QString(QLatin1String("PATH=%1")).arg(QString::fromLocal8Bit(path)));
-        }
-        // add systemroot if needed
-        if (envStrings.filter(QRegExp("^SystemRoot=",Qt::CaseInsensitive)).isEmpty()) {
-            QByteArray systemRoot = qgetenv("SystemRoot");
-            if (!systemRoot.isEmpty())
-                envStrings.prepend(QString(QLatin1String("SystemRoot=%1")).arg(QString::fromLocal8Bit(systemRoot)));
-        }
-#ifdef UNICODE
-        if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) {
-            for (QStringList::ConstIterator it = envStrings.constBegin(); it != envStrings.constEnd(); it++ ) {
-                QString tmp = *it;
-                uint tmpSize = sizeof(TCHAR) * (tmp.length()+1);
-                envlist.resize(envlist.size() + tmpSize);
-                memcpy(envlist.data()+pos, tmp.utf16(), tmpSize);
-                pos += tmpSize;
-            }
-            // add the 2 terminating 0 (actually 4, just to be on the safe side)
-            envlist.resize(envlist.size() + 4);
-            envlist[pos++] = 0;
-            envlist[pos++] = 0;
-            envlist[pos++] = 0;
-            envlist[pos++] = 0;
-        } else
-#endif // UNICODE
-        {
-            for (QStringList::ConstIterator it = envStrings.constBegin(); it != envStrings.constEnd(); it++) {
-                QByteArray tmp = (*it).toLocal8Bit();
-                uint tmpSize = tmp.length() + 1;
-                envlist.resize(envlist.size() + tmpSize);
-                memcpy(envlist.data()+pos, tmp.data(), tmpSize);
-                pos += tmpSize;
+    while (m_stubSocket->canReadLine()) {
+        QByteArray out = m_stubSocket->readLine();
+        out.chop(2); // \r\n
+        if (out.startsWith("err:chdir ")) {
+            emit processError(tr("Cannot change to working directory %1: %2")
+                              .arg(workingDirectory(), errorMsg(out.mid(10).toInt())));
+        } else if (out.startsWith("err:exec ")) {
+            emit processError(tr("Cannot execute %1: %2")
+                              .arg(m_executable, errorMsg(out.mid(9).toInt())));
+        } else if (out.startsWith("pid ")) {
+            // Will not need it any more
+            delete m_tempFile;
+            m_tempFile = 0;
+
+            m_appPid = out.mid(4).toInt();
+            m_hInferior = OpenProcess(
+                    SYNCHRONIZE | PROCESS_QUERY_INFORMATION | PROCESS_TERMINATE,
+                    FALSE, m_appPid);
+            if (m_hInferior == NULL) {
+                emit processError(tr("Cannot obtain a handle to the inferior: %1")
+                                  .arg(errorMsg(GetLastError())));
+                // Uhm, and now what?
+                continue;
             }
-            // add the terminating 0 (actually 2, just to be on the safe side)
-            envlist.resize(envlist.size() + 2);
-            envlist[pos++] = 0;
-            envlist[pos++] = 0;
+            inferiorFinishedNotifier = new QWinEventNotifier(m_hInferior, this);
+            connect(inferiorFinishedNotifier, SIGNAL(activated(HANDLE)), SLOT(inferiorExited()));
+            emit processStarted();
+        } else {
+            emit processError(tr("Unexpected output from helper program."));
+            TerminateProcess(m_pid->hProcess, (unsigned)-1);
+            break;
         }
     }
-    return envlist;
+}
+
+void ConsoleProcess::cleanupInferior()
+{
+    delete inferiorFinishedNotifier;
+    inferiorFinishedNotifier = 0;
+    CloseHandle(m_hInferior);
+    m_hInferior = NULL;
+    m_appPid = 0;
+}
+
+void ConsoleProcess::inferiorExited()
+{
+    DWORD chldStatus;
+
+    if (!GetExitCodeProcess(m_hInferior, &chldStatus))
+        emit processError(tr("Cannot obtain exit status from inferior: %1")
+                          .arg(errorMsg(GetLastError())));
+    cleanupInferior();
+    m_appStatus = QProcess::NormalExit;
+    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;
+}
+
+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();
+    cleanupStub();
+    if (m_hInferior != NULL) {
+        TerminateProcess(m_hInferior, (unsigned)-1);
+        cleanupInferior();
+        m_appStatus = QProcess::CrashExit;
+        m_appCode = -1;
+        emit processStopped();
+    }
+    emit wrapperStopped();
+}
+
+QStringList ConsoleProcess::fixEnvironment(const QStringList &env)
+{
+    QStringList envStrings = env;
+    // add PATH if necessary (for DLL loading)
+    if (envStrings.filter(QRegExp("^PATH=",Qt::CaseInsensitive)).isEmpty()) {
+        QByteArray path = qgetenv("PATH");
+        if (!path.isEmpty())
+            envStrings.prepend(QString(QLatin1String("PATH=%1")).arg(QString::fromLocal8Bit(path)));
+    }
+    // add systemroot if needed
+    if (envStrings.filter(QRegExp("^SystemRoot=",Qt::CaseInsensitive)).isEmpty()) {
+        QByteArray systemRoot = qgetenv("SystemRoot");
+        if (!systemRoot.isEmpty())
+            envStrings.prepend(QString(QLatin1String("SystemRoot=%1")).arg(QString::fromLocal8Bit(systemRoot)));
+    }
+    return envStrings;
 }
 
 QString ConsoleProcess::createCommandline(const QString &program, const QStringList &args)
diff --git a/src/libs/utils/process_stub.pro b/src/libs/utils/process_stub.pro
new file mode 100644
index 0000000000000000000000000000000000000000..e0f0a473eebc5967f2a9d8f58265ef4d09aaf20d
--- /dev/null
+++ b/src/libs/utils/process_stub.pro
@@ -0,0 +1,18 @@
+TEMPLATE        = app
+TARGET          = qtcreator_process_stub
+DESTDIR         = ../../../bin
+
+CONFIG          += warn_on console use_c_linker
+CONFIG          -= qt app_bundle
+
+build_all:!build_pass {
+    CONFIG -= build_all
+    CONFIG += release
+}
+
+unix {
+    SOURCES += process_stub_unix.c
+} else {
+    SOURCES += process_stub_win.c
+}
+
diff --git a/src/libs/utils/process_stub_unix.c b/src/libs/utils/process_stub_unix.c
new file mode 100644
index 0000000000000000000000000000000000000000..e49bea8d51de60cca07f38ed68a2527f6a85aaed
--- /dev/null
+++ b/src/libs/utils/process_stub_unix.c
@@ -0,0 +1,216 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact:  Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file.  Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <sys/ptrace.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+extern char **environ;
+
+static int qtcFd;
+static char *sleepMsg;
+
+static void __attribute__((noreturn)) doExit(int code)
+{
+    tcsetpgrp(0, getpid());
+    puts(sleepMsg);
+    fgets(sleepMsg, 2, stdin); /* Minimal size to make it wait */
+    exit(code);
+}
+
+static void sendMsg(const char *msg, int num)
+{
+    int pidStrLen;
+    int ioRet;
+    char pidStr[64];
+
+    pidStrLen = sprintf(pidStr, msg, num);
+    if ((ioRet = write(qtcFd, pidStr, pidStrLen)) != pidStrLen) {
+        fprintf(stderr, "Cannot write to creator comm socket: %s\n",
+                        (ioRet < 0) ? strerror(errno) : "short write");
+        doExit(3);
+    }
+}
+
+enum {
+    ArgCmd = 0,
+    ArgAction,
+    ArgSocket,
+    ArgMsg,
+    ArgDir,
+    ArgEnv
+};
+
+/* syntax: $0 {"run"|"debug"} <pid-socket> <continuation-msg> <workdir> <env...> "" <exe> <args...> */
+/* exit codes: 0 = ok, 1 = invocation error, 3 = internal error */
+int main(int argc, char *argv[])
+{
+    int envIdx = ArgEnv;
+    int errNo;
+    int chldPid;
+    int chldStatus;
+    int chldPipe[2];
+    struct sockaddr_un sau;
+
+    if (argc < ArgEnv) {
+        fprintf(stderr, "This is an internal helper of Qt Creator. Do not run it manually.\n");
+        return 1;
+    }
+    sleepMsg = argv[ArgMsg];
+
+    /* Connect to the master, i.e. Creator. */
+    if ((qtcFd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
+        perror("Cannot create creator comm socket");
+        doExit(3);
+    }
+    sau.sun_family = AF_UNIX;
+    strcpy(sau.sun_path, argv[ArgSocket]);
+    if (connect(qtcFd, (struct sockaddr *)&sau, sizeof(sau))) {
+        fprintf(stderr, "Cannot connect creator comm socket %s: %s\n", sau.sun_path, strerror(errno));
+        doExit(1);
+    }
+
+    if (*argv[ArgDir] && chdir(argv[ArgDir])) {
+        /* Only expected error: no such file or direcotry */
+        sendMsg("err:chdir %d\n", errno);
+        return 1;
+    }
+
+    /* Create execution result notification pipe. */
+    if (pipe(chldPipe)) {
+        perror("Cannot create status pipe");
+        doExit(3);
+    }
+    /* The debugged program is not supposed to inherit these handles. But we cannot
+     * close the writing end before calling exec(). Just handle both ends the same way ... */
+    fcntl(chldPipe[0], F_SETFD, FD_CLOEXEC);
+    fcntl(chldPipe[1], F_SETFD, FD_CLOEXEC);
+    switch ((chldPid = fork())) {
+        case -1:
+            perror("Cannot fork child process failed");
+            doExit(3);
+        case 0:
+            close(qtcFd);
+
+            /* Put the process into an own process group and make it the foregroud
+             * group on this terminal, so it will receive ctrl-c events, etc.
+             * This is the main reason for *all* this stub magic in the first place. */
+            /* If one of these calls fails, the world is about to end anyway, so
+             * don't bother checking the return values. */
+            setpgid(0, 0);
+            tcsetpgrp(0, getpid());
+
+            /* Get a SIGTRAP after exec() has loaded the new program. */
+#ifdef __linux__
+            ptrace(PTRACE_TRACEME);
+#else
+            ptrace(PT_TRACE_ME, 0, 0, 0);
+#endif
+
+            for (envIdx = ArgEnv; *argv[envIdx]; ++envIdx) ;
+            if (envIdx != ArgEnv) {
+                argv[envIdx] = 0;
+                environ = argv + ArgEnv;
+            }
+            ++envIdx;
+
+            execvp(argv[envIdx], argv + envIdx);
+            /* Only expected error: no such file or direcotry, i.e. executable not found */
+            errNo = errno;
+            write(chldPipe[1], &errNo, sizeof(errNo)); /* Only realistic error case is SIGPIPE */
+            _exit(0);
+        default:
+            for (;;) {
+                if (wait(&chldStatus) < 0) {
+                    perror("Cannot obtain exit status of child process");
+                    doExit(3);
+                }
+                if (WIFSTOPPED(chldStatus)) {
+                    /* The child stopped. This can be only the result of ptrace(TRACE_ME). */
+                    /* We won't need the notification pipe any more, as we know that
+                     * the exec() succeeded. */
+                    close(chldPipe[0]);
+                    close(chldPipe[1]);
+                    chldPipe[0] = -1;
+                    /* If we are not debugging, just skip the "handover enabler".
+                     * This is suboptimal, as it makes us ignore setuid/-gid bits. */
+                    if (!strcmp(argv[ArgAction], "debug")) {
+                        /* Stop the child after we detach from it, so we can hand it over to gdb.
+                         * If the signal delivery is not queued, things will go awry. It works on
+                         * Linux and MacOSX ... */
+                        kill(chldPid, SIGSTOP);
+                    }
+#ifdef __linux__
+                    ptrace(PTRACE_DETACH, chldPid, 0, 0);
+#else
+                    ptrace(PT_DETACH, chldPid, 0, 0);
+#endif
+                    sendMsg("pid %d\n", chldPid);
+                } else if (WIFEXITED(chldStatus)) {
+                    /* The child exited normally. */
+                    if (chldPipe[0] >= 0) {
+                        /* The child exited before being stopped by ptrace(). That can only
+                         * mean that the exec() failed. */
+                        switch (read(chldPipe[0], &errNo, sizeof(errNo))) {
+                            default:
+                                /* Read of unknown length. Should never happen ... */
+                                errno = EPROTO;
+                            case -1:
+                                /* Read failed. Should never happen, either ... */
+                                perror("Cannot read status from child process");
+                                doExit(3);
+                            case sizeof(errNo):
+                                /* Child telling us the errno from exec(). */
+                                sendMsg("err:exec %d\n", errNo);
+                                return 3;
+                        }
+                    }
+                    sendMsg("exit %d\n", WEXITSTATUS(chldStatus));
+                    doExit(0);
+                } else {
+                    sendMsg("crash %d\n", WTERMSIG(chldStatus));
+                    doExit(0);
+                }
+            }
+            break;
+    }
+}
diff --git a/src/libs/utils/process_stub_win.c b/src/libs/utils/process_stub_win.c
new file mode 100644
index 0000000000000000000000000000000000000000..152c83c3b121811f6ef5dfae9c0feaff6c4fbb07
--- /dev/null
+++ b/src/libs/utils/process_stub_win.c
@@ -0,0 +1,202 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact:  Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file.  Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+
+#define _WIN32_WINNT 0x0501 /* WinXP, needed for DebugActiveProcessStop() */
+
+#include <windows.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <direct.h>
+
+static FILE *qtcFd;
+static wchar_t *sleepMsg;
+
+/* Print some "press enter" message, wait for that, exit. */
+static void doExit(int code)
+{
+    char buf[2];
+    _putws(sleepMsg);
+    fgets(buf, 2, stdin); /* Minimal size to make it wait */
+    exit(code);
+}
+
+/* Print an error message for unexpected Windows system errors, wait, exit. */
+static void systemError(const char *str)
+{
+    fprintf(stderr, str, GetLastError());
+    doExit(3);
+}
+
+/* Send a message to the master. */
+static void sendMsg(const char *msg, int num)
+{
+    int pidStrLen;
+    char pidStr[64];
+
+    pidStrLen = sprintf(pidStr, msg, num);
+    if (fwrite(pidStr, pidStrLen, 1, qtcFd) != 1 || fflush(qtcFd)) {
+        fprintf(stderr, "Cannot write to creator comm socket: %s\n",
+                strerror(errno));
+        doExit(3);
+    }
+}
+
+/* Ignore the first ctrl-c/break within a second. */
+static BOOL WINAPI ctrlHandler(DWORD dwCtrlType)
+{
+    static ULARGE_INTEGER lastTime;
+    ULARGE_INTEGER thisTime;
+    SYSTEMTIME sysTime;
+    FILETIME fileTime;
+
+    if (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT) {
+        GetSystemTime(&sysTime);
+        SystemTimeToFileTime(&sysTime, &fileTime);
+        thisTime.LowPart = fileTime.dwLowDateTime;
+        thisTime.HighPart = fileTime.dwHighDateTime;
+        if (lastTime.QuadPart + 10000000 < thisTime.QuadPart) {
+            lastTime.QuadPart = thisTime.QuadPart;
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+enum {
+    ArgCmd = 0,
+    ArgAction,
+    ArgSocket,
+    ArgDir,
+    ArgEnv,
+    ArgCmdLine,
+    ArgMsg,
+    ArgCount
+};
+
+/* syntax: $0 {"run"|"debug"} <pid-socket> <workdir> <env-file> <cmdline> <continuation-msg> */
+/* exit codes: 0 = ok, 1 = invocation error, 3 = internal error */
+int main()
+{
+    int argc;
+    wchar_t **argv;
+    wchar_t *env = 0;
+    STARTUPINFOW si;
+    PROCESS_INFORMATION pi;
+    DEBUG_EVENT dbev;
+
+    argv = CommandLineToArgvW(GetCommandLine(), &argc);
+
+    if (argc != ArgCount) {
+        fprintf(stderr, "This is an internal helper of Qt Creator. Do not run it manually.\n");
+        return 1;
+    }
+    sleepMsg = argv[ArgMsg];
+
+    /* Connect to the master, i.e. Creator. */
+    if (!(qtcFd = _wfopen(argv[ArgSocket], L"w"))) {
+        fprintf(stderr, "Cannot connect creator comm pipe %S: %s\n",
+                argv[ArgSocket], strerror(errno));
+        doExit(1);
+    }
+
+    if (*argv[ArgDir] && !SetCurrentDirectoryW(argv[ArgDir])) {
+        /* Only expected error: no such file or direcotry */
+        sendMsg("err:chdir %d\n", GetLastError());
+        return 1;
+    }
+
+    if (*argv[ArgEnv]) {
+        FILE *envFd;
+        long size;
+        if (!(envFd = _wfopen(argv[ArgEnv], L"r"))) {
+            fprintf(stderr, "Cannot read creator env file %S: %s\n",
+                    argv[ArgEnv], strerror(errno));
+            doExit(1);
+        }
+        fseek(envFd, 0, SEEK_END);
+        size = ftell(envFd);
+        rewind(envFd);
+        env = malloc(size);
+        if (fread(env, 1, size, envFd) != size) {
+            perror("Failed to read env file");
+            doExit(1);
+        }
+        fclose(envFd);
+    }
+
+    ZeroMemory(&pi, sizeof(pi));
+    ZeroMemory(&si, sizeof(si));
+    si.cb = sizeof(si);
+
+    int creationFlags = CREATE_UNICODE_ENVIRONMENT;
+    if (!wcscmp(argv[ArgAction], L"debug"))
+        creationFlags |= DEBUG_ONLY_THIS_PROCESS;
+    if (!CreateProcessW(0, argv[ArgCmdLine], 0, 0, FALSE, creationFlags, env, 0, &si, &pi)) {
+        /* Only expected error: no such file or direcotry, i.e. executable not found */
+        sendMsg("err:exec %d\n", GetLastError());
+        doExit(1);
+    }
+
+    /* This is somewhat convoluted. What we actually want is creating a
+       suspended process and letting gdb attach to it. Unfortunately,
+       the Windows kernel runs amok when we attempt this.
+       So instead we start a debugged process, eat all the initial
+       debug events, suspend the process and detach from it. If gdb
+       tries to attach *now*, everthing goes smoothly. Yay. */
+    if (creationFlags & DEBUG_ONLY_THIS_PROCESS) {
+        do {
+            if (!WaitForDebugEvent (&dbev, INFINITE))
+                systemError("Cannot fetch debug event, error %d\n");
+            if (dbev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) {
+                /* The first exception to be delivered is a trap
+                   which indicates completion of startup. */
+                if (SuspendThread(pi.hThread) == (DWORD)-1)
+                    systemError("Cannot suspend debugee, error %d\n");
+            }
+            if (!ContinueDebugEvent(dbev.dwProcessId, dbev.dwThreadId, DBG_CONTINUE))
+                systemError("Cannot continue debug event, error %d\n");
+        } while (dbev.dwDebugEventCode != EXCEPTION_DEBUG_EVENT);
+        if (!DebugActiveProcessStop(dbev.dwProcessId))
+            systemError("Cannot detach from debugee, error %d\n");
+    }
+
+    SetConsoleCtrlHandler(ctrlHandler, TRUE);
+
+    sendMsg("pid %d\n", pi.dwProcessId);
+
+    if (WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_FAILED)
+        systemError("Wait for debugee failed, error %d\n");
+    doExit(0);
+    return 0;
+}
diff --git a/src/libs/utils/utils.pro b/src/libs/utils/utils.pro
index 74f25b0488c4f3aa935c2a9d81c8df681019f5c1..e8a5451602faf968633c92b3f3ed4658c8d8ec13 100644
--- a/src/libs/utils/utils.pro
+++ b/src/libs/utils/utils.pro
@@ -1,5 +1,6 @@
 TEMPLATE = lib
 TARGET = Utils
+QT += network
 
 DEFINES += QWORKBENCH_UTILS_LIBRARY
 
diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro
index f17533ee5d3de8736e1a496408ef4a38000bc54c..b3f98ec41b978280c0bdc54138f472dd6d96390a 100644
--- a/src/plugins/debugger/debugger.pro
+++ b/src/plugins/debugger/debugger.pro
@@ -9,6 +9,8 @@ include(../../plugins/coreplugin/coreplugin.pri)
 include(../../plugins/texteditor/texteditor.pri)
 include(../../plugins/cpptools/cpptools.pri)
 include(../../libs/cplusplus/cplusplus.pri)
+include(../../libs/utils/utils.pri)
+INCLUDEPATH += $$PWD/../../libs/utils
 
 QT += gui network script
 
diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h
index 54a2f93f778c5cecfdf216684f2e101b9c554ef7..04f8c6c8e2360cb0a3a579db328a8ae8eb98f725 100644
--- a/src/plugins/debugger/debuggermanager.h
+++ b/src/plugins/debugger/debuggermanager.h
@@ -381,6 +381,7 @@ public:
     QString m_buildDir;
     QStringList m_processArgs;
     int m_attachedPID;
+    bool m_useTerminal;
 
 private:
     void init();
diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp
index 674ac47bb1f5191e8bbe1258b4303f19c8997c34..15116aaf38af11dde485dcd82cd612e8a944b91e 100644
--- a/src/plugins/debugger/debuggerrunner.cpp
+++ b/src/plugins/debugger/debuggerrunner.cpp
@@ -130,6 +130,8 @@ void DebuggerRunControl::start()
     m_manager->m_processArgs = rc->commandLineArguments();
     m_manager->m_buildDir =
         project->buildDirectory(project->activeBuildConfiguration());
+    m_manager->m_useTerminal = rc->runMode() == ApplicationRunConfiguration::Console;
+
     //<daniel> andre: + "\qtc-gdbmacros\"
 
     //emit addToOutputWindow(this, tr("Debugging %1").arg(m_executable));
diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp
index dcc0382668bc373970ec86130c5a7179b57399fd..311608709bac99c4b56c8e7e7d26f02fdddc150a 100644
--- a/src/plugins/debugger/gdbengine.cpp
+++ b/src/plugins/debugger/gdbengine.cpp
@@ -98,6 +98,7 @@ enum GdbCommandType
     GdbAsyncOutput2,
     GdbStart,
     GdbAttached,
+    GdbStubAttached,
     GdbExecRun,
     GdbExecRunToFunction,
     GdbExecStep,
@@ -241,6 +242,7 @@ GdbEngine::GdbEngine(DebuggerManager *parent)
 {
     q = parent;
     qq = parent->engineInterface();
+    m_stubProc.setDebug(true);
     initializeVariables();
     initializeConnections();
 }
@@ -263,6 +265,10 @@ void GdbEngine::initializeConnections()
     connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)), q,
         SLOT(exitDebugger()));
 
+    connect(&m_stubProc, SIGNAL(processError(QString)), SLOT(stubError(QString)));
+    connect(&m_stubProc, SIGNAL(processStarted()), SLOT(stubStarted()));
+    connect(&m_stubProc, SIGNAL(wrapperStopped()), q, SLOT(exitDebugger()));
+
     // Output
     connect(&m_outputCollector, SIGNAL(byteDelivery(QByteArray)),
             SLOT(readDebugeeOutput(QByteArray)));
@@ -543,6 +549,25 @@ void GdbEngine::handleResponse(const QByteArray &buff)
     }
 }
 
+void GdbEngine::handleStubAttached()
+{
+    qq->notifyInferiorStopped();
+    m_waitingForBreakpointSynchronizationToContinue = true;
+    handleAqcuiredInferior();
+}
+
+void GdbEngine::stubStarted()
+{
+    q->m_attachedPID = m_stubProc.applicationPID();
+    qq->notifyInferiorPidChanged(q->m_attachedPID);
+    sendCommand("attach " + QString::number(q->m_attachedPID), GdbStubAttached);
+}
+
+void GdbEngine::stubError(const QString &msg)
+{
+    QMessageBox::critical(q->mainWindow(), tr("Debugger Error"), msg);
+}
+
 void GdbEngine::readGdbStandardError()
 {
     qWarning() << "Unexpected gdb stderr:" << m_gdbProc.readAllStandardError();
@@ -721,6 +746,9 @@ void GdbEngine::handleResult(const GdbResultRecord & record, int type,
     const QVariant & cookie)
 {
     switch (type) {
+        case GdbStubAttached:
+            handleStubAttached();
+            break;
         case GdbExecNext:
         case GdbExecStep:
         case GdbExecNextI:
@@ -1211,6 +1239,20 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
             QVariant var = QVariant::fromValue<GdbMi>(data);
             sendCommand("p 0", GdbAsyncOutput2, var);  // dummy
         } else {
+#ifdef Q_OS_LINUX
+            // For some reason, attaching to a stopped process causes *two* stops
+            // when trying to continue (kernel 2.6.24-23-ubuntu).
+            // Interestingly enough, on MacOSX no signal is delivered at all.
+            if (reason == QLatin1String("signal-received")
+                && data.findChild("signal-name").data() == "SIGSTOP") {
+                GdbMi frameData = data.findChild("frame");
+                if (frameData.findChild("func").data() == "_start"
+                    && frameData.findChild("from").data() == "/lib/ld-linux.so.2") {
+                    sendCommand("-exec-continue");
+                    return;
+                }
+            }
+#endif
             q->showStatusMessage(tr("Stopped: \"%1\"").arg(reason));
             handleAsyncOutput2(data);
         }
@@ -1461,23 +1503,31 @@ bool GdbEngine::startDebugger()
         return false;
     }
 
-    if (!m_outputCollector.listen()) {
-        QMessageBox::critical(q->mainWindow(), tr("Debugger Startup Failure"),
-                              tr("Cannot set up communication with child process: %1")
-                              .arg(m_outputCollector.errorString()));
-        return false;
-    }
-
-    gdbArgs.prepend(QLatin1String("--tty=") + m_outputCollector.serverName());
-
     //gdbArgs.prepend(QLatin1String("--quiet"));
     gdbArgs.prepend(QLatin1String("mi"));
     gdbArgs.prepend(QLatin1String("-i"));
 
-    if (!q->m_workingDir.isEmpty())
-        m_gdbProc.setWorkingDirectory(q->m_workingDir);
-    if (!q->m_environment.isEmpty())
-        m_gdbProc.setEnvironment(q->m_environment);
+    if (q->m_useTerminal) {
+        m_stubProc.stop(); // We leave the console open, so recycle it now.
+
+        m_stubProc.setWorkingDirectory(q->m_workingDir);
+        m_stubProc.setEnvironment(q->m_environment);
+        if (!m_stubProc.start(q->m_executable, q->m_processArgs))
+            return false; // Error message for user is delivered via a signal.
+    } else {
+        if (!m_outputCollector.listen()) {
+            QMessageBox::critical(q->mainWindow(), tr("Debugger Startup Failure"),
+                                  tr("Cannot set up communication with child process: %1")
+                                  .arg(m_outputCollector.errorString()));
+            return false;
+        }
+        gdbArgs.prepend(QLatin1String("--tty=") + m_outputCollector.serverName());
+
+        if (!q->m_workingDir.isEmpty())
+            m_gdbProc.setWorkingDirectory(q->m_workingDir);
+        if (!q->m_environment.isEmpty())
+            m_gdbProc.setEnvironment(q->m_environment);
+    }
 
     #if 0
     qDebug() << "Command: " << q->settings()->m_gdbCmd;
@@ -1495,6 +1545,9 @@ bool GdbEngine::startDebugger()
         QMessageBox::critical(q->mainWindow(), tr("Debugger Startup Failure"),
                               tr("Cannot start debugger: %1").arg(m_gdbProc.errorString()));
         m_outputCollector.shutdown();
+        m_stubProc.blockSignals(true);
+        m_stubProc.stop();
+        m_stubProc.blockSignals(false);
         return false;
     }
 
@@ -1575,7 +1628,7 @@ bool GdbEngine::startDebugger()
 
     if (q->startMode() == DebuggerManager::AttachExternal) {
         sendCommand("attach " + QString::number(q->m_attachedPID), GdbAttached);
-    } else {
+    } else if (!q->m_useTerminal) {
         // StartInternal or StartExternal
         sendCommand("-file-exec-and-symbols " + fileName, GdbFileExecAndSymbols);
         //sendCommand("file " + fileName, GdbFileExecAndSymbols);
diff --git a/src/plugins/debugger/gdbengine.h b/src/plugins/debugger/gdbengine.h
index b247202c534d3242902d4530714d435d9a9a8607..79def1362e5c36e0c68d318fa594695b77421b13 100644
--- a/src/plugins/debugger/gdbengine.h
+++ b/src/plugins/debugger/gdbengine.h
@@ -34,6 +34,8 @@
 #include "gdbmi.h"
 #include "outputcollector.h"
 
+#include <consoleprocess.h>
+
 #include <QtCore/QByteArray>
 #include <QtCore/QHash>
 #include <QtCore/QMap>
@@ -172,12 +174,15 @@ private slots:
     void readGdbStandardOutput();
     void readGdbStandardError();
     void readDebugeeOutput(const QByteArray &data);
+    void stubStarted();
+    void stubError(const QString &msg);
 
 private:
     int terminationIndex(const QByteArray &buffer, int &length);
     void handleResponse(const QByteArray &buff);
     void handleStart(const GdbResultRecord &response);
     void handleAttach();
+    void handleStubAttached();
     void handleAqcuiredInferior();
     void handleAsyncOutput2(const GdbMi &data);
     void handleAsyncOutput(const GdbMi &data);
@@ -202,6 +207,8 @@ private:
 
     QProcess m_gdbProc;
 
+    Core::Utils::ConsoleProcess m_stubProc;
+
     QHash<int, GdbCookie> m_cookieForToken;
     QHash<int, QByteArray> m_customOutputForToken;
 
diff --git a/src/plugins/projectexplorer/winguiprocess.cpp b/src/plugins/projectexplorer/winguiprocess.cpp
index 82ec4cf609c77b503a75111288f3a1cf958c4529..86b905091864a0862280ca656b8b087b37b5dce0 100644
--- a/src/plugins/projectexplorer/winguiprocess.cpp
+++ b/src/plugins/projectexplorer/winguiprocess.cpp
@@ -34,6 +34,22 @@
 
 using namespace ProjectExplorer::Internal;
 
+static QByteArray createEnvironment(const QStringList &env)
+{
+    QByteArray envlist;
+    int pos = 0;
+    foreach (const QString &tmp, env) {
+        uint tmpSize = sizeof(TCHAR) * (tmp.length() + 1);
+        envlist.resize(envlist.size() + tmpSize);
+        memcpy(envlist.data() + pos, tmp.utf16(), tmpSize);
+        pos += tmpSize;
+    }
+    envlist.resize(envlist.size() + 2);
+    envlist[pos++] = 0;
+    envlist[pos++] = 0;
+    return envlist;
+}
+
 WinGuiProcess::WinGuiProcess(QObject *parent)
     : QThread(parent)
 {
@@ -113,7 +129,7 @@ void WinGuiProcess::run()
     bool success = CreateProcessW(0, (WCHAR*)cmdLine.utf16(),
                                   0, 0, TRUE, CREATE_UNICODE_ENVIRONMENT,
                                   environment().isEmpty() ? 0
-                                  : ConsoleProcess::createEnvironment(environment()).data(),
+                                  : createEnvironment(ConsoleProcess::fixEnvironment(environment())).data(),
                                   workingDirectory().isEmpty() ? 0
                                   : (WCHAR*)QDir::convertSeparators(workingDirectory()).utf16(),
                                   &si, m_pid);