From 063d13e00f7233f89d960973295193bccf26c944 Mon Sep 17 00:00:00 2001
From: hjk <qtc-committer@nokia.com>
Date: Thu, 24 Sep 2009 10:08:17 +0200
Subject: [PATCH] debugger: work on general shutdown handling

---
 src/plugins/debugger/debuggermanager.cpp      | 103 ++++++-----
 src/plugins/debugger/debuggermanager.h        |   5 +-
 src/plugins/debugger/debuggerplugin.cpp       |  65 ++++---
 src/plugins/debugger/debuggerplugin.h         |   1 -
 src/plugins/debugger/gdb/abstractgdbadapter.h |  12 +-
 src/plugins/debugger/gdb/attachgdbadapter.h   |   1 +
 src/plugins/debugger/gdb/coregdbadapter.h     |   1 +
 src/plugins/debugger/gdb/gdbengine.cpp        | 166 ++++++++++--------
 src/plugins/debugger/gdb/gdbengine.h          |   4 +-
 src/plugins/debugger/gdb/plaingdbadapter.h    |   1 +
 src/plugins/debugger/gdb/remotegdbadapter.h   |   1 +
 src/plugins/debugger/gdb/trkgdbadapter.cpp    |  28 +--
 src/plugins/debugger/gdb/trkgdbadapter.h      |   1 +
 13 files changed, 203 insertions(+), 186 deletions(-)

diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp
index 903407750c0..63b50dc4e4b 100644
--- a/src/plugins/debugger/debuggermanager.cpp
+++ b/src/plugins/debugger/debuggermanager.cpp
@@ -82,6 +82,16 @@
 #include <QtGui/QToolButton>
 #include <QtGui/QToolTip>
 
