forked from qt-creator/qt-creator
fix shutdowns triggered while inferior is not stopped
Reviewed-by: hjk
This commit is contained in:
@@ -75,9 +75,11 @@ enum DebuggerState
|
||||
InferiorStartFailed,
|
||||
|
||||
InferiorRunningRequested, // Debuggee requested to run
|
||||
InferiorRunningRequested_Kill, // Debuggee requested to run, but want to kill it
|
||||
InferiorRunning, // Debuggee running
|
||||
|
||||
InferiorStopping, // Debuggee running, stop requested
|
||||
InferiorStopping_Kill, // Debuggee running, stop requested, want to kill it
|
||||
InferiorStopped, // Debuggee stopped
|
||||
InferiorStopFailed, // Debuggee not stopped, will kill debugger
|
||||
|
||||
|
||||
@@ -192,9 +192,11 @@ const char *DebuggerManager::stateName(int s)
|
||||
SN(InferiorStarting)
|
||||
SN(InferiorStartFailed)
|
||||
SN(InferiorRunningRequested)
|
||||
SN(InferiorRunningRequested_Kill)
|
||||
SN(InferiorRunning)
|
||||
SN(InferiorUnrunnable)
|
||||
SN(InferiorStopping)
|
||||
SN(InferiorStopping_Kill)
|
||||
SN(InferiorStopped)
|
||||
SN(InferiorStopFailed)
|
||||
SN(InferiorShuttingDown)
|
||||
@@ -1578,11 +1580,17 @@ static bool isAllowedTransition(int from, int to)
|
||||
return to == EngineShuttingDown;
|
||||
|
||||
case InferiorRunningRequested:
|
||||
return to == InferiorRunning || to == InferiorStopped
|
||||
|| to == InferiorRunningRequested_Kill;
|
||||
case InferiorRunningRequested_Kill:
|
||||
return to == InferiorRunning || to == InferiorStopped;
|
||||
case InferiorRunning:
|
||||
return to == InferiorStopping;
|
||||
|
||||
case InferiorStopping:
|
||||
return to == InferiorStopped || to == InferiorStopFailed
|
||||
|| to == InferiorStopping_Kill;
|
||||
case InferiorStopping_Kill:
|
||||
return to == InferiorStopped || to == InferiorStopFailed;
|
||||
case InferiorStopped:
|
||||
return to == InferiorRunningRequested || to == InferiorShuttingDown;
|
||||
@@ -1705,6 +1713,8 @@ bool DebuggerManager::debuggerActionsEnabled() const
|
||||
case AdapterStarted:
|
||||
case AdapterStartFailed:
|
||||
case InferiorStartFailed:
|
||||
case InferiorRunningRequested_Kill:
|
||||
case InferiorStopping_Kill:
|
||||
case InferiorStopFailed:
|
||||
case InferiorShuttingDown:
|
||||
case InferiorShutDown:
|
||||
|
||||
@@ -115,8 +115,10 @@ static bool stateAcceptsGdbCommands(DebuggerState state)
|
||||
case InferiorStarting:
|
||||
case InferiorStartFailed:
|
||||
case InferiorRunningRequested:
|
||||
case InferiorRunningRequested_Kill:
|
||||
case InferiorRunning:
|
||||
case InferiorStopping:
|
||||
case InferiorStopping_Kill:
|
||||
case InferiorStopped:
|
||||
case InferiorShuttingDown:
|
||||
case InferiorShutDown:
|
||||
@@ -649,6 +651,16 @@ void GdbEngine::interruptInferior()
|
||||
m_gdbAdapter->interruptInferior();
|
||||
}
|
||||
|
||||
void GdbEngine::interruptInferiorTemporarily()
|
||||
{
|
||||
interruptInferior();
|
||||
foreach (const GdbCommand &cmd, m_commandsToRunOnTemporaryBreak)
|
||||
if (cmd.flags & LosesChild) {
|
||||
setState(InferiorStopping_Kill);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0)
|
||||
{
|
||||
const qint64 pid = pid0.toLongLong();
|
||||
@@ -731,12 +743,20 @@ void GdbEngine::postCommandHelper(const GdbCommand &cmd)
|
||||
debugMessage(_("QUEUING COMMAND ") + cmd.command);
|
||||
m_commandsToRunOnTemporaryBreak.append(cmd);
|
||||
if (state() == InferiorStopping) {
|
||||
if (cmd.flags & LosesChild)
|
||||
setState(InferiorStopping_Kill);
|
||||
debugMessage(_("CHILD ALREADY BEING INTERRUPTED"));
|
||||
} else if (state() == InferiorStopping_Kill) {
|
||||
debugMessage(_("CHILD ALREADY BEING INTERRUPTED (KILL PENDING)"));
|
||||
} else if (state() == InferiorRunningRequested) {
|
||||
if (cmd.flags & LosesChild)
|
||||
setState(InferiorRunningRequested_Kill);
|
||||
debugMessage(_("RUNNING REQUESTED; POSTPONING INTERRUPT"));
|
||||
} else if (state() == InferiorRunningRequested_Kill) {
|
||||
debugMessage(_("RUNNING REQUESTED; POSTPONING INTERRUPT (KILL PENDING)"));
|
||||
} else if (state() == InferiorRunning) {
|
||||
showStatusMessage(tr("Stopping temporarily."), 1000);
|
||||
interruptInferior();
|
||||
interruptInferiorTemporarily();
|
||||
} else {
|
||||
qDebug() << "ATTEMPTING TO QUEUE COMMAND IN INAPPROPRIATE STATE" << state();
|
||||
}
|
||||
@@ -775,6 +795,9 @@ void GdbEngine::flushCommand(const GdbCommand &cmd0)
|
||||
gdbInputAvailable(LogInput, cmd.command);
|
||||
|
||||
m_gdbAdapter->write(cmd.command.toLatin1() + "\r\n");
|
||||
|
||||
if (cmd.flags & LosesChild)
|
||||
setState(InferiorShuttingDown);
|
||||
}
|
||||
|
||||
void GdbEngine::handleResultRecord(GdbResponse *response)
|
||||
@@ -888,7 +911,7 @@ void GdbEngine::handleResultRecord(GdbResponse *response)
|
||||
// This is done after the command callbacks so the running-requesting commands
|
||||
// can assert on the right state.
|
||||
if (state() == InferiorRunning && !m_commandsToRunOnTemporaryBreak.isEmpty())
|
||||
interruptInferior();
|
||||
interruptInferiorTemporarily();
|
||||
|
||||
// Continue only if there are no commands wire anymore, so this will
|
||||
// be fully synchroneous.
|
||||
@@ -1075,11 +1098,16 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
|
||||
}
|
||||
|
||||
if (!m_commandsToRunOnTemporaryBreak.isEmpty()) {
|
||||
QTC_ASSERT(state() == InferiorStopping, qDebug() << state())
|
||||
QTC_ASSERT(state() == InferiorStopping || state() == InferiorStopping_Kill,
|
||||
qDebug() << state())
|
||||
setState(InferiorStopped);
|
||||
flushQueuedCommands();
|
||||
QTC_ASSERT(m_commandsDoneCallback == 0, /**/);
|
||||
m_commandsDoneCallback = &GdbEngine::autoContinueInferior;
|
||||
if (state() == InferiorStopped) {
|
||||
QTC_ASSERT(m_commandsDoneCallback == 0, /**/);
|
||||
m_commandsDoneCallback = &GdbEngine::autoContinueInferior;
|
||||
} else {
|
||||
QTC_ASSERT(state() == InferiorShuttingDown, qDebug() << state())
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1320,6 +1348,12 @@ void GdbEngine::handleExecContinue(const GdbResponse &response)
|
||||
// The "running" state is picked up in handleResponse()
|
||||
QTC_ASSERT(state() == InferiorRunning, /**/);
|
||||
} else {
|
||||
if (state() == InferiorRunningRequested_Kill) {
|
||||
setState(InferiorStopped);
|
||||
m_commandsToRunOnTemporaryBreak.clear();
|
||||
shutdown();
|
||||
return;
|
||||
}
|
||||
QTC_ASSERT(state() == InferiorRunningRequested, /**/);
|
||||
setState(InferiorStopped);
|
||||
QByteArray msg = response.data.findChild("msg").data();
|
||||
@@ -1369,6 +1403,8 @@ void GdbEngine::shutdown()
|
||||
case EngineStarting: // We can't get here, really
|
||||
case InferiorShuttingDown: // Will auto-trigger further shutdown steps
|
||||
case EngineShuttingDown: // Do not disturb! :)
|
||||
case InferiorRunningRequested_Kill:
|
||||
case InferiorStopping_Kill:
|
||||
break;
|
||||
case AdapterStarting: // GDB is up, adapter is "doing something"
|
||||
setState(AdapterStartFailed);
|
||||
@@ -1388,8 +1424,7 @@ void GdbEngine::shutdown()
|
||||
case InferiorStopped:
|
||||
// FIXME set some timeout?
|
||||
postCommand(_(m_gdbAdapter->inferiorShutdownCommand()),
|
||||
NeedsStop, CB(handleInferiorShutdown));
|
||||
setState(InferiorShuttingDown); // Do it after posting the command!
|
||||
NeedsStop | LosesChild, CB(handleInferiorShutdown));
|
||||
break;
|
||||
case AdapterStarted: // We can't get here, really
|
||||
case InferiorStartFailed:
|
||||
|
||||
@@ -176,8 +176,9 @@ private: ////////// Gdb Command Management //////////
|
||||
RebuildModel = 4, // Trigger model rebuild when no such commands are pending any more
|
||||
WatchUpdate = Discardable | RebuildModel,
|
||||
EmbedToken = 8, // Expand %1 in the command to the command token
|
||||
RunRequest = 16, // Callback expect GdbResultRunning instead of GdbResultDone
|
||||
ExitRequest = 32 // Callback expect GdbResultExit instead of GdbResultDone
|
||||
RunRequest = 16, // Callback expects GdbResultRunning instead of GdbResultDone
|
||||
ExitRequest = 32, // Callback expects GdbResultExit instead of GdbResultDone
|
||||
LosesChild = 64 // Auto-set inferior shutdown related states
|
||||
};
|
||||
Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag)
|
||||
private:
|
||||
@@ -283,6 +284,7 @@ private: ////////// Inferior Management //////////
|
||||
void autoContinueInferior();
|
||||
virtual void continueInferior();
|
||||
virtual void interruptInferior();
|
||||
void interruptInferiorTemporarily();
|
||||
|
||||
virtual void runToLineExec(const QString &fileName, int lineNumber);
|
||||
virtual void runToFunctionExec(const QString &functionName);
|
||||
|
||||
Reference in New Issue
Block a user