Commit e760700f authored by hjk's avatar hjk

debugger: overhaul "state machine"

This mainly allows for more precise shutdown and tightens the set
of allowed transitions.
parent 6089bc1b
...@@ -232,9 +232,14 @@ void CdbEngine::setState(DebuggerState state, const char *func, int line) ...@@ -232,9 +232,14 @@ void CdbEngine::setState(DebuggerState state, const char *func, int line)
DebuggerEngine::setState(state); DebuggerEngine::setState(state);
} }
void CdbEngine::shutdown() void CdbEngine::shutdownInferior()
{ {
exitDebugger(); notifyInferiorShutdownOk();
}
void CdbEngine::shutdownEngine()
{
m_d->endDebugging();
} }
QString CdbEngine::editorToolTip(const QString &exp, const QString &function) QString CdbEngine::editorToolTip(const QString &exp, const QString &function)
...@@ -376,7 +381,7 @@ void CdbEngine::startupChecks() ...@@ -376,7 +381,7 @@ void CdbEngine::startupChecks()
void CdbEngine::setupEngine() void CdbEngine::setupEngine()
{ {
QTC_ASSERT(state() == EngineSettingUp, qDebug() << state()); QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
const DebuggerStartParameters &sp = startParameters(); const DebuggerStartParameters &sp = startParameters();
if (debugCDBExecution) if (debugCDBExecution)
qDebug() << "startDebugger"; qDebug() << "startDebugger";
...@@ -426,7 +431,7 @@ void CdbEngine::setupEngine() ...@@ -426,7 +431,7 @@ void CdbEngine::setupEngine()
void CdbEngine::setupInferior() void CdbEngine::setupInferior()
{ {
QTC_ASSERT(state() == InferiorSettingUp, qDebug() << state()); QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
notifyInferiorSetupOk(); notifyInferiorSetupOk();
} }
...@@ -499,7 +504,7 @@ bool CdbEngine::startAttachDebugger(qint64 pid, DebuggerStartMode sm, QString *e ...@@ -499,7 +504,7 @@ bool CdbEngine::startAttachDebugger(qint64 pid, DebuggerStartMode sm, QString *e
void CdbEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG64 initialThreadHandle) void CdbEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG64 initialThreadHandle)
{ {
m_engine->setState(InferiorRunningRequested, Q_FUNC_INFO, __LINE__); m_engine->setState(InferiorRunRequested, Q_FUNC_INFO, __LINE__);
setDebuggeeHandles(reinterpret_cast<HANDLE>(processHandle), reinterpret_cast<HANDLE>(initialThreadHandle)); setDebuggeeHandles(reinterpret_cast<HANDLE>(processHandle), reinterpret_cast<HANDLE>(initialThreadHandle));
ULONG currentThreadId; ULONG currentThreadId;
if (SUCCEEDED(interfaces().debugSystemObjects->GetThreadIdByHandle(initialThreadHandle, &currentThreadId))) { if (SUCCEEDED(interfaces().debugSystemObjects->GetThreadIdByHandle(initialThreadHandle, &currentThreadId))) {
...@@ -526,7 +531,7 @@ void CdbEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG64 ini ...@@ -526,7 +531,7 @@ void CdbEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG64 ini
m_engine->warning(QString::fromLatin1("Handshake failed on event #%1: %2").arg(evtNr).arg(CdbCore::msgComFailed("SetNotifyEventHandle", hr))); m_engine->warning(QString::fromLatin1("Handshake failed on event #%1: %2").arg(evtNr).arg(CdbCore::msgComFailed("SetNotifyEventHandle", hr)));
} }
} }
m_engine->setState(InferiorRunning, Q_FUNC_INFO, __LINE__); m_engine->setState(InferiorRunOk, Q_FUNC_INFO, __LINE__);
if (debugCDBExecution) if (debugCDBExecution)
qDebug() << "<processCreatedAttached"; qDebug() << "<processCreatedAttached";
} }
...@@ -534,13 +539,13 @@ void CdbEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG64 ini ...@@ -534,13 +539,13 @@ void CdbEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG64 ini
void CdbEngine::processTerminated(unsigned long exitCode) void CdbEngine::processTerminated(unsigned long exitCode)
{ {
showMessage(tr("The process exited with exit code %1.").arg(exitCode)); showMessage(tr("The process exited with exit code %1.").arg(exitCode));
if (state() != InferiorStopping) if (state() != InferiorStopRequested)
setState(InferiorStopping, Q_FUNC_INFO, __LINE__); setState(InferiorStopRequested, Q_FUNC_INFO, __LINE__);
setState(InferiorStopped, Q_FUNC_INFO, __LINE__); setState(InferiorStopOk, Q_FUNC_INFO, __LINE__);
setState(InferiorShuttingDown, Q_FUNC_INFO, __LINE__); setState(InferiorShutdownRequested, Q_FUNC_INFO, __LINE__);
m_d->setDebuggeeHandles(0, 0); m_d->setDebuggeeHandles(0, 0);
m_d->clearForRun(); m_d->clearForRun();
setState(InferiorShutDown, Q_FUNC_INFO, __LINE__); setState(InferiorShutdownOk, Q_FUNC_INFO, __LINE__);
// Avoid calls from event handler. // Avoid calls from event handler.
QTimer::singleShot(0, this, SLOT(quitDebugger())); QTimer::singleShot(0, this, SLOT(quitDebugger()));
} }
...@@ -548,7 +553,7 @@ void CdbEngine::processTerminated(unsigned long exitCode) ...@@ -548,7 +553,7 @@ void CdbEngine::processTerminated(unsigned long exitCode)
bool CdbEnginePrivate::endInferior(EndInferiorAction action, QString *errorMessage) bool CdbEnginePrivate::endInferior(EndInferiorAction action, QString *errorMessage)
{ {
// Process must be stopped in order to terminate // Process must be stopped in order to terminate
m_engine->setState(InferiorShuttingDown, Q_FUNC_INFO, __LINE__); // pretend it is shutdown m_engine->setState(InferiorShutdownRequested, Q_FUNC_INFO, __LINE__); // pretend it is shutdown
const bool wasRunning = isDebuggeeRunning(); const bool wasRunning = isDebuggeeRunning();
if (wasRunning) { if (wasRunning) {
interruptInterferiorProcess(errorMessage); interruptInterferiorProcess(errorMessage);
...@@ -577,7 +582,7 @@ bool CdbEnginePrivate::endInferior(EndInferiorAction action, QString *errorMessa ...@@ -577,7 +582,7 @@ bool CdbEnginePrivate::endInferior(EndInferiorAction action, QString *errorMessa
// Perform cleanup even when failed..no point clinging to the process // Perform cleanup even when failed..no point clinging to the process
setDebuggeeHandles(0, 0); setDebuggeeHandles(0, 0);
killWatchTimer(); killWatchTimer();
m_engine->setState(success ? InferiorShutDown : InferiorShutdownFailed, Q_FUNC_INFO, __LINE__); m_engine->setState(success ? InferiorShutdownOk : InferiorShutdownFailed, Q_FUNC_INFO, __LINE__);
return success; return success;
} }
...@@ -594,7 +599,7 @@ void CdbEnginePrivate::endDebugging(EndDebuggingMode em) ...@@ -594,7 +599,7 @@ void CdbEnginePrivate::endDebugging(EndDebuggingMode em)
return; return;
// Do we need to stop the process? // Do we need to stop the process?
QString errorMessage; QString errorMessage;
if (oldState != InferiorShutDown && m_hDebuggeeProcess) { if (oldState != InferiorShutdownOk && m_hDebuggeeProcess) {
EndInferiorAction action; EndInferiorAction action;
switch (em) { switch (em) {
case EndDebuggingAuto: case EndDebuggingAuto:
...@@ -618,7 +623,7 @@ void CdbEnginePrivate::endDebugging(EndDebuggingMode em) ...@@ -618,7 +623,7 @@ void CdbEnginePrivate::endDebugging(EndDebuggingMode em)
errorMessage.clear(); errorMessage.clear();
} }
// Clean up resources (open files, etc.) // Clean up resources (open files, etc.)
m_engine->setState(EngineShuttingDown, Q_FUNC_INFO, __LINE__); m_engine->setState(EngineShutdownRequested, Q_FUNC_INFO, __LINE__);
clearForRun(); clearForRun();
const bool endedCleanly = endSession(&errorMessage); const bool endedCleanly = endSession(&errorMessage);
m_engine->setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__); m_engine->setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__);
...@@ -628,11 +633,6 @@ void CdbEnginePrivate::endDebugging(EndDebuggingMode em) ...@@ -628,11 +633,6 @@ void CdbEnginePrivate::endDebugging(EndDebuggingMode em)
} }
} }
void CdbEngine::exitDebugger()
{
m_d->endDebugging();
}
void CdbEngine::detachDebugger() void CdbEngine::detachDebugger()
{ {
m_d->endDebugging(CdbEnginePrivate::EndDebuggingDetach); m_d->endDebugging(CdbEnginePrivate::EndDebuggingDetach);
...@@ -712,15 +712,15 @@ bool CdbEnginePrivate::executeContinueCommand(const QString &command) ...@@ -712,15 +712,15 @@ bool CdbEnginePrivate::executeContinueCommand(const QString &command)
qDebug() << Q_FUNC_INFO << command; qDebug() << Q_FUNC_INFO << command;
clearForRun(); clearForRun();
updateCodeLevel(); // Step by instruction updateCodeLevel(); // Step by instruction
m_engine->setState(InferiorRunningRequested, Q_FUNC_INFO, __LINE__); m_engine->setState(InferiorRunRequested, Q_FUNC_INFO, __LINE__);
m_engine->showMessage(CdbEngine::tr("Continuing with '%1'...").arg(command)); m_engine->showMessage(CdbEngine::tr("Continuing with '%1'...").arg(command));
QString errorMessage; QString errorMessage;
const bool success = executeDebuggerCommand(command, &errorMessage); const bool success = executeDebuggerCommand(command, &errorMessage);
if (success) { if (success) {
m_engine->setState(InferiorRunning, Q_FUNC_INFO, __LINE__); m_engine->setState(InferiorRunOk, Q_FUNC_INFO, __LINE__);
startWatchTimer(); startWatchTimer();
} else { } else {
m_engine->setState(InferiorStopped, Q_FUNC_INFO, __LINE__); m_engine->setState(InferiorStopOk, Q_FUNC_INFO, __LINE__);
m_engine->warning(CdbEngine::tr("Unable to continue: %1").arg(errorMessage)); m_engine->warning(CdbEngine::tr("Unable to continue: %1").arg(errorMessage));
} }
return success; return success;
...@@ -772,7 +772,7 @@ bool CdbEngine::step(unsigned long executionStatus) ...@@ -772,7 +772,7 @@ bool CdbEngine::step(unsigned long executionStatus)
|| threadsHandler()->threads().size() == 1; || threadsHandler()->threads().size() == 1;
m_d->clearForRun(); // clears thread ids m_d->clearForRun(); // clears thread ids
m_d->updateCodeLevel(); // Step by instruction or source line m_d->updateCodeLevel(); // Step by instruction or source line
setState(InferiorRunningRequested, Q_FUNC_INFO, __LINE__); setState(InferiorRunRequested, Q_FUNC_INFO, __LINE__);
bool success = false; bool success = false;
if (sameThread && executionStatus != CdbExtendedExecutionStatusStepOut) { // Step event-triggering thread, use fast API if (sameThread && executionStatus != CdbExtendedExecutionStatusStepOut) { // Step event-triggering thread, use fast API
const HRESULT hr = m_d->interfaces().debugControl->SetExecutionStatus(executionStatus); const HRESULT hr = m_d->interfaces().debugControl->SetExecutionStatus(executionStatus);
...@@ -806,9 +806,9 @@ bool CdbEngine::step(unsigned long executionStatus) ...@@ -806,9 +806,9 @@ bool CdbEngine::step(unsigned long executionStatus)
if (executionStatus == DEBUG_STATUS_STEP_INTO || executionStatus == DEBUG_STATUS_REVERSE_STEP_INTO) if (executionStatus == DEBUG_STATUS_STEP_INTO || executionStatus == DEBUG_STATUS_REVERSE_STEP_INTO)
m_d->m_breakEventMode = CdbEnginePrivate::BreakEventIgnoreOnce; m_d->m_breakEventMode = CdbEnginePrivate::BreakEventIgnoreOnce;
m_d->startWatchTimer(); m_d->startWatchTimer();
setState(InferiorRunning, Q_FUNC_INFO, __LINE__); setState(InferiorRunOk, Q_FUNC_INFO, __LINE__);
} else { } else {
setState(InferiorStopped, Q_FUNC_INFO, __LINE__); setState(InferiorStopOk, Q_FUNC_INFO, __LINE__);
} }
if (debugCDBExecution) if (debugCDBExecution)
qDebug() << "<step samethread" << sameThread << "succeeded" << success; qDebug() << "<step samethread" << sameThread << "succeeded" << success;
...@@ -879,7 +879,7 @@ bool CdbEnginePrivate::continueInferior(QString *errorMessage) ...@@ -879,7 +879,7 @@ bool CdbEnginePrivate::continueInferior(QString *errorMessage)
return true; return true;
} }
// Request continue // Request continue
m_engine->setState(InferiorRunningRequested, Q_FUNC_INFO, __LINE__); m_engine->setState(InferiorRunRequested, Q_FUNC_INFO, __LINE__);
bool success = false; bool success = false;
do { do {
clearForRun(); clearForRun();
...@@ -895,9 +895,9 @@ bool CdbEnginePrivate::continueInferior(QString *errorMessage) ...@@ -895,9 +895,9 @@ bool CdbEnginePrivate::continueInferior(QString *errorMessage)
success = true; success = true;
} while (false); } while (false);
if (success) { if (success) {
m_engine->setState(InferiorRunning, Q_FUNC_INFO, __LINE__); m_engine->setState(InferiorRunOk, Q_FUNC_INFO, __LINE__);
} else { } else {
m_engine->setState(InferiorStopped, Q_FUNC_INFO, __LINE__); // No RunningRequestFailed? m_engine->setState(InferiorStopOk, Q_FUNC_INFO, __LINE__); // No RunningRequestFailed?
} }
return true; return true;
} }
...@@ -922,7 +922,7 @@ void CdbEnginePrivate::slotModulesLoaded() ...@@ -922,7 +922,7 @@ void CdbEnginePrivate::slotModulesLoaded()
// spawned by the debug handler and inherits the handles, // spawned by the debug handler and inherits the handles,
// the event handling does not work reliably (that is, the crash // the event handling does not work reliably (that is, the crash
// event is not delivered). In that case, force a break // event is not delivered). In that case, force a break
if (m_mode == AttachCrashedExternal && m_engine->state() != InferiorStopped) if (m_mode == AttachCrashedExternal && m_engine->state() != InferiorStopOk)
QTimer::singleShot(10, m_engine, SLOT(slotBreakAttachToCrashed())); QTimer::singleShot(10, m_engine, SLOT(slotBreakAttachToCrashed()));
} }
...@@ -930,7 +930,7 @@ void CdbEngine::slotBreakAttachToCrashed() ...@@ -930,7 +930,7 @@ void CdbEngine::slotBreakAttachToCrashed()
{ {
// Force a break when attaching to crashed process (if Creator was not spawned // Force a break when attaching to crashed process (if Creator was not spawned
// from handler). // from handler).
if (state() != InferiorStopped) { if (state() != InferiorStopOk) {
showMessage(QLatin1String("Forcing break...")); showMessage(QLatin1String("Forcing break..."));
m_d->m_dumper->disable(); m_d->m_dumper->disable();
interruptInferior(); interruptInferior();
...@@ -943,7 +943,7 @@ void CdbEngine::interruptInferior() ...@@ -943,7 +943,7 @@ void CdbEngine::interruptInferior()
return; return;
QString errorMessage; QString errorMessage;
setState(InferiorStopping, Q_FUNC_INFO, __LINE__); setState(InferiorStopRequested, Q_FUNC_INFO, __LINE__);
if (!m_d->interruptInterferiorProcess(&errorMessage)) { if (!m_d->interruptInterferiorProcess(&errorMessage)) {
setState(InferiorStopFailed, Q_FUNC_INFO, __LINE__); setState(InferiorStopFailed, Q_FUNC_INFO, __LINE__);
warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage)); warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage));
...@@ -1022,7 +1022,7 @@ void CdbEngine::activateFrame(int frameIndex) ...@@ -1022,7 +1022,7 @@ void CdbEngine::activateFrame(int frameIndex)
if (debugCDB) if (debugCDB)
qDebug() << Q_FUNC_INFO << frameIndex; qDebug() << Q_FUNC_INFO << frameIndex;
if (state() != InferiorStopped) { if (state() != InferiorStopOk) {
qWarning("WARNING %s: invoked while debuggee is running\n", Q_FUNC_INFO); qWarning("WARNING %s: invoked while debuggee is running\n", Q_FUNC_INFO);
return; return;
} }
...@@ -1237,7 +1237,7 @@ void CdbEngine::requestModuleSymbols(const QString &moduleName) ...@@ -1237,7 +1237,7 @@ void CdbEngine::requestModuleSymbols(const QString &moduleName)
void CdbEngine::reloadRegisters() void CdbEngine::reloadRegisters()
{ {
if (state() != InferiorStopped) if (state() != InferiorStopOk)
return; return;
const int intBase = 10; const int intBase = 10;
if (debugCDB) if (debugCDB)
...@@ -1272,7 +1272,7 @@ void CdbEngine::slotConsoleStubMessage(const QString &msg, bool) ...@@ -1272,7 +1272,7 @@ void CdbEngine::slotConsoleStubMessage(const QString &msg, bool)
void CdbEngine::slotConsoleStubTerminated() void CdbEngine::slotConsoleStubTerminated()
{ {
exitDebugger(); shutdownEngine();
} }
void CdbEngine::warning(const QString &msg) void CdbEngine::warning(const QString &msg)
...@@ -1331,9 +1331,9 @@ void CdbEnginePrivate::handleDebugEvent() ...@@ -1331,9 +1331,9 @@ void CdbEnginePrivate::handleDebugEvent()
case BreakEventHandle: { case BreakEventHandle: {
// If this is triggered by breakpoint/crash: Set state to stopping // If this is triggered by breakpoint/crash: Set state to stopping
// to avoid warnings as opposed to interrupt inferior // to avoid warnings as opposed to interrupt inferior
if (m_engine->state() != InferiorStopping) if (m_engine->state() != InferiorStopRequested)
m_engine->setState(InferiorStopping, Q_FUNC_INFO, __LINE__); m_engine->setState(InferiorStopRequested, Q_FUNC_INFO, __LINE__);
m_engine->setState(InferiorStopped, Q_FUNC_INFO, __LINE__); m_engine->setState(InferiorStopOk, Q_FUNC_INFO, __LINE__);
// Indicate artifical thread that is created when interrupting as such, // Indicate artifical thread that is created when interrupting as such,
// else use stop message with cleaned newlines and blanks. // else use stop message with cleaned newlines and blanks.
const QString currentThreadState = const QString currentThreadState =
...@@ -1424,7 +1424,7 @@ ULONG CdbEnginePrivate::updateThreadList(const QString &currentThreadState) ...@@ -1424,7 +1424,7 @@ ULONG CdbEnginePrivate::updateThreadList(const QString &currentThreadState)
ULONG currentThreadId; ULONG currentThreadId;
QString errorMessage; QString errorMessage;
// When interrupting, an artifical thread with a breakpoint is created. // When interrupting, an artifical thread with a breakpoint is created.
const bool stopped = m_engine->state() == InferiorStopped; const bool stopped = m_engine->state() == InferiorStopOk;
if (!CdbStackTraceContext::getThreads(interfaces(), if (!CdbStackTraceContext::getThreads(interfaces(),
stopped, stopped,
&threads, &currentThreadId, &threads, &currentThreadId,
......
...@@ -55,12 +55,12 @@ public: ...@@ -55,12 +55,12 @@ public:
static DebuggerEngine *create(const DebuggerStartParameters &sp, static DebuggerEngine *create(const DebuggerStartParameters &sp,
QString *errorMessage); QString *errorMessage);
virtual void shutdown();
virtual void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos); virtual void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos);
virtual void setupEngine(); virtual void setupEngine();
virtual void setupInferior(); virtual void setupInferior();
virtual void runEngine(); virtual void runEngine();
virtual void exitDebugger(); virtual void shutdownInferior();
virtual void shutdownEngine();
virtual void detachDebugger(); virtual void detachDebugger();
virtual void updateWatchData(const WatchData &data); virtual void updateWatchData(const WatchData &data);
virtual unsigned debuggerCapabilities() const; virtual unsigned debuggerCapabilities() const;
......
...@@ -79,29 +79,34 @@ enum DebuggerState ...@@ -79,29 +79,34 @@ enum DebuggerState
{ {
DebuggerNotReady, // Debugger not started DebuggerNotReady, // Debugger not started
EngineSettingUp, // Engine starts EngineSetupRequested, // Engine starts
EngineSetupFailed, EngineSetupFailed,
EngineSetupOk, EngineSetupOk,
InferiorUnrunnable, // Used in the core dump adapter InferiorSetupRequested,
InferiorSettingUp,
InferiorSetupFailed, InferiorSetupFailed,
InferiorSetupOk,
InferiorRunningRequested, // Debuggee requested to run EngineRunRequested,
InferiorRunningRequested_Kill, // Debuggee requested to run, but want to kill it EngineRunFailed,
InferiorRunning, // Debuggee running InferiorUnrunnable, // Used in the core dump adapter
InferiorRunRequested, // Debuggee requested to run
InferiorRunOk, // Debuggee running
InferiorRunFailed, // Debuggee running
InferiorStopping, // Debuggee running, stop requested InferiorStopRequested, // Debuggee running, stop requested
InferiorStopping_Kill, // Debuggee running, stop requested, want to kill it InferiorStopOk, // Debuggee stopped
InferiorStopped, // Debuggee stopped
InferiorStopFailed, // Debuggee not stopped, will kill debugger InferiorStopFailed, // Debuggee not stopped, will kill debugger
InferiorShuttingDown, InferiorShutdownRequested,
InferiorShutDown, InferiorShutdownOk,
InferiorShutdownFailed, InferiorShutdownFailed,
EngineShuttingDown EngineShutdownRequested,
EngineShutdownOk,
EngineShutdownFailed,
DebuggerFinished
}; };
enum DebuggerStartMode enum DebuggerStartMode
......
...@@ -88,6 +88,13 @@ using namespace Debugger::Internal; ...@@ -88,6 +88,13 @@ using namespace Debugger::Internal;
using namespace ProjectExplorer; using namespace ProjectExplorer;
using namespace TextEditor; using namespace TextEditor;
//#define DEBUG_STATE 1
#if DEBUG_STATE
# define SDEBUG(s) qDebug() << s
#else
# define SDEBUG(s)
#endif
# define XSDEBUG(s) qDebug() << s
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// //
...@@ -143,24 +150,27 @@ const char *DebuggerEngine::stateName(int s) ...@@ -143,24 +150,27 @@ const char *DebuggerEngine::stateName(int s)
# define SN(x) case x: return #x; # define SN(x) case x: return #x;
switch (s) { switch (s) {
SN(DebuggerNotReady) SN(DebuggerNotReady)
SN(EngineSettingUp) SN(EngineSetupRequested)
SN(EngineSetupOk) SN(EngineSetupOk)
SN(EngineSetupFailed) SN(EngineSetupFailed)
SN(InferiorSettingUp) SN(EngineRunFailed)
SN(InferiorSetupRequested)
SN(InferiorSetupFailed) SN(InferiorSetupFailed)
SN(InferiorSetupOk) SN(EngineRunRequested)
SN(InferiorRunningRequested) SN(InferiorRunRequested)
SN(InferiorRunningRequested_Kill) SN(InferiorRunOk)
SN(InferiorRunning) SN(InferiorRunFailed)
SN(InferiorUnrunnable) SN(InferiorUnrunnable)
SN(InferiorStopping) SN(InferiorStopRequested)
SN(InferiorStopping_Kill) SN(InferiorStopOk)
SN(InferiorStopped)
SN(InferiorStopFailed) SN(InferiorStopFailed)
SN(InferiorShuttingDown) SN(InferiorShutdownRequested)
SN(InferiorShutDown) SN(InferiorShutdownOk)
SN(InferiorShutdownFailed) SN(InferiorShutdownFailed)
SN(EngineShuttingDown) SN(EngineShutdownRequested)
SN(EngineShutdownOk)
SN(EngineShutdownFailed)
SN(DebuggerFinished)
} }
return "<unknown>"; return "<unknown>";
# undef SN # undef SN
...@@ -208,6 +218,7 @@ public: ...@@ -208,6 +218,7 @@ public:
m_runControl(0), m_runControl(0),
m_startParameters(sp), m_startParameters(sp),
m_state(DebuggerNotReady), m_state(DebuggerNotReady),
m_lastGoodState(DebuggerNotReady),
m_breakHandler(engine), m_breakHandler(engine),
m_commandHandler(engine), m_commandHandler(engine),
m_modulesHandler(engine), m_modulesHandler(engine),
...@@ -227,16 +238,28 @@ public slots: ...@@ -227,16 +238,28 @@ public slots:
void doSetupInferior(); void doSetupInferior();
void doRunEngine(); void doRunEngine();
void doShutdown(); void doShutdownEngine();
void doShutdownInferior();
void doInterruptInferior(); void doInterruptInferior();
void doFinishDebugger();
public: public:
DebuggerState state() const { return m_state; }
DebuggerEngine *m_engine; // Not owned. DebuggerEngine *m_engine; // Not owned.
DebuggerRunControl *m_runControl; // Not owned. DebuggerRunControl *m_runControl; // Not owned.
DebuggerStartParameters m_startParameters; DebuggerStartParameters m_startParameters;
// The current state.
DebuggerState m_state; DebuggerState m_state;
// The state we had before something unexpected happend.
DebuggerState m_lastGoodState;
// The state we are aiming for.
DebuggerState m_targetState;
qint64 m_inferiorPid; qint64 m_inferiorPid;
BreakHandler m_breakHandler; BreakHandler m_breakHandler;
...@@ -413,7 +436,7 @@ void DebuggerEngine::handleCommand(int role, const QVariant &value) ...@@ -413,7 +436,7 @@ void DebuggerEngine::handleCommand(int role, const QVariant &value)
break; break;
case RequestExecExitRole: case RequestExecExitRole:
exitDebugger(); d->doShutdownInferior();
break; break;
case RequestExecSnapshotRole: case RequestExecSnapshotRole:
...@@ -626,7 +649,7 @@ void DebuggerEngine::startDebugger(DebuggerRunControl *runControl) ...@@ -626,7 +649,7 @@ void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
d->m_runControl = runControl; d->m_runControl = runControl;
QTC_ASSERT(state() == DebuggerNotReady, setState(DebuggerNotReady)); QTC_ASSERT(state() == DebuggerNotReady, qDebug() << state());