diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 8b1e3b2c380ac949e611f1327664d3cd13fb1448..7572c30fba3cca963821bb7b66d319e6486ecb72 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -692,10 +692,10 @@ void GdbEngine::postCommandHelper(const GdbCommand &cmd) if (cmd.flags & RebuildModel) { ++m_pendingRequests; - PENDING_DEBUG(" CALLBACK" << cmd.callbackName + PENDING_DEBUG(" COMMAND" << cmd.callbackName << "INCREMENTS PENDING TO:" << m_pendingRequests << cmd.command); } else { - PENDING_DEBUG(" UNKNOWN CALLBACK" << cmd.callbackName + PENDING_DEBUG(" UNKNOWN COMMAND" << cmd.callbackName << "LEAVES PENDING AT:" << m_pendingRequests << cmd.command); } @@ -816,14 +816,14 @@ void GdbEngine::handleResultRecord(GdbResponse *response) if (cmd.flags & RebuildModel) { --m_pendingRequests; - PENDING_DEBUG(" TYPE " << cmd.callbackName << " DECREMENTS PENDING TO: " + PENDING_DEBUG(" RESULT " << cmd.callbackName << " DECREMENTS PENDING TO: " << m_pendingRequests << cmd.command); if (m_pendingRequests <= 0) { PENDING_DEBUG("\n\n .... AND TRIGGERS MODEL UPDATE\n"); rebuildModel(); } } else { - PENDING_DEBUG(" UNKNOWN TYPE " << cmd.callbackName << " LEAVES PENDING AT: " + PENDING_DEBUG(" UNKNOWN RESULT " << cmd.callbackName << " LEAVES PENDING AT: " << m_pendingRequests << cmd.command); } @@ -1120,6 +1120,8 @@ void GdbEngine::handleStopResponse(const GdbMi &data) if (initHelpers && reason == "signal-received" && data.findChild("signal-name").data() != "SIGTRAP") initHelpers = false; + if (isSynchroneous()) + initHelpers = false; if (initHelpers) { tryLoadDebuggingHelpers(); QVariant var = QVariant::fromValue<GdbMi>(data); @@ -2952,6 +2954,22 @@ void GdbEngine::updateWatchData(const WatchData &data) #else if (data.iname.endsWith(_("."))) return; + + // Avoid endless loops created by faulty dumpers. + QString processedName = QString(_("%1-%2").arg(1).arg(data.iname)); + //qDebug() << "PROCESSED NAMES: " << processedName << m_processedNames; + if (m_processedNames.contains(processedName)) { + WatchData data1 = data; + gdbInputAvailable(LogStatus, + _("<Breaking endless loop for %1>").arg(data1.iname)); + data1.setAllUnneeded(); + data1.setValue(_("<unavailable>")); + data1.setHasChildren(false); + insertData(data1); + return; + } + m_processedNames.insert(processedName); + updateLocals(); #endif } else { @@ -2990,7 +3008,8 @@ void GdbEngine::rebuildModel() { static int count = 0; ++count; - m_processedNames.clear(); + if (!isSynchroneous()) + m_processedNames.clear(); PENDING_DEBUG("REBUILDING MODEL" << count); gdbInputAvailable(LogStatus, _("<Rebuild Watchmodel %1>").arg(count)); showStatusMessage(tr("Finished retrieving data."), 400); @@ -3359,27 +3378,26 @@ void GdbEngine::handleDebuggingHelperValue3(const GdbResponse &response) void GdbEngine::updateLocals(const QVariant &cookie) { m_pendingRequests = 0; - m_processedNames.clear(); - - PENDING_DEBUG("\nRESET PENDING"); - //m_toolTipCache.clear(); - m_toolTipExpression.clear(); - manager()->watchHandler()->beginCycle(); - - // Asynchronous load of injected library, initialize in first stop - if (m_dumperInjectionLoad && m_debuggingHelperState == DebuggingHelperLoadTried - && m_dumperHelper.typeCount() == 0 - && inferiorPid() > 0) - tryQueryDebuggingHelpers(); - if (isSynchroneous()) { QStringList expanded = m_manager->watchHandler()->expandedINames().toList(); postCommand(_("bb %1 %2") .arg(int(theDebuggerBoolSetting(UseDebuggingHelpers))) .arg(expanded.join(_(","))), - CB(handleStackFrame1)); - postCommand(_("p 1"), CB(handleStackFrame2)); + CB(handleStackFrame)); } else { + m_processedNames.clear(); + + PENDING_DEBUG("\nRESET PENDING"); + //m_toolTipCache.clear(); + m_toolTipExpression.clear(); + manager()->watchHandler()->beginCycle(); + + // Asynchronous load of injected library, initialize in first stop + if (m_dumperInjectionLoad && m_debuggingHelperState == DebuggingHelperLoadTried + && m_dumperHelper.typeCount() == 0 + && inferiorPid() > 0) + tryQueryDebuggingHelpers(); + QString level = QString::number(currentFrame()); // '2' is 'list with type and value' QString cmd = _("-stack-list-arguments 2 ") + level + _c(' ') + level; @@ -3390,27 +3408,13 @@ void GdbEngine::updateLocals(const QVariant &cookie) } } -void GdbEngine::handleStackFrame1(const GdbResponse &response) -{ - if (response.resultClass == GdbResultDone) { - QByteArray out = response.data.findChild("consolestreamoutput").data(); - while (out.endsWith(' ') || out.endsWith('\n')) - out.chop(1); - //qDebug() << "FIRST CHUNK: " << out; - m_firstChunk = out; - } else { - QTC_ASSERT(false, qDebug() << response.toString()); - } -} - -void GdbEngine::handleStackFrame2(const GdbResponse &response) +void GdbEngine::handleStackFrame(const GdbResponse &response) { if (response.resultClass == GdbResultDone) { QByteArray out = response.data.findChild("consolestreamoutput").data(); while (out.endsWith(' ') || out.endsWith('\n')) out.chop(1); //qDebug() << "SECOND CHUNK: " << out; - out = m_firstChunk + out; int pos = out.indexOf("locals="); if (pos != 0) { qDebug() << "DISCARDING JUNK AT BEGIN OF RESPONSE: " @@ -3436,7 +3440,13 @@ void GdbEngine::handleStackFrame2(const GdbResponse &response) // FIXME: //manager()->watchHandler()->updateWatchers(); - rebuildModel(); + PENDING_DEBUG("AFTER handleStackFrame()"); + // FIXME: This should only be used when updateLocals() was + // triggered by expanding an item in the view. + if (m_pendingRequests <= 0) { + PENDING_DEBUG("\n\n .... AND TRIGGERS MODEL UPDATE\n"); + rebuildModel(); + } } else { QTC_ASSERT(false, /**/); } diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 786ac7696a66937d82c9cf78a76e28f8d847c69b..9e23fee2b2ec67c93274d4a6b70aceab4a4ccc0f 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -370,14 +370,12 @@ private: ////////// View & Data Stuff ////////// void handleStackListFrames(const GdbResponse &response); void handleStackSelectThread(const GdbResponse &response); void handleStackListThreads(const GdbResponse &response); - void handleStackFrame1(const GdbResponse &response); - void handleStackFrame2(const GdbResponse &response); + void handleStackFrame(const GdbResponse &response); Q_SLOT void reloadStack(bool forceGotoLocation); Q_SLOT void reloadFullStack(); int currentFrame() const; QList<GdbMi> m_currentFunctionArgs; - QByteArray m_firstChunk; QString m_currentFrame; //