+#define DEBUG_STATE 1
+#ifdef DEBUG_STATE
+// use  Q_FUNC_INFO?
+#   define STATE_DEBUG(s) \
+    { QString msg; QTextStream ts(&msg); ts << s; \
+      showDebuggerOutput(LogDebug, msg); }
+#else
+#   define STATE_DEBUG(s)
+#endif
+
 namespace Debugger {
 namespace Internal {
 
@@ -458,8 +468,7 @@ QList<Core::IOptionsPage*> DebuggerManager::initializeEngines(unsigned enabledTy
     }
 
     m_engine = 0;
-    if (Debugger::Constants::Internal::debug)
-        qDebug() << Q_FUNC_INFO << gdbEngine << winEngine << scriptEngine << rc.size();
+    STATE_DEBUG(gdbEngine << winEngine << scriptEngine << rc.size());
     return rc;
 }
 
@@ -526,8 +535,6 @@ void DebuggerManager::clearStatusMessage()
 void DebuggerManager::showStatusMessage(const QString &msg, int timeout)
 {
     Q_UNUSED(timeout)
-    if (Debugger::Constants::Internal::debug)
-        qDebug() << "STATUS MSG: " << msg;
     showDebuggerOutput(LogStatus, msg);
     m_statusLabel->setText(QLatin1String("   ") + msg);
     if (timeout > 0) {
@@ -572,8 +579,7 @@ void DebuggerManager::notifyInferiorExited()
 
 void DebuggerManager::notifyInferiorPidChanged(qint64 pid)
 {
-    if (Debugger::Constants::Internal::debug)
-        qDebug() << Q_FUNC_INFO << m_inferiorPid << pid;
+    STATE_DEBUG(m_inferiorPid << pid);
 
     if (m_inferiorPid != pid) {
         m_inferiorPid = pid;
@@ -588,9 +594,7 @@ void DebuggerManager::showApplicationOutput(const QString &str)
 
 void DebuggerManager::shutdown()
 {
-    if (Debugger::Constants::Internal::debug)
-        qDebug() << Q_FUNC_INFO << m_engine;
-
+    STATE_DEBUG(m_engine);
     if (m_engine)
         m_engine->shutdown();
     m_engine = 0;
@@ -643,9 +647,7 @@ void DebuggerManager::toggleBreakpoint()
 
 void DebuggerManager::toggleBreakpoint(const QString &fileName, int lineNumber)
 {
-    if (Debugger::Constants::Internal::debug)
-        qDebug() << Q_FUNC_INFO << fileName << lineNumber;
-
+    STATE_DEBUG(fileName << lineNumber);
     QTC_ASSERT(m_breakHandler, return);
     if (status() != DebuggerInferiorRunning
          && status() != DebuggerInferiorStopped
@@ -666,9 +668,7 @@ void DebuggerManager::toggleBreakpoint(const QString &fileName, int lineNumber)
 
 void DebuggerManager::toggleBreakpointEnabled(const QString &fileName, int lineNumber)
 {
-    if (Debugger::Constants::Internal::debug)
-        qDebug() << Q_FUNC_INFO << fileName << lineNumber;
-
+    STATE_DEBUG(fileName << lineNumber);
     QTC_ASSERT(m_breakHandler, return);
     if (status() != DebuggerInferiorRunning
          && status() != DebuggerInferiorStopped
@@ -726,8 +726,6 @@ static IDebuggerEngine *debuggerEngineForToolChain(ProjectExplorer::ToolChain::T
     default:
         break;
     }
-    if (Debugger::Constants::Internal::debug)
-        qDebug()  << "Toolchain" << tc << rc;
     return rc;
 }
 
@@ -819,9 +817,6 @@ static IDebuggerEngine *determineDebuggerEngine(int  /* pid */,
 void DebuggerManager::startNewDebugger(const DebuggerStartParametersPtr &sp)
 {
     m_startParameters = sp;
-    if (Debugger::Constants::Internal::debug)
-        qDebug() << Q_FUNC_INFO << '\n' << *m_startParameters;
-
     m_inferiorPid = m_startParameters->attachPID > 0
         ? m_startParameters->attachPID : 0;
     const QString toolChainName = ProjectExplorer::ToolChain::toolChainName(static_cast<ProjectExplorer::ToolChain::ToolChainType>(m_startParameters->toolChainType));
@@ -849,7 +844,7 @@ void DebuggerManager::startNewDebugger(const DebuggerStartParametersPtr &sp)
     }
 
     if (!m_engine) {
-        debuggingFinished();
+        emit debuggingFinished();
         // Create Message box with possibility to go to settings
         QAbstractButton *settingsButton = 0;
         QMessageBox msgBox(QMessageBox::Warning, tr("Warning"),
@@ -865,9 +860,7 @@ void DebuggerManager::startNewDebugger(const DebuggerStartParametersPtr &sp)
         return;
     }
 
-    if (Debugger::Constants::Internal::debug)
-        qDebug() << m_startParameters->executable << m_engine;
-
+    STATE_DEBUG(m_startParameters->executable << m_engine);
     setBusyCursor(false);
     setStatus(DebuggerProcessStartingUp);
     connect(m_engine, SIGNAL(startFailed()), this, SLOT(startFailed()));
@@ -878,7 +871,7 @@ void DebuggerManager::startFailed()
 {
     disconnect(m_engine, SIGNAL(startFailed()), this, SLOT(startFailed()));
     setStatus(DebuggerProcessNotReady);
-    debuggingFinished();
+    emit debuggingFinished();
 }
 
 void DebuggerManager::cleanupViews()
@@ -895,9 +888,7 @@ void DebuggerManager::cleanupViews()
 
 void DebuggerManager::exitDebugger()
 {
-    if (Debugger::Constants::Internal::debug)
-        qDebug() << Q_FUNC_INFO;
-
+    STATE_DEBUG("");
     if (m_engine)
         m_engine->exitDebugger();
     cleanupViews();
@@ -906,6 +897,14 @@ void DebuggerManager::exitDebugger()
     emit debuggingFinished();
 }
 
+void DebuggerManager::notifyEngineFinished()
+{
+    cleanupViews();
+    setStatus(DebuggerProcessNotReady);
+    setBusyCursor(false);
+    emit debuggingFinished();
+}
+
 DebuggerStartParametersPtr DebuggerManager::startParameters() const
 {
     return m_startParameters;
@@ -1004,9 +1003,7 @@ void DebuggerManager::executeDebuggerCommand()
 
 void DebuggerManager::executeDebuggerCommand(const QString &command)
 {
-    if (Debugger::Constants::Internal::debug)
-        qDebug() << Q_FUNC_INFO <<command;
-
+    STATE_DEBUG(command);
     QTC_ASSERT(m_engine, return);
     m_engine->executeDebuggerCommand(command);
 }
@@ -1074,9 +1071,7 @@ void DebuggerManager::addToWatchWindow()
 
 void DebuggerManager::setBreakpoint(const QString &fileName, int lineNumber)
 {
-    if (Debugger::Constants::Internal::debug)
-        qDebug() << Q_FUNC_INFO << fileName << lineNumber;
-
+    STATE_DEBUG(Q_FUNC_INFO << fileName << lineNumber);
     QTC_ASSERT(m_breakHandler, return);
     m_breakHandler->setBreakpoint(fileName, lineNumber);
     attemptBreakpointSynchronization();
@@ -1114,14 +1109,13 @@ static bool isAllowedTransition(int from, int to)
 
 void DebuggerManager::setStatus(int status)
 {
-    if (Debugger::Constants::Internal::debug)
-        qDebug() << Q_FUNC_INFO << "STATUS CHANGE: from" << stateName(m_status)
-            << "to" << stateName(status);
+    STATE_DEBUG("STATUS CHANGE: FROM " << stateName(m_status)
+            << " TO " << stateName(status));
 
     if (status == m_status)
         return;
 
-    if (1 && !isAllowedTransition(m_status, status)) {
+    if (!isAllowedTransition(m_status, status)) {
         const QString msg = QString::fromLatin1("%1: UNEXPECTED TRANSITION: %2 -> %3")
             .arg(_(Q_FUNC_INFO), _(stateName(m_status)), _(stateName(status)));
         qWarning("%s", qPrintable(msg));
@@ -1138,6 +1132,10 @@ void DebuggerManager::setStatus(int status)
 
     const bool ready = status == DebuggerInferiorStopped
             && m_startParameters->startMode != AttachCore;
+
+    STATE_DEBUG("STARTED: " << started << " RUNNING: " << running
+        << " READY: " << ready);
+
     if (ready)
         QApplication::alert(mainWindow(), 3000);
 
@@ -1171,7 +1169,7 @@ void DebuggerManager::setStatus(int status)
 
 void DebuggerManager::setBusyCursor(bool busy)
 {
-    //qDebug() << "BUSY FROM: " << m_busy << " TO: " <<  m_busy;
+    //STATE_DEBUG("BUSY FROM: " << m_busy << " TO: " << m_busy);
     if (busy == m_busy)
         return;
     m_busy = busy;
@@ -1209,8 +1207,7 @@ void DebuggerManager::detachDebugger()
 
 void DebuggerManager::interruptDebuggingRequest()
 {
-    if (Debugger::Constants::Internal::debug)
-        qDebug() << Q_FUNC_INFO << status();
+    STATE_DEBUG(status());
     if (!m_engine)
         return;
     bool interruptIsExit = (status() != DebuggerInferiorRunning);
@@ -1228,8 +1225,7 @@ void DebuggerManager::runToLineExec()
     int lineNumber = -1;
     emit currentTextEditorRequested(&fileName, &lineNumber, 0);
     if (m_engine && !fileName.isEmpty()) {
-        if (Debugger::Constants::Internal::debug)
-            qDebug() << Q_FUNC_INFO << fileName << lineNumber;
+        STATE_DEBUG(fileName << lineNumber);
         m_engine->runToLineExec(fileName, lineNumber);
     }
 }
@@ -1261,8 +1257,7 @@ void DebuggerManager::runToFunctionExec()
             }
         }
     }
-    if (Debugger::Constants::Internal::debug)
-        qDebug() << Q_FUNC_INFO << functionName;
+    STATE_DEBUG(functionName);
 
     if (m_engine && !functionName.isEmpty())
         m_engine->runToFunctionExec(functionName);
@@ -1274,8 +1269,7 @@ void DebuggerManager::jumpToLineExec()
     int lineNumber = -1;
     emit currentTextEditorRequested(&fileName, &lineNumber, 0);
     if (m_engine && !fileName.isEmpty()) {
-        if (Debugger::Constants::Internal::debug)
-            qDebug() << Q_FUNC_INFO << fileName << lineNumber;
+        STATE_DEBUG(fileName << lineNumber);
         m_engine->jumpToLineExec(fileName, lineNumber);
     }
 }
@@ -1412,8 +1406,10 @@ QString DebuggerManager::qtDumperLibraryName() const
 QStringList DebuggerManager::qtDumperLibraryLocations() const
 {
     if (theDebuggerAction(UseCustomDebuggingHelperLocation)->value().toBool()) {
-        const QString customLocation = theDebuggerAction(CustomDebuggingHelperLocation)->value().toString();
-        const QString location = tr("%1 (explicitly set in the Debugger Options)").arg(customLocation);
+        const QString customLocation =
+            theDebuggerAction(CustomDebuggingHelperLocation)->value().toString();
+        const QString location =
+            tr("%1 (explicitly set in the Debugger Options)").arg(customLocation);
         return QStringList(location);
     }
     return m_startParameters->dumperLibraryLocations;
@@ -1422,9 +1418,12 @@ QStringList DebuggerManager::qtDumperLibraryLocations() const
 void DebuggerManager::showQtDumperLibraryWarning(const QString &details)
 {
     QMessageBox dialog(mainWindow());
-    QPushButton *qtPref = dialog.addButton(tr("Open Qt preferences"), QMessageBox::ActionRole);
-    QPushButton *helperOff = dialog.addButton(tr("Turn helper usage off"), QMessageBox::ActionRole);
-    QPushButton *justContinue = dialog.addButton(tr("Continue anyway"), QMessageBox::AcceptRole);
+    QPushButton *qtPref = dialog.addButton(tr("Open Qt preferences"),
+        QMessageBox::ActionRole);
+    QPushButton *helperOff = dialog.addButton(tr("Turn helper usage off"),
+        QMessageBox::ActionRole);
+    QPushButton *justContinue = dialog.addButton(tr("Continue anyway"),
+        QMessageBox::AcceptRole);
     dialog.setDefaultButton(justContinue);
     dialog.setWindowTitle(tr("Debugging helper missing"));
     dialog.setText(tr("The debugger did not find the debugging helper library."));
diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h
index bf51de7822d..4f68df9c8f9 100644
--- a/src/plugins/debugger/debuggermanager.h
+++ b/src/plugins/debugger/debuggermanager.h
@@ -227,6 +227,7 @@ private:
     virtual void notifyInferiorRunning() = 0;
     virtual void notifyInferiorExited() = 0;
     virtual void notifyInferiorPidChanged(qint64) = 0;
+    virtual void notifyEngineFinished() {} // FIXME: make pure
 
     virtual ModulesHandler *modulesHandler() = 0;
     virtual BreakHandler *breakHandler() = 0;
@@ -374,6 +375,7 @@ private:
     void notifyInferiorRunning();
     void notifyInferiorExited();
     void notifyInferiorPidChanged(qint64);
+    void notifyEngineFinished();
 
     void cleanupViews();
 
@@ -395,9 +397,6 @@ public:
     // stuff in this block should be made private by moving it to
     // one of the interfaces
     int status() const { return m_status; }
-    // FIXME: hide this in the engines?
-    //DebuggerStartMode startMode() const;
-
     QList<Symbol> moduleSymbols(const QString &moduleName);
 
 signals:
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index f01d9b569d0..6864fbccdf0 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -453,19 +453,19 @@ void DebuggerPlugin::shutdown()
     m_manager = 0;
 }
 
-static inline QString msgParameterMissing(const QString &a)
+static QString msgParameterMissing(const QString &a)
 {
     return DebuggerPlugin::tr("Option '%1' is missing the parameter.").arg(a);
 }
 
-static inline QString msgInvalidNumericParameter(const QString &a, const QString &number)
+static QString msgInvalidNumericParameter(const QString &a, const QString &number)
 {
     return DebuggerPlugin::tr("The parameter '%1' of option '%2' is not a number.").arg(number, a);
 }
 
 // Parse arguments
 bool DebuggerPlugin::parseArgument(QStringList::const_iterator &it,
-                                   const QStringList::const_iterator& cend,
+                                   const QStringList::const_iterator &cend,
                                    QString *errorMessage)
 {
     const QString &option = *it;
@@ -529,7 +529,9 @@ bool DebuggerPlugin::parseArguments(const QStringList &args, QString *errorMessa
         if (!parseArgument(it, cend, errorMessage))
             return false;
     if (Debugger::Constants::Internal::debug)
-        qDebug().nospace() << args << "engines=0x" << QString::number(m_cmdLineEnabledEngines, 16) << " pid" << m_cmdLineAttachPid << '\n';
+        qDebug().nospace() << args << "engines=0x"
+            << QString::number(m_cmdLineEnabledEngines, 16)
+            << " pid" << m_cmdLineAttachPid << '\n';
     return true;
 }
 
@@ -537,13 +539,15 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
 {
     // Do not fail the whole plugin if something goes wrong here
     if (!parseArguments(arguments, errorMessage)) {
-        *errorMessage = tr("Error evaluating command line arguments: %1").arg(*errorMessage);
+        *errorMessage = tr("Error evaluating command line arguments: %1")
+            .arg(*errorMessage);
         qWarning("%s\n", qPrintable(*errorMessage));
         errorMessage->clear();
     }
 
     m_manager = new DebuggerManager;
-    const QList<Core::IOptionsPage *> engineOptionPages = m_manager->initializeEngines(m_cmdLineEnabledEngines);
+    const QList<Core::IOptionsPage *> engineOptionPages =
+        m_manager->initializeEngines(m_cmdLineEnabledEngines);
 
     ICore *core = ICore::instance();
     QTC_ASSERT(core, return false);
@@ -889,9 +893,6 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
         this, SLOT(activatePreviousMode()));
     connect(m_manager, SIGNAL(debugModeRequested()),
         this, SLOT(activateDebugMode()));
-    connect(m_manager, SIGNAL(statusChanged(int)),
-        this, SLOT(updateActions(int)));
-
 
     connect(theDebuggerAction(SettingsDialog), SIGNAL(triggered()),
         this, SLOT(showSettingsDialog()));
@@ -1112,7 +1113,7 @@ void DebuggerPlugin::gotoLocation(const StackFrame &frame, bool setMarker)
 
 void DebuggerPlugin::changeStatus(int status)
 {
-    bool startIsContinue = (status == DebuggerInferiorStopped);
+    const bool startIsContinue = (status == DebuggerInferiorStopped);
     ICore *core = ICore::instance();
     if (startIsContinue) {
         core->addAdditionalContext(m_gdbRunningContext);
@@ -1121,6 +1122,27 @@ void DebuggerPlugin::changeStatus(int status)
         core->removeAdditionalContext(m_gdbRunningContext);
         core->updateContext();
     }
+
+    const bool started = status == DebuggerInferiorRunning
+        || status == DebuggerInferiorRunningRequested
+        || status == DebuggerInferiorStopRequested
+        || status == DebuggerInferiorStopped;
+
+    const bool starting = status == DebuggerProcessStartingUp;
+    //const bool running = status == DebuggerInferiorRunning;
+
+    const bool ready = status == DebuggerInferiorStopped
+            && m_manager->startParameters()->startMode != AttachCore;
+
+    m_startExternalAction->setEnabled(!started && !starting);
+    m_attachExternalAction->setEnabled(!started && !starting);
+#ifdef Q_OS_WIN
+    m_attachCoreAction->setEnabled(false);
+#else
+    m_attachCoreAction->setEnabled(!started && !starting);
+#endif
+    m_startRemoteAction->setEnabled(!started && !starting);
+    m_detachAction->setEnabled(ready);
 }
 
 void DebuggerPlugin::writeSettings() const
@@ -1337,29 +1359,6 @@ void DebuggerPlugin::attachRemoteTcf()
         runControl->start();
 }
 
-void DebuggerPlugin::updateActions(int status)
-{
-    const bool started = status == DebuggerInferiorRunning
-        || status == DebuggerInferiorRunningRequested
-        || status == DebuggerInferiorStopRequested
-        || status == DebuggerInferiorStopped;
-
-    const bool starting = status == DebuggerProcessStartingUp;
-    //const bool running = status == DebuggerInferiorRunning;
-
-    const bool ready = status == DebuggerInferiorStopped
-            && m_manager->startParameters()->startMode != AttachCore;
-    m_startExternalAction->setEnabled(!started && !starting);
-    m_attachExternalAction->setEnabled(!started && !starting);
-#ifdef Q_OS_WIN
-    m_attachCoreAction->setEnabled(false);
-#else
-    m_attachCoreAction->setEnabled(!started && !starting);
-#endif
-    m_startRemoteAction->setEnabled(!started && !starting);
-    m_detachAction->setEnabled(ready);
-}
-
 #include "debuggerplugin.moc"
 
 Q_EXPORT_PLUGIN(DebuggerPlugin)
diff --git a/src/plugins/debugger/debuggerplugin.h b/src/plugins/debugger/debuggerplugin.h
index a4cf504412d..1beefb56319 100644
--- a/src/plugins/debugger/debuggerplugin.h
+++ b/src/plugins/debugger/debuggerplugin.h
@@ -94,7 +94,6 @@ private slots:
     void setConfigValue(const QString &name, const QVariant &value);
     void requestContextMenu(TextEditor::ITextEditor *editor,
         int lineNumber, QMenu *menu);
-    void updateActions(int status);
 
     void resetLocation();
     void gotoLocation(const StackFrame &frame, bool setMarker);
diff --git a/src/plugins/debugger/gdb/abstractgdbadapter.h b/src/plugins/debugger/gdb/abstractgdbadapter.h
index 5f055ddfcf3..9819c4aafc4 100644
--- a/src/plugins/debugger/gdb/abstractgdbadapter.h
+++ b/src/plugins/debugger/gdb/abstractgdbadapter.h
@@ -87,8 +87,7 @@ public:
     virtual void interruptInferior() = 0;
     virtual void shutdown() = 0;
 
-    virtual const DebuggerStartParameters &startParameters() const
-        { return m_engine->startParameters(); }
+    virtual bool dumpersAvailable() const = 0;
 
 signals:
     void adapterStarted();
@@ -111,9 +110,14 @@ signals:
     void readyReadStandardError();
 
 public:
-    virtual GdbAdapterState state() const { return m_state; }
+    GdbAdapterState state() const { return m_state; }
+    // Called by GdbEngine::handleAsyncOutput
+    void notifyInferiorExited();
+
 protected:
-    virtual void setState(GdbAdapterState state) { m_state = state; }
+    void setState(GdbAdapterState state);
+    const DebuggerStartParameters &startParameters() const
+        { return m_engine->startParameters(); }
 
     GdbEngine * const m_engine;
     GdbAdapterState m_state;
diff --git a/src/plugins/debugger/gdb/attachgdbadapter.h b/src/plugins/debugger/gdb/attachgdbadapter.h
index 6bedcbfc002..066473c9bbc 100644
--- a/src/plugins/debugger/gdb/attachgdbadapter.h
+++ b/src/plugins/debugger/gdb/attachgdbadapter.h
@@ -59,6 +59,7 @@ private:
     void setWorkingDirectory(const QString &dir) { m_gdbProc.setWorkingDirectory(dir); }
     void setEnvironment(const QStringList &env) { m_gdbProc.setEnvironment(env); }
     bool isTrkAdapter() const { return false; }
+    bool dumpersAvailable() const { return false; }
 
     void startAdapter();
     void prepareInferior();
diff --git a/src/plugins/debugger/gdb/coregdbadapter.h b/src/plugins/debugger/gdb/coregdbadapter.h
index 152c9bebf57..45c623b35ca 100644
--- a/src/plugins/debugger/gdb/coregdbadapter.h
+++ b/src/plugins/debugger/gdb/coregdbadapter.h
@@ -59,6 +59,7 @@ private:
     void setWorkingDirectory(const QString &dir) { m_gdbProc.setWorkingDirectory(dir); }
     void setEnvironment(const QStringList &env) { m_gdbProc.setEnvironment(env); }
     bool isTrkAdapter() const { return false; }
+    bool dumpersAvailable() const { return false; }
 
     void startAdapter();
     void prepareInferior();
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index ae532e2da69..9116c4d47dc 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -271,45 +271,12 @@ void GdbEngine::connectAdapter()
         this, SLOT(handleInferiorShutdownFailed(QString)));
 
     connect(m_gdbAdapter, SIGNAL(adapterCrashed()),
-        m_manager, SLOT(exitDebugger()));
+        this, SLOT(handleAdapterCrashed()));
 }
 
-
 void GdbEngine::disconnectAdapter()
 {
-    // Gdb Process interaction
-    disconnect(m_gdbAdapter, SIGNAL(error(QProcess::ProcessError)),
-        this, SLOT(gdbProcError(QProcess::ProcessError)));
-    disconnect(m_gdbAdapter, SIGNAL(readyReadStandardOutput()),
-        this, SLOT(readGdbStandardOutput()));
-    disconnect(m_gdbAdapter, SIGNAL(readyReadStandardError()),
-        this, SLOT(readGdbStandardError()));
-
-    disconnect(m_gdbAdapter, SIGNAL(adapterStarted()),
-        this, SLOT(handleAdapterStarted()));
-    disconnect(m_gdbAdapter, SIGNAL(adapterStartFailed(QString)),
-        this, SLOT(handleAdapterStartFailed(QString)));
-    disconnect(m_gdbAdapter, SIGNAL(adapterShutDown()),
-        this, SLOT(handleAdapterShutDown()));
-    disconnect(m_gdbAdapter, SIGNAL(adapterShutdownFailed(QString)),
-        this, SLOT(handleAdapterShutdownFailed(QString)));
-
-    disconnect(m_gdbAdapter, SIGNAL(inferiorPrepared()),
-        this, SLOT(handleInferiorPrepared()));
-    disconnect(m_gdbAdapter, SIGNAL(inferiorPreparationFailed(QString)),
-        this, SLOT(handleInferiorPreparationFailed(QString)));
-
-    disconnect(m_gdbAdapter, SIGNAL(inferiorStarted()),
-        this, SLOT(handleInferiorStarted()));
-    disconnect(m_gdbAdapter, SIGNAL(inferiorStartFailed(QString)),
-        this, SLOT(handleInferiorStartFailed(QString)));
-    disconnect(m_gdbAdapter, SIGNAL(inferiorShutDown()),
-        this, SLOT(handleInferiorShutDown()));
-    disconnect(m_gdbAdapter, SIGNAL(inferiorShutdownFailed(QString)),
-        this, SLOT(handleInferiorShutdownFailed(QString)));
-
-    disconnect(m_gdbAdapter, SIGNAL(adapterCrashed()),
-        m_manager, SLOT(exitDebugger()));
+    disconnect(m_gdbAdapter, 0, this, 0);
 }
 
 void GdbEngine::initializeVariables()
@@ -386,9 +353,7 @@ void GdbEngine::gdbProcError(QProcess::ProcessError error)
 
     showStatusMessage(msg);
     showMessageBox(QMessageBox::Critical, tr("Error"), msg);
-    // act as if it was closed by the core
-    //if (kill)
-        m_manager->exitDebugger();
+    shutdown(); 
 }
 
 #if 0
@@ -696,7 +661,7 @@ void GdbEngine::interruptInferior()
 
     if (m_gdbAdapter->state() == AdapterNotRunning) {
         debugMessage(_("TRYING TO INTERRUPT INFERIOR WITHOUT RUNNING GDB"));
-        qq->notifyInferiorExited();
+        shutdown();
         return;
     }
 
@@ -833,7 +798,7 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record)
             showMessageBox(QMessageBox::Critical,
                 tr("Executable failed"), QString::fromLocal8Bit(msg));
             showStatusMessage(tr("Process failed to start."));
-            exitDebugger();
+            shutdown();
         }
         return;
     }
@@ -1100,7 +1065,7 @@ void GdbEngine::handleAqcuiredInferior()
     }
     #endif
 
-    // nicer to see a bit of the world we live in
+    // It's nicer to see a bit of the world we live in.
     reloadModules();
     attemptBreakpointSynchronization();
 }
@@ -1110,19 +1075,21 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
     const QByteArray reason = data.findChild("reason").data();
 
     if (isExitedReason(reason)) {
-        qq->notifyInferiorExited();
+        // Give adapter a chance to take notice of regular exits.
+        m_gdbAdapter->notifyInferiorExited();
+
         QString msg;
         if (reason == "exited") {
-            msg = tr("Program exited with exit code %1")
+            msg = tr("Program exited with exit code %1.")
                 .arg(_(data.findChild("exit-code").toString()));
         } else if (reason == "exited-signalled" || reason == "signal-received") {
-            msg = tr("Program exited after receiving signal %1")
+            msg = tr("Program exited after receiving signal %1.")
                 .arg(_(data.findChild("signal-name").toString()));
         } else {
-            msg = tr("Program exited normally");
+            msg = tr("Program exited normally.");
         }
         showStatusMessage(msg);
-        postCommand(_("-gdb-exit"), CB(handleExit));
+        shutdown();
         return;
     }
 
@@ -1421,7 +1388,7 @@ void GdbEngine::handleFileExecAndSymbols(const GdbResultRecord &response, const
         showMessageBox(QMessageBox::Critical, tr("Starting executable failed"), msg);
         QTC_ASSERT(status() == DebuggerInferiorRunning, /**/);
         //interruptInferior();
-        qq->notifyInferiorExited();
+        shutdown();
     }
 }
 
@@ -1441,7 +1408,7 @@ void GdbEngine::handleExecContinue(const GdbResultRecord &response, const QVaria
             showMessageBox(QMessageBox::Critical, tr("Error"),
                 tr("Starting executable failed:\n") + QString::fromLocal8Bit(msg));
             QTC_ASSERT(status() == DebuggerInferiorRunning, /**/);
-            qq->notifyInferiorExited();
+            shutdown();
         }
     }
 }
@@ -1484,6 +1451,7 @@ QString GdbEngine::fullName(const QStringList &candidates)
 
 void GdbEngine::shutdown()
 {
+    debugMessage(_("INITIATE GDBENGINE SHUTDOWN"));
     m_outputCollector.shutdown();
     initializeVariables();
     m_gdbAdapter->shutdown();
@@ -1495,7 +1463,7 @@ void GdbEngine::detachDebugger()
     shutdown();
 }
 
-void GdbEngine::exitDebugger()
+void GdbEngine::exitDebugger() // called from the manager
 {
     disconnectDebuggingHelperActions();
     m_outputCollector.shutdown();
@@ -1517,8 +1485,6 @@ void GdbEngine::startDebugger(const DebuggerStartParametersPtr &sp)
     //QTC_ASSERT(m_gdbAdapter == 0, delete m_gdbAdapter; m_gdbAdapter = 0);
 
     m_startParameters = sp;
-    if (startModeAllowsDumpers())
-        connectDebuggingHelperActions();
 
     if (m_gdbAdapter)
         disconnectAdapter();
@@ -1534,6 +1500,9 @@ void GdbEngine::startDebugger(const DebuggerStartParametersPtr &sp)
     else 
         m_gdbAdapter = m_plainAdapter;
 
+    if (startModeAllowsDumpers())
+        connectDebuggingHelperActions();
+
     initializeVariables();
     connectAdapter();
 
@@ -1620,11 +1589,6 @@ void GdbEngine::handleTargetRemote(const GdbResultRecord &record, const QVariant
 }
 #endif
 
-void GdbEngine::handleExit(const GdbResultRecord &, const QVariant &)
-{
-    showStatusMessage(tr("Debugger exited."));
-}
-
 void GdbEngine::stepExec()
 {
     setTokenBarrier();
@@ -2364,7 +2328,10 @@ void GdbEngine::handleStackListFrames(const GdbResultRecord &record, const QVari
             gotoLocation(frame, true);
         }
     } else {
-        qDebug() << "LISTING STACK FAILED: " << record.toString();
+        // That always happens on symbian gdb with
+        // ^error,data={msg="Previous frame identical to this frame (corrupt stack?)"
+        // logstreamoutput="Previous frame identical to this frame (corrupt stack?)\n"
+        //qDebug() << "LISTING STACK FAILED: " << record.toString();
     }
 }
 
@@ -3062,22 +3029,25 @@ void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record, const
     //qDebug() << "DATA DUMPER TRIAL:" << record.toString();
 
     GdbMi contents;
-    QTC_ASSERT(parseConsoleStream(record, &contents), /**/);
-    const bool ok = m_dumperHelper.parseQuery(contents, QtDumperHelper::GdbDebugger) && m_dumperHelper.typeCount();
+    QTC_ASSERT(parseConsoleStream(record, &contents), qDebug() << record.toString());
+    const bool ok = m_dumperHelper.parseQuery(contents, QtDumperHelper::GdbDebugger)
+        && m_dumperHelper.typeCount();
     if (ok) {
         // Get version and sizes from dumpers. Expression cache
         // currently causes errors.
         const double dumperVersion = getDumperVersion(contents);
         if (dumperVersion < dumperVersionRequired) {
-            qq->showQtDumperLibraryWarning(QtDumperHelper::msgDumperOutdated(dumperVersionRequired, dumperVersion));
+            qq->showQtDumperLibraryWarning(
+                QtDumperHelper::msgDumperOutdated(dumperVersionRequired, dumperVersion));
             m_debuggingHelperState = DebuggingHelperUnavailable;
             return;
         }
         m_debuggingHelperState = DebuggingHelperAvailable;
-        const QString successMsg = tr("Dumper version %1, %n custom dumpers found.", 0, m_dumperHelper.typeCount()).arg(dumperVersion);
+        const QString successMsg = tr("Dumper version %1, %n custom dumpers found.",
+            0, m_dumperHelper.typeCount()).arg(dumperVersion);
         showStatusMessage(successMsg);
     } else {
-            if (!m_dumperInjectionLoad) // Retry if thread has not terminated yet.
+        if (!m_dumperInjectionLoad) // Retry if thread has not terminated yet.
             m_debuggingHelperState = DebuggingHelperUnavailable;
         showStatusMessage(tr("Debugging helpers not found."));
     }
@@ -3816,8 +3786,7 @@ void GdbEngine::recheckDebuggingHelperAvailability()
 
 bool GdbEngine::startModeAllowsDumpers() const
 {
-    const DebuggerStartMode m = startMode();
-    return m == StartInternal || m == StartExternal || m == AttachExternal;
+    return m_gdbAdapter->dumpersAvailable();
 }
 
 void GdbEngine::watchPoint(const QPoint &pnt)
@@ -4052,8 +4021,7 @@ void GdbEngine::handleAdapterStartFailed(const QString &msg)
 {
     debugMessage(_("ADAPTER START FAILED"));
     showMessageBox(QMessageBox::Critical, tr("Adapter start failed"), msg);
-    qq->notifyInferiorExited();
-    m_manager->exitDebugger();
+    shutdown();
 }
 
 void GdbEngine::handleAdapterStarted()
@@ -4069,8 +4037,6 @@ void GdbEngine::handleInferiorPreparationFailed(const QString &msg)
     showMessageBox(QMessageBox::Critical,
         tr("Inferior start preparation failed"), msg);
     shutdown();
-    qq->notifyInferiorExited();
-    m_manager->exitDebugger();
 }
 
 void GdbEngine::handleInferiorPrepared()
@@ -4203,8 +4169,7 @@ void GdbEngine::handleInferiorStartFailed(const QString &msg)
 {
     debugMessage(_("INFERIOR START FAILED"));
     showMessageBox(QMessageBox::Critical, tr("Inferior start failed"), msg);
-    qq->notifyInferiorExited();
-    m_manager->exitDebugger();
+    shutdown();
 }
 
 void GdbEngine::handleInferiorStarted()
@@ -4221,24 +4186,28 @@ void GdbEngine::handleInferiorShutDown()
 void GdbEngine::handleInferiorShutdownFailed(const QString &msg)
 {
     debugMessage(_("INFERIOR SHUTDOWN FAILED"));
-    showMessageBox(QMessageBox::Critical,
-        tr("Inferior shutdown failed"), msg);
-    qq->notifyInferiorExited();
-    m_manager->exitDebugger();
+    showMessageBox(QMessageBox::Critical, tr("Inferior shutdown failed"), msg);
+    shutdown(); // continue with adapter shutdown
+}
+
+void GdbEngine::handleAdapterCrashed()
+{
+    debugMessage(_("ADAPTER CRASHED"));
+    showMessageBox(QMessageBox::Critical, tr("Adapter crashed"), QString());
+    shutdown();
 }
 
 void GdbEngine::handleAdapterShutDown()
 {
     debugMessage(_("ADAPTER SUCCESSFULLY SHUT DOWN"));
-    qq->notifyInferiorExited();
+    qq->notifyEngineFinished();
 }
 
 void GdbEngine::handleAdapterShutdownFailed(const QString &msg)
 {
     debugMessage(_("ADAPTER SHUTDOWN FAILED"));
-    showMessageBox(QMessageBox::Critical,
-        tr("Inferior shutdown failed"), msg);
-    qq->notifyInferiorExited();
+    showMessageBox(QMessageBox::Critical, tr("Inferior shutdown failed"), msg);
+    qq->notifyEngineFinished();
 }
 
 void GdbEngine::addOptionPages(QList<Core::IOptionsPage*> *opts) const
@@ -4253,6 +4222,47 @@ void GdbEngine::showMessageBox(int icon, const QString &title, const QString &te
     m_manager->showMessageBox(icon, title, text);
 }
 
+//
+// AbstractGdbAdapter
+//
+
+static bool isAllowedTransition(int from, int to)
+{
+    return (from == -1)
+      || (from == AdapterNotRunning && to == AdapterNotRunning)
+      || (from == AdapterNotRunning && to == AdapterStarting)
+      || (from == AdapterStarting && to == AdapterStarted)
+      || (from == AdapterStarting && to == AdapterStartFailed)
+      || (from == AdapterStarted && to == InferiorPreparing)
+      || (from == InferiorPreparing && to == InferiorPrepared)
+      || (from == InferiorPreparing && to == InferiorPreparationFailed)
+      || (from == InferiorPrepared && to == InferiorStarting)
+      || (from == InferiorStarting && to == InferiorStarted)
+      || (from == InferiorStarting && to == InferiorStartFailed)
+      || (from == InferiorStarted && to == InferiorShuttingDown)
+      || (from == InferiorShuttingDown && to == InferiorShutDown)
+      || (from == InferiorShuttingDown && to == InferiorShutdownFailed)
+      || (from == InferiorShutDown && to == AdapterShuttingDown)
+      || (from == AdapterShuttingDown && to == AdapterNotRunning)
+    ;
+}
+
+void AbstractGdbAdapter::setState(GdbAdapterState state)
+{
+    QString msg = _("Adapter state from %1 to state %2.").arg(m_state).arg(state);
+    if (!isAllowedTransition(m_state, state))
+        qDebug() << "UNEXPECTED ADAPTER TRANSITION: " << msg;
+    m_engine->debugMessage(msg);
+    m_state = state;
+}
+
+void AbstractGdbAdapter::notifyInferiorExited()
+{
+    QTC_ASSERT(state() == InferiorStarted, /**/);
+    setState(InferiorShuttingDown);
+    setState(InferiorShutDown);
+}
+
 //
 // Factory
 //
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index d39546f9b81..b24e8dfd5e3 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -247,6 +247,7 @@ private slots:
     void handleInferiorShutDown();
     void handleInferiorShutdownFailed(const QString &msg);
 
+    void handleAdapterCrashed();
     void handleAdapterShutDown();
     void handleAdapterShutdownFailed(const QString &msg);
 
@@ -270,9 +271,6 @@ private:
     void handleShowVersion(const GdbResultRecord &response, const QVariant &);
     void handleQueryPwd(const GdbResultRecord &response, const QVariant &);
     void handleQuerySources(const GdbResultRecord &response, const QVariant &);
-    void handleExit(const GdbResultRecord &, const QVariant &);
-    //void handleSetTargetAsync(const GdbResultRecord &, const QVariant &);
-    //void handleTargetRemote(const GdbResultRecord &, const QVariant &);
     void handleWatchPoint(const GdbResultRecord &, const QVariant &);
     bool showToolTip();
 
diff --git a/src/plugins/debugger/gdb/plaingdbadapter.h b/src/plugins/debugger/gdb/plaingdbadapter.h
index f10d822da7f..eff136eaf3d 100644
--- a/src/plugins/debugger/gdb/plaingdbadapter.h
+++ b/src/plugins/debugger/gdb/plaingdbadapter.h
@@ -60,6 +60,7 @@ public:
     void setWorkingDirectory(const QString &dir) { m_gdbProc.setWorkingDirectory(dir); }
     void setEnvironment(const QStringList &env) { m_gdbProc.setEnvironment(env); }
     bool isTrkAdapter() const { return false; }
+    bool dumpersAvailable() const { return true; }
 
     void startAdapter();
     void prepareInferior();
diff --git a/src/plugins/debugger/gdb/remotegdbadapter.h b/src/plugins/debugger/gdb/remotegdbadapter.h
index cd15b87e599..613f1fecae6 100644
--- a/src/plugins/debugger/gdb/remotegdbadapter.h
+++ b/src/plugins/debugger/gdb/remotegdbadapter.h
@@ -59,6 +59,7 @@ private:
     void setWorkingDirectory(const QString &dir) { m_gdbProc.setWorkingDirectory(dir); }
     void setEnvironment(const QStringList &env) { m_gdbProc.setEnvironment(env); }
     bool isTrkAdapter() const { return false; }
+    bool dumpersAvailable() const { return true; }
 
     void startAdapter();
     void prepareInferior();
diff --git a/src/plugins/debugger/gdb/trkgdbadapter.cpp b/src/plugins/debugger/gdb/trkgdbadapter.cpp
index 05980ba90e5..b2d35ad1b65 100644
--- a/src/plugins/debugger/gdb/trkgdbadapter.cpp
+++ b/src/plugins/debugger/gdb/trkgdbadapter.cpp
@@ -240,7 +240,7 @@ void TrkGdbAdapter::startInferiorEarly()
     if (!m_trkDevice.open(device, &errorMessage)) {
         logMessage(QString::fromLatin1("Waiting on %1 (%2)").arg(device, errorMessage));
         // Do not loop forever
-        if (m_waitCount++ < (m_options->mode == TrkOptions::BlueTooth ? 3 : 5)) {
+        if (m_waitCount++ < (m_options->mode == TrkOptions::BlueTooth ? 60 : 5)) {
             QTimer::singleShot(1000, this, SLOT(startInferiorEarly()));
         } else {
             QString msg = QString::fromLatin1("Failed to connect to %1 after "
@@ -1327,8 +1327,8 @@ void TrkGdbAdapter::handleGdbFinished(int exitCode, QProcess::ExitStatus exitSta
 {
     logMessage(QString("GDB: ProcessFinished %1 %2")
         .arg(exitCode).arg(exitStatus));
-    //setState(AdapterNotRunning);
-    //emit adapterShutDown();
+    setState(AdapterNotRunning);
+    emit adapterShutDown();
 }
 
 void TrkGdbAdapter::handleGdbStarted()
@@ -1395,14 +1395,12 @@ void TrkGdbAdapter::handleTargetRemote(const GdbResultRecord &record, const QVar
 {
     QTC_ASSERT(state() == InferiorPreparing, qDebug() << state());
     if (record.resultClass == GdbResultDone) {
-        //postCommand(_("-exec-continue"), CB(handleExecContinue));
         setState(InferiorPrepared);
         emit inferiorPrepared();
     } else if (record.resultClass == GdbResultError) {
-        // 16^error,msg="hd:5555: Connection timed out."
-        QString msg = __(record.data.findChild("msg").data());
-        QString msg1 = tr("Connecting to remote server failed:");
-        emit inferiorPreparationFailed(msg1 + _c(' ') + msg);
+        QString msg = tr("Connecting to trk server adapter failed:\n")
+            + _(record.data.findChild("msg").data());
+        emit inferiorPreparationFailed(msg);
     }
 }
 
@@ -1411,14 +1409,17 @@ void TrkGdbAdapter::startInferior()
     QTC_ASSERT(state() == InferiorPrepared, qDebug() << state());
     setState(InferiorStarting);
     m_engine->postCommand(_("-exec-continue"), CB(handleFirstContinue));
+    // FIXME: Is there a way to properly recognize a successful start?
+    setState(InferiorStarted);
+    emit inferiorStarted();
 }
 
 void TrkGdbAdapter::handleFirstContinue(const GdbResultRecord &record, const QVariant &)
 {
-    QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
+    //QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
+    QTC_ASSERT(state() == InferiorStarted, qDebug() << state());
     if (record.resultClass == GdbResultDone) {
-        setState(InferiorStarted);
-        emit inferiorStarted();
+        // inferiorStarted already emitted above, see FIXME
     } else if (record.resultClass == GdbResultError) {
         //QString msg = __(record.data.findChild("msg").data());
         QString msg1 = tr("Connecting to remote server failed:");
@@ -1589,20 +1590,22 @@ void TrkGdbAdapter::setEnvironment(const QStringList &env)
 
 void TrkGdbAdapter::shutdown()
 {
+    qDebug() << "ADAPTER SHUTDOWN " << state();
     if (state() == InferiorStarted) {
         setState(InferiorShuttingDown);
+        qDebug() << "kill";
         m_engine->postCommand(_("kill"), CB(handleKill));
         return;
     }
 
     if (state() == InferiorShutDown) {
         setState(AdapterShuttingDown);
+        qDebug() << "gdb-exit";
         m_engine->postCommand(_("-gdb-exit"), CB(handleExit));
         return;
     }
 
     QTC_ASSERT(state() == AdapterNotRunning, qDebug() << state());
-    emit adapterShutDown();
 }
 
 void TrkGdbAdapter::handleKill(const GdbResultRecord &response, const QVariant &)
@@ -1622,6 +1625,7 @@ void TrkGdbAdapter::handleKill(const GdbResultRecord &response, const QVariant &
 void TrkGdbAdapter::handleExit(const GdbResultRecord &response, const QVariant &)
 {
     if (response.resultClass == GdbResultDone) {
+        qDebug() << "EXITED, NO MESSAGE...";
         // don't set state here, this will be handled in handleGdbFinished()
     } else if (response.resultClass == GdbResultError) {
         QString msg = tr("Gdb process could not be stopped:\n") +
diff --git a/src/plugins/debugger/gdb/trkgdbadapter.h b/src/plugins/debugger/gdb/trkgdbadapter.h
index 7c6ecda322a..80874ddf6ed 100644
--- a/src/plugins/debugger/gdb/trkgdbadapter.h
+++ b/src/plugins/debugger/gdb/trkgdbadapter.h
@@ -114,6 +114,7 @@ public:
     void setWorkingDirectory(const QString &dir);
     void setEnvironment(const QStringList &env);
     bool isTrkAdapter() const { return true; }
+    bool dumpersAvailable() const { return false; }
 
     void startAdapter();
     void prepareInferior();
-- 
GitLab