Debugger: Fix a state transition regression

Task-number: QTCREATORBUG-14028
Change-Id: I426baf1549d138f4a35d23d5ab814def2125dfbe
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com>
Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
This commit is contained in:
hjk
2015-02-24 15:30:42 +01:00
parent 30d80ad020
commit 7b8c58b99b
2 changed files with 87 additions and 64 deletions

View File

@@ -98,6 +98,15 @@ enum { debugPending = 0 };
#define CB(callback) [this](const DebuggerResponse &r) { callback(r); } #define CB(callback) [this](const DebuggerResponse &r) { callback(r); }
#define CHECK_STATE(s) \
do { \
if (state() != s) { \
showMessage(QString::fromLatin1("UNEXPECTED STATE: %1 WANTED: %2 IN %3:%4") \
.arg(state()).arg(s).arg(QLatin1String(__FILE__)).arg(__LINE__), LogError); \
QTC_ASSERT(false, qDebug() << state() << s); \
} \
} while (0)
QByteArray GdbEngine::tooltipIName(const QString &exp) QByteArray GdbEngine::tooltipIName(const QString &exp)
{ {
return "tooltip." + exp.toLatin1().toHex(); return "tooltip." + exp.toLatin1().toHex();
@@ -788,8 +797,7 @@ void GdbEngine::readGdbStandardOutput()
void GdbEngine::interruptInferior() void GdbEngine::interruptInferior()
{ {
QTC_ASSERT(state() == InferiorStopRequested, CHECK_STATE(InferiorStopRequested);
qDebug() << "INTERRUPT INFERIOR: " << state(); return);
if (terminal()->sendInterrupt()) if (terminal()->sendInterrupt())
return; return;
@@ -1323,10 +1331,6 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
showMessage(_("IGNORING TERMINAL SIGTRAP"), LogMisc); showMessage(_("IGNORING TERMINAL SIGTRAP"), LogMisc);
return; return;
} }
// This is gdb 7+'s initial *stopped in response to attach.
// For consistency, we just discard it.
if (state() == InferiorSetupRequested)
return;
if (isDying()) { if (isDying()) {
notifyInferiorStopOk(); notifyInferiorStopOk();
@@ -1337,6 +1341,8 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
threadsHandler()->notifyStopped(threads.data()); threadsHandler()->notifyStopped(threads.data());
const QByteArray reason = data["reason"].data(); const QByteArray reason = data["reason"].data();
const GdbMi frame = data["frame"];
const QByteArray func = frame["from"].data();
if (isExitedReason(reason)) { if (isExitedReason(reason)) {
// // The user triggered a stop, but meanwhile the app simply exited ... // // The user triggered a stop, but meanwhile the app simply exited ...
@@ -1358,6 +1364,19 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
return; return;
} }
// Ignore signals from the process stub.
if (startParameters().useTerminal
&& data["reason"].data() == "signal-received"
&& data["signal-name"].data() == "SIGSTOP"
&& (func.endsWith("/ld-linux.so.2")
|| func.endsWith("/ld-linux-x86-64.so.2")))
{
showMessage(_("INTERNAL CONTINUE AFTER SIGSTOP FROM STUB"), LogMisc);
notifyInferiorSpontaneousStop();
continueInferiorInternal();
return;
}
bool gotoHandleStop1 = true; bool gotoHandleStop1 = true;
if (!m_fullStartDone) { if (!m_fullStartDone) {
m_fullStartDone = true; m_fullStartDone = true;
@@ -1367,8 +1386,6 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
} }
BreakpointResponseId rid(data["bkptno"].data()); BreakpointResponseId rid(data["bkptno"].data());
const GdbMi frame = data["frame"];
int lineNumber = 0; int lineNumber = 0;
QString fullName; QString fullName;
QByteArray function; QByteArray function;
@@ -1410,14 +1427,14 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
gotoLocation(Location(fullName, lineNumber)); gotoLocation(Location(fullName, lineNumber));
if (!m_commandsToRunOnTemporaryBreak.isEmpty()) { if (!m_commandsToRunOnTemporaryBreak.isEmpty()) {
QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state()); CHECK_STATE(InferiorStopRequested);
notifyInferiorStopOk(); notifyInferiorStopOk();
flushQueuedCommands(); flushQueuedCommands();
if (state() == InferiorStopOk) { if (state() == InferiorStopOk) {
QTC_CHECK(m_commandsDoneCallback == 0); QTC_CHECK(m_commandsDoneCallback == 0);
m_commandsDoneCallback = &GdbEngine::autoContinueInferior; m_commandsDoneCallback = &GdbEngine::autoContinueInferior;
} else { } else {
QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state()); CHECK_STATE(InferiorShutdownRequested);
} }
return; return;
} }
@@ -1441,12 +1458,18 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
notifyInferiorSpontaneousStop(); notifyInferiorSpontaneousStop();
} else if (state() == InferiorStopOk) { } else if (state() == InferiorStopOk) {
// That's expected. // That's expected.
} else { } else if (state() == InferiorStopRequested) {
QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state());
notifyInferiorStopOk(); notifyInferiorStopOk();
} else if (state() == EngineRunRequested) {
// This is gdb 7+'s initial *stopped in response to attach that
// appears before the ^done is seen.
notifyEngineRunAndInferiorStopOk();
return;
} else {
QTC_CHECK(false);
} }
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); CHECK_STATE(InferiorStopOk);
if (gotoHandleStop1) if (gotoHandleStop1)
handleStop1(data); handleStop1(data);
@@ -1459,7 +1482,7 @@ static QByteArray stopSignal(const Abi &abi)
void GdbEngine::handleStop1(const GdbMi &data) void GdbEngine::handleStop1(const GdbMi &data)
{ {
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); CHECK_STATE(InferiorStopOk);
QTC_ASSERT(!isDying(), return); QTC_ASSERT(!isDying(), return);
const GdbMi frame = data["frame"]; const GdbMi frame = data["frame"];
const QByteArray reason = data["reason"].data(); const QByteArray reason = data["reason"].data();
@@ -1531,7 +1554,7 @@ void GdbEngine::handleStop1(const GdbMi &data)
void GdbEngine::handleStop2(const GdbMi &data) void GdbEngine::handleStop2(const GdbMi &data)
{ {
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); CHECK_STATE(InferiorStopOk);
QTC_ASSERT(!isDying(), return); QTC_ASSERT(!isDying(), return);
// A user initiated stop looks like the following. Note that there is // A user initiated stop looks like the following. Note that there is
@@ -1560,23 +1583,10 @@ void GdbEngine::handleStop2(const GdbMi &data)
// dState changed from InferiorStopRequested(13) to InferiorStopOk(14). // dState changed from InferiorStopRequested(13) to InferiorStopOk(14).
const QByteArray reason = data["reason"].data(); const QByteArray reason = data["reason"].data();
const QByteArray func = data["frame"]["from"].data();
const DebuggerStartParameters &sp = startParameters(); const DebuggerStartParameters &sp = startParameters();
bool isStopperThread = false; bool isStopperThread = false;
if (sp.useTerminal
&& reason == "signal-received"
&& data["signal-name"].data() == "SIGSTOP"
&& (func.endsWith("/ld-linux.so.2")
|| func.endsWith("/ld-linux-x86-64.so.2")))
{
// Ignore signals from the process stub.
showMessage(_("INTERNAL CONTINUE AFTER SIGSTOP FROM STUB"), LogMisc);
continueInferiorInternal();
return;
}
if (sp.toolChainAbi.os() == Abi::WindowsOS if (sp.toolChainAbi.os() == Abi::WindowsOS
&& sp.useTerminal && sp.useTerminal
&& reason == "signal-received" && reason == "signal-received"
@@ -1711,13 +1721,13 @@ void GdbEngine::handleListFeatures(const DebuggerResponse &response)
void GdbEngine::handlePythonSetup(const DebuggerResponse &response) void GdbEngine::handlePythonSetup(const DebuggerResponse &response)
{ {
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); CHECK_STATE(EngineSetupRequested);
if (response.resultClass == ResultDone) { if (response.resultClass == ResultDone) {
GdbMi data; GdbMi data;
data.fromStringMultiple(response.consoleStreamOutput); data.fromStringMultiple(response.consoleStreamOutput);
watchHandler()->addDumpers(data["dumpers"]); watchHandler()->addDumpers(data["dumpers"]);
loadInitScript(); loadInitScript();
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); CHECK_STATE(EngineSetupRequested);
showMessage(_("ENGINE SUCCESSFULLY STARTED")); showMessage(_("ENGINE SUCCESSFULLY STARTED"));
notifyEngineSetupOk(); notifyEngineSetupOk();
} else { } else {
@@ -1740,7 +1750,7 @@ void GdbEngine::showExecutionError(const QString &message)
void GdbEngine::handleExecuteContinue(const DebuggerResponse &response) void GdbEngine::handleExecuteContinue(const DebuggerResponse &response)
{ {
QTC_ASSERT(state() == InferiorRunRequested, qDebug() << state()); CHECK_STATE(InferiorRunRequested);
if (response.resultClass == ResultRunning) { if (response.resultClass == ResultRunning) {
// All is fine. Waiting for a *running. // All is fine. Waiting for a *running.
notifyInferiorRunOk(); // Only needed for gdb < 7.0. notifyInferiorRunOk(); // Only needed for gdb < 7.0.
@@ -1753,7 +1763,7 @@ void GdbEngine::handleExecuteContinue(const DebuggerResponse &response)
return; return;
if (!m_commandsToRunOnTemporaryBreak.isEmpty()) if (!m_commandsToRunOnTemporaryBreak.isEmpty())
flushQueuedCommands(); flushQueuedCommands();
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); CHECK_STATE(InferiorStopOk);
showStatusMessage(tr("Stopped."), 5000); showStatusMessage(tr("Stopped."), 5000);
reloadStack(); reloadStack();
} else if (msg.startsWith("Cannot access memory at address")) { } else if (msg.startsWith("Cannot access memory at address")) {
@@ -1762,7 +1772,7 @@ void GdbEngine::handleExecuteContinue(const DebuggerResponse &response)
notifyInferiorRunFailed(); notifyInferiorRunFailed();
if (isDying()) if (isDying())
return; return;
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); CHECK_STATE(InferiorStopOk);
// FIXME: Fix translation in master. // FIXME: Fix translation in master.
showStatusMessage(QString::fromLocal8Bit(msg), 5000); showStatusMessage(QString::fromLocal8Bit(msg), 5000);
gotoLocation(stackHandler()->currentFrame()); gotoLocation(stackHandler()->currentFrame());
@@ -1837,7 +1847,7 @@ QString GdbEngine::cleanupFullName(const QString &fileName)
void GdbEngine::shutdownInferior() void GdbEngine::shutdownInferior()
{ {
QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state()); CHECK_STATE(InferiorShutdownRequested);
m_commandsToRunOnTemporaryBreak.clear(); m_commandsToRunOnTemporaryBreak.clear();
switch (startParameters().closeMode) { switch (startParameters().closeMode) {
case KillAtClose: case KillAtClose:
@@ -1853,7 +1863,7 @@ void GdbEngine::shutdownInferior()
void GdbEngine::handleInferiorShutdown(const DebuggerResponse &response) void GdbEngine::handleInferiorShutdown(const DebuggerResponse &response)
{ {
QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state()); CHECK_STATE(InferiorShutdownRequested);
if (response.resultClass == ResultDone) { if (response.resultClass == ResultDone) {
notifyInferiorShutdownOk(); notifyInferiorShutdownOk();
return; return;
@@ -1875,13 +1885,13 @@ void GdbEngine::handleInferiorShutdown(const DebuggerResponse &response)
void GdbEngine::notifyAdapterShutdownFailed() void GdbEngine::notifyAdapterShutdownFailed()
{ {
showMessage(_("ADAPTER SHUTDOWN FAILED")); showMessage(_("ADAPTER SHUTDOWN FAILED"));
QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state()); CHECK_STATE(EngineShutdownRequested);
notifyEngineShutdownFailed(); notifyEngineShutdownFailed();
} }
void GdbEngine::notifyAdapterShutdownOk() void GdbEngine::notifyAdapterShutdownOk()
{ {
QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state()); CHECK_STATE(EngineShutdownRequested);
showMessage(_("INITIATE GDBENGINE SHUTDOWN IN STATE %1, PROC: %2") showMessage(_("INITIATE GDBENGINE SHUTDOWN IN STATE %1, PROC: %2")
.arg(lastGoodState()).arg(m_gdbProc->state())); .arg(lastGoodState()).arg(m_gdbProc->state()));
m_commandsDoneCallback = 0; m_commandsDoneCallback = 0;
@@ -1925,7 +1935,7 @@ void GdbEngine::handleGdbExit(const DebuggerResponse &response)
void GdbEngine::detachDebugger() void GdbEngine::detachDebugger()
{ {
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); CHECK_STATE(InferiorStopOk);
QTC_ASSERT(startMode() != AttachCore, qDebug() << startMode()); QTC_ASSERT(startMode() != AttachCore, qDebug() << startMode());
postCommand("detach", GdbEngine::ExitRequest, CB(handleDetach)); postCommand("detach", GdbEngine::ExitRequest, CB(handleDetach));
} }
@@ -1933,7 +1943,7 @@ void GdbEngine::detachDebugger()
void GdbEngine::handleDetach(const DebuggerResponse &response) void GdbEngine::handleDetach(const DebuggerResponse &response)
{ {
Q_UNUSED(response); Q_UNUSED(response);
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); CHECK_STATE(InferiorStopOk);
notifyInferiorExited(); notifyInferiorExited();
} }
@@ -2008,10 +2018,10 @@ bool GdbEngine::hasCapability(unsigned cap) const
void GdbEngine::continueInferiorInternal() void GdbEngine::continueInferiorInternal()
{ {
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); CHECK_STATE(InferiorStopOk);
notifyInferiorRunRequested(); notifyInferiorRunRequested();
showStatusMessage(tr("Running requested..."), 5000); showStatusMessage(tr("Running requested..."), 5000);
QTC_ASSERT(state() == InferiorRunRequested, qDebug() << state()); CHECK_STATE(InferiorRunRequested);
postCommand("-exec-continue", RunRequest, CB(handleExecuteContinue)); postCommand("-exec-continue", RunRequest, CB(handleExecuteContinue));
} }
@@ -2024,14 +2034,14 @@ void GdbEngine::autoContinueInferior()
void GdbEngine::continueInferior() void GdbEngine::continueInferior()
{ {
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); CHECK_STATE(InferiorStopOk);
setTokenBarrier(); setTokenBarrier();
continueInferiorInternal(); continueInferiorInternal();
} }
void GdbEngine::executeStep() void GdbEngine::executeStep()
{ {
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); CHECK_STATE(InferiorStopOk);
setTokenBarrier(); setTokenBarrier();
notifyInferiorRunRequested(); notifyInferiorRunRequested();
showStatusMessage(tr("Step requested..."), 5000); showStatusMessage(tr("Step requested..."), 5000);
@@ -2054,7 +2064,7 @@ void GdbEngine::handleExecuteStep(const DebuggerResponse &response)
QTC_CHECK(state() == InferiorStopOk); QTC_CHECK(state() == InferiorStopOk);
return; return;
} }
QTC_ASSERT(state() == InferiorRunRequested, qDebug() << state()); CHECK_STATE(InferiorRunRequested);
if (response.resultClass == ResultRunning) { if (response.resultClass == ResultRunning) {
// All is fine. Waiting for a *running. // All is fine. Waiting for a *running.
notifyInferiorRunOk(); // Only needed for gdb < 7.0. notifyInferiorRunOk(); // Only needed for gdb < 7.0.
@@ -2086,7 +2096,7 @@ void GdbEngine::handleExecuteStep(const DebuggerResponse &response)
void GdbEngine::executeStepI() void GdbEngine::executeStepI()
{ {
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); CHECK_STATE(InferiorStopOk);
setTokenBarrier(); setTokenBarrier();
notifyInferiorRunRequested(); notifyInferiorRunRequested();
showStatusMessage(tr("Step by instruction requested..."), 5000); showStatusMessage(tr("Step by instruction requested..."), 5000);
@@ -2098,7 +2108,7 @@ void GdbEngine::executeStepI()
void GdbEngine::executeStepOut() void GdbEngine::executeStepOut()
{ {
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); CHECK_STATE(InferiorStopOk);
postCommand("-stack-select-frame 0", Discardable); postCommand("-stack-select-frame 0", Discardable);
setTokenBarrier(); setTokenBarrier();
notifyInferiorRunRequested(); notifyInferiorRunRequested();
@@ -2108,7 +2118,7 @@ void GdbEngine::executeStepOut()
void GdbEngine::executeNext() void GdbEngine::executeNext()
{ {
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); CHECK_STATE(InferiorStopOk);
setTokenBarrier(); setTokenBarrier();
notifyInferiorRunRequested(); notifyInferiorRunRequested();
showStatusMessage(tr("Step next requested..."), 5000); showStatusMessage(tr("Step next requested..."), 5000);
@@ -2132,16 +2142,16 @@ void GdbEngine::handleExecuteNext(const DebuggerResponse &response)
if (response.resultClass == ResultDone) { if (response.resultClass == ResultDone) {
// Step was finishing too quick, and a '*stopped' messages should // Step was finishing too quick, and a '*stopped' messages should
// have preceded it, so just ignore this result. // have preceded it, so just ignore this result.
QTC_CHECK(state() == InferiorStopOk); CHECK_STATE(InferiorStopOk);
return; return;
} }
QTC_ASSERT(state() == InferiorRunRequested, qDebug() << state()); CHECK_STATE(InferiorRunRequested);
if (response.resultClass == ResultRunning) { if (response.resultClass == ResultRunning) {
// All is fine. Waiting for a *running. // All is fine. Waiting for a *running.
notifyInferiorRunOk(); // Only needed for gdb < 7.0. notifyInferiorRunOk(); // Only needed for gdb < 7.0.
return; return;
} }
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); CHECK_STATE(InferiorStopOk);
QByteArray msg = response.data["msg"].data(); QByteArray msg = response.data["msg"].data();
if (msg.startsWith("Cannot find bounds of current function") if (msg.startsWith("Cannot find bounds of current function")
|| msg.contains("Error accessing memory address ")) { || msg.contains("Error accessing memory address ")) {
@@ -2162,7 +2172,7 @@ void GdbEngine::handleExecuteNext(const DebuggerResponse &response)
void GdbEngine::executeNextI() void GdbEngine::executeNextI()
{ {
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); CHECK_STATE(InferiorStopOk);
setTokenBarrier(); setTokenBarrier();
notifyInferiorRunRequested(); notifyInferiorRunRequested();
showStatusMessage(tr("Step next instruction requested..."), 5000); showStatusMessage(tr("Step next instruction requested..."), 5000);
@@ -2179,7 +2189,7 @@ static QByteArray addressSpec(quint64 address)
void GdbEngine::executeRunToLine(const ContextData &data) void GdbEngine::executeRunToLine(const ContextData &data)
{ {
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); CHECK_STATE(InferiorStopOk);
setTokenBarrier(); setTokenBarrier();
resetLocation(); resetLocation();
notifyInferiorRunRequested(); notifyInferiorRunRequested();
@@ -2204,7 +2214,7 @@ void GdbEngine::executeRunToLine(const ContextData &data)
void GdbEngine::executeRunToFunction(const QString &functionName) void GdbEngine::executeRunToFunction(const QString &functionName)
{ {
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); CHECK_STATE(InferiorStopOk);
setTokenBarrier(); setTokenBarrier();
resetLocation(); resetLocation();
postCommand("-break-insert -t " + functionName.toLatin1()); postCommand("-break-insert -t " + functionName.toLatin1());
@@ -2214,7 +2224,7 @@ void GdbEngine::executeRunToFunction(const QString &functionName)
void GdbEngine::executeJumpToLine(const ContextData &data) void GdbEngine::executeJumpToLine(const ContextData &data)
{ {
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); CHECK_STATE(InferiorStopOk);
QByteArray loc; QByteArray loc;
if (data.address) if (data.address)
loc = addressSpec(data.address); loc = addressSpec(data.address);
@@ -2234,7 +2244,7 @@ void GdbEngine::executeJumpToLine(const ContextData &data)
void GdbEngine::executeReturn() void GdbEngine::executeReturn()
{ {
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); CHECK_STATE(InferiorStopOk);
setTokenBarrier(); setTokenBarrier();
notifyInferiorRunRequested(); notifyInferiorRunRequested();
showStatusMessage(tr("Immediate return from function requested..."), 5000); showStatusMessage(tr("Immediate return from function requested..."), 5000);
@@ -4417,7 +4427,7 @@ void GdbEngine::resetInferior()
void GdbEngine::handleAdapterStartFailed(const QString &msg, Id settingsIdHint) void GdbEngine::handleAdapterStartFailed(const QString &msg, Id settingsIdHint)
{ {
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); CHECK_STATE(EngineSetupOk);
showMessage(_("ADAPTER START FAILED")); showMessage(_("ADAPTER START FAILED"));
if (!msg.isEmpty()) { if (!msg.isEmpty()) {
const QString title = tr("Adapter start failed"); const QString title = tr("Adapter start failed");
@@ -4442,7 +4452,7 @@ void GdbEngine::handleInferiorPrepared()
{ {
const DebuggerStartParameters &sp = startParameters(); const DebuggerStartParameters &sp = startParameters();
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); CHECK_STATE(InferiorSetupRequested);
if (!sp.commandsAfterConnect.isEmpty()) { if (!sp.commandsAfterConnect.isEmpty()) {
QByteArray commands = globalMacroExpander()->expand(sp.commandsAfterConnect); QByteArray commands = globalMacroExpander()->expand(sp.commandsAfterConnect);
@@ -4475,7 +4485,7 @@ void GdbEngine::handleInferiorPrepared()
void GdbEngine::finishInferiorSetup() void GdbEngine::finishInferiorSetup()
{ {
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); CHECK_STATE(InferiorSetupRequested);
if (startParameters().startMode == AttachCore) { if (startParameters().startMode == AttachCore) {
notifyInferiorSetupOk(); // No breakpoints in core files. notifyInferiorSetupOk(); // No breakpoints in core files.

View File

@@ -140,11 +140,13 @@ void GdbTermEngine::runEngine()
void GdbTermEngine::handleStubAttached(const DebuggerResponse &response) void GdbTermEngine::handleStubAttached(const DebuggerResponse &response)
{ {
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); // InferiorStopOk can happen if the "*stopped" in response to the
// 'attach' comes in before its '^done'
QTC_ASSERT(state() == EngineRunRequested || state() == InferiorStopOk,
qDebug() << state());
switch (response.resultClass) { switch (response.resultClass) {
case ResultDone: case ResultDone:
case ResultRunning:
if (startParameters().toolChainAbi.os() != ProjectExplorer::Abi::WindowsOS) { if (startParameters().toolChainAbi.os() != ProjectExplorer::Abi::WindowsOS) {
showMessage(_("INFERIOR ATTACHED")); showMessage(_("INFERIOR ATTACHED"));
} else { } else {
@@ -160,8 +162,19 @@ void GdbTermEngine::handleStubAttached(const DebuggerResponse &response)
LogWarning); LogWarning);
} }
} }
notifyEngineRunAndInferiorStopOk(); if (state() == EngineRunRequested) {
continueInferiorInternal(); // We will get a '*stopped' later that we'll interpret as 'spontaneous'
// So acknowledge the current state and put a delayed 'continue' in the pipe.
notifyEngineRunAndInferiorRunOk();
} else {
//postCommand("print 43", NoFlags, [this](const DebuggerResponse &) { continueInferiorInternal(); });
continueInferiorInternal();
}
break;
case ResultRunning:
// Has anyone seen such a result lately?
showMessage(_("INFERIOR ATTACHED AND RUNNING"));
notifyEngineRunAndInferiorRunOk();
break; break;
case ResultError: case ResultError:
if (response.data["msg"].data() == "ptrace: Operation not permitted.") { if (response.data["msg"].data() == "ptrace: Operation not permitted.") {
@@ -170,11 +183,11 @@ void GdbTermEngine::handleStubAttached(const DebuggerResponse &response)
break; break;
} }
showMessage(QString::fromLocal8Bit(response.data["msg"].data())); showMessage(QString::fromLocal8Bit(response.data["msg"].data()));
notifyEngineRunFailed(); notifyEngineIll();
break; break;
default: default:
showMessage(QString::fromLatin1("Invalid response %1").arg(response.resultClass)); showMessage(QString::fromLatin1("Invalid response %1").arg(response.resultClass));
notifyEngineRunFailed(); notifyEngineIll();
break; break;
} }
} }