From e0de01190f8ccd460d2c7925b1e22cace2708928 Mon Sep 17 00:00:00 2001
From: Friedemann Kleint <Friedemann.Kleint@nokia.com>
Date: Wed, 6 May 2009 14:26:20 +0200
Subject: [PATCH] Started Console process handling for CDB.

Introduced "Suspend" mode for the process stub and corresponding
mode enumeration in console process (Windows).
---
 src/libs/utils/consoleprocess.cpp             | 86 +++++++++++++++++++
 src/libs/utils/consoleprocess.h               | 16 +++-
 src/libs/utils/consoleprocess_unix.cpp        | 43 +++++-----
 src/libs/utils/consoleprocess_win.cpp         | 45 +++++-----
 src/libs/utils/process_stub_win.c             | 19 +++-
 src/libs/utils/utils.pro                      |  3 +-
 src/plugins/debugger/cdb/cdbdebugengine.cpp   | 23 +++--
 .../debugger/cdb/cdbdebugeventcallback.cpp    |  9 +-
 src/plugins/debugger/cdb/cdbdumperhelper.cpp  |  4 +-
 src/plugins/debugger/gdbengine.cpp            |  2 +-
 10 files changed, 183 insertions(+), 67 deletions(-)
 create mode 100644 src/libs/utils/consoleprocess.cpp

