From b3addf14f154cc615b41def18f08f3ded5555957 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen <oswald.buddenhagen@nokia.com> Date: Tue, 20 Oct 2009 11:02:16 +0200 Subject: [PATCH] fix shutdown paths this includes: - move the gdb ownership back to the engine (thus strip down the adaptors as far as possible) - make gdb startup synchronous - make adapter shutdown synchronous - fix the state transitions relating to shutdown --- src/plugins/debugger/cdb/cdbdebugengine.cpp | 12 +- src/plugins/debugger/debuggerconstants.h | 6 +- src/plugins/debugger/debuggermanager.cpp | 95 +++--- src/plugins/debugger/debuggermanager.h | 2 +- .../debugger/gdb/abstractgdbadapter.cpp | 25 +- src/plugins/debugger/gdb/abstractgdbadapter.h | 38 ++- src/plugins/debugger/gdb/attachgdbadapter.cpp | 73 +---- src/plugins/debugger/gdb/attachgdbadapter.h | 8 +- src/plugins/debugger/gdb/coregdbadapter.cpp | 55 +--- src/plugins/debugger/gdb/coregdbadapter.h | 6 - src/plugins/debugger/gdb/gdbengine.cpp | 276 ++++++++++++------ src/plugins/debugger/gdb/gdbengine.h | 11 +- src/plugins/debugger/gdb/plaingdbadapter.cpp | 93 +----- src/plugins/debugger/gdb/plaingdbadapter.h | 7 +- src/plugins/debugger/gdb/remotegdbadapter.cpp | 74 +---- src/plugins/debugger/gdb/remotegdbadapter.h | 6 - src/plugins/debugger/gdb/trkgdbadapter.cpp | 146 +-------- src/plugins/debugger/gdb/trkgdbadapter.h | 14 +- src/plugins/debugger/idebuggerengine.h | 2 +- 19 files changed, 301 insertions(+), 648 deletions(-) diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp index e96c864baa7..d03c68bab7f 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.cpp +++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp @@ -824,6 +824,9 @@ void CdbDebugEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG6 void CdbDebugEngine::processTerminated(unsigned long exitCode) { manager()->showDebuggerOutput(LogMisc, tr("The process exited with exit code %1.").arg(exitCode)); + if (m_engine->state() != InferiorStopping) + setState(InferiorStopping, Q_FUNC_INFO, __LINE__); + setState(InferiorStopped, Q_FUNC_INFO, __LINE__); setState(InferiorShuttingDown, Q_FUNC_INFO, __LINE__); m_d->setDebuggeeHandles(0, 0); m_d->clearForRun(); @@ -919,14 +922,11 @@ void CdbDebugEnginePrivate::endDebugging(EndDebuggingMode em) errorMessage.clear(); } // Clean up resources (open files, etc.) - m_engine->setState(AdapterShuttingDown, Q_FUNC_INFO, __LINE__); + m_engine->setState(EngineShuttingDown, Q_FUNC_INFO, __LINE__); clearForRun(); const HRESULT hr = m_cif.debugClient->EndSession(DEBUG_END_PASSIVE); - if (SUCCEEDED(hr)) { - m_engine->setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__); - } else { - m_engine->setState(AdapterShutdownFailed, Q_FUNC_INFO, __LINE__); - m_engine->setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__); + m_engine->setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__); + if (!SUCCEEDED(hr)) { errorMessage = QString::fromLatin1("There were errors trying to end debugging: %1").arg(msgComFailed("EndSession", hr)); manager()->showDebuggerOutput(LogError, errorMessage); } diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h index 2100aa873fe..d3bc9d20f40 100644 --- a/src/plugins/debugger/debuggerconstants.h +++ b/src/plugins/debugger/debuggerconstants.h @@ -79,15 +79,13 @@ enum DebuggerState InferiorStopping, // Debuggee running, stop requested InferiorStopped, // Debuggee stopped - InferiorStopFailed, // Debuggee stopped + InferiorStopFailed, // Debuggee not stopped, will kill debugger InferiorShuttingDown, InferiorShutDown, InferiorShutdownFailed, - AdapterShuttingDown, - //AdapterShutDown, // Use DebuggerNotReady instead - AdapterShutdownFailed, + EngineShuttingDown }; enum DebuggerStartMode diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index c7f541293fc..1bcb97a955c 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -101,43 +101,35 @@ // gdbserver, the trk client etc are referred to as 'Adapter', // whereas the debugged process is referred to as 'Inferior'. // -// 0 == DebuggerNotReady +// 0 == DebuggerNotReady // | -// EngineStarting +// EngineStarting // | -// AdapterStarting --> AdapterStartFailed --> 0 +// AdapterStarting --> AdapterStartFailed --> 0 // | -// AdapterStarted -// | -// InferiorStarting --> InferiorStartFailed --> 0 -// | -// (core) | (attach) (remote) -// .-----------------<-|->--------------------. -// | v | -// InferiorUnrunnable | | -// | | v -// | | (plain) -// | | (trk) -// | | -// | | .------------------------------------. -// | | v | -// | InferiorRunningRequested v | -// | | | | -// | .---- InferiorRunning | | -// | | | | | -// | | InferiorStopping | | -// | | | | | -// | v v | | -// | |<--- InferiorStopped <-----------' | -// | | | | -// | | `---------------------------------------' -// | | -// | '---> InferiorShuttingDown -> InferiorShutdownFailed -// | | -// | InferiorShutDown -// | | -// | v -// '------------> AdapterShuttingDown -> AdapterShutdownFailed --> 0 +// AdapterStarted ------------------------------------. +// | v +// InferiorStarting ----> InferiorStartFailed -------->| +// | | +// (core) | (attach) (term) (remote) | +// .-----------------<-|->------------------. | +// | v | | +// InferiorUnrunnable | (plain) | | +// | | (trk) | | +// | | | | +// | .--> InferiorRunningRequested | | +// | | | | | +// | | InferiorRunning | | +// | | | | | +// | | InferiorStopping | | +// | | | | | +// | '------ InferiorStopped <-----------' | +// | | v +// | InferiorShuttingDown -> InferiorShutdownFailed ---->| +// | | | +// | InferiorShutDown | +// | | | +// '--------> EngineShuttingDown <--------------------------------' // | // 0 // @@ -208,8 +200,7 @@ static const char *stateName(int s) SN(InferiorShuttingDown) SN(InferiorShutDown) SN(InferiorShutdownFailed) - SN(AdapterShuttingDown) - SN(AdapterShutdownFailed) + SN(EngineShuttingDown) } return "<unknown>"; #undef SN @@ -1574,7 +1565,7 @@ static bool isAllowedTransition(int from, int to) case AdapterStarting: return to == AdapterStarted || to == AdapterStartFailed; case AdapterStarted: - return to == InferiorStarting; + return to == InferiorStarting || to == EngineShuttingDown; case AdapterStartFailed: return to == DebuggerNotReady; @@ -1582,37 +1573,38 @@ static bool isAllowedTransition(int from, int to) return to == InferiorRunningRequested || to == InferiorStopped || to == InferiorStartFailed || to == InferiorUnrunnable; case InferiorStartFailed: - return to == DebuggerNotReady; + return to == EngineShuttingDown; case InferiorRunningRequested: return to == InferiorRunning; case InferiorRunning: - return to == InferiorStopping || to == InferiorShuttingDown; + return to == InferiorStopping; case InferiorStopping: return to == InferiorStopped || to == InferiorStopFailed; case InferiorStopped: return to == InferiorRunningRequested || to == InferiorShuttingDown; case InferiorStopFailed: - return to == DebuggerNotReady; + return to == EngineShuttingDown; case InferiorUnrunnable: - return to == AdapterShuttingDown; + return to == EngineShuttingDown; case InferiorShuttingDown: return to == InferiorShutDown || to == InferiorShutdownFailed; case InferiorShutDown: - return to == AdapterShuttingDown; + return to == EngineShuttingDown; + case InferiorShutdownFailed: + return to == EngineShuttingDown; - case AdapterShuttingDown: + case EngineShuttingDown: return to == DebuggerNotReady; - - default: - qDebug() << "UNKNOWN STATE: " << from; } + + qDebug() << "UNKNOWN STATE:" << from; return false; } -void DebuggerManager::setState(DebuggerState state) +void DebuggerManager::setState(DebuggerState state, bool forced) { //STATE_DEBUG("STATUS CHANGE: FROM " << stateName(d->m_state) // << " TO " << stateName(state)); @@ -1621,7 +1613,7 @@ void DebuggerManager::setState(DebuggerState state) .arg(stateName(d->m_state)).arg(d->m_state).arg(stateName(state)).arg(state); //if (!((d->m_state == -1 && state == 0) || (d->m_state == 0 && state == 0))) // qDebug() << msg; - if (!isAllowedTransition(d->m_state, state)) + if (!forced && !isAllowedTransition(d->m_state, state)) qDebug() << "UNEXPECTED STATE TRANSITION: " << msg; showDebuggerOutput(LogDebug, msg); @@ -1715,8 +1707,7 @@ bool DebuggerManager::debuggerActionsEnabled() const case InferiorShuttingDown: case InferiorShutDown: case InferiorShutdownFailed: - case AdapterShuttingDown: - case AdapterShutdownFailed: + case EngineShuttingDown: break; } return false; @@ -1793,9 +1784,9 @@ DebuggerState IDebuggerEngine::state() const return m_manager->state(); } -void IDebuggerEngine::setState(DebuggerState state) +void IDebuggerEngine::setState(DebuggerState state, bool forced) { - m_manager->setState(state); + m_manager->setState(state, forced); } ////////////////////////////////////////////////////////////////////// diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h index bc82ec187ba..c82bacb1e0e 100644 --- a/src/plugins/debugger/debuggermanager.h +++ b/src/plugins/debugger/debuggermanager.h @@ -285,7 +285,7 @@ private: void cleanupViews(); - void setState(DebuggerState state); + void setState(DebuggerState state, bool forced = false); // // internal implementation diff --git a/src/plugins/debugger/gdb/abstractgdbadapter.cpp b/src/plugins/debugger/gdb/abstractgdbadapter.cpp index 52c76107606..cd99fec311e 100644 --- a/src/plugins/debugger/gdb/abstractgdbadapter.cpp +++ b/src/plugins/debugger/gdb/abstractgdbadapter.cpp @@ -47,35 +47,18 @@ AbstractGdbAdapter::~AbstractGdbAdapter() disconnect(); } -// This cannot be in the c'tor, as it would not connect the "virtual" slots -void AbstractGdbAdapter::commonInit() +void AbstractGdbAdapter::shutdown() { - QTC_ASSERT(state() == EngineStarting, qDebug() << state()); - connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)), - this, SLOT(handleGdbError(QProcess::ProcessError))); - connect(&m_gdbProc, SIGNAL(started()), - this, SLOT(handleGdbStarted())); - connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)), - this, SLOT(handleGdbFinished(int, QProcess::ExitStatus))); - connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()), - this, SIGNAL(readyReadStandardOutput())); - connect(&m_gdbProc, SIGNAL(readyReadStandardError()), - this, SIGNAL(readyReadStandardError())); } -QByteArray AbstractGdbAdapter::readAllStandardOutput() +const char *AbstractGdbAdapter::inferiorShutdownCommand() const { - return m_gdbProc.readAllStandardOutput(); -} - -QByteArray AbstractGdbAdapter::readAllStandardError() -{ - return m_gdbProc.readAllStandardError(); + return "kill"; } void AbstractGdbAdapter::write(const QByteArray &data) { - m_gdbProc.write(data); + m_engine->m_gdbProc.write(data); } bool AbstractGdbAdapter::isTrkAdapter() const diff --git a/src/plugins/debugger/gdb/abstractgdbadapter.h b/src/plugins/debugger/gdb/abstractgdbadapter.h index 7765401e1a6..9dc018e0380 100644 --- a/src/plugins/debugger/gdb/abstractgdbadapter.h +++ b/src/plugins/debugger/gdb/abstractgdbadapter.h @@ -42,7 +42,7 @@ namespace Internal { // debugging and TrkGdbAdapter used for on-device debugging. // In the PlainGdbAdapter case it's just a wrapper around a QProcess running // gdb, in the TrkGdbAdapter case it's the interface to the gdb process in -// the whole rfomm/gdb/gdbserver combo. +// the whole rfcomm/gdb/gdbserver combo. class AbstractGdbAdapter : public QObject { Q_OBJECT @@ -51,34 +51,39 @@ public: AbstractGdbAdapter(GdbEngine *engine, QObject *parent = 0); virtual ~AbstractGdbAdapter(); - QByteArray readAllStandardOutput(); - QByteArray readAllStandardError(); virtual void write(const QByteArray &data); virtual bool isTrkAdapter() const; // isUtterlyBrokenAdapter virtual void startAdapter() = 0; virtual void startInferior() = 0; virtual void interruptInferior() = 0; - virtual void shutdown() = 0; + virtual void shutdown(); + virtual const char *inferiorShutdownCommand() const; virtual bool dumpersAvailable() const = 0; + static QString msgGdbStopFailed(const QString &why); + static QString msgInferiorStopFailed(const QString &why); + static QString msgAttachedToStoppedInferior(); + static QString msgInferiorStarted(); + static QString msgInferiorRunning(); + static QString msgConnectRemoteServerFailed(const QString &why); + signals: void adapterStarted(); + + // Something went wrong with the adapter *before* adapterStarted() was emitted. + // Make sure to clean up everything before emitting this signal. void adapterStartFailed(const QString &msg, const QString &settingsIdHint); - void adapterShutDown(); - void adapterShutdownFailed(const QString &msg); + + // Something went wrong with the adapter *after* adapterStarted() was emitted. + // Make sure to clean up everything before emitting this signal. void adapterCrashed(const QString &msg); + // The adapter is still running just fine, but it failed to acquire a debuggee. void inferiorStartFailed(const QString &msg); - void inferiorShutDown(); - void inferiorShutdownFailed(const QString &msg); - void readyReadStandardOutput(); - void readyReadStandardError(); - protected: - void commonInit(); DebuggerState state() const { return m_engine->state(); } void setState(DebuggerState state) @@ -90,16 +95,7 @@ protected: void showStatusMessage(const QString &msg) const { m_engine->showStatusMessage(msg); } - static QString msgGdbStopFailed(const QString &why); - static QString msgInferiorStopFailed(const QString &why); - static QString msgAttachedToStoppedInferior(); - static QString msgInferiorStarted(); - static QString msgInferiorRunning(); - static QString msgConnectRemoteServerFailed(const QString &why); - GdbEngine * const m_engine; - - QProcess m_gdbProc; }; } // namespace Internal diff --git a/src/plugins/debugger/gdb/attachgdbadapter.cpp b/src/plugins/debugger/gdb/attachgdbadapter.cpp index 578884a56bd..f89421e5929 100644 --- a/src/plugins/debugger/gdb/attachgdbadapter.cpp +++ b/src/plugins/debugger/gdb/attachgdbadapter.cpp @@ -53,7 +53,6 @@ namespace Internal { AttachGdbAdapter::AttachGdbAdapter(GdbEngine *engine, QObject *parent) : AbstractGdbAdapter(engine, parent) { - commonInit(); } void AttachGdbAdapter::startAdapter() @@ -62,27 +61,12 @@ void AttachGdbAdapter::startAdapter() setState(AdapterStarting); debugMessage(_("TRYING TO START ADAPTER")); - QStringList gdbArgs; - gdbArgs.prepend(_("mi")); - gdbArgs.prepend(_("-i")); - - QString location = theDebuggerStringSetting(GdbLocation); - m_gdbProc.start(location, gdbArgs); -} + if (!m_engine->startGdb()) + return; -void AttachGdbAdapter::handleGdbStarted() -{ - QTC_ASSERT(state() == AdapterStarting, qDebug() << state()); emit adapterStarted(); } -void AttachGdbAdapter::handleGdbError(QProcess::ProcessError error) -{ - debugMessage(_("PLAIN ADAPTER, HANDLE GDB ERROR")); - emit adapterCrashed(m_engine->errorMessage(error)); - shutdown(); -} - void AttachGdbAdapter::startInferior() { QTC_ASSERT(state() == InferiorStarting, qDebug() << state()); @@ -113,58 +97,5 @@ void AttachGdbAdapter::interruptInferior() debugMessage(_("CANNOT INTERRUPT %1").arg(pid)); } -void AttachGdbAdapter::shutdown() -{ - switch (state()) { - - case InferiorStartFailed: - m_engine->postCommand(_("-gdb-exit")); - setState(DebuggerNotReady); - return; - - case InferiorStopped: - setState(InferiorShuttingDown); - m_engine->postCommand(_("detach"), CB(handleDetach)); - return; - - case InferiorShutDown: - setState(AdapterShuttingDown); - m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit)); - return; - - default: - QTC_ASSERT(false, qDebug() << state()); - } -} - -void AttachGdbAdapter::handleDetach(const GdbResponse &response) -{ - if (response.resultClass == GdbResultDone) { - setState(InferiorShutDown); - emit inferiorShutDown(); - shutdown(); // re-iterate... - } else { - const QString msg = msgInferiorStopFailed(__(response.data.findChild("msg").data())); - setState(InferiorShutdownFailed); - emit inferiorShutdownFailed(msg); - } -} - -void AttachGdbAdapter::handleExit(const GdbResponse &response) -{ - if (response.resultClass == GdbResultDone) { - // don't set state here, this will be handled in handleGdbFinished() - } else { - const QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data())); - emit adapterShutdownFailed(msg); - } -} - -void AttachGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus) -{ - debugMessage(_("GDB PROESS FINISHED")); - emit adapterShutDown(); -} - } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/gdb/attachgdbadapter.h b/src/plugins/debugger/gdb/attachgdbadapter.h index 34196725417..1ae5b1c7cae 100644 --- a/src/plugins/debugger/gdb/attachgdbadapter.h +++ b/src/plugins/debugger/gdb/attachgdbadapter.h @@ -57,16 +57,10 @@ public: void startAdapter(); void startInferior(); void interruptInferior(); - void shutdown(); + const char *inferiorShutdownCommand() const { return "detach"; } private: void handleAttach(const GdbResponse &response); - void handleDetach(const GdbResponse &response); - void handleExit(const GdbResponse &response); - - Q_SLOT void handleGdbStarted(); - Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus); - Q_SLOT void handleGdbError(QProcess::ProcessError error); }; } // namespace Internal diff --git a/src/plugins/debugger/gdb/coregdbadapter.cpp b/src/plugins/debugger/gdb/coregdbadapter.cpp index 5f5de78f1fe..7f70b60609b 100644 --- a/src/plugins/debugger/gdb/coregdbadapter.cpp +++ b/src/plugins/debugger/gdb/coregdbadapter.cpp @@ -53,7 +53,6 @@ namespace Internal { CoreGdbAdapter::CoreGdbAdapter(GdbEngine *engine, QObject *parent) : AbstractGdbAdapter(engine, parent) { - commonInit(); } void CoreGdbAdapter::startAdapter() @@ -62,27 +61,12 @@ void CoreGdbAdapter::startAdapter() setState(AdapterStarting); debugMessage(_("TRYING TO START ADAPTER")); - QStringList gdbArgs; - gdbArgs.prepend(_("mi")); - gdbArgs.prepend(_("-i")); - - QString location = theDebuggerStringSetting(GdbLocation); - m_gdbProc.start(location, gdbArgs); -} + if (!m_engine->startGdb()) + return; -void CoreGdbAdapter::handleGdbStarted() -{ - QTC_ASSERT(state() == AdapterStarting, qDebug() << state()); emit adapterStarted(); } -void CoreGdbAdapter::handleGdbError(QProcess::ProcessError error) -{ - debugMessage(_("PLAIN ADAPTER, HANDLE GDB ERROR")); - emit adapterCrashed(m_engine->errorMessage(error)); - shutdown(); -} - void CoreGdbAdapter::startInferior() { QTC_ASSERT(state() == InferiorStarting, qDebug() << state()); @@ -175,45 +159,12 @@ void CoreGdbAdapter::handleTargetCore2(const GdbResponse &response) // emit inferiorStartFailed(msg); } } + void CoreGdbAdapter::interruptInferior() { // A core should never 'run' QTC_ASSERT(false, /**/); } -void CoreGdbAdapter::shutdown() -{ - switch (state()) { - - case DebuggerNotReady: - return; - - case InferiorUnrunnable: - case InferiorShutDown: - setState(AdapterShuttingDown); - m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit)); - return; - - default: - QTC_ASSERT(false, qDebug() << state()); - } -} - -void CoreGdbAdapter::handleExit(const GdbResponse &response) -{ - if (response.resultClass == GdbResultDone) { - // don't set state here, this will be handled in handleGdbFinished() - } else { - const QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data())); - emit adapterShutdownFailed(msg); - } -} - -void CoreGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus) -{ - debugMessage(_("GDB PROESS FINISHED")); - emit adapterShutDown(); -} - } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/gdb/coregdbadapter.h b/src/plugins/debugger/gdb/coregdbadapter.h index 4a3fe67799d..69f7d067da2 100644 --- a/src/plugins/debugger/gdb/coregdbadapter.h +++ b/src/plugins/debugger/gdb/coregdbadapter.h @@ -57,18 +57,12 @@ public: void startAdapter(); void startInferior(); void interruptInferior(); - void shutdown(); private: void handleTargetCore1(const GdbResponse &response); void handleDetach1(const GdbResponse &response); void handleFileExecAndSymbols(const GdbResponse &response); void handleTargetCore2(const GdbResponse &response); - void handleExit(const GdbResponse &response); - - Q_SLOT void handleGdbStarted(); - Q_SLOT void handleGdbError(QProcess::ProcessError error); - Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus); QString m_executable; }; diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 3d63dfe69f5..93916267abb 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -105,17 +105,29 @@ namespace Internal { static bool stateAcceptsGdbCommands(DebuggerState state) { - return state == AdapterStarted - || state == InferiorUnrunnable - || state == InferiorStarting - || state == InferiorRunningRequested - || state == InferiorRunning - || state == InferiorStopping - || state == InferiorStopped - || state == InferiorShuttingDown - || state == InferiorShutDown - || state == AdapterShuttingDown; -}; + switch (state) { + case AdapterStarting: + case AdapterStarted: + case AdapterStartFailed: + case InferiorUnrunnable: + case InferiorStarting: + case InferiorStartFailed: + case InferiorRunningRequested: + case InferiorRunning: + case InferiorStopping: + case InferiorStopped: + case InferiorShuttingDown: + case InferiorShutDown: + case InferiorShutdownFailed: + return true; + case DebuggerNotReady: + case EngineStarting: + case InferiorStopFailed: + case EngineShuttingDown: + break; + } + return false; +} static int ¤tToken() { @@ -217,27 +229,13 @@ GdbEngine::~GdbEngine() void GdbEngine::connectAdapter() { - // Gdb Process interaction - connect(m_gdbAdapter, SIGNAL(readyReadStandardOutput()), - this, SLOT(readGdbStandardOutput())); - connect(m_gdbAdapter, SIGNAL(readyReadStandardError()), - this, SLOT(readGdbStandardError())); - connect(m_gdbAdapter, SIGNAL(adapterStarted()), this, SLOT(handleAdapterStarted())); connect(m_gdbAdapter, SIGNAL(adapterStartFailed(QString,QString)), this, SLOT(handleAdapterStartFailed(QString,QString))); - connect(m_gdbAdapter, SIGNAL(adapterShutDown()), - this, SLOT(handleAdapterShutDown())); - connect(m_gdbAdapter, SIGNAL(adapterShutdownFailed(QString)), - this, SLOT(handleAdapterShutdownFailed(QString))); connect(m_gdbAdapter, SIGNAL(inferiorStartFailed(QString)), this, SLOT(handleInferiorStartFailed(QString))); - connect(m_gdbAdapter, SIGNAL(inferiorShutDown()), - this, SLOT(handleInferiorShutDown())); - connect(m_gdbAdapter, SIGNAL(inferiorShutdownFailed(QString)), - this, SLOT(handleInferiorShutdownFailed(QString))); connect(m_gdbAdapter, SIGNAL(adapterCrashed(QString)), this, SLOT(handleAdapterCrashed(QString))); @@ -571,7 +569,7 @@ void GdbEngine::handleResponse(const QByteArray &buff) void GdbEngine::readGdbStandardError() { - qWarning() << "Unexpected gdb stderr:" << m_gdbAdapter->readAllStandardError(); + qWarning() << "Unexpected gdb stderr:" << m_gdbProc.readAllStandardError(); } void GdbEngine::readGdbStandardOutput() @@ -579,7 +577,7 @@ void GdbEngine::readGdbStandardOutput() int newstart = 0; int scan = m_inbuffer.size(); - m_inbuffer.append(m_gdbAdapter->readAllStandardOutput()); + m_inbuffer.append(m_gdbProc.readAllStandardOutput()); while (newstart < m_inbuffer.size()) { int start = newstart; @@ -1366,8 +1364,73 @@ QString GdbEngine::fullName(const QStringList &candidates) void GdbEngine::shutdown() { debugMessage(_("INITIATE GDBENGINE SHUTDOWN")); - initializeVariables(); - m_gdbAdapter->shutdown(); + switch (state()) { + case DebuggerNotReady: // Nothing to do! :) + case EngineStarting: // We can't get here, really + case InferiorShuttingDown: // Will auto-trigger further shutdown steps + case EngineShuttingDown: // Do not disturb! :) + break; + case AdapterStarting: // GDB is up, adapter is "doing something" + setState(AdapterStartFailed); + m_gdbAdapter->shutdown(); + // fall-through + case AdapterStartFailed: // Adapter "did something", but it did not help + // FIXME set some timeout? + postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleGdbExit)); + break; + case InferiorRunningRequested: + case InferiorRunning: + case InferiorStopping: + case InferiorStopped: + // FIXME set some timeout? + postCommand(_(m_gdbAdapter->inferiorShutdownCommand()), + NeedsStop, CB(handleInferiorShutdown)); + setState(InferiorShuttingDown); // Do it after posting the command! + break; + case AdapterStarted: // We can't get here, really + case InferiorStartFailed: + case InferiorShutDown: + case InferiorShutdownFailed: // Whatever + case InferiorUnrunnable: + // FIXME set some timeout? + postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleGdbExit)); + setState(EngineShuttingDown); // Do it after posting the command! + break; + case InferiorStarting: // This may take some time, so just short-circuit it + setState(InferiorStartFailed); + // fall-through + case InferiorStopFailed: // Tough luck, I guess. But unreachable as of now anyway. + setState(EngineShuttingDown); + m_gdbProc.terminate(); + break; + } +} + +void GdbEngine::handleInferiorShutdown(const GdbResponse &response) +{ + QTC_ASSERT(state() == InferiorShuttingDown, qDebug() << state()); + if (response.resultClass == GdbResultDone) { + debugMessage(_("INFERIOR SUCCESSFULLY SHUT DOWN")); + setState(InferiorShutDown); + } else { + debugMessage(_("INFERIOR SHUTDOWN FAILED")); + setState(InferiorShutdownFailed); + QString msg = m_gdbAdapter->msgInferiorStopFailed(_(response.data.findChild("msg").data())); + showMessageBox(QMessageBox::Critical, tr("Inferior shutdown failed"), msg); + } + shutdown(); // re-iterate... +} + +void GdbEngine::handleGdbExit(const GdbResponse &response) +{ + if (response.resultClass == GdbResultExit) { + debugMessage(_("GDB CLAIMS EXIT; WAITING")); + // don't set state here, this will be handled in handleGdbFinished() + } else { + QString msg = m_gdbAdapter->msgGdbStopFailed(_(response.data.findChild("msg").data())); + debugMessage(_("GDB WON'T EXIT (%1); KILLING IT").arg(msg)); + m_gdbProc.terminate(); + } } void GdbEngine::detachDebugger() @@ -1383,8 +1446,7 @@ void GdbEngine::detachDebugger() void GdbEngine::exitDebugger() // called from the manager { disconnectDebuggingHelperActions(); - initializeVariables(); - m_gdbAdapter->shutdown(); + shutdown(); } int GdbEngine::currentFrame() const @@ -1445,17 +1507,17 @@ void GdbEngine::startDebugger(const DebuggerStartParametersPtr &sp) // initializeVariables()); //QTC_ASSERT(m_gdbAdapter == 0, delete m_gdbAdapter; m_gdbAdapter = 0); + initializeVariables(); + m_startParameters = sp; delete m_gdbAdapter; m_gdbAdapter = createAdapter(sp); + connectAdapter(); if (startModeAllowsDumpers()) connectDebuggingHelperActions(); - initializeVariables(); - connectAdapter(); - m_gdbAdapter->startAdapter(); } @@ -4089,19 +4151,37 @@ void GdbEngine::gotoLocation(const StackFrame &frame, bool setMarker) // Starting up & shutting down // -void GdbEngine::handleAdapterStartFailed(const QString &msg, const QString &settingsIdHint) +bool GdbEngine::startGdb(const QStringList &args, const QString &gdb) { - setState(AdapterStartFailed); - debugMessage(_("ADAPTER START FAILED")); - Core::ICore::instance()->showWarningWithOptions(tr("Adapter start failed"), msg, QString(), - QLatin1String(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY), settingsIdHint); - shutdown(); -} + debugMessage(_("STARTING GDB ") + gdb); -void GdbEngine::handleAdapterStarted() -{ - setState(AdapterStarted); - debugMessage(_("ADAPTER SUCCESSFULLY STARTED, INITIALIZING GDB")); + m_gdbProc.disconnect(); // From any previous runs + + QString location = gdb; + if (location.isEmpty()) + location = theDebuggerStringSetting(GdbLocation); + QStringList gdbArgs; + gdbArgs << _("-i"); + gdbArgs << _("mi"); + gdbArgs += args; + m_gdbProc.start(location, gdbArgs); + + if (!m_gdbProc.waitForStarted()) { + handleAdapterStartFailed(m_gdbProc.errorString()); + return false; + } + + // Do this only after the process is running, so we get no needless error notifications + connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)), + SLOT(handleGdbError(QProcess::ProcessError))); + connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)), + SLOT(handleGdbFinished(int, QProcess::ExitStatus))); + connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()), + SLOT(readGdbStandardOutput())); + connect(&m_gdbProc, SIGNAL(readyReadStandardError()), + SLOT(readGdbStandardError())); + + debugMessage(_("GDB STARTED, INITIALIZING IT")); postCommand(_("show version"), CB(handleShowVersion)); postCommand(_("help bb"), CB(handleIsSynchroneous)); @@ -4185,12 +4265,69 @@ void GdbEngine::handleAdapterStarted() } } + return true; +} + +void GdbEngine::handleGdbError(QProcess::ProcessError error) +{ + debugMessage(_("HANDLE GDB ERROR")); + switch (error) { + case QProcess::Crashed: + break; // will get a processExited() as well + // impossible case QProcess::FailedToStart: + case QProcess::ReadError: + case QProcess::WriteError: + case QProcess::Timedout: + default: + m_gdbProc.terminate(); + setState(EngineShuttingDown, true); + showMessageBox(QMessageBox::Critical, tr("Gdb I/O Error"), + errorMessage(error)); + break; + } +} + +void GdbEngine::handleGdbFinished(int code, QProcess::ExitStatus type) +{ + debugMessage(_("GDB PROCESS FINISHED, status %1, code %2").arg(type).arg(code)); + if (state() == EngineShuttingDown) { + m_gdbAdapter->shutdown(); + } else if (state() != AdapterStartFailed) { + showMessageBox(QMessageBox::Critical, tr("Unexpected Gdb Exit"), + tr("The gdb process exited unexpectedly (%1).") + .arg((type == QProcess::CrashExit) + ? tr("crashed") : tr("code %1").arg(code))); + m_gdbAdapter->shutdown(); + } + initializeVariables(); + setState(DebuggerNotReady, true); +} + +void GdbEngine::handleAdapterStartFailed(const QString &msg, const QString &settingsIdHint) +{ + setState(AdapterStartFailed); + debugMessage(_("ADAPTER START FAILED")); + Core::ICore::instance()->showWarningWithOptions( + tr("Adapter start failed"), msg, QString(), + _(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY), settingsIdHint); + shutdown(); +} + +void GdbEngine::handleAdapterStarted() +{ + setState(AdapterStarted); + debugMessage(_("ADAPTER SUCCESSFULLY STARTED")); + // Initial attempt to set breakpoints showStatusMessage(tr("Setting breakpoints...")); attemptBreakpointSynchronization(); - QTC_ASSERT(m_commandsDoneCallback == 0, /**/); - m_commandsDoneCallback = &GdbEngine::startInferior; + if (m_cookieForToken.isEmpty()) { + startInferior(); + } else { + QTC_ASSERT(m_commandsDoneCallback == 0, /**/); + m_commandsDoneCallback = &GdbEngine::startInferior; + } } void GdbEngine::startInferior() @@ -4209,46 +4346,21 @@ void GdbEngine::handleInferiorStartFailed(const QString &msg) shutdown(); } -void GdbEngine::handleInferiorShutDown() -{ - debugMessage(_("INFERIOR SUCCESSFULLY SHUT DOWN")); -} - -void GdbEngine::handleInferiorShutdownFailed(const QString &msg) -{ - debugMessage(_("INFERIOR SHUTDOWN FAILED")); - showMessageBox(QMessageBox::Critical, tr("Inferior shutdown failed"), msg); - shutdown(); // continue with adapter shutdown -} - void GdbEngine::handleAdapterCrashed(const QString &msg) { debugMessage(_("ADAPTER CRASHED")); - switch (state()) { - // All fall-through. - case InferiorRunning: - setState(InferiorShuttingDown); - case InferiorShuttingDown: - setState(InferiorShutDown); - case InferiorShutDown: - setState(AdapterShuttingDown); - default: - setState(DebuggerNotReady); - } - showMessageBox(QMessageBox::Critical, tr("Adapter crashed"), msg); -} -void GdbEngine::handleAdapterShutDown() -{ - debugMessage(_("ADAPTER SUCCESSFULLY SHUT DOWN")); - setState(DebuggerNotReady); -} + // The adapter is expected to have cleaned up after itself when we get here, + // so the effect is about the same as AdapterStartFailed => use it. + // Don't bother with state transitions - this can happen in any state and + // the end result is always the same, so it makes little sense to find a + // "path" which does not assert. + setState(AdapterStartFailed, true); -void GdbEngine::handleAdapterShutdownFailed(const QString &msg) -{ - debugMessage(_("ADAPTER SHUTDOWN FAILED")); - showMessageBox(QMessageBox::Critical, tr("Adapter shutdown failed"), msg); - setState(DebuggerNotReady); + // No point in being friendly here ... + m_gdbProc.terminate(); + + showMessageBox(QMessageBox::Critical, tr("Adapter crashed"), msg); } void GdbEngine::addOptionPages(QList<Core::IOptionsPage*> *opts) const diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 83f3239c031..91c230dacc9 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -125,14 +125,20 @@ private: ////////// Gdb Process Management ////////// AbstractGdbAdapter *createAdapter(const DebuggerStartParametersPtr &dp); void connectAdapter(); + bool startGdb(const QStringList &args = QStringList(), const QString &gdb = QString()); void startInferior(); + void handleInferiorShutdown(const GdbResponse &response); + void handleGdbExit(const GdbResponse &response); + void gdbInputAvailable(int channel, const QString &msg) { m_manager->showDebuggerInput(channel, msg); } void gdbOutputAvailable(int channel, const QString &msg) { m_manager->showDebuggerOutput(channel, msg); } private slots: + void handleGdbFinished(int, QProcess::ExitStatus status); + void handleGdbError(QProcess::ProcessError error); void readGdbStandardOutput(); void readGdbStandardError(); void readDebugeeOutput(const QByteArray &data); @@ -141,12 +147,8 @@ private slots: void handleAdapterStartFailed(const QString &msg, const QString &settingsIdHint = QString()); void handleInferiorStartFailed(const QString &msg); - void handleInferiorShutDown(); - void handleInferiorShutdownFailed(const QString &msg); void handleAdapterCrashed(const QString &msg); - void handleAdapterShutDown(); - void handleAdapterShutdownFailed(const QString &msg); private: QTextCodec *m_outputCodec; @@ -154,6 +156,7 @@ private: QByteArray m_inbuffer; + QProcess m_gdbProc; AbstractGdbAdapter *m_gdbAdapter; private: ////////// Gdb Command Management ////////// diff --git a/src/plugins/debugger/gdb/plaingdbadapter.cpp b/src/plugins/debugger/gdb/plaingdbadapter.cpp index a879968a3c5..2a16c27628f 100644 --- a/src/plugins/debugger/gdb/plaingdbadapter.cpp +++ b/src/plugins/debugger/gdb/plaingdbadapter.cpp @@ -58,8 +58,6 @@ namespace Internal { PlainGdbAdapter::PlainGdbAdapter(GdbEngine *engine, QObject *parent) : AbstractGdbAdapter(engine, parent) { - commonInit(); - // Output connect(&m_outputCollector, SIGNAL(byteDelivery(QByteArray)), engine, SLOT(readDebugeeOutput(QByteArray))); @@ -72,36 +70,27 @@ void PlainGdbAdapter::startAdapter() debugMessage(_("TRYING TO START ADAPTER")); QStringList gdbArgs; - gdbArgs.prepend(_("mi")); - gdbArgs.prepend(_("-i")); if (!m_outputCollector.listen()) { emit adapterStartFailed(tr("Cannot set up communication with child process: %1") .arg(m_outputCollector.errorString()), QString()); return; } - gdbArgs.prepend(_("--tty=") + m_outputCollector.serverName()); + gdbArgs.append(_("--tty=") + m_outputCollector.serverName()); if (!startParameters().workingDir.isEmpty()) - m_gdbProc.setWorkingDirectory(startParameters().workingDir); + m_engine->m_gdbProc.setWorkingDirectory(startParameters().workingDir); if (!startParameters().environment.isEmpty()) - m_gdbProc.setEnvironment(startParameters().environment); + m_engine->m_gdbProc.setEnvironment(startParameters().environment); - m_gdbProc.start(theDebuggerStringSetting(GdbLocation), gdbArgs); -} + if (!m_engine->startGdb(gdbArgs)) { + m_outputCollector.shutdown(); + return; + } -void PlainGdbAdapter::handleGdbStarted() -{ - QTC_ASSERT(state() == AdapterStarting, qDebug() << state()); emit adapterStarted(); } -void PlainGdbAdapter::handleGdbError(QProcess::ProcessError error) -{ - debugMessage(_("PLAIN ADAPTER, HANDLE GDB ERROR")); - emit adapterCrashed(m_engine->errorMessage(error)); -} - void PlainGdbAdapter::startInferior() { QTC_ASSERT(state() == InferiorStarting, qDebug() << state()); @@ -159,74 +148,6 @@ void PlainGdbAdapter::shutdown() { debugMessage(_("PLAIN ADAPTER SHUTDOWN %1").arg(state())); m_outputCollector.shutdown(); - switch (state()) { - - case InferiorRunningRequested: - case InferiorRunning: - case InferiorStopping: - case InferiorStopped: - setState(InferiorShuttingDown); - m_engine->postCommand(_("kill"), CB(handleKill)); - return; - - case InferiorShuttingDown: - // FIXME: How can we end up here? - QTC_ASSERT(false, qDebug() << state()); - // Fall through. - - case InferiorShutDown: - setState(AdapterShuttingDown); - m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit)); - return; - -/* - case InferiorShutdownFailed: - m_gdbProc.terminate(); - // 20s can easily happen when loading webkit debug information - m_gdbProc.waitForFinished(20000); - setState(AdapterShuttingDown); - debugMessage(_("FORCING TERMINATION: %1").arg(state())); - if (state() != QProcess::NotRunning) { - debugMessage(_("PROBLEM STOPPING DEBUGGER: STATE %1") - .arg(state())); - m_gdbProc.kill(); - } - m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit)); - return; -*/ - default: - QTC_ASSERT(false, qDebug() << state()); - } -} - -void PlainGdbAdapter::handleKill(const GdbResponse &response) -{ - debugMessage(_("PLAIN ADAPTER HANDLE KILL " + response.toString())); - if (response.resultClass == GdbResultDone) { - setState(InferiorShutDown); - emit inferiorShutDown(); - shutdown(); // re-iterate... - } else { - const QString msg = msgInferiorStopFailed(__(response.data.findChild("msg").data())); - setState(InferiorShutdownFailed); - emit inferiorShutdownFailed(msg); - } -} - -void PlainGdbAdapter::handleExit(const GdbResponse &response) -{ - if (response.resultClass == GdbResultDone) { - // don't set state here, this will be handled in handleGdbFinished() - } else { - const QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data())); - emit adapterShutdownFailed(msg); - } -} - -void PlainGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus) -{ - debugMessage(_("GDB PROCESS FINISHED")); - emit adapterShutDown(); } } // namespace Internal diff --git a/src/plugins/debugger/gdb/plaingdbadapter.h b/src/plugins/debugger/gdb/plaingdbadapter.h index 52311b372b4..fb445d3b329 100644 --- a/src/plugins/debugger/gdb/plaingdbadapter.h +++ b/src/plugins/debugger/gdb/plaingdbadapter.h @@ -59,17 +59,12 @@ public: void startInferior(); void interruptInferior(); void shutdown(); + const char *inferiorShutdownCommand() const { return "kill"; } private: void handleFileExecAndSymbols(const GdbResponse &response); - void handleKill(const GdbResponse &response); - void handleExit(const GdbResponse &response); void handleExecRun(const GdbResponse &response); - Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus status); - Q_SLOT void handleGdbError(QProcess::ProcessError error); - Q_SLOT void handleGdbStarted(); - OutputCollector m_outputCollector; }; diff --git a/src/plugins/debugger/gdb/remotegdbadapter.cpp b/src/plugins/debugger/gdb/remotegdbadapter.cpp index 40d598f293d..504e0a56208 100644 --- a/src/plugins/debugger/gdb/remotegdbadapter.cpp +++ b/src/plugins/debugger/gdb/remotegdbadapter.cpp @@ -54,8 +54,6 @@ namespace Internal { RemoteGdbAdapter::RemoteGdbAdapter(GdbEngine *engine, QObject *parent) : AbstractGdbAdapter(engine, parent) { - commonInit(); - connect(&m_uploadProc, SIGNAL(error(QProcess::ProcessError)), this, SLOT(uploadProcError(QProcess::ProcessError))); connect(&m_uploadProc, SIGNAL(readyReadStandardOutput()), @@ -70,12 +68,6 @@ void RemoteGdbAdapter::startAdapter() setState(AdapterStarting); debugMessage(_("TRYING TO START ADAPTER")); - QStringList gdbArgs; - gdbArgs.prepend(_("mi")); - gdbArgs.prepend(_("-i")); - - QString location = theDebuggerStringSetting(GdbLocation); - // FIXME: make asynchroneous // Start the remote server if (startParameters().serverStartScript.isEmpty()) { @@ -86,23 +78,13 @@ void RemoteGdbAdapter::startAdapter() m_uploadProc.waitForStarted(); } - // Start the debugger - m_gdbProc.start(location, gdbArgs); -} + if (!m_engine->startGdb()) + // FIXME: cleanup missing + return; -void RemoteGdbAdapter::handleGdbStarted() -{ - QTC_ASSERT(state() == AdapterStarting, qDebug() << state()); emit adapterStarted(); } -void RemoteGdbAdapter::handleGdbError(QProcess::ProcessError error) -{ - debugMessage(_("ADAPTER, HANDLE GDB ERROR")); - emit adapterCrashed(m_engine->errorMessage(error)); - shutdown(); -} - void RemoteGdbAdapter::uploadProcError(QProcess::ProcessError error) { QString msg; @@ -232,55 +214,7 @@ void RemoteGdbAdapter::interruptInferior() void RemoteGdbAdapter::shutdown() { - switch (state()) { - - case InferiorRunning: - case InferiorStopped: - setState(InferiorShuttingDown); - m_engine->postCommand(_("kill"), CB(handleKill)); - return; - - default: - QTC_ASSERT(false, qDebug() << state()); - // fall through - - case InferiorStartFailed: - case InferiorShutDown: - setState(AdapterShuttingDown); - m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit)); - return; - - } -} - -void RemoteGdbAdapter::handleKill(const GdbResponse &response) -{ - QTC_ASSERT(state() == InferiorShuttingDown, qDebug() << state()); - if (response.resultClass == GdbResultDone) { - setState(InferiorShutDown); - emit inferiorShutDown(); - shutdown(); // re-iterate... - } else { - QString msg = msgInferiorStopFailed(__(response.data.findChild("msg").data())); - setState(InferiorShutdownFailed); - emit inferiorShutdownFailed(msg); - } -} - -void RemoteGdbAdapter::handleExit(const GdbResponse &response) -{ - if (response.resultClass == GdbResultDone) { - // don't set state here, this will be handled in handleGdbFinished() - } else { - QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data())); - emit adapterShutdownFailed(msg); - } -} - -void RemoteGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus) -{ - debugMessage(_("GDB PROESS FINISHED")); - emit adapterShutDown(); + // FIXME: cleanup missing } } // namespace Internal diff --git a/src/plugins/debugger/gdb/remotegdbadapter.h b/src/plugins/debugger/gdb/remotegdbadapter.h index 38fc7ac6555..a7f4bc645a4 100644 --- a/src/plugins/debugger/gdb/remotegdbadapter.h +++ b/src/plugins/debugger/gdb/remotegdbadapter.h @@ -69,12 +69,6 @@ private: #endif void handleFileExecAndSymbols(const GdbResponse &response); void handleTargetRemote(const GdbResponse &response); - void handleKill(const GdbResponse &response); - void handleExit(const GdbResponse &response); - - Q_SLOT void handleGdbStarted(); - Q_SLOT void handleGdbError(QProcess::ProcessError error); - Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus); QProcess m_uploadProc; }; diff --git a/src/plugins/debugger/gdb/trkgdbadapter.cpp b/src/plugins/debugger/gdb/trkgdbadapter.cpp index d517c2ca449..e1405d86f42 100644 --- a/src/plugins/debugger/gdb/trkgdbadapter.cpp +++ b/src/plugins/debugger/gdb/trkgdbadapter.cpp @@ -204,10 +204,6 @@ TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine, const TrkOptionsPtr &options) : #endif m_gdbServerName = _("127.0.0.1:%1").arg(2222 + portOffset); - commonInit(); - connect(&m_gdbProc, SIGNAL(stateChanged(QProcess::ProcessState)), - this, SLOT(handleGdbStateChanged(QProcess::ProcessState))); - connect(&m_rfcommProc, SIGNAL(readyReadStandardError()), this, SLOT(handleRfcommReadyReadStandardError())); connect(&m_rfcommProc, SIGNAL(readyReadStandardOutput()), @@ -380,17 +376,6 @@ QByteArray TrkGdbAdapter::trkInterruptMessage() return ba; } -void TrkGdbAdapter::emitDelayedAdapterStartFailed(const QString &msg) -{ - m_adapterFailMessage = msg; - QTimer::singleShot(0, this, SLOT(slotEmitDelayedAdapterStartFailed())); -} - -void TrkGdbAdapter::slotEmitDelayedAdapterStartFailed() -{ - emit adapterStartFailed(m_adapterFailMessage, TrkOptionsPage::settingsId()); -} - void TrkGdbAdapter::emitDelayedInferiorStartFailed(const QString &msg) { m_adapterFailMessage = msg; @@ -437,7 +422,7 @@ void TrkGdbAdapter::waitForTrkConnect() // "10 " + formatString("C:\\data\\usingdlls.sisx")); // Open File //sendTrkMessage(0x4B, 0, "00 00 00 01 73 1C 3A C8"); // Close File - maybeAdapterStarted(); + emit adapterStarted(); } void TrkGdbAdapter::logMessage(const QString &msg) @@ -1527,50 +1512,6 @@ void TrkGdbAdapter::interruptInferior() sendTrkMessage(0x1a, TrkCallback(), trkInterruptMessage(), "Interrupting..."); } -void TrkGdbAdapter::handleGdbError(QProcess::ProcessError error) -{ - if (error == QProcess::FailedToStart) { - const QString msg = QString::fromLatin1("GDB: Cannot start '%1': %2. Please check the settings.").arg(m_options->gdb).arg(m_gdbProc.errorString()); - emitDelayedAdapterStartFailed(msg); // Emitted from QProcess::start() on Windows - } else { - // Others should trigger handleGdbFinished - const QString msg = QString::fromLatin1("GDB: Process error %1: %2").arg(error).arg(m_gdbProc.errorString()); - logMessage(msg); - } -} - -void TrkGdbAdapter::handleGdbFinished(int exitCode, QProcess::ExitStatus exitStatus) -{ - const QString msg = exitStatus == QProcess::NormalExit ? - QString::fromLatin1("GDB: Process finished (exit code: %1).").arg(exitCode) : - QString::fromLatin1("GDB: Process crashed: %1").arg(m_gdbProc.errorString()); - if (state() == AdapterStarting) { - emitDelayedAdapterStartFailed(msg);// Potentially emitted from QProcess::start() on Windows - } else { - logMessage(msg); - emit adapterShutDown(); - } -} - -void TrkGdbAdapter::handleGdbStarted() -{ - logMessage(QString("GDB: Process Started")); - maybeAdapterStarted(); -} - -void TrkGdbAdapter::maybeAdapterStarted() -{ - QTC_ASSERT(state() == AdapterStarting, qDebug() << state()); - if (m_gdbProc.state() == QProcess::Running && m_trkDevice.isOpen()) { - emit adapterStarted(); - } -} - -void TrkGdbAdapter::handleGdbStateChanged(QProcess::ProcessState newState) -{ - logMessage(_("GDB: Process State %1").arg(newState)); -} - void TrkGdbAdapter::startAdapter() { // Retrieve parameters @@ -1632,13 +1573,12 @@ void TrkGdbAdapter::startAdapter() connect(m_gdbServer, SIGNAL(newConnection()), this, SLOT(handleGdbConnection())); - logMessage("STARTING GDB"); - logMessage(_("### Starting gdb %1").arg(m_options->gdb)); QStringList gdbArgs; gdbArgs.append(QLatin1String("--nx")); // Do not read .gdbinit file - gdbArgs.append(QLatin1String("-i")); - gdbArgs.append(QLatin1String("mi")); - m_gdbProc.start(m_options->gdb, gdbArgs); + if (!m_engine->startGdb(gdbArgs, m_options->gdb)) { + cleanup(); + return; + } waitForTrkConnect(); } @@ -1792,7 +1732,7 @@ void TrkGdbAdapter::write(const QByteArray &data) trkReadMemoryMessage(m_session.dataseg, 12)); return; } - m_gdbProc.write(data); + m_engine->m_gdbProc.write(data); } uint oldPC; @@ -1990,79 +1930,7 @@ void TrkGdbAdapter::cleanup() void TrkGdbAdapter::shutdown() { - switch (state()) { - case AdapterStarting: - case AdapterStartFailed: - cleanup(); - setState(DebuggerNotReady); - return; - - case InferiorStopping: - case InferiorRunningRequested: - case InferiorRunning: - //sendTrkMessage(0x1a, TrkCallback(), trkInterruptMessage(), "Interrupting..."); - // Fall through. - - case InferiorStopped: - //sendTrkMessage(0x41, TrkCallback(), trkDeleteProcessMessage(), "Delete process"); - //sendTrkMessage(0x02, TrkCB(handleDisconnect)); - setState(InferiorShuttingDown); - m_engine->postCommand(_("kill"), CB(handleKill)); - return; - - case InferiorShutDown: - setState(AdapterShuttingDown); - cleanup(); - m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit)); - return; - -/* - if (m_options->mode == TrkOptions::BlueTooth - && m_rfcommProc.state() == QProcess::Running) - m_rfcommProc.kill(); - m_rfcommProc.terminate(); - m_rfcommProc.write(ba); - m_rfcommProc.terminate(); - m_rfcommProc.waitForFinished(); - - m_gdbProc.kill(); - m_gdbProc.terminate(); - - QByteArray ba; - ba.append(0x03); - QProcess proc; - proc.start("rfcomm release " + m_options->blueToothDevice); - proc.waitForFinished(); - m_gdbProc.waitForFinished(msecs); -*/ - - default: - QTC_ASSERT(false, qDebug() << state()); - } -} - -void TrkGdbAdapter::handleKill(const GdbResponse &response) -{ - if (response.resultClass == GdbResultDone) { - setState(InferiorShutDown); - emit inferiorShutDown(); - shutdown(); // re-iterate... - } else { - const QString msg = msgInferiorStopFailed(__(response.data.findChild("msg").data())); - setState(InferiorShutdownFailed); - emit inferiorShutdownFailed(msg); - } -} - -void TrkGdbAdapter::handleExit(const GdbResponse &response) -{ - if (response.resultClass == GdbResultDone) { - qDebug() << "EXITED, NO MESSAGE..."; - // don't set state here, this will be handled in handleGdbFinished() - } else { - const QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data())); - emit adapterShutdownFailed(msg); - } + cleanup(); } } // namespace Internal diff --git a/src/plugins/debugger/gdb/trkgdbadapter.h b/src/plugins/debugger/gdb/trkgdbadapter.h index 5e2e4939a42..72a996ef01f 100644 --- a/src/plugins/debugger/gdb/trkgdbadapter.h +++ b/src/plugins/debugger/gdb/trkgdbadapter.h @@ -163,8 +163,6 @@ public: // void start(const QString &program, const QStringList &args, QIODevice::OpenMode mode = QIODevice::ReadWrite); - QByteArray readAllStandardError(); - QByteArray readAllStandardOutput(); void write(const QByteArray &data); bool isTrkAdapter() const { return true; } bool dumpersAvailable() const { return false; } @@ -174,15 +172,12 @@ private: void startInferior(); void interruptInferior(); void shutdown(); + void cleanup(); - void emitDelayedAdapterStartFailed(const QString &msg); - Q_SLOT void slotEmitDelayedAdapterStartFailed(); void emitDelayedInferiorStartFailed(const QString &msg); Q_SLOT void slotEmitDelayedInferiorStartFailed(); Q_SLOT void waitForTrkConnect(); - void handleKill(const GdbResponse &response); - void handleExit(const GdbResponse &response); void handleTargetRemote(const GdbResponse &response); void handleFirstContinue(const GdbResponse &response); @@ -285,13 +280,6 @@ private: bool sendGdbServerPacket(const QByteArray &packet, bool doFlush); void tryAnswerGdbMemoryRequest(bool buffered); - Q_SLOT void handleGdbError(QProcess::ProcessError error); - Q_SLOT void handleGdbFinished(int exitCode, QProcess::ExitStatus exitStatus); - Q_SLOT void handleGdbStarted(); - Q_SLOT void handleGdbStateChanged(QProcess::ProcessState newState); - - void maybeAdapterStarted(); - void logMessage(const QString &msg); // triggers output() if m_verbose Q_SLOT void trkLogMessage(const QString &msg); diff --git a/src/plugins/debugger/idebuggerengine.h b/src/plugins/debugger/idebuggerengine.h index 619ac2bddb9..7766b73b7c2 100644 --- a/src/plugins/debugger/idebuggerengine.h +++ b/src/plugins/debugger/idebuggerengine.h @@ -123,7 +123,7 @@ public: protected: void showStatusMessage(const QString &msg, int timeout = -1); DebuggerState state() const; - void setState(DebuggerState state); + void setState(DebuggerState state, bool forced = false); DebuggerManager *manager() const { return m_manager; } DebuggerManager *m_manager; -- GitLab