From 732334a0b884d5dad63faada0bdfd4dda9ca708d Mon Sep 17 00:00:00 2001 From: Kai Koehne <kai.koehne@nokia.com> Date: Thu, 29 Sep 2011 16:49:18 +0200 Subject: [PATCH] QmlCppDebugger: Decouple states of engines 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 | 6 + src/plugins/debugger/qml/qmlcppengine.cpp | 268 ++++++++++------------ src/plugins/debugger/qml/qmlengine.cpp | 6 +- 3 files changed, 134 insertions(+), 146 deletions(-) diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 7065a3e1e5a..352189a1510 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -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(); diff --git a/src/plugins/debugger/qml/qmlcppengine.cpp b/src/plugins/debugger/qml/qmlcppengine.cpp index 1247dc77fdd..ee54f390d56 100644 --- a/src/plugins/debugger/qml/qmlcppengine.cpp +++ b/src/plugins/debugger/qml/qmlcppengine.cpp @@ -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(); + } } } diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 03a723831d8..c64f77d6adf 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -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) -- GitLab