diff --git a/src/libs/utils/consoleprocess.cpp b/src/libs/utils/consoleprocess.cpp
new file mode 100644
index 00000000000..f55233dcfa6
--- /dev/null
+++ b/src/libs/utils/consoleprocess.cpp
@@ -0,0 +1,86 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact:  Qt Software Information (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+**************************************************************************/
+
+#include "consoleprocess.h"
+
+namespace Core {
+namespace Utils {
+
+QString ConsoleProcess::modeOption(Mode m)
+{
+    switch (m) {
+        case Debug:
+        return QLatin1String("debug");
+        case Suspend:
+        return QLatin1String("suspend");
+        case Run:
+        break;
+    }
+    return QLatin1String("run");
+}
+
+QString ConsoleProcess::msgCommChannelFailed(const QString &error)
+{
+    return tr("Cannot set up communication channel: %1").arg(error);
+}
+
+QString ConsoleProcess::msgPromptToClose()
+{
+    //! Showed in a terminal which might have
+    //! a different character set on Windows.
+    return tr("Press <RETURN> to close this window...");
+}
+
+QString ConsoleProcess::msgCannotCreateTempFile(const QString &why)
+{
+    return tr("Cannot create temporary file: %1").arg(why);
+}
+
+QString ConsoleProcess::msgCannotCreateTempDir(const QString & dir, const QString &why)
+{
+    return tr("Cannot create temporary directory '%1': %2").arg(dir, why);
+}
+
+QString ConsoleProcess::msgUnexpectedOutput()
+{
+    return tr("Unexpected output from helper program.");
+}
+
+QString ConsoleProcess::msgCannotChangeToWorkDir(const QString & dir, const QString &why)
+{
+    return tr("Cannot change to working directory '%1': %2").arg(dir, why);
+}
+
+QString ConsoleProcess::msgCannotExecute(const QString & p, const QString &why)
+{
+    return tr("Cannot execute '%1': %2").arg(p, why);
+}
+
+}
+}
diff --git a/src/libs/utils/consoleprocess.h b/src/libs/utils/consoleprocess.h
index 6da57e375b9..4604a1f6752 100644
--- a/src/libs/utils/consoleprocess.h
+++ b/src/libs/utils/consoleprocess.h
@@ -59,14 +59,15 @@ class QWORKBENCH_UTILS_EXPORT ConsoleProcess : public QObject, public AbstractPr
     Q_OBJECT
 
 public:
+    enum Mode { Run, Debug, Suspend };
     ConsoleProcess(QObject *parent = 0);
     ~ConsoleProcess();
 
     bool start(const QString &program, const QStringList &args);
     void stop();
 
-    void setDebug(bool on) { m_debug = on; }
-    bool isDebug() const { return m_debug; }
+    void setMode(Mode m) { m_mode = m; }
+    Mode mode() const { return m_mode; }
 
     bool isRunning() const; // This reflects the state of the console+stub
     qint64 applicationPID() const { return m_appPid; }
@@ -99,6 +100,15 @@ private slots:
 #endif
 
 private:
+    static QString modeOption(Mode m);
+    static QString msgCommChannelFailed(const QString &error);
+    static QString msgPromptToClose();
+    static QString msgCannotCreateTempFile(const QString &why);
+    static QString msgCannotCreateTempDir(const QString & dir, const QString &why);
+    static QString msgUnexpectedOutput();
+    static QString msgCannotChangeToWorkDir(const QString & dir, const QString &why);
+    static QString msgCannotExecute(const QString & p, const QString &why);
+
     QString stubServerListen();
     void stubServerShutdown();
 #ifdef Q_OS_WIN
@@ -106,7 +116,7 @@ private:
     void cleanupInferior();
 #endif
 
-    bool m_debug;
+    Mode m_mode;
     qint64 m_appPid;
     int m_appCode;
     QString m_executable;
diff --git a/src/libs/utils/consoleprocess_unix.cpp b/src/libs/utils/consoleprocess_unix.cpp
index c1183734d09..226dc18ca3a 100644
--- a/src/libs/utils/consoleprocess_unix.cpp
+++ b/src/libs/utils/consoleprocess_unix.cpp
@@ -44,14 +44,13 @@
 
 using namespace Core::Utils;
 
-ConsoleProcess::ConsoleProcess(QObject *parent)
-    : QObject(parent)
+ConsoleProcess::ConsoleProcess(QObject *parent)  :
+    QObject(parent),
+    m_mode(Run),
+    m_appPid(0),
+    m_stubSocket(0),
+    m_settings(0)
 {
-    m_debug = false;
-    m_appPid = 0;
-    m_stubSocket = 0;
-    m_settings = 0;
-
     connect(&m_stubServer, SIGNAL(newConnection()), SLOT(stubConnectionAvailable()));
 
     m_process.setProcessChannelMode(QProcess::ForwardedChannels);
@@ -69,9 +68,9 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
     if (isRunning())
         return false;
 
-    QString err = stubServerListen();
+    const QString err = stubServerListen();
     if (!err.isEmpty()) {
-        emit processError(tr("Cannot set up communication channel: %1").arg(err));
+        emit processError(msgCommChannelFailed(err));
         return false;
     }
 
@@ -79,7 +78,7 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
         m_tempFile = new QTemporaryFile();
         if (!m_tempFile->open()) {
             stubServerShutdown();
-            emit processError(tr("Cannot create temporary file: %1").arg(m_tempFile->errorString()));
+            emit processError(msgCannotCreateTempFile(m_tempFile->errorString()));
             delete m_tempFile;
             m_tempFile = 0;
             return false;
@@ -94,13 +93,13 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
     QStringList xtermArgs = terminalEmulator(m_settings).split(QLatin1Char(' ')); // FIXME: quoting
     xtermArgs
 #ifdef Q_OS_MAC
-              << (QCoreApplication::applicationDirPath() + "/../Resources/qtcreator_process_stub")
+              << (QCoreApplication::applicationDirPath() + QLatin1String("/../Resources/qtcreator_process_stub"))
 #else
-              << (QCoreApplication::applicationDirPath() + "/qtcreator_process_stub")
+              << (QCoreApplication::applicationDirPath() + QLatin1String("/qtcreator_process_stub"))
 #endif
-              << (m_debug ? "debug" : "exec")
+              << modeOption(m_mode)
               << m_stubServer.fullServerName()
-              << tr("Press <RETURN> to close this window...")
+              << msgPromptToClose()
               << workingDirectory()
               << (m_tempFile ? m_tempFile->fileName() : 0)
               << program << args;
@@ -145,7 +144,7 @@ QString ConsoleProcess::stubServerListen()
         {
             QTemporaryFile tf;
             if (!tf.open())
-                return tr("Cannot create temporary file: %1").arg(tf.errorString());
+                return msgCannotCreateTempFile(tf.errorString());
             stubFifoDir = QFile::encodeName(tf.fileName());
         }
         // By now the temp file was deleted again
@@ -153,9 +152,9 @@ QString ConsoleProcess::stubServerListen()
         if (!::mkdir(m_stubServerDir.constData(), 0700))
             break;
         if (errno != EEXIST)
-            return tr("Cannot create temporary directory '%1': %2").arg(stubFifoDir, strerror(errno));
+            return msgCannotCreateTempDir(stubFifoDir, QString::fromLocal8Bit(strerror(errno)));
     }
-    QString stubServer  = stubFifoDir + "/stub-socket";
+    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());
@@ -190,11 +189,9 @@ void ConsoleProcess::readStubOutput()
         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())));
