debugger: re-do state transitions in combined C++/Qml engine

This still needs a lot of work and sanitizing.
This commit is contained in:
hjk
2011-01-14 14:25:02 +01:00
parent adf74394bb
commit 7195c6b5ad
7 changed files with 463 additions and 324 deletions

View File

@@ -114,9 +114,12 @@ enum DebuggerState
InferiorSetupRequested, InferiorSetupRequested,
InferiorSetupFailed, InferiorSetupFailed,
InferiorSetupOk,
EngineRunRequested, EngineRunRequested,
EngineRunFailed, EngineRunFailed,
EngineRunOk,
InferiorUnrunnable, // Used in the core dump adapter InferiorUnrunnable, // Used in the core dump adapter
InferiorRunRequested, // Debuggee requested to run InferiorRunRequested, // Debuggee requested to run
@@ -124,16 +127,19 @@ enum DebuggerState
InferiorRunFailed, // Debuggee running InferiorRunFailed, // Debuggee running
InferiorStopRequested, // Debuggee running, stop requested InferiorStopRequested, // Debuggee running, stop requested
InferiorStopSpontaneous, // Debuggee stopped spontaneously
InferiorStopOk, // Debuggee stopped InferiorStopOk, // Debuggee stopped
InferiorStopFailed, // Debuggee not stopped, will kill debugger InferiorStopFailed, // Debuggee not stopped, will kill debugger
InferiorExitOk,
InferiorShutdownRequested, InferiorShutdownRequested,
InferiorShutdownOk,
InferiorShutdownFailed, InferiorShutdownFailed,
InferiorShutdownOk,
EngineShutdownRequested, EngineShutdownRequested,
EngineShutdownOk,
EngineShutdownFailed, EngineShutdownFailed,
EngineShutdownOk,
DebuggerFinished DebuggerFinished
}; };

View File

