OSDN Git Service

debugger: prevent endless recursion due to broken dumpers
authorhjk <qtc-committer@nokia.com>
Tue, 27 Oct 2009 15:36:23 +0000 (16:36 +0100)
committerhjk <qtc-committer@nokia.com>
Tue, 27 Oct 2009 15:36:23 +0000 (16:36 +0100)
src/plugins/debugger/gdb/gdbengine.cpp
src/plugins/debugger/gdb/gdbengine.h

index 8b1e3b2..7572c30 100644 (file)
@@ -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, /**/);
     }
index 786ac76..9e23fee 100644 (file)
@@ -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;
 
     //