+            emit processError(msgCannotChangeToWorkDir(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())));
+            emit processError(msgCannotExecute(m_executable, errorMsg(out.mid(9).toInt())));
         } else if (out.startsWith("pid ")) {
             // Will not need it any more
             delete m_tempFile;
@@ -213,7 +210,7 @@ void ConsoleProcess::readStubOutput()
             m_appPid = 0;
             emit processStopped();
         } else {
-            emit processError(tr("Unexpected output from helper program."));
+            emit processError(msgUnexpectedOutput());
             m_process.terminate();
             break;
         }
@@ -250,7 +247,7 @@ QString ConsoleProcess::defaultTerminalEmulator()
 
 QString ConsoleProcess::terminalEmulator(const QSettings *settings)
 {
-    QString dflt = defaultTerminalEmulator() + QLatin1String(" -e");
+    const QString dflt = defaultTerminalEmulator() + QLatin1String(" -e");
     if (!settings)
         return dflt;
     return settings->value(QLatin1String("General/TerminalEmulator"), dflt).toString();
diff --git a/src/libs/utils/consoleprocess_win.cpp b/src/libs/utils/consoleprocess_win.cpp
index bc4b9a31e91..71b589061ad 100644
--- a/src/libs/utils/consoleprocess_win.cpp
+++ b/src/libs/utils/consoleprocess_win.cpp
@@ -42,18 +42,17 @@
 
 using namespace Core::Utils;
 
-ConsoleProcess::ConsoleProcess(QObject *parent)
-    : QObject(parent)
+ConsoleProcess::ConsoleProcess(QObject *parent) :
+    QObject(parent),
+    m_mode(Run),
+    m_appPid(0),
+    m_pid(0),
+    m_hInferior(NULL),
+    m_tempFile(0),
+    m_stubSocket(0),
+    processFinishedNotifier(0),
+    inferiorFinishedNotifier(0)
 {
-    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()));
 }
 
@@ -67,9 +66,9 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
     if (isRunning())
         return false;
 
-    QString err = stubServerListen();
+    const QString err = stubServerListen();
     if (!err.isEmpty()) {
-        emit processError(tr("Cannot set up communication channel: %1").arg(err));
+        emit processError(msgCommChannelFailed(err));
         return false;
     }
 
@@ -77,7 +76,7 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
         m_tempFile = new QTemporaryFile();
         if (!m_tempFile->open()) {
             stubServerShutdown();
-            emit processError(tr("Cannot create temporary file: %1").arg(m_tempFile->errorString()));
+            emit processError(msgCannotCreateTempFile(m_tempFile->errorString()));
             delete m_tempFile;
             m_tempFile = 0;
             return false;
@@ -102,15 +101,15 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
         workDir.append('\\');
 
     QStringList stubArgs;
-    stubArgs << (m_debug ? "debug" : "exec")
+    stubArgs << modeOption(m_mode)
              << m_stubServer.fullServerName()
              << workDir
              << (m_tempFile ? m_tempFile->fileName() : 0)
              << createWinCommandline(program, args)
-             << tr("Press <RETURN> to close this window...");
+             << msgPromptToClose();
 
-    QString cmdLine = createWinCommandline(
-            QCoreApplication::applicationDirPath() + "/qtcreator_process_stub.exe", stubArgs);
+    const QString cmdLine = createWinCommandline(
+            QCoreApplication::applicationDirPath() + QLatin1String("/qtcreator_process_stub.exe"), stubArgs);
 
     bool success = CreateProcessW(0, (WCHAR*)cmdLine.utf16(),
                                   0, 0, FALSE, CREATE_NEW_CONSOLE,
@@ -180,13 +179,11 @@ void ConsoleProcess::readStubOutput()
         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(), winErrorMessage(out.mid(10).toInt())));