@@ -182,7 +182,8 @@ public:
m_threadsHandler(), m_threadsHandler(),
m_watchHandler(engine), m_watchHandler(engine),
m_disassemblerAgent(engine), m_disassemblerAgent(engine),
m_memoryAgent(engine) m_memoryAgent(engine),
m_isStateDebugging(false)
{ {
connect(&m_locationTimer, SIGNAL(timeout()), SLOT(resetLocation())); connect(&m_locationTimer, SIGNAL(timeout()), SLOT(resetLocation()));
} }
@@ -229,8 +230,8 @@ public slots:
void raiseApplication() void raiseApplication()
{ {
QTC_ASSERT(m_runControl, return); QTC_ASSERT(runControl(), return);
m_runControl->bringApplicationToForeground(m_inferiorPid); runControl()->bringApplicationToForeground(m_inferiorPid);
} }
void scheduleResetLocation() void scheduleResetLocation()
@@ -250,6 +251,9 @@ public slots:
public: public:
DebuggerState state() const { return m_state; } DebuggerState state() const { return m_state; }
bool isMasterEngine() const { return m_engine->isMasterEngine(); }
DebuggerRunControl *runControl() const
{ return m_masterEngine ? m_masterEngine->runControl() : m_runControl; }
DebuggerEngine *m_engine; // Not owned. DebuggerEngine *m_engine; // Not owned.
DebuggerEngine *m_masterEngine; // Not owned DebuggerEngine *m_masterEngine; // Not owned
@@ -280,6 +284,8 @@ public:
MemoryAgent m_memoryAgent; MemoryAgent m_memoryAgent;
QScopedPointer<TextEditor::BaseTextMark> m_locationMark; QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
QTimer m_locationTimer; QTimer m_locationTimer;
bool m_isStateDebugging;
}; };
@@ -310,16 +316,20 @@ const char *DebuggerEngine::stateName(int s)
SN(EngineSetupOk) SN(EngineSetupOk)
SN(EngineSetupFailed) SN(EngineSetupFailed)
SN(EngineRunFailed) SN(EngineRunFailed)
SN(EngineRunOk)
SN(InferiorSetupRequested) SN(InferiorSetupRequested)
SN(InferiorSetupFailed) SN(InferiorSetupFailed)
SN(InferiorSetupOk)
SN(EngineRunRequested) SN(EngineRunRequested)
SN(InferiorRunRequested) SN(InferiorRunRequested)
SN(InferiorRunOk) SN(InferiorRunOk)
SN(InferiorRunFailed) SN(InferiorRunFailed)
SN(InferiorUnrunnable) SN(InferiorUnrunnable)
SN(InferiorStopSpontaneous)
SN(InferiorStopRequested) SN(InferiorStopRequested)
SN(InferiorStopOk) SN(InferiorStopOk)
SN(InferiorStopFailed) SN(InferiorStopFailed)
SN(InferiorExitOk)
SN(InferiorShutdownRequested) SN(InferiorShutdownRequested)
SN(InferiorShutdownOk) SN(InferiorShutdownOk)
SN(InferiorShutdownFailed) SN(InferiorShutdownFailed)
@@ -476,6 +486,10 @@ void DebuggerEngine::setRegisterValue(int regnr, const QString &value)
void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) const void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) const
{ {
if (d->m_masterEngine) {
d->m_masterEngine->showMessage(msg, channel, timeout);
return;
}
//if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper()) //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
// qDebug() << qPrintable(msg) << "IN STATE" << state(); // qDebug() << qPrintable(msg) << "IN STATE" << state();
debuggerCore()->showMessage(msg, channel, timeout); debuggerCore()->showMessage(msg, channel, timeout);
@@ -488,16 +502,15 @@ void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) c
void DebuggerEngine::startDebugger(DebuggerRunControl *runControl) void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{ {
if (!isSlaveEngine()) { QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
d->m_progress.setProgressRange(0, 1000); d->m_progress.setProgressRange(0, 1000);
Core::FutureProgress *fp = Core::ICore::instance()->progressManager() Core::FutureProgress *fp = Core::ICore::instance()->progressManager()
->addTask(d->m_progress.future(), ->addTask(d->m_progress.future(),
tr("Launching"), _("Debugger.Launcher")); tr("Launching"), _("Debugger.Launcher"));
fp->setKeepOnFinish(Core::FutureProgress::DontKeepOnFinish); fp->setKeepOnFinish(Core::FutureProgress::DontKeepOnFinish);
d->m_progress.reportStarted(); d->m_progress.reportStarted();
}
QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
d->m_runControl = runControl; d->m_runControl = runControl;
@@ -671,32 +684,42 @@ static bool isAllowedTransition(DebuggerState from, DebuggerState to)
return to == InferiorSetupRequested || to == EngineShutdownRequested; return to == InferiorSetupRequested || to == EngineShutdownRequested;
case InferiorSetupRequested: case InferiorSetupRequested:
return to == EngineRunRequested || to == InferiorSetupFailed; return to == InferiorSetupOk || to == InferiorSetupFailed;
case InferiorSetupFailed: case InferiorSetupFailed:
return to == EngineShutdownRequested; return to == EngineShutdownRequested;
case InferiorSetupOk:
return to == EngineRunRequested;
case EngineRunRequested: case EngineRunRequested:
return to == InferiorRunRequested || to == InferiorStopRequested return to == EngineRunOk || EngineRunFailed;
|| to == InferiorUnrunnable || to == EngineRunFailed;
case EngineRunFailed: case EngineRunFailed:
return to == EngineShutdownRequested; return to == EngineShutdownRequested;
case EngineRunOk:
return InferiorRunOk || to == InferiorStopOk
|| to == InferiorUnrunnable;
case InferiorRunRequested: case InferiorRunRequested:
return to == InferiorRunOk || to == InferiorRunFailed; return to == InferiorRunOk || to == InferiorRunFailed;
case InferiorRunFailed: case InferiorRunFailed:
return to == InferiorStopOk; return to == InferiorStopOk;
case InferiorRunOk: case InferiorRunOk:
return to == InferiorStopRequested || to == InferiorStopOk; return to == InferiorStopRequested || to == InferiorStopSpontaneous
|| InferiorExitOk;
//|| to == InferiorStopOk;
case InferiorStopRequested: case InferiorStopRequested:
return to == InferiorStopOk || to == InferiorStopFailed; return to == InferiorStopOk || to == InferiorStopFailed;
case InferiorStopSpontaneous:
return to == InferiorStopOk;
case InferiorStopOk: case InferiorStopOk:
return to == InferiorRunRequested || to == InferiorShutdownRequested return to == InferiorRunRequested || to == InferiorShutdownRequested
|| to == InferiorStopOk; || to == InferiorStopOk || InferiorExitOk;
case InferiorStopFailed: case InferiorStopFailed:
return to == EngineShutdownRequested; return to == EngineShutdownRequested;
case InferiorExitOk:
return to == InferiorShutdownOk;
case InferiorUnrunnable: case InferiorUnrunnable:
return to == InferiorShutdownRequested; return to == InferiorShutdownRequested;
case InferiorShutdownRequested: case InferiorShutdownRequested:
@@ -724,27 +747,28 @@ static bool isAllowedTransition(DebuggerState from, DebuggerState to)
void DebuggerEngine::notifyEngineSetupFailed() void DebuggerEngine::notifyEngineSetupFailed()
{ {
showMessage(_("NOTE: ENGINE SETUP FAILED")); showMessage(_("NOTE: ENGINE SETUP FAILED"));
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
setState(EngineSetupFailed); setState(EngineSetupFailed);
QTC_ASSERT(d->m_runControl, return); if (isMasterEngine())
d->m_runControl->startFailed(); runControl()->startFailed();
setState(DebuggerFinished); setState(DebuggerFinished);
} }
void DebuggerEngine::notifyEngineSetupOk() void DebuggerEngine::notifyEngineSetupOk()
{ {
showMessage(_("NOTE: ENGINE SETUP OK")); showMessage(_("NOTE: ENGINE SETUP OK"));
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
setState(EngineSetupOk); setState(EngineSetupOk);
QTC_ASSERT(d->m_runControl, return);
showMessage(_("QUEUE: SETUP INFERIOR")); showMessage(_("QUEUE: SETUP INFERIOR"));
if (isMasterEngine())
QTimer::singleShot(0, d, SLOT(doSetupInferior())); QTimer::singleShot(0, d, SLOT(doSetupInferior()));
} }
void DebuggerEnginePrivate::doSetupInferior() void DebuggerEnginePrivate::doSetupInferior()
{ {
QTC_ASSERT(isMasterEngine(), return);
m_engine->showMessage(_("CALL: SETUP INFERIOR")); m_engine->showMessage(_("CALL: SETUP INFERIOR"));
QTC_ASSERT(state() == EngineSetupOk, qDebug() << state()); QTC_ASSERT(state() == EngineSetupOk, qDebug() << m_engine << state());
m_progress.setProgressValue(250); m_progress.setProgressValue(250);
m_engine->setState(InferiorSetupRequested); m_engine->setState(InferiorSetupRequested);
m_engine->setupInferior(); m_engine->setupInferior();
@@ -753,22 +777,26 @@ void DebuggerEnginePrivate::doSetupInferior()
void DebuggerEngine::notifyInferiorSetupFailed() void DebuggerEngine::notifyInferiorSetupFailed()
{ {
showMessage(_("NOTE: INFERIOR SETUP FAILED")); showMessage(_("NOTE: INFERIOR SETUP FAILED"));
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
setState(InferiorSetupFailed); setState(InferiorSetupFailed);
if (isMasterEngine())
d->queueShutdownEngine(); d->queueShutdownEngine();
} }
void DebuggerEngine::notifyInferiorSetupOk() void DebuggerEngine::notifyInferiorSetupOk()
{ {
showMessage(_("NOTE: INFERIOR SETUP OK")); showMessage(_("NOTE: INFERIOR SETUP OK"));
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
setState(InferiorSetupOk);
if (isMasterEngine())
d->queueRunEngine(); d->queueRunEngine();
} }
void DebuggerEnginePrivate::doRunEngine() void DebuggerEnginePrivate::doRunEngine()
{ {
QTC_ASSERT(isMasterEngine(), return);
m_engine->showMessage(_("CALL: RUN ENGINE")); m_engine->showMessage(_("CALL: RUN ENGINE"));
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state()); QTC_ASSERT(state() == EngineRunRequested, qDebug() << m_engine << state());
m_progress.setProgressValue(300); m_progress.setProgressValue(300);
m_engine->runEngine(); m_engine->runEngine();
} }
@@ -778,18 +806,19 @@ void DebuggerEngine::notifyInferiorUnrunnable()
showMessage(_("NOTE: INFERIOR UNRUNNABLE")); showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
d->m_progress.setProgressValue(1000); d->m_progress.setProgressValue(1000);
d->m_progress.reportFinished(); d->m_progress.reportFinished();
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state()); QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
setState(InferiorUnrunnable); setState(InferiorUnrunnable);
} }
void DebuggerEngine::notifyEngineRunFailed() void DebuggerEngine::notifyEngineRunFailed()
{ {
showMessage(_("NOTE: ENGINE RUN FAILED")); showMessage(_("NOTE: ENGINE RUN FAILED"));
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state()); QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
d->m_progress.setProgressValue(900); d->m_progress.setProgressValue(900);
d->m_progress.reportCanceled(); d->m_progress.reportCanceled();
d->m_progress.reportFinished(); d->m_progress.reportFinished();
setState(EngineRunFailed); setState(EngineRunFailed);
if (isMasterEngine())
d->queueShutdownEngine(); d->queueShutdownEngine();
} }
@@ -798,9 +827,10 @@ void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
showMessage(_("NOTE: ENGINE RUN AND INFERIOR RUN OK")); showMessage(_("NOTE: ENGINE RUN AND INFERIOR RUN OK"));
d->m_progress.setProgressValue(1000); d->m_progress.setProgressValue(1000);
d->m_progress.reportFinished(); d->m_progress.reportFinished();
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state()); QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
setState(InferiorRunRequested); setState(EngineRunOk);
notifyInferiorRunOk(); if (isMasterEngine())
setState(InferiorRunOk);
} }
void DebuggerEngine::notifyEngineRunAndInferiorStopOk() void DebuggerEngine::notifyEngineRunAndInferiorStopOk()
@@ -808,29 +838,30 @@ void DebuggerEngine::notifyEngineRunAndInferiorStopOk()
showMessage(_("NOTE: ENGINE RUN AND INFERIOR STOP OK")); showMessage(_("NOTE: ENGINE RUN AND INFERIOR STOP OK"));
d->m_progress.setProgressValue(1000); d->m_progress.setProgressValue(1000);
d->m_progress.reportFinished(); d->m_progress.reportFinished();
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state()); QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
setState(InferiorStopRequested); setState(EngineRunOk);
notifyInferiorStopOk(); if (isMasterEngine())
setState(InferiorStopOk);
} }
void DebuggerEngine::notifyInferiorRunRequested() void DebuggerEngine::notifyInferiorRunRequested()
{ {
showMessage(_("NOTE: INFERIOR RUN REQUESTED")); showMessage(_("NOTE: INFERIOR RUN REQUESTED"));
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); QTC_ASSERT(state() == InferiorStopOk, qDebug() << this << state());
setState(InferiorRunRequested); setState(InferiorRunRequested);
} }
void DebuggerEngine::notifyInferiorRunOk() void DebuggerEngine::notifyInferiorRunOk()
{ {
showMessage(_("NOTE: INFERIOR RUN OK")); showMessage(_("NOTE: INFERIOR RUN OK"));
QTC_ASSERT(state() == InferiorRunRequested, qDebug() << state()); QTC_ASSERT(state() == InferiorRunRequested, qDebug() << this << state());
setState(InferiorRunOk); setState(InferiorRunOk);
} }
void DebuggerEngine::notifyInferiorRunFailed() void DebuggerEngine::notifyInferiorRunFailed()
{ {
showMessage(_("NOTE: INFERIOR RUN FAILED")); showMessage(_("NOTE: INFERIOR RUN FAILED"));
QTC_ASSERT(state() == InferiorRunRequested, qDebug() << state()); QTC_ASSERT(state() == InferiorRunRequested, qDebug() << this << state());
setState(InferiorRunFailed); setState(InferiorRunFailed);
setState(InferiorStopOk); setState(InferiorStopOk);
if (isDying()) if (isDying())
@@ -856,28 +887,32 @@ void DebuggerEngine::notifyInferiorStopOk()
showMessage(_("NOTE: ... IGNORING STOP MESSAGE")); showMessage(_("NOTE: ... IGNORING STOP MESSAGE"));
return; return;
} }
QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state()); QTC_ASSERT(state() == InferiorStopRequested, qDebug() << this << state());
setState(InferiorStopOk); setState(InferiorStopOk);
} }
void DebuggerEngine::notifyInferiorSpontaneousStop() void DebuggerEngine::notifyInferiorSpontaneousStop()
{ {
showMessage(_("NOTE: INFERIOR SPONTANEOUES STOP")); showMessage(_("NOTE: INFERIOR SPONTANEOUES STOP"));
QTC_ASSERT(state() == InferiorRunOk, qDebug() << state()); QTC_ASSERT(state() == InferiorRunOk, qDebug() << this << state());
setState(InferiorStopSpontaneous);
if (isMasterEngine())
setState(InferiorStopOk); setState(InferiorStopOk);
} }
void DebuggerEngine::notifyInferiorStopFailed() void DebuggerEngine::notifyInferiorStopFailed()
{ {
showMessage(_("NOTE: INFERIOR STOP FAILED")); showMessage(_("NOTE: INFERIOR STOP FAILED"));
QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state()); QTC_ASSERT(state() == InferiorStopRequested, qDebug() << this << state());
setState(InferiorStopFailed); setState(InferiorStopFailed);
if (isMasterEngine())
d->queueShutdownEngine(); d->queueShutdownEngine();
} }
void DebuggerEnginePrivate::doInterruptInferior() void DebuggerEnginePrivate::doInterruptInferior()
{ {
QTC_ASSERT(state() == InferiorRunOk, qDebug() << state()); //QTC_ASSERT(isMasterEngine(), return);
QTC_ASSERT(state() == InferiorRunOk, qDebug() << m_engine << state());
m_engine->setState(InferiorStopRequested); m_engine->setState(InferiorStopRequested);
m_engine->showMessage(_("CALL: INTERRUPT INFERIOR")); m_engine->showMessage(_("CALL: INTERRUPT INFERIOR"));
m_engine->interruptInferior(); m_engine->interruptInferior();
@@ -885,7 +920,8 @@ void DebuggerEnginePrivate::doInterruptInferior()
void DebuggerEnginePrivate::doShutdownInferior() void DebuggerEnginePrivate::doShutdownInferior()
{ {
QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state()); //QTC_ASSERT(isMasterEngine(), return);
QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << m_engine << state());
resetLocation(); resetLocation();
m_targetState = DebuggerFinished; m_targetState = DebuggerFinished;
m_engine->showMessage(_("CALL: SHUTDOWN INFERIOR")); m_engine->showMessage(_("CALL: SHUTDOWN INFERIOR"));
@@ -895,9 +931,10 @@ void DebuggerEnginePrivate::doShutdownInferior()
void DebuggerEngine::notifyInferiorShutdownOk() void DebuggerEngine::notifyInferiorShutdownOk()
{ {
showMessage(_("INFERIOR SUCCESSFULLY SHUT DOWN")); showMessage(_("INFERIOR SUCCESSFULLY SHUT DOWN"));
QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state()); QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << this << state());
d->m_lastGoodState = DebuggerNotReady; // A "neutral" value. d->m_lastGoodState = DebuggerNotReady; // A "neutral" value.
setState(InferiorShutdownOk); setState(InferiorShutdownOk);
if (isMasterEngine())
d->queueShutdownEngine(); d->queueShutdownEngine();
} }
@@ -906,6 +943,7 @@ void DebuggerEngine::notifyInferiorShutdownFailed()
showMessage(_("INFERIOR SHUTDOWN FAILED")); showMessage(_("INFERIOR SHUTDOWN FAILED"));
QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << this << state()); QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << this << state());
setState(InferiorShutdownFailed); setState(InferiorShutdownFailed);
if (isMasterEngine())
d->queueShutdownEngine(); d->queueShutdownEngine();
} }
@@ -928,7 +966,8 @@ void DebuggerEngine::notifyInferiorIll()
void DebuggerEnginePrivate::doShutdownEngine() void DebuggerEnginePrivate::doShutdownEngine()
{ {
QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state()); QTC_ASSERT(isMasterEngine(), qDebug() << m_engine; return);
QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << m_engine << state());
m_targetState = DebuggerFinished; m_targetState = DebuggerFinished;
m_engine->showMessage(_("CALL: SHUTDOWN ENGINE")); m_engine->showMessage(_("CALL: SHUTDOWN ENGINE"));
m_engine->shutdownEngine(); m_engine->shutdownEngine();
@@ -937,29 +976,30 @@ void DebuggerEnginePrivate::doShutdownEngine()
void DebuggerEngine::notifyEngineShutdownOk() void DebuggerEngine::notifyEngineShutdownOk()
{ {
showMessage(_("NOTE: ENGINE SHUTDOWN OK")); showMessage(_("NOTE: ENGINE SHUTDOWN OK"));
QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state()); QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << this << state());
setState(EngineShutdownOk); setState(EngineShutdownOk);
if (isMasterEngine())
d->queueFinishDebugger(); d->queueFinishDebugger();
} }
void DebuggerEngine::notifyEngineShutdownFailed() void DebuggerEngine::notifyEngineShutdownFailed()
{ {
showMessage(_("NOTE: ENGINE SHUTDOWN FAILED")); showMessage(_("NOTE: ENGINE SHUTDOWN FAILED"));
QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state()); QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << this << state());
setState(EngineShutdownFailed); setState(EngineShutdownFailed);
if (isMasterEngine())
d->queueFinishDebugger(); d->queueFinishDebugger();
} }
void DebuggerEnginePrivate::doFinishDebugger() void DebuggerEnginePrivate::doFinishDebugger()
{ {
QTC_ASSERT(isMasterEngine(), return);
m_engine->showMessage(_("NOTE: FINISH DEBUGGER")); m_engine->showMessage(_("NOTE: FINISH DEBUGGER"));
QTC_ASSERT(state() == DebuggerFinished, qDebug() << state()); QTC_ASSERT(state() == DebuggerFinished, qDebug() << m_engine << state());
resetLocation(); resetLocation();
if (!m_engine->isSlaveEngine()) { if (isMasterEngine())
QTC_ASSERT(m_runControl, return);
m_runControl->debuggingFinished(); m_runControl->debuggingFinished();
} }
}
void DebuggerEngine::notifyEngineIll() void DebuggerEngine::notifyEngineIll()
{ {
@@ -980,9 +1020,11 @@ void DebuggerEngine::notifyEngineIll()
case InferiorStopOk: case InferiorStopOk:
showMessage(_("FORWARDING STATE TO InferiorShutdownFailed")); showMessage(_("FORWARDING STATE TO InferiorShutdownFailed"));
setState(InferiorShutdownFailed, true); setState(InferiorShutdownFailed, true);
if (isMasterEngine())
d->queueShutdownEngine(); d->queueShutdownEngine();
break; break;
default: default:
if (isMasterEngine())
d->queueShutdownEngine(); d->queueShutdownEngine();
break; break;
} }
@@ -992,14 +1034,16 @@ void DebuggerEngine::notifyEngineSpontaneousShutdown()
{ {
showMessage(_("NOTE: ENGINE SPONTANEOUS SHUTDOWN")); showMessage(_("NOTE: ENGINE SPONTANEOUS SHUTDOWN"));
setState(EngineShutdownOk, true); setState(EngineShutdownOk, true);
if (isMasterEngine())
d->queueFinishDebugger(); d->queueFinishDebugger();
} }
void DebuggerEngine::notifyInferiorExited() void DebuggerEngine::notifyInferiorExited()
{ {
qDebug() << "\nSPONTANEUOUS EXIT: " << this << d->m_state;
showMessage(_("NOTE: INFERIOR EXITED")); showMessage(_("NOTE: INFERIOR EXITED"));
d->resetLocation(); d->resetLocation();
/*
// This can be issued in almost any state. We assume, though, // This can be issued in almost any state. We assume, though,
// that at this point of time the inferior is not running anymore, // that at this point of time the inferior is not running anymore,
// even if stop notification were not issued or got lost. // even if stop notification were not issued or got lost.
@@ -1009,13 +1053,28 @@ void DebuggerEngine::notifyInferiorExited()
} }
setState(InferiorShutdownRequested); setState(InferiorShutdownRequested);
setState(InferiorShutdownOk); setState(InferiorShutdownOk);
*/
setState(InferiorExitOk);
if (isMasterEngine()) {
setState(InferiorShutdownOk);
d->queueShutdownEngine(); d->queueShutdownEngine();
} }
}
void DebuggerEngine::slaveEngineStateChanged(DebuggerEngine *slaveEngine,
DebuggerState state)
{
Q_UNUSED(slaveEngine);
Q_UNUSED(state);
}
void DebuggerEngine::setState(DebuggerState state, bool forced) void DebuggerEngine::setState(DebuggerState state, bool forced)
{ {
//qDebug() << "STATUS CHANGE: FROM " << stateName(d->m_state) if (isStateDebugging()) {
// << " TO " << stateName(state); qDebug() << "STATUS CHANGE: " << this
<< " FROM " << stateName(d->m_state) << " TO " << stateName(state)
<< isMasterEngine();
}
DebuggerState oldState = d->m_state; DebuggerState oldState = d->m_state;
d->m_state = state; d->m_state = state;
@@ -1024,7 +1083,7 @@ void DebuggerEngine::setState(DebuggerState state, bool forced)
.arg(stateName(oldState)).arg(oldState).arg(stateName(state)).arg(state) .arg(stateName(oldState)).arg(oldState).arg(stateName(state)).arg(state)
.arg(forced ? " BY FORCE" : ""); .arg(forced ? " BY FORCE" : "");
if (!forced && !isAllowedTransition(oldState, state)) if (!forced && !isAllowedTransition(oldState, state))
qDebug() << "UNEXPECTED STATE TRANSITION: " << msg; qDebug() << "*** UNEXPECTED STATE TRANSITION: " << this << msg;
if (state == DebuggerFinished) { if (state == DebuggerFinished) {
// Give up ownership on claimed breakpoints. // Give up ownership on claimed breakpoints.
@@ -1040,15 +1099,30 @@ void DebuggerEngine::setState(DebuggerState state, bool forced)
showMessage(msg, LogDebug); showMessage(msg, LogDebug);
updateViews(); updateViews();
if (isMasterEngine())
emit stateChanged(d->m_state); emit stateChanged(d->m_state);
if (isSlaveEngine())
masterEngine()->slaveEngineStateChanged(this, state);
}
void DebuggerEngine::setSilentState(DebuggerState state)
{
qDebug() << "SILENT STATUS CHANGE: " << this
<< " FROM " << stateName(d->m_state) << " TO " << stateName(state)
<< isMasterEngine();
DebuggerState oldState = d->m_state;
d->m_state = state;
if (!isAllowedTransition(oldState, state))
qDebug() << "*** SILENT UNEXPECTED STATE TRANSITION " << this;
} }
void DebuggerEngine::updateViews() void DebuggerEngine::updateViews()
{ {
// The slave engines are not entitled to change the view. Their wishes // The slave engines are not entitled to change the view. Their wishes
// should be coordinated by their master engine. // should be coordinated by their master engine.
if (isSlaveEngine()) if (isMasterEngine())
return;
debuggerCore()->updateState(this); debuggerCore()->updateState(this);
} }
@@ -1057,6 +1131,11 @@ bool DebuggerEngine::isSlaveEngine() const
return d->m_masterEngine != 0; return d->m_masterEngine != 0;
} }
bool DebuggerEngine::isMasterEngine() const
{
return d->m_masterEngine == 0;
}
DebuggerEngine *DebuggerEngine::masterEngine() const DebuggerEngine *DebuggerEngine::masterEngine() const
{ {
return d->m_masterEngine; return d->m_masterEngine;
@@ -1078,14 +1157,18 @@ bool DebuggerEngine::debuggerActionsEnabled(DebuggerState state)
case InferiorStopRequested: case InferiorStopRequested:
case InferiorRunRequested: case InferiorRunRequested:
case InferiorRunFailed: case InferiorRunFailed:
case InferiorSetupOk:
case DebuggerNotReady: case DebuggerNotReady:
case EngineSetupRequested: case EngineSetupRequested:
case EngineSetupOk: case EngineSetupOk:
case EngineSetupFailed: case EngineSetupFailed:
case EngineRunRequested: case EngineRunRequested:
case EngineRunFailed: case EngineRunFailed:
case EngineRunOk:
case InferiorSetupFailed: case InferiorSetupFailed:
case InferiorStopFailed: case InferiorStopFailed:
case InferiorStopSpontaneous:
case InferiorExitOk:
case InferiorShutdownRequested: case InferiorShutdownRequested:
case InferiorShutdownOk: case InferiorShutdownOk:
case InferiorShutdownFailed: case InferiorShutdownFailed:
@@ -1150,7 +1233,7 @@ void DebuggerEngine::progressPing()
DebuggerRunControl *DebuggerEngine::runControl() const DebuggerRunControl *DebuggerEngine::runControl() const
{ {
return d->m_runControl; return d->runControl();
} }
void DebuggerEngine::setToolTipExpression void DebuggerEngine::setToolTipExpression
@@ -1305,21 +1388,21 @@ void DebuggerEngine::attemptBreakpointSynchronization()
void DebuggerEngine::insertBreakpoint(BreakpointId id) void DebuggerEngine::insertBreakpoint(BreakpointId id)
{ {
BreakpointState state = breakHandler()->state(id); BreakpointState state = breakHandler()->state(id);
QTC_ASSERT(state == BreakpointInsertRequested, qDebug() << state); QTC_ASSERT(state == BreakpointInsertRequested, qDebug() << id << this << state);
QTC_ASSERT(false, /**/); QTC_ASSERT(false, /**/);
} }
void DebuggerEngine::removeBreakpoint(BreakpointId id) void DebuggerEngine::removeBreakpoint(BreakpointId id)
{ {
BreakpointState state = breakHandler()->state(id); BreakpointState state = breakHandler()->state(id);
QTC_ASSERT(state == BreakpointRemoveRequested, qDebug() << state); QTC_ASSERT(state == BreakpointRemoveRequested, qDebug() << id << this << state);
QTC_ASSERT(false, /**/); QTC_ASSERT(false, /**/);
} }
void DebuggerEngine::changeBreakpoint(BreakpointId id) void DebuggerEngine::changeBreakpoint(BreakpointId id)
{ {
BreakpointState state = breakHandler()->state(id); BreakpointState state = breakHandler()->state(id);
QTC_ASSERT(state == BreakpointChangeRequested, qDebug() << state); QTC_ASSERT(state == BreakpointChangeRequested, qDebug() << id << this << state);
QTC_ASSERT(false, /**/); QTC_ASSERT(false, /**/);
} }
@@ -1511,6 +1594,16 @@ void DebuggerEngine::handleRemoteSetupFailed(const QString &message)
Q_UNUSED(message); Q_UNUSED(message);
} }
bool DebuggerEngine::isStateDebugging() const
{
return d->m_isStateDebugging;
}
void DebuggerEngine::setStateDebugging(bool on)
{
d->m_isStateDebugging = on;
}
} // namespace Debugger } // namespace Debugger
#include "debuggerengine.moc" #include "debuggerengine.moc"

