From 41caca27636a3836479a691c3cd9cb0f2ab38858 Mon Sep 17 00:00:00 2001 From: hjk <qtc-committer@nokia.com> Date: Tue, 22 Sep 2009 09:27:19 +0200 Subject: [PATCH] debugger: reorganize trk startup --- src/plugins/debugger/gdb/gdbengine.cpp | 23 ++- src/plugins/debugger/gdb/trkgdbadapter.cpp | 156 ++++++++++++++++----- src/plugins/debugger/gdb/trkgdbadapter.h | 10 +- 3 files changed, 144 insertions(+), 45 deletions(-) diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 7985e28417c..8bdf71ae711 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -83,12 +83,12 @@ #endif #include <ctype.h> +// FIXME: temporary hack to evalute tbreak based step-over behaviour static QString lastFile; static int lastLine; namespace Debugger { namespace Internal { -using namespace Debugger::Constants; //#define DEBUG_PENDING 1 //#define DEBUG_SUBITEM 1 @@ -103,6 +103,18 @@ using namespace Debugger::Constants; #define STRINGIFY(x) STRINGIFY_INTERNAL(x) #define CB(callback) &GdbEngine::callback, STRINGIFY(callback) +static bool stateAcceptsGdbCommands(GdbAdapterState state) +{ + return state == AdapterStarted + || state == InferiorPreparing + || state == InferiorPrepared + || state == InferiorStarting + || state == InferiorStarted + || state == InferiorShuttingDown + || state == InferiorShutDown + || state == AdapterShuttingDown; +}; + static int ¤tToken() { static int token = 0; @@ -729,7 +741,8 @@ void GdbEngine::postCommand(const QString &command, GdbCommandFlags flags, void GdbEngine::postCommandHelper(const GdbCommand &cmd) { - if (m_gdbAdapter->state() == AdapterNotRunning) { + if (!stateAcceptsGdbCommands(m_gdbAdapter->state())) { + PENDING_DEBUG(_("NO GDB PROCESS RUNNING, CMD IGNORED: ") + cmd.command); debugMessage(_("NO GDB PROCESS RUNNING, CMD IGNORED: ") + cmd.command); return; } @@ -737,10 +750,12 @@ void GdbEngine::postCommandHelper(const GdbCommand &cmd) if (cmd.flags & RebuildModel) { ++m_pendingRequests; PENDING_DEBUG(" CALLBACK" << cmd.callbackName - << "INCREMENTS PENDING TO:" << m_pendingRequests << cmd.command); + << "INCREMENTS PENDING TO:" << m_pendingRequests << cmd.command + << m_gdbAdapter->state()); } else { PENDING_DEBUG(" UNKNOWN CALLBACK" << cmd.callbackName - << "LEAVES PENDING AT:" << m_pendingRequests << cmd.command); + << "LEAVES PENDING AT:" << m_pendingRequests << cmd.command + << m_gdbAdapter->state()); } if ((cmd.flags & NeedsStop) && status() != DebuggerInferiorStopped diff --git a/src/plugins/debugger/gdb/trkgdbadapter.cpp b/src/plugins/debugger/gdb/trkgdbadapter.cpp index efce356ebe2..12e47e9401d 100644 --- a/src/plugins/debugger/gdb/trkgdbadapter.cpp +++ b/src/plugins/debugger/gdb/trkgdbadapter.cpp @@ -37,9 +37,17 @@ # include <unistd.h> #endif +#include <utils/qtcassert.h> + #include <QtCore/QTimer> #include <QtCore/QDir> +#define STRINGIFY_INTERNAL(x) #x +#define STRINGIFY(x) STRINGIFY_INTERNAL(x) +#define CB(callback) \ + static_cast<GdbEngine::AdapterCallback>(&TrkGdbAdapter::callback), \ + STRINGIFY(callback) + #define TrkCB(s) TrkCallback(this, &TrkGdbAdapter::s) @@ -84,7 +92,7 @@ TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine, const TrkOptionsPtr &options) : m_bufferedMemoryRead(true), m_waitCount(0) { - + setState(AdapterNotRunning); #ifdef Q_OS_WIN const DWORD portOffset = GetCurrentProcessId() % 100; #else @@ -117,6 +125,11 @@ TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine, const TrkOptionsPtr &options) : connect(&m_rfcommProc, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(handleRfcommStateChanged(QProcess::ProcessState))); + connect(&m_trkDevice, SIGNAL(messageReceived(trk::TrkResult)), + this, SLOT(handleTrkResult(trk::TrkResult))); + connect(&m_trkDevice, SIGNAL(error(QString)), + this, SLOT(handleTrkError(QString))); + if (m_verbose > 1) m_trkDevice.setVerbose(true); m_trkDevice.setSerialFrame(m_options->mode != TrkOptions::BlueTooth); @@ -219,6 +232,7 @@ QByteArray TrkGdbAdapter::trkStepRangeMessage(byte option) void TrkGdbAdapter::startInferiorEarly() { + QTC_ASSERT(state() == AdapterStarting, qDebug() << state()); QString errorMessage; const QString device = effectiveTrkDevice(); if (!m_trkDevice.open(device, &errorMessage)) { @@ -230,9 +244,9 @@ void TrkGdbAdapter::startInferiorEarly() QString msg = QString::fromLatin1("Failed to connect to %1 after " "%2 attempts").arg(device).arg(m_waitCount); logMessage(msg); + setState(AdapterNotRunning); emit adapterStartFailed(msg); } - QTimer::singleShot(1000, this, SLOT(startInferiorEarly())); return; } @@ -947,6 +961,7 @@ void TrkGdbAdapter::handleCpuType(const TrkResult &result) void TrkGdbAdapter::handleCreateProcess(const TrkResult &result) { + QTC_ASSERT(state() == AdapterStarting, qDebug() << state()); // 40 00 00] //logMessage(" RESULT: " + result.toString()); // [80 08 00 00 00 01 B5 00 00 01 B6 78 67 40 00 00 40 00 00] @@ -1284,6 +1299,7 @@ void TrkGdbAdapter::readMemory(uint addr, uint len) void TrkGdbAdapter::interruptInferior() { + QTC_ASSERT(state() == AdapterStarted, qDebug() << state()); qDebug() << "TRYING TO INTERRUPT INFERIOR"; QByteArray ba; // stop the thread (2) or the process (1) or the whole system (0) @@ -1302,30 +1318,42 @@ void TrkGdbAdapter::handleGdbError(QProcess::ProcessError error) void TrkGdbAdapter::handleGdbFinished(int exitCode, QProcess::ExitStatus exitStatus) { logMessage(QString("GDB: ProcessFinished %1 %2").arg(exitCode).arg(exitStatus)); + //setState(AdapterNotRunning); + //emit adapterShutDown(); } void TrkGdbAdapter::handleGdbStarted() { + QTC_ASSERT(state() == AdapterStarting, qDebug() << state()); logMessage(QString("GDB: Process Started")); + setState(AdapterStarted); emit adapterStarted(); } void TrkGdbAdapter::handleGdbStateChanged(QProcess::ProcessState newState) { - logMessage(QString("GDB: Process State %1").arg(newState)); + logMessage(_("GDB: Process State %1").arg(newState)); } void TrkGdbAdapter::startAdapter(const DebuggerStartParametersPtr &sp) { + QTC_ASSERT(state() == AdapterNotRunning, qDebug() << state()); + setState(AdapterStarting); + debugMessage(_("TRYING TO START ADAPTER")); m_startParameters = sp; logMessage(QLatin1String("### Starting TrkGdbAdapter")); if (m_options->mode == TrkOptions::BlueTooth) { const QString device = effectiveTrkDevice(); const QString blueToothListener = QLatin1String("rfcomm"); - logMessage(QString::fromLatin1("### Starting BlueTooth listener %1 on %2") - .arg(blueToothListener, device)); - m_rfcommProc.start(blueToothListener + QLatin1String(" -r listen ") - + m_options->blueToothDevice + QLatin1String(" 1")); + QStringList blueToothListenerArguments; + blueToothListenerArguments.append(_("-r")); + blueToothListenerArguments.append(_("listen")); + blueToothListenerArguments.append(m_options->blueToothDevice); + blueToothListenerArguments.append(_("1")); + logMessage(_("### Starting BlueTooth listener %1 on %2: %3 %4") + .arg(blueToothListener).arg(device).arg(blueToothListener) + .arg(blueToothListenerArguments.join(" "))); + m_rfcommProc.start(blueToothListener, blueToothListenerArguments); m_rfcommProc.waitForStarted(); if (m_rfcommProc.state() != QProcess::Running) { QString msg = QString::fromLatin1("Failed to start BlueTooth " @@ -1338,24 +1366,56 @@ void TrkGdbAdapter::startAdapter(const DebuggerStartParametersPtr &sp) } m_waitCount = 0; - connect(&m_trkDevice, SIGNAL(messageReceived(trk::TrkResult)), - this, SLOT(handleTrkResult(trk::TrkResult))); - connect(&m_trkDevice, SIGNAL(error(QString)), - this, SLOT(handleTrkError(QString))); - startInferiorEarly(); } void TrkGdbAdapter::prepareInferior() { - // we already prepared the inferior during the adapter start - emit inferiorPrepared(); + QTC_ASSERT(state() == AdapterStarted, qDebug() << state()); + // We already started the inferior process during the adapter start. + // Now make gdb aware of it. + setState(InferiorPreparing); + QString fileName = m_engine->startParameters().executable; + m_engine->postCommand(_("add-symbol-file \"%1\" %2").arg(fileName) + .arg(m_session.codeseg)); + m_engine->postCommand(_("symbol-file \"%1\"").arg(fileName)); + m_engine->postCommand(_("target remote ") + gdbServerName(), + CB(handleTargetRemote)); +} + +void TrkGdbAdapter::handleTargetRemote(const GdbResultRecord &record, const QVariant &) +{ + 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); + } } void TrkGdbAdapter::startInferior() { - // we already started the inferior during the adapter start - emit inferiorStarted(); + QTC_ASSERT(state() == InferiorPrepared, qDebug() << state()); + setState(InferiorStarting); + m_engine->postCommand(_("-exec-continue"), CB(handleFirstContinue)); +} + +void TrkGdbAdapter::handleFirstContinue(const GdbResultRecord &record, const QVariant &) +{ + QTC_ASSERT(state() == InferiorStarting, qDebug() << state()); + if (record.resultClass == GdbResultDone) { + setState(InferiorStarted); + emit inferiorStarted(); + } else if (record.resultClass == GdbResultError) { + //QString msg = __(record.data.findChild("msg").data()); + QString msg1 = tr("Connecting to remote server failed:"); + emit inferiorStartFailed(msg1 + record.toString()); + } } #ifdef Q_OS_WIN @@ -1383,10 +1443,12 @@ static void setGdbCygwinEnvironment(const QString &cygwin, QProcess *process) void TrkGdbAdapter::startGdb() { + QTC_ASSERT(state() == AdapterStarting, qDebug() << state()); if (!m_gdbServer.listen(QHostAddress(gdbServerIP()), gdbServerPort())) { QString msg = QString("Unable to start the gdb server at %1: %2.") .arg(m_gdbServerName).arg(m_gdbServer.errorString()); logMessage(msg); + setState(AdapterNotRunning); emit adapterStartFailed(msg); return; } @@ -1458,7 +1520,7 @@ void TrkGdbAdapter::handleRfcommStateChanged(QProcess::ProcessState newState) } // -// GdbProcessBase +// AbstractGdbAdapter interface implementation // void TrkGdbAdapter::kill() @@ -1475,6 +1537,7 @@ void TrkGdbAdapter::terminate() m_gdbProc.terminate(); } +/* bool TrkGdbAdapter::waitForFinished(int msecs) { QByteArray ba; @@ -1487,12 +1550,7 @@ bool TrkGdbAdapter::waitForFinished(int msecs) proc.waitForFinished(); return m_gdbProc.waitForFinished(msecs); } - -GdbAdapterState TrkGdbAdapter::state() const -{ - //return m_gdbProc.state(); - return AdapterNotRunning; // FIXME -} +*/ QString TrkGdbAdapter::errorString() const { @@ -1524,31 +1582,53 @@ void TrkGdbAdapter::setEnvironment(const QStringList &env) m_gdbProc.setEnvironment(env); } +void TrkGdbAdapter::shutdownInferior() +{ + m_engine->postCommand(_("kill"), CB(handleKill)); +} + void TrkGdbAdapter::shutdownAdapter() { + if (state() == InferiorStarted) { + setState(InferiorShuttingDown); + m_engine->postCommand(_("kill"), CB(handleKill)); + return; + } + + if (state() == InferiorShutDown) { + setState(AdapterShuttingDown); + m_engine->postCommand(_("-gdb-exit"), CB(handleExit)); + return; + } + + QTC_ASSERT(state() == AdapterNotRunning, qDebug() << state()); emit adapterShutDown(); } -void TrkGdbAdapter::shutdownInferior() +void TrkGdbAdapter::handleKill(const GdbResultRecord &response, const QVariant &) { - emit inferiorShutDown(); + if (response.resultClass == GdbResultDone) { + setState(InferiorShutDown); + emit inferiorShutDown(); + shutdownAdapter(); // re-iterate... + } else if (response.resultClass == GdbResultError) { + QString msg = tr("Inferior process could not be stopped:\n") + + __(response.data.findChild("msg").data()); + setState(InferiorShutdownFailed); + emit inferiorShutdownFailed(msg); + } } -/* -void TrkGdbAdapter::attach() +void TrkGdbAdapter::handleExit(const GdbResultRecord &response, const QVariant &) { -#ifdef STANDALONE_RUNNER -#else - QString fileName = m_engine->startParameters().executable; - m_engine->postCommand(_("add-symbol-file \"%1\" %2").arg(fileName) - .arg(m_session.codeseg)); - m_engine->postCommand(_("symbol-file \"%1\"").arg(fileName)); - //m_engine->postCommand(_("target remote ") + gdbServerName(), - // &GdbEngine::handleTargetRemote, "handleTargetRemote"); - m_engine->postCommand(_("target remote ") + gdbServerName()); -#endif + if (response.resultClass == GdbResultDone) { + // 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") + + __(response.data.findChild("msg").data()); + emit adapterShutdownFailed(msg); + } } -*/ } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/gdb/trkgdbadapter.h b/src/plugins/debugger/gdb/trkgdbadapter.h index 43ae3a4633a..f725fa635b9 100644 --- a/src/plugins/debugger/gdb/trkgdbadapter.h +++ b/src/plugins/debugger/gdb/trkgdbadapter.h @@ -101,6 +101,7 @@ private: QProcess m_rfcommProc; bool m_running; DebuggerStartParametersPtr m_startParameters; + void debugMessage(const QString &msg) { m_engine->debugMessage(msg); } public: // @@ -110,8 +111,6 @@ public: QIODevice::OpenMode mode = QIODevice::ReadWrite); void kill(); void terminate(); - bool waitForFinished(int msecs = 30000); - GdbAdapterState state() const; QString errorString() const; QByteArray readAllStandardError(); QByteArray readAllStandardOutput(); @@ -121,7 +120,7 @@ public: bool isAdapter() const { return true; } //void attach(); void interruptInferior(); - void startInferiorEarly(); + Q_SLOT void startInferiorEarly(); void startAdapter(const DebuggerStartParametersPtr &sp); void prepareInferior(); @@ -129,6 +128,11 @@ public: void shutdownInferior(); void shutdownAdapter(); + void handleKill(const GdbResultRecord &, const QVariant &); + void handleExit(const GdbResultRecord &, const QVariant &); + void handleTargetRemote(const GdbResultRecord &, const QVariant &); + void handleFirstContinue(const GdbResultRecord &, const QVariant &); + // // TRK // -- GitLab