+            emit processError(msgCannotChangeToWorkDir(workingDirectory(), winErrorMessage(out.mid(10).toInt())));
         } else if (out.startsWith("err:exec ")) {
-            emit processError(tr("Cannot execute '%1': %2")
-                              .arg(m_executable, winErrorMessage(out.mid(9).toInt())));
+            emit processError(msgCannotExecute(m_executable, winErrorMessage(out.mid(9).toInt())));
         } else if (out.startsWith("pid ")) {
-            // Will not need it any more
+            // Wil not need it any more
             delete m_tempFile;
             m_tempFile = 0;
 
@@ -204,7 +201,7 @@ void ConsoleProcess::readStubOutput()
             connect(inferiorFinishedNotifier, SIGNAL(activated(HANDLE)), SLOT(inferiorExited()));
             emit processStarted();
         } else {
-            emit processError(tr("Unexpected output from helper program."));
+            emit processError(msgUnexpectedOutput());
             TerminateProcess(m_pid->hProcess, (unsigned)-1);
             break;
         }
diff --git a/src/libs/utils/process_stub_win.c b/src/libs/utils/process_stub_win.c
index 961f1d5ae08..ed64260ab80 100644
--- a/src/libs/utils/process_stub_win.c
+++ b/src/libs/utils/process_stub_win.c
@@ -39,6 +39,8 @@
 static FILE *qtcFd;
 static wchar_t *sleepMsg;
 
+enum RunMode { Run, Debug, Suspend };
+
 /* Print some "press enter" message, wait for that, exit. */
 static void doExit(int code)
 {
@@ -112,6 +114,7 @@ int main()
     STARTUPINFOW si;
     PROCESS_INFORMATION pi;
     DEBUG_EVENT dbev;
+    enum RunMode mode = Run;
 
     argv = CommandLineToArgvW(GetCommandLine(), &argc);
 
@@ -158,8 +161,20 @@ int main()
     si.cb = sizeof(si);
 
     creationFlags = CREATE_UNICODE_ENVIRONMENT;
-    if (!wcscmp(argv[ArgAction], L"debug"))
+    if (!wcscmp(argv[ArgAction], L"debug")) {
+        mode = Debug;
+    } else if (!wcscmp(argv[ArgAction], L"suspend")) {
+        mode = Suspend;
+    }
+
+    switch (mode) {
+    case Debug:
         creationFlags |= DEBUG_ONLY_THIS_PROCESS;
+        break;
+    case Suspend:
+        creationFlags |= CREATE_SUSPENDED;
+        break;
+    }
     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());
@@ -172,7 +187,7 @@ int main()
        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*, everything goes smoothly. Yay. */