View File

@@ -241,6 +241,7 @@ public:
virtual void updateViews(); virtual void updateViews();
bool isSlaveEngine() const; bool isSlaveEngine() const;
bool isMasterEngine() const;
DebuggerEngine *masterEngine() const; DebuggerEngine *masterEngine() const;
signals: signals:
@@ -320,7 +321,7 @@ protected:
virtual void frameUp(); virtual void frameUp();
virtual void frameDown(); virtual void frameDown();
DebuggerRunControl *runControl() const; // FIXME: Protect. DebuggerRunControl *runControl() const;
static QString msgWatchpointTriggered(BreakpointId id, static QString msgWatchpointTriggered(BreakpointId id,
int number, quint64 address); int number, quint64 address);
@@ -338,12 +339,18 @@ protected:
static bool isCppBreakpoint(const Internal::BreakpointParameters &p); static bool isCppBreakpoint(const Internal::BreakpointParameters &p);
bool isStateDebugging() const;
void setStateDebugging(bool on);
private: private:
// Wrapper engine needs access to state of its subengines. // Wrapper engine needs access to state of its subengines.
friend class Internal::QmlCppEngine; friend class Internal::QmlCppEngine;
friend class Internal::DebuggerPluginPrivate; friend class Internal::DebuggerPluginPrivate;
void setState(DebuggerState state, bool forced = false); virtual void setState(DebuggerState state, bool forced = false);
virtual void setSilentState(DebuggerState state);
virtual void slaveEngineStateChanged(DebuggerEngine *engine,
DebuggerState state);
friend class DebuggerEnginePrivate; friend class DebuggerEnginePrivate;
DebuggerEnginePrivate *d; DebuggerEnginePrivate *d;

