OSDN Git Service

QmlCppDebugger: Decouple states of engines
authorKai Koehne <kai.koehne@nokia.com>
Thu, 29 Sep 2011 14:49:18 +0000 (16:49 +0200)
committerKai Koehne <kai.koehne@nokia.com>
Tue, 4 Oct 2011 14:00:15 +0000 (16:00 +0200)
The main engine now follows mostly the state of the gdb engine,
only if a breakpoint is hit/while stepping the state of the qml
engine is used. This allows us to hit C++ breakpoints at any time
(also when the qml engine hasn't been able to connect yet), and
also fixes the invalid transition warnings.

Change-Id: If67a56fd28b098952be2606d0a46e04c27835f66
Reviewed-on: http://codereview.qt-project.org/5897
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
src/plugins/debugger/debuggerengine.cpp
src/plugins/debugger/qml/qmlcppengine.cpp
src/plugins/debugger/qml/qmlengine.cpp

index 7065a3e..352189a 100644 (file)
@@ -1208,6 +1208,12 @@ void DebuggerEngine::quitDebugger()
     case InferiorRunOk:
         d->doInterruptInferior();
         break;
+    case EngineRunRequested:
+        notifyEngineRunFailed();
+        break;
+    case EngineRunFailed:
+    case DebuggerFinished:
+        break;
     default:
         // FIXME: We should disable the actions connected to that.
         notifyInferiorIll();
index 1247dc7..ee54f39 100644 (file)
@@ -283,16 +283,18 @@ void QmlCppEngine::updateAll()
 
 void QmlCppEngine::attemptBreakpointSynchronization()
 {
-    if (d->m_qmlEngine->state() == InferiorRunOk
-            || d->m_qmlEngine->state() == InferiorRunRequested
-            || d->m_qmlEngine->state() == InferiorStopOk
-            || d->m_qmlEngine->state() == InferiorStopRequested) {
-        // We expect both engines to be set up correctly before hitting
-        // any breakpoints, therefore ignore any breakpoints that would
-        // be hit before QDeclarativeEngine is set up.
-        d->m_cppEngine->attemptBreakpointSynchronization();
+    d->m_cppEngine->attemptBreakpointSynchronization();
+
+    switch (d->m_qmlEngine->state()) {
+    case InferiorRunOk:
+    case InferiorRunRequested:
+    case InferiorStopOk: // fall through
+    case InferiorStopRequested:
+        d->m_qmlEngine->attemptBreakpointSynchronization();
+        break;
+    default:
+        break;
     }
-    d->m_qmlEngine->attemptBreakpointSynchronization();
 }
 
 bool QmlCppEngine::acceptsBreakpoint(BreakpointModelId id) const
@@ -470,6 +472,7 @@ void QmlCppEngine::runEngine()
 void QmlCppEngine::shutdownInferior()
 {
     EDEBUG("\nMASTER SHUTDOWN INFERIOR");
+    d->m_cppEngine->quitDebugger();
     d->m_qmlEngine->quitDebugger();
 }
 
@@ -498,173 +501,150 @@ void QmlCppEngine::slaveEngineStateChanged
     EDEBUG("  OTHER ENGINE: " << otherEngine << otherEngine->state());
     EDEBUG("  COMBINED ENGINE: " << this << state() << isDying());
 
-    switch (newState) {
+    // Idea is to follow the state of the cpp engine,
+    // except where we are stepping in QML
 
-    case DebuggerNotReady:
-        break;
-
-    case EngineSetupRequested:
-        break;
+    if (slaveEngine == d->m_cppEngine) {
+        switch (newState) {
+        case DebuggerNotReady:
+            // Can this ever happen?
+            break;
+        case EngineSetupRequested:
+            QTC_CHECK(state() == EngineSetupRequested);
+            break;
 
-    case EngineSetupFailed:
-        notifyEngineSetupFailed();
-        break;
+        case EngineSetupFailed:
+            qmlEngine()->quitDebugger();
+            notifyEngineSetupFailed();
+            break;
 
-    case EngineSetupOk:
-        if (otherEngine->state() == EngineSetupOk)
+        case EngineSetupOk:
             notifyEngineSetupOk();
-        else
-            EDEBUG("... WAITING FOR OTHER ENGINE SETUP...");
-        break;
-
+            break;
 
-    case InferiorSetupRequested:
-        break;
+        case InferiorSetupRequested:
+            break;
 
-    case InferiorSetupFailed:
-        if (otherEngine->state() == InferiorRunOk)
-            otherEngine->quitDebugger();
-        else
+        case InferiorSetupFailed:
+            qmlEngine()->quitDebugger();
             notifyInferiorSetupFailed();
-        break;
+            break;
 
-    case InferiorSetupOk:
-        if (otherEngine->state() == InferiorSetupOk)
+        case InferiorSetupOk:
             notifyInferiorSetupOk();
-        else
-            EDEBUG("... WAITING FOR OTHER INFERIOR SETUP...");
-        break;
-
+            break;
 
-    case EngineRunRequested:
-        break;
+        case EngineRunRequested:
+            break;
 
-    case EngineRunFailed:
-        if (otherEngine->state() == InferiorRunOk)
-            otherEngine->quitDebugger();
-        else
+        case EngineRunFailed:
+            qmlEngine()->quitDebugger();
             notifyEngineRunFailed();
-        break;
+            break;
 
-    case InferiorUnrunnable:
-        break;
+        case InferiorUnrunnable:
+            notifyInferiorUnrunnable();
+            break;
 
-    case InferiorRunRequested:
-        break;
+        case InferiorRunRequested:
+            break;
 
-    case InferiorRunOk:
-        if (state() == EngineRunRequested) {
-            if (otherEngine->state() == InferiorRunOk) {
-                attemptBreakpointSynchronization();
+        case InferiorRunOk:
+            if (state() == EngineRunRequested)
                 notifyEngineRunAndInferiorRunOk();
-            } else {
-                EDEBUG("... WAITING FOR OTHER INFERIOR RUN");
-            }
-        } else {
-            if (otherEngine->state() == InferiorRunOk) {
-                EDEBUG("PLANNED INFERIOR RUN");
-                if (state() == InferiorStopOk) {
-                    notifyInferiorRunRequested();
-                }
+            else if (state() == InferiorRunRequested)
                 notifyInferiorRunOk();
-            } else if (otherEngine->state() == InferiorStopOk) {
-                EDEBUG("PLANNED SINGLE INFERIOR RUN");
-            } else {
-                EDEBUG(" **** INFERIOR RUN NOT OK ****");
-            }
-        }
-        break;
+            break;
 
-    case InferiorRunFailed:
-        notifyInferiorRunFailed();
-        break;
+        case InferiorRunFailed:
+            qmlEngine()->quitDebugger();
+            notifyInferiorRunFailed();
+            break;
 
-    case InferiorStopRequested:
-        break;
+        case InferiorStopRequested:
+            break;
 
-    case InferiorStopOk:
-        if (isDying()) {
-            EDEBUG("... AN INFERIOR STOPPED DURING SHUTDOWN ");
-            if (state() == InferiorStopRequested) {
-                notifyInferiorStopOk();
-            }
-        } else {
-            if (slaveEngine != d->m_activeEngine) {
-                QString engineName = slaveEngine == d->m_cppEngine
-                    ? QLatin1String("C++") : QLatin1String("QML");
-                showStatusMessage(tr("%1 debugger activated").arg(engineName));
-                d->m_activeEngine = slaveEngine;
-            }
-            if (otherEngine->state() == InferiorStopOk) {
-                EDEBUG("... BOTH STOPPED ");
-            } else if (otherEngine->state() == InferiorShutdownOk) {
-                EDEBUG("... STOPP ");
-            } else if (state() == InferiorStopRequested) {
-                EDEBUG("... AN INFERIOR STOPPED EXPECTEDLY");
-                notifyInferiorStopOk();
-            } else if (state() == EngineRunRequested) {
-                EDEBUG("... AN INFERIOR FAILED STARTUP, OTHER STOPPED EXPECTEDLY");
-                // wait for failure notification from other engine
+        case InferiorStopOk:
+            if (isDying()) {
+                EDEBUG("... CPP ENGINE STOPPED DURING SHUTDOWN ");
+                if (state() == InferiorStopRequested)
+                    notifyInferiorStopOk();
             } else {
-                EDEBUG("... AN INFERIOR STOPPED SPONTANEOUSLY");
-                notifyInferiorSpontaneousStop();
+                if (d->m_activeEngine != cppEngine()) {
+                    showStatusMessage(tr("Cpp debugger activated"));
+                    d->m_activeEngine = cppEngine();
+                }
+                switch (state()) {
+                case InferiorStopRequested:
+                    EDEBUG("... CPP ENGINE STOPPED EXPECTEDLY");
+                    notifyInferiorStopOk();
+                    break;
+                case EngineRunRequested:
+                    EDEBUG("... CPP ENGINE STOPPED ON STARTUP");
+                    notifyEngineRunAndInferiorStopOk();
+                    break;
+                default:
+                    QTC_CHECK(state() == InferiorRunOk);
+                    EDEBUG("... CPP ENGINE STOPPED SPONTANEOUSLY");
+                    notifyInferiorSpontaneousStop();
+                    break;
+                }
             }
-        }
-        break;
+            break;
 
-    case InferiorStopFailed:
-        notifyInferiorStopFailed();
-        break;
+        case InferiorStopFailed:
+            notifyInferiorStopFailed();
+            break;
 
-    case InferiorExitOk:
-        break;
+        case InferiorExitOk:
+            qmlEngine()->quitDebugger();
+            notifyInferiorExited();
+            break;
 
-    case InferiorShutdownRequested:
-        break;
+        case InferiorShutdownRequested:
+            break;
 
-    case InferiorShutdownFailed:
-        notifyInferiorShutdownFailed();
-        break;
+        case InferiorShutdownFailed:
+            notifyInferiorShutdownFailed();
+            break;
 
-    case InferiorShutdownOk:
-        if (otherEngine->state() == InferiorShutdownOk) {
-            if (state() == InferiorRunOk)
-                notifyInferiorExited();
-            else
+        case InferiorShutdownOk:
+            if (state() == InferiorShutdownRequested)
                 notifyInferiorShutdownOk();
-        } else if (otherEngine->state() == InferiorRunOk) {
-            otherEngine->quitDebugger();
-        } else if (otherEngine->state() == InferiorStopOk) {
-            otherEngine->quitDebugger();
-        } else if (otherEngine->state() == EngineRunFailed) {
-            EDEBUG("... INFERIOR STOPPED, OTHER ENGINE FAILED");
-            notifyEngineRunFailed();
-        } else if (otherEngine->state() == InferiorSetupFailed) {
-            EDEBUG("... INFERIOR STOPPED, OTHER INFERIOR FAILED");
-            notifyInferiorSetupFailed();
-        }
-        break;
-
-    case EngineShutdownRequested:
-        break;
+            break;
 
-    case EngineShutdownFailed:
-        notifyEngineShutdownFailed();
-        break;
+        case EngineShutdownRequested:
+            break;
 
-    case EngineShutdownOk:
-        if (otherEngine->state() == EngineShutdownOk)
-            ; // Wait for DebuggerFinished.
-        else
-            EDEBUG("... WAITING FOR OTHER ENGINE SHUTDOWN...");
-        break;
+        case EngineShutdownFailed:
+            qmlEngine()->quitDebugger();
+            notifyEngineShutdownFailed();
+            break;
 
-    case DebuggerFinished:
-        if (otherEngine->state() == DebuggerFinished)
+        case EngineShutdownOk: {
+            qmlEngine()->quitDebugger();
             notifyEngineShutdownOk();
-        else
-            EDEBUG("... WAITING FOR OTHER DEBUGGER TO FINISH...");
-        break;
+            break;
+        }
+
+        case DebuggerFinished:
+            break;
+        }
+    } else {
+        // QML engine state change
+        if (newState == InferiorStopOk) {
+            if (d->m_activeEngine != qmlEngine()) {
+                showStatusMessage(tr("QML debugger activated"));
+                d->m_activeEngine = qmlEngine();
+            }
+            if (state() == InferiorRunOk)
+                notifyInferiorSpontaneousStop();
+            else
+                notifyInferiorStopOk();
+        } else if (newState == InferiorRunOk) {
+            if (d->m_activeEngine == qmlEngine())
+                notifyInferiorRunOk();
+        }
     }
 }
 
index 03a7238..c64f77d 100644 (file)
@@ -249,8 +249,10 @@ void QmlEngine::connectionError(QAbstractSocket::SocketError socketError)
     if (socketError == QAbstractSocket::RemoteHostClosedError)
         showMessage(tr("QML Debugger: Remote host closed connection."), StatusBar);
 
-    notifyInferiorSpontaneousStop();
-    notifyInferiorIll();
+    if (!isSlaveEngine()) { // normal flow for slave engine when gdb exits
+        notifyInferiorSpontaneousStop();
+        notifyInferiorIll();
+    }
 }
 
 void QmlEngine::serviceConnectionError(const QString &serviceName)