-    if (creationFlags & DEBUG_ONLY_THIS_PROCESS) {
+    if (mode == Debug) {
         do {
             if (!WaitForDebugEvent (&dbev, INFINITE))
                 systemError("Cannot fetch debug event, error %d\n");
diff --git a/src/libs/utils/utils.pro b/src/libs/utils/utils.pro
index ebce693dc4b..6502e40d035 100644
--- a/src/libs/utils/utils.pro
+++ b/src/libs/utils/utils.pro
@@ -26,7 +26,8 @@ SOURCES += \
     savedaction.cpp \
     submiteditorwidget.cpp \
     synchronousprocess.cpp \
-    submitfieldwidget.cpp
+    submitfieldwidget.cpp \
+    consoleprocess.cpp
 
 win32 {
     SOURCES += abstractprocess_win.cpp \
diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp
index 72a60595ca1..39c52525b64 100644
--- a/src/plugins/debugger/cdb/cdbdebugengine.cpp
+++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp
@@ -392,7 +392,7 @@ CdbDebugEngine::CdbDebugEngine(DebuggerManager *parent, const QSharedPointer<Cdb
     IDebuggerEngine(parent),
     m_d(new CdbDebugEnginePrivate(parent, options, this))
 {
-    // m_d->m_consoleStubProc.setDebug(true);
+    m_d->m_consoleStubProc.setMode(Core::Utils::ConsoleProcess::Suspend);
     connect(&m_d->m_consoleStubProc, SIGNAL(processError(QString)), this, SLOT(slotConsoleStubError(QString)));
     connect(&m_d->m_consoleStubProc, SIGNAL(processStarted()), this, SLOT(slotConsoleStubStarted()));
     connect(&m_d->m_consoleStubProc, SIGNAL(wrapperStopped()), this, SLOT(slotConsoleStubTerminated()));
@@ -469,10 +469,12 @@ bool CdbDebugEngine::startDebugger()
     m_d->m_debuggerManager->showStatusMessage("Starting Debugger", -1);
     QString errorMessage;
     bool rc = false;
+    bool needWatchTimer = false;
     m_d->clearForRun();
     switch (mode) {
     case AttachExternal:
         rc = startAttachDebugger(m_d->m_debuggerManager->m_attachedPID, &errorMessage);
+        needWatchTimer = true;
         break;
     case StartInternal:
     case StartExternal:
@@ -484,7 +486,9 @@ bool CdbDebugEngine::startDebugger()
             rc = m_d->m_consoleStubProc.start(m_d->m_debuggerManager->m_executable, m_d->m_debuggerManager->m_processArgs);
             if (!rc)
                 errorMessage = tr("The console stub process was unable to start '%1'.").arg(m_d->m_debuggerManager->m_executable);
+            // continues in slotConsoleStubStarted()...
         } else {
+            needWatchTimer = true;
             rc = startDebuggerWithExecutable(mode, &errorMessage);
         }
         break;
@@ -494,7 +498,8 @@ bool CdbDebugEngine::startDebugger()
     }
     if (rc) {
         m_d->m_debuggerManager->showStatusMessage(tr("Debugger Running"), -1);
-        startWatchTimer();
+        if (needWatchTimer)
+            startWatchTimer();
     } else {
         qWarning("%s\n", qPrintable(errorMessage));
     }
@@ -503,12 +508,12 @@ bool CdbDebugEngine::startDebugger()
 
 bool CdbDebugEngine::startAttachDebugger(qint64 pid, QString *errorMessage)
 {
-    // Need to aatrach invasively, otherwise, no notification signals
+    // Need to attrach invasively, otherwise, no notification signals
     // for for CreateProcess/ExitProcess occur.
-    const HRESULT hr = m_d->m_cif.debugClient->AttachProcess(NULL, pid,
-                                                          DEBUG_ATTACH_INVASIVE_RESUME_PROCESS);
+    const ULONG flags = DEBUG_ATTACH_INVASIVE_RESUME_PROCESS;
+    const HRESULT hr = m_d->m_cif.debugClient->AttachProcess(NULL, pid, flags);
     if (debugCDB)
-        qDebug() << "Attaching to " << pid << " returns " << hr;
+        qDebug() << "Attaching to " << pid << " returns " << hr << executionStatusString(m_d->m_cif.debugControl);
     if (FAILED(hr)) {
         *errorMessage = tr("AttachProcess failed for pid %1: %2").arg(pid).arg(msgDebugEngineComResult(hr));
         return false;
@@ -560,7 +565,6 @@ bool CdbDebugEngine::startDebuggerWithExecutable(DebuggerStartMode sm, QString *
         m_d->m_mode = sm;
     }
     m_d->m_debuggerManagerAccess->notifyInferiorRunning();
-
     return true;
 }
 
@@ -1318,7 +1322,9 @@ void CdbDebugEngine::slotConsoleStubStarted()
     QString errorMessage;
     if (startAttachDebugger(appPid, &errorMessage)) {
         m_d->m_debuggerManager->m_attachedPID = appPid;
+        startWatchTimer();
         m_d->m_debuggerManagerAccess->notifyInferiorPidChanged(appPid);
+        m_d->m_debuggerManagerAccess->notifyInferiorRunning();
     } else {
         QMessageBox::critical(m_d->m_debuggerManager->mainWindow(), tr("Debugger Error"), errorMessage);
     }
@@ -1343,7 +1349,8 @@ void CdbDebugEnginePrivate::notifyCrashed()
 void CdbDebugEnginePrivate::handleDebugEvent()
 {
     if (debugCDB)
-        qDebug() << Q_FUNC_INFO << m_hDebuggeeProcess;
+        qDebug() << Q_FUNC_INFO << '\n'  << m_hDebuggeeProcess << m_breakEventMode
+                << executionStatusString(m_cif.debugControl);
 
     // restore mode and do special handling
     const HandleBreakEventMode mode = m_breakEventMode;
diff --git a/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp b/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp
index 42e48b3dc91..eefb0bd06c9 100644
--- a/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp
+++ b/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp
@@ -34,7 +34,7 @@
 #include "breakhandler.h"
 #include "cdbstacktracecontext.h"
 
-enum { cppExceptionCode = 0xe06d7363 };
+enum { cppExceptionCode = 0xe06d7363, startupCompleteTrap = 0x406d1388 };
 
 #include <QtCore/QDebug>
 #include <QtCore/QTextStream>
@@ -245,6 +245,9 @@ void formatException(const EXCEPTION_RECORD64 *e, QTextStream &str)
     case cppExceptionCode:
         str << "C++ exception";
         break;
+    case startupCompleteTrap:
+        str << "Startup complete";
+        break;
     case EXCEPTION_ACCESS_VIOLATION: {
             const bool writeOperation = e->ExceptionInformation[0];
             str << (writeOperation ? "write" : "read")
@@ -341,7 +344,7 @@ static bool isFatalException(LONG code)
     switch (code) {
     case EXCEPTION_BREAKPOINT:
     case EXCEPTION_SINGLE_STEP:
-    case 0x406d1388: // Mysterious exception at start of application
+    case startupCompleteTrap: // Mysterious exception at start of application
         return false;
     default:
         break;
@@ -362,7 +365,7 @@ STDMETHODIMP CdbDebugEventCallback::Exception(
     }
     const bool fatal = isFatalException(Exception->ExceptionCode);
     if (debugCDB)
-        qDebug() << Q_FUNC_INFO << '\n' << fatal << msg;
+        qDebug() << Q_FUNC_INFO << "\nex=" << Exception->ExceptionCode << " fatal=" << fatal << msg;
     m_pEngine->m_d->m_debuggerManagerAccess->showApplicationOutput(msg);
     if (fatal)
         m_pEngine->m_d->notifyCrashed();
diff --git a/src/plugins/debugger/cdb/cdbdumperhelper.cpp b/src/plugins/debugger/cdb/cdbdumperhelper.cpp
index b76398254d0..c6d2337d0de 100644
--- a/src/plugins/debugger/cdb/cdbdumperhelper.cpp
+++ b/src/plugins/debugger/cdb/cdbdumperhelper.cpp
@@ -352,7 +352,7 @@ bool CdbDumperHelper::ensureInitialized(QString *errorMessage)
                 return false;
             case CallLoadNoQtApp:
                 m_access->showDebuggerOutput(m_messagePrefix, QCoreApplication::translate("CdbDumperHelper", "The debuggee does not appear to be Qt application."));
-                disable();
+                m_state = Disabled; // No message here
                 return true;
             }
         break;
@@ -367,7 +367,7 @@ bool CdbDumperHelper::ensureInitialized(QString *errorMessage)
         m_access->showDebuggerOutput(m_messagePrefix, m_helper.toString());
         m_state = Initialized;
     } else {
-        disable();
+        m_state = Disabled; // No message here
         *errorMessage = QCoreApplication::translate("CdbDumperHelper", "The custom dumper library could not be initialized: %1").arg(*errorMessage);
         m_access->showDebuggerOutput(m_messagePrefix, *errorMessage);
         m_access->showQtDumperLibraryWarning(*errorMessage);
diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp
index db84d268e57..f80b76b5f19 100644
--- a/src/plugins/debugger/gdbengine.cpp
+++ b/src/plugins/debugger/gdbengine.cpp
@@ -117,7 +117,7 @@ GdbEngine::GdbEngine(DebuggerManager *parent)
 {
     q = parent;
     qq = parent->engineInterface();
-    m_stubProc.setDebug(true);
+    m_stubProc.setMode(Core::Utils::ConsoleProcess::Debug);
     initializeVariables();
     initializeConnections();
 }
-- 
GitLab