View File

@@ -141,7 +141,10 @@ static bool stateAcceptsGdbCommands(DebuggerState state)
return true; return true;
case DebuggerNotReady: case DebuggerNotReady:
case InferiorStopFailed: case InferiorStopFailed:
case InferiorStopSpontaneous:
case InferiorSetupOk:
case EngineRunFailed: case EngineRunFailed:
case EngineRunOk:
case InferiorRunFailed: case InferiorRunFailed:
case EngineShutdownOk: case EngineShutdownOk:
case EngineShutdownFailed: case EngineShutdownFailed:

View File

@@ -5,9 +5,12 @@
#include "debuggercore.h" #include "debuggercore.h"
#include <qmljseditor/qmljseditorconstants.h> #include <qmljseditor/qmljseditorconstants.h>
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h> #include <coreplugin/editormanager/ieditor.h>
#include <utils/qtcassert.h>
#include <QtCore/QTimer> #include <QtCore/QTimer>
namespace Debugger { namespace Debugger {
@@ -42,14 +45,12 @@ private:
DebuggerEngine *m_qmlEngine; DebuggerEngine *m_qmlEngine;
DebuggerEngine *m_cppEngine; DebuggerEngine *m_cppEngine;
DebuggerEngine *m_activeEngine; DebuggerEngine *m_activeEngine;
DebuggerState m_errorState;
}; };
QmlCppEnginePrivate::QmlCppEnginePrivate() QmlCppEnginePrivate::QmlCppEnginePrivate()
: m_qmlEngine(0), : m_qmlEngine(0),
m_cppEngine(0), m_cppEngine(0),
m_activeEngine(0), m_activeEngine(0)
m_errorState(InferiorRunOk)
{} {}
@@ -70,10 +71,12 @@ QmlCppEngine::QmlCppEngine(const DebuggerStartParameters &sp)
} }
d->m_activeEngine = d->m_cppEngine; d->m_activeEngine = d->m_cppEngine;
connect(d->m_cppEngine, SIGNAL(stateChanged(DebuggerState)),
SLOT(slaveEngineStateChanged(DebuggerState))); if (1) {
connect(d->m_qmlEngine, SIGNAL(stateChanged(DebuggerState)), setStateDebugging(true);
SLOT(slaveEngineStateChanged(DebuggerState))); d->m_cppEngine->setStateDebugging(true);
d->m_qmlEngine->setStateDebugging(true);
}
} }
QmlCppEngine::~QmlCppEngine() QmlCppEngine::~QmlCppEngine()
@@ -217,61 +220,66 @@ void QmlCppEngine::detachDebugger()
void QmlCppEngine::executeStep() void QmlCppEngine::executeStep()
{ {
notifyInferiorRunRequested();
d->m_activeEngine->executeStep(); d->m_activeEngine->executeStep();
} }
void QmlCppEngine::executeStepOut() void QmlCppEngine::executeStepOut()
{ {
notifyInferiorRunRequested();
d->m_activeEngine->executeStepOut(); d->m_activeEngine->executeStepOut();
} }
void QmlCppEngine::executeNext() void QmlCppEngine::executeNext()
{ {
notifyInferiorRunRequested();
d->m_activeEngine->executeNext(); d->m_activeEngine->executeNext();
} }
void QmlCppEngine::executeStepI() void QmlCppEngine::executeStepI()
{ {
notifyInferiorRunRequested();
d->m_activeEngine->executeStepI(); d->m_activeEngine->executeStepI();
} }
void QmlCppEngine::executeNextI() void QmlCppEngine::executeNextI()
{ {
notifyInferiorRunRequested();
d->m_activeEngine->executeNextI(); d->m_activeEngine->executeNextI();
} }
void QmlCppEngine::executeReturn() void QmlCppEngine::executeReturn()
{ {
notifyInferiorRunRequested();
d->m_activeEngine->executeReturn(); d->m_activeEngine->executeReturn();
} }
void QmlCppEngine::continueInferior() void QmlCppEngine::continueInferior()
{ {
if (d->m_activeEngine->state() == InferiorStopOk) { qDebug() << "\nMASTER CONTINUE INFERIOR"
d->m_activeEngine->continueInferior(); << d->m_cppEngine->state() << d->m_qmlEngine->state();
} else {
notifyInferiorRunRequested(); notifyInferiorRunRequested();
if (d->m_cppEngine->state() == InferiorStopOk) {
d->m_cppEngine->continueInferior();
} else if (d->m_qmlEngine->state() == InferiorStopOk) {
d->m_qmlEngine->continueInferior();
} else {
QTC_ASSERT(false, qDebug() << "MASTER CANNOT CONTINUE INFERIOR"
<< d->m_cppEngine->state() << d->m_qmlEngine->state());
notifyEngineIll();
} }
} }
void QmlCppEngine::interruptInferior() void QmlCppEngine::interruptInferior()
{ {
if (d->m_activeEngine->state() == InferiorRunOk) { qDebug() << "\nMASTER INTERRUPT INFERIOR";
d->m_activeEngine->requestInterruptInferior();
} else {
if (d->m_activeEngine->state() == InferiorStopOk && (!checkErrorState(InferiorStopFailed))) {
notifyInferiorStopOk();
}
}
} }
void QmlCppEngine::requestInterruptInferior() void QmlCppEngine::requestInterruptInferior()
{ {
qDebug() << "\nMASTER REQUEST INTERUPT INFERIOR";
DebuggerEngine::requestInterruptInferior(); DebuggerEngine::requestInterruptInferior();
d->m_cppEngine->requestInterruptInferior();
if (d->m_activeEngine->state() == InferiorRunOk) {
d->m_activeEngine->requestInterruptInferior();
}
} }
void QmlCppEngine::executeRunToLine(const QString &fileName, int lineNumber) void QmlCppEngine::executeRunToLine(const QString &fileName, int lineNumber)
@@ -306,240 +314,264 @@ void QmlCppEngine::frameDown()
///////////////////////////////////////////////////////// /////////////////////////////////////////////////////////
bool QmlCppEngine::checkErrorState(const DebuggerState stateToCheck) void QmlCppEngine::setupEngine()
{ {
if (d->m_errorState != stateToCheck) qDebug() << "\nMASTER SETUP ENGINE";
return false; QTC_ASSERT(d->m_cppEngine->state() == DebuggerNotReady, /**/);
QTC_ASSERT(d->m_qmlEngine->state() == DebuggerNotReady, /**/);
// reset state ( so that more than one error can accumulate over time ) d->m_qmlEngine->setSilentState(EngineSetupRequested);
d->m_errorState = InferiorRunOk; d->m_cppEngine->setSilentState(EngineSetupRequested);
switch (stateToCheck) { d->m_qmlEngine->setupEngine(); // Always succeeds.
case InferiorRunOk: d->m_cppEngine->setupEngine(); // May fail.
// nothing to do
break;
case EngineRunFailed:
notifyEngineRunFailed();
break;
case EngineSetupFailed:
notifyEngineSetupFailed();
break;
case EngineShutdownFailed:
notifyEngineShutdownFailed();
break;
case InferiorSetupFailed:
notifyInferiorSetupFailed();
break;
case InferiorRunFailed:
notifyInferiorRunFailed();
break;
case InferiorUnrunnable:
notifyInferiorUnrunnable();
break;
case InferiorStopFailed:
notifyInferiorStopFailed();
break;
case InferiorShutdownFailed:
notifyInferiorShutdownFailed();
break;
default:
// unexpected
break;
} }
return true;
void QmlCppEngine::notifyEngineRunAndInferiorRunOk()
{
qDebug() << "\nMASTER NOTIFY ENGINE RUN AND INFERIOR RUN OK";
DebuggerEngine::notifyEngineRunAndInferiorRunOk();
} }
void QmlCppEngine::notifyInferiorRunOk() void QmlCppEngine::notifyInferiorRunOk()
{ {
qDebug() << "\nMASTER NOTIFY INFERIOR RUN OK";
DebuggerEngine::notifyInferiorRunOk(); DebuggerEngine::notifyInferiorRunOk();
} }
void QmlCppEngine::setupEngine() void QmlCppEngine::notifyInferiorSpontaneousStop()
{ {
d->m_cppEngine->startDebugger(runControl()); qDebug() << "\nMASTER SPONTANEOUS STOP OK";
DebuggerEngine::notifyInferiorSpontaneousStop();
}
void QmlCppEngine::notifyInferiorShutdownOk()
{
qDebug() << "\nMASTER INFERIOR SHUTDOWN OK";
DebuggerEngine::notifyInferiorShutdownOk();
} }
void QmlCppEngine::setupInferior() void QmlCppEngine::setupInferior()
{ {
if (!checkErrorState(InferiorSetupFailed)) { qDebug() << "\nMASTER SETUP INFERIOR";
notifyInferiorSetupOk(); QTC_ASSERT(d->m_cppEngine->state() == EngineSetupOk, /**/);
} QTC_ASSERT(d->m_qmlEngine->state() == EngineSetupOk, /**/);
d->m_qmlEngine->setSilentState(InferiorSetupRequested);
d->m_cppEngine->setSilentState(InferiorSetupRequested);
d->m_cppEngine->setupInferior();
d->m_qmlEngine->setupInferior();
} }
void QmlCppEngine::runEngine() void QmlCppEngine::runEngine()
{ {
if (!checkErrorState(EngineRunFailed)) { qDebug() << "\nMASTER RUN ENGINE";
if (d->m_errorState == InferiorRunOk) { QTC_ASSERT(d->m_cppEngine->state() == InferiorSetupOk, /**/);
switch (d->m_activeEngine->state()) { QTC_ASSERT(d->m_qmlEngine->state() == InferiorSetupOk, /**/);
case InferiorRunOk: d->m_qmlEngine->setSilentState(EngineRunRequested);
notifyEngineRunAndInferiorRunOk(); d->m_cppEngine->setSilentState(EngineRunRequested);
break; d->m_cppEngine->runEngine();
case InferiorStopOk: d->m_qmlEngine->runEngine();
notifyEngineRunAndInferiorStopOk();
break;
default: // not supported?
notifyEngineRunFailed();
break;
}
} else {
notifyEngineRunFailed();
}
}
} }
void QmlCppEngine::shutdownInferior() void QmlCppEngine::shutdownInferior()
{ {
if (!checkErrorState(InferiorShutdownFailed)) { qDebug() << "\nMASTER SHUTDOWN INFERIOR";
if (d->m_cppEngine->state() == InferiorStopOk) {
d->m_cppEngine->quitDebugger();
} else {
notifyInferiorShutdownOk();
}
}
}
void QmlCppEngine::initEngineShutdown()
{
if (d->m_qmlEngine->state() != DebuggerFinished) {
d->m_qmlEngine->quitDebugger(); d->m_qmlEngine->quitDebugger();
} else
if (d->m_cppEngine->state() != DebuggerFinished) {
d->m_cppEngine->quitDebugger();
} else
if (state() == EngineSetupRequested) {
if (!runControl() || d->m_errorState == EngineSetupFailed) {
notifyEngineSetupFailed();
} else {
notifyEngineSetupOk();
}
} else
if (state() == InferiorStopRequested) {
checkErrorState(InferiorStopFailed);
} else
if (state() == InferiorShutdownRequested && !checkErrorState(InferiorShutdownFailed)) {
notifyInferiorShutdownOk();
} else
if (state() != DebuggerFinished) {
quitDebugger();
}
} }
void QmlCppEngine::shutdownEngine() void QmlCppEngine::shutdownEngine()
{ {
if (!checkErrorState(EngineShutdownFailed)) { qDebug() << "\nMASTER SHUTDOWN ENGINE";
showStatusMessage(tr("Debugging finished")); QTC_ASSERT(d->m_cppEngine->state() == InferiorShutdownOk, /**/);
notifyEngineShutdownOk(); QTC_ASSERT(d->m_qmlEngine->state() == InferiorShutdownOk, /**/);
} d->m_qmlEngine->setSilentState(EngineShutdownRequested);
d->m_cppEngine->setSilentState(EngineShutdownRequested);
d->m_qmlEngine->shutdownEngine();
d->m_cppEngine->shutdownEngine();
} }
void QmlCppEngine::setupSlaveEngine() void QmlCppEngine::setState(DebuggerState newState, bool forced)
{ {
if (d->m_qmlEngine->state() == DebuggerNotReady) qDebug() << "SET MASTER STATE: " << newState;
d->m_qmlEngine->startDebugger(runControl()); qDebug() << " CPP STATE: " << d->m_cppEngine->state();
qDebug() << " QML STATE: " << d->m_qmlEngine->state();
DebuggerEngine::setState(newState, forced);
} }
void QmlCppEngine::slaveEngineStateChanged(const DebuggerState newState) void QmlCppEngine::slaveEngineStateChanged
(DebuggerEngine *slaveEngine, const DebuggerState newState)
{ {
DebuggerEngine *slaveEngine = qobject_cast<DebuggerEngine *>(sender()); const bool isCpp = slaveEngine == d->m_cppEngine;
if (newState == InferiorStopOk && slaveEngine != d->m_activeEngine) { //const bool isQml = slaveEngine == d->m_qmlEngine;
QString engineName = slaveEngine == d->m_cppEngine DebuggerEngine *otherEngine = isCpp ? d->m_qmlEngine : d->m_cppEngine;
? QLatin1String("C++") : QLatin1String("QML");
showStatusMessage(tr("%1 debugger activated").arg(engineName)); qDebug() << "GOT SLAVE STATE: " << slaveEngine << newState;
d->m_activeEngine = d->m_qmlEngine; qDebug() << " OTHER ENGINE: " << otherEngine << otherEngine->state();
} qDebug() << " COMBINED ENGINE: " << this << state() << isDying();
switch (newState) { switch (newState) {
case InferiorRunOk:
// startup? case DebuggerNotReady:
if (d->m_qmlEngine->state() == DebuggerNotReady) { case InferiorUnrunnable:
setupSlaveEngine(); break;
} else
if (d->m_cppEngine->state() == DebuggerNotReady) { case EngineSetupRequested:
setupEngine(); break;
} else
if (state() == EngineSetupRequested) { case EngineSetupFailed:
notifyEngineSetupFailed();
break;
case EngineSetupOk:
if (otherEngine->state() == EngineSetupOk)
notifyEngineSetupOk(); notifyEngineSetupOk();
} else else
// breakpoint? qDebug() << "... WAITING FOR OTHER ENGINE SETUP...";
if (state() == InferiorStopOk) { break;
continueInferior();
} else
if (state() == InferiorStopRequested) { case InferiorSetupRequested:
checkErrorState(InferiorStopFailed); break;
} else
if (state() == InferiorRunRequested && (!checkErrorState(InferiorRunFailed)) && (!checkErrorState(InferiorUnrunnable))) { case InferiorSetupFailed:
notifyInferiorRunOk(); notifyInferiorSetupFailed();
break;
case InferiorSetupOk:
if (otherEngine->state() == InferiorSetupOk)
notifyInferiorSetupOk();
else
qDebug() << "... WAITING FOR OTHER INFERIOR SETUP...";
break;
case EngineRunRequested:
break;
case EngineRunFailed:
notifyEngineRunFailed();
break;
case EngineRunOk:
if (otherEngine->state() == EngineRunOk) {
// This is conditionalized on isMasterEngine() in the
// base class, so do it here manually.
slaveEngine->setSilentState(InferiorRunOk);
otherEngine->setSilentState(InferiorRunOk);
notifyEngineRunAndInferiorRunOk();
} else {
qDebug() << "... WAITING FOR OTHER ENGINE RUN...";
} }
break; break;
case InferiorRunRequested: case InferiorRunRequested:
// follow the inferior break;
if (state() == InferiorStopOk && checkErrorState(InferiorRunOk)) {
continueInferior(); case InferiorRunFailed:
notifyInferiorRunFailed();
break;
case InferiorRunOk:
qDebug() << "PLANNED INFERIOR RUN";
if (otherEngine->state() == InferiorRunOk)
notifyInferiorRunOk();
else
qDebug() << " **** INFERIOR RUN NOT OK ****";
break;
case InferiorStopSpontaneous:
notifyInferiorSpontaneousStop();
slaveEngine->setSilentState(InferiorStopOk);
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;
} }
break; break;
case InferiorStopRequested: case InferiorStopRequested:
// follow the inferior break;
if (state() == InferiorRunOk && checkErrorState(InferiorRunOk)) {
requestInterruptInferior(); case InferiorStopFailed:
} notifyInferiorStopFailed();
break; break;
case InferiorStopOk: case InferiorStopOk:
// check breakpoints if (isDying()) {
if (state() == InferiorRunRequested) { qDebug() << "... AN INFERIOR STOPPED DURING SHUTDOWN ";
checkErrorState(InferiorRunFailed); } else {
} else if (otherEngine->state() == InferiorShutdownOk) {
if (checkErrorState(InferiorRunOk)) { qDebug() << "... STOPP ";
if (state() == InferiorRunOk) { } else if (state() == InferiorStopRequested) {
requestInterruptInferior(); qDebug() << "... AN INFERIOR STOPPED EXPECTEDLY";
} else notifyInferiorStopOk();
if (state() == InferiorStopRequested) { } else {
interruptInferior(); qDebug() << "... AN INFERIOR STOPPED UNEXPECTEDLY";
notifyInferiorSpontaneousStop();
} }
} }
break; break;
case EngineRunFailed:
case EngineSetupFailed: case InferiorExitOk:
case EngineShutdownFailed: slaveEngine->setSilentState(InferiorShutdownOk);
case InferiorSetupFailed: if (otherEngine->state() == InferiorShutdownOk) {
case InferiorRunFailed: notifyInferiorExited();
case InferiorUnrunnable: } else {
case InferiorStopFailed: if (state() == InferiorRunOk)
case InferiorShutdownFailed: notifyInferiorSpontaneousStop();
if (d->m_errorState == InferiorRunOk) { otherEngine->notifyInferiorExited();
d->m_errorState = newState;
} }
break; break;
case InferiorShutdownRequested: case InferiorShutdownRequested:
break; break;
case EngineShutdownRequested: case InferiorShutdownFailed:
// we have to abort the setup before the sub-engines die notifyInferiorShutdownFailed();
// because we depend on an active runcontrol that will be shut down by the dying engine
if (state() == EngineSetupRequested)
notifyEngineSetupFailed();
break; break;
case InferiorShutdownOk:
if (otherEngine->state() == InferiorShutdownOk)
notifyInferiorShutdownOk();
else if (otherEngine->state() == InferiorRunOk)
otherEngine->quitDebugger();
else if (otherEngine->state() == InferiorStopOk)
otherEngine->quitDebugger();
break;
case EngineShutdownRequested:
break;
case EngineShutdownFailed:
notifyEngineShutdownFailed();
break;
case EngineShutdownOk:
if (otherEngine->state() == EngineShutdownOk)
notifyEngineShutdownOk();
else
qDebug() << "... WAITING FOR OTHER ENGINE SHUTDOWN...";
break;
case DebuggerFinished: case DebuggerFinished:
initEngineShutdown();
break;
default:
break; break;
} }
} }
void QmlCppEngine::handleRemoteSetupDone(int gdbServerPort, int qmlPort) void QmlCppEngine::handleRemoteSetupDone(int gdbServerPort, int qmlPort)
{ {
//qDebug() << "MASETER REMOTE SETUP DONE";
d->m_qmlEngine->handleRemoteSetupDone(gdbServerPort, qmlPort); d->m_qmlEngine->handleRemoteSetupDone(gdbServerPort, qmlPort);
d->m_cppEngine->handleRemoteSetupDone(gdbServerPort, qmlPort); d->m_cppEngine->handleRemoteSetupDone(gdbServerPort, qmlPort);
} }
void QmlCppEngine::handleRemoteSetupFailed(const QString &message) void QmlCppEngine::handleRemoteSetupFailed(const QString &message)
{ {
//qDebug() << "MASETER REMOTE SETUP FAILED";
d->m_qmlEngine->handleRemoteSetupFailed(message); d->m_qmlEngine->handleRemoteSetupFailed(message);
d->m_cppEngine->handleRemoteSetupFailed(message); d->m_cppEngine->handleRemoteSetupFailed(message);
} }

View File

@@ -16,86 +16,83 @@ class DEBUGGER_EXPORT QmlCppEngine : public DebuggerEngine
public: public:
explicit QmlCppEngine(const DebuggerStartParameters &sp); explicit QmlCppEngine(const DebuggerStartParameters &sp);
virtual ~QmlCppEngine(); ~QmlCppEngine();
virtual void setToolTipExpression(const QPoint &mousePos, void setToolTipExpression(const QPoint &mousePos,
TextEditor::ITextEditor * editor, int cursorPos); TextEditor::ITextEditor * editor, int cursorPos);
virtual void updateWatchData(const WatchData &data, void updateWatchData(const WatchData &data,
const WatchUpdateFlags &flags); const WatchUpdateFlags &flags);
virtual void watchPoint(const QPoint &); void watchPoint(const QPoint &);
virtual void fetchMemory(MemoryAgent *, QObject *, void fetchMemory(MemoryAgent *, QObject *, quint64 addr, quint64 length);
quint64 addr, quint64 length); void fetchDisassembler(DisassemblerAgent *);
virtual void fetchDisassembler(DisassemblerAgent *); void activateFrame(int index);
virtual void activateFrame(int index);
virtual void reloadModules(); void reloadModules();
virtual void examineModules(); void examineModules();
virtual void loadSymbols(const QString &moduleName); void loadSymbols(const QString &moduleName);
virtual void loadAllSymbols(); void loadAllSymbols();
virtual void requestModuleSymbols(const QString &moduleName); void requestModuleSymbols(const QString &moduleName);
virtual void reloadRegisters(); void reloadRegisters();
virtual void reloadSourceFiles(); void reloadSourceFiles();
virtual void reloadFullStack(); void reloadFullStack();
virtual void setRegisterValue(int regnr, const QString &value); void setRegisterValue(int regnr, const QString &value);
virtual unsigned debuggerCapabilities() const; unsigned debuggerCapabilities() const;
virtual bool isSynchronous() const; bool isSynchronous() const;
virtual QByteArray qtNamespace() const; QByteArray qtNamespace() const;
virtual void createSnapshot(); void createSnapshot();
virtual void updateAll(); void updateAll();
virtual void attemptBreakpointSynchronization(); void attemptBreakpointSynchronization();
virtual bool acceptsBreakpoint(BreakpointId id) const; bool acceptsBreakpoint(BreakpointId id) const;
virtual void selectThread(int index); void selectThread(int index);
virtual void assignValueInDebugger(const WatchData *data, void assignValueInDebugger(const WatchData *data,
const QString &expr, const QVariant &value); const QString &expr, const QVariant &value);
DebuggerEngine *cppEngine() const; DebuggerEngine *cppEngine() const;
virtual void handleRemoteSetupDone(int gdbServerPort, int qmlPort); void handleRemoteSetupDone(int gdbServerPort, int qmlPort);
virtual void handleRemoteSetupFailed(const QString &message); void handleRemoteSetupFailed(const QString &message);
protected: protected:
virtual void detachDebugger(); void detachDebugger();
virtual void executeStep(); void executeStep();
virtual void executeStepOut(); void executeStepOut();
virtual void executeNext(); void executeNext();
virtual void executeStepI(); void executeStepI();
virtual void executeNextI(); void executeNextI();
virtual void executeReturn(); void executeReturn();
virtual void continueInferior(); void continueInferior();
virtual void interruptInferior(); void interruptInferior();
virtual void requestInterruptInferior(); void requestInterruptInferior();
virtual void executeRunToLine(const QString &fileName, int lineNumber); void executeRunToLine(const QString &fileName, int lineNumber);
virtual void executeRunToFunction(const QString &functionName); void executeRunToFunction(const QString &functionName);
virtual void executeJumpToLine(const QString &fileName, int lineNumber); void executeJumpToLine(const QString &fileName, int lineNumber);
virtual void executeDebuggerCommand(const QString &command); void executeDebuggerCommand(const QString &command);
virtual void frameUp(); void frameUp();
virtual void frameDown(); void frameDown();
virtual void notifyInferiorRunOk(); void setupEngine();
void setupInferior();
void runEngine();
void shutdownInferior();
void shutdownEngine();
protected: void notifyInferiorRunOk();
virtual void setupEngine(); void notifyInferiorSpontaneousStop();
virtual void setupInferior(); void notifyEngineRunAndInferiorRunOk();
virtual void runEngine(); void notifyInferiorShutdownOk();
virtual void shutdownInferior();
virtual void shutdownEngine();
private slots:
void slaveEngineStateChanged(DebuggerState state);
void setupSlaveEngine();
private: private:
void initEngineShutdown();
bool checkErrorState(DebuggerState stateToCheck);
void engineStateChanged(DebuggerState newState); void engineStateChanged(DebuggerState newState);
void setState(DebuggerState newState, bool forced = false);
void slaveEngineStateChanged(DebuggerEngine *slaveEngine, DebuggerState state);
private: private:
QScopedPointer<QmlCppEnginePrivate> d; QScopedPointer<QmlCppEnginePrivate> d;

View File

@@ -675,7 +675,8 @@ void QmlEngine::messageReceived(const QByteArray &message)
stream >> command; stream >> command;
if (command == "STOPPED") { if (command == "STOPPED") {
if (state() == InferiorRunOk) qDebug() << command << this << state();
if (state() == InferiorRunOk || state() == EngineRunOk)
notifyInferiorSpontaneousStop(); notifyInferiorSpontaneousStop();
QString logString = QString(command); QString logString = QString(command);