forked from qt-creator/qt-creator
Debugger: Ignore async GDB notifications while extracting variables
Recent builds of GDB started to deliver *running and *stopped notifications for expression evaluation, even unpaired at times. Since we know that we are stopped when we start variable extraction and we are stopped when it ends, the intermediate notifications can be ignored. Change-Id: I800082afb7df600ad4e6f97b534f4ea901c02d8a Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
This commit is contained in:
@@ -241,6 +241,7 @@ GdbEngine::GdbEngine(const DebuggerRunParameters &startParameters)
|
|||||||
m_fullStartDone = false;
|
m_fullStartDone = false;
|
||||||
m_systemDumpersLoaded = false;
|
m_systemDumpersLoaded = false;
|
||||||
m_rerunPending = false;
|
m_rerunPending = false;
|
||||||
|
m_inUpdateLocals = false;
|
||||||
|
|
||||||
m_debugInfoTaskHandler = new DebugInfoTaskHandler(this);
|
m_debugInfoTaskHandler = new DebugInfoTaskHandler(this);
|
||||||
//ExtensionSystem::PluginManager::addObject(m_debugInfoTaskHandler);
|
//ExtensionSystem::PluginManager::addObject(m_debugInfoTaskHandler);
|
||||||
@@ -442,23 +443,31 @@ void GdbEngine::handleResponse(const QByteArray &buff)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (asyncClass == "stopped") {
|
if (asyncClass == "stopped") {
|
||||||
handleStopResponse(result);
|
if (m_inUpdateLocals) {
|
||||||
m_pendingLogStreamOutput.clear();
|
showMessage(_("UNEXPECTED *stopped NOTIFICATION IGNORED"), LogWarning);
|
||||||
m_pendingConsoleStreamOutput.clear();
|
|
||||||
} else if (asyncClass == "running") {
|
|
||||||
GdbMi threads = result["thread-id"];
|
|
||||||
threadsHandler()->notifyRunning(threads.data());
|
|
||||||
if (state() == InferiorRunOk || state() == InferiorSetupRequested) {
|
|
||||||
// We get multiple *running after thread creation and in Windows terminals.
|
|
||||||
showMessage(QString::fromLatin1("NOTE: INFERIOR STILL RUNNING IN STATE %1.").
|
|
||||||
arg(QLatin1String(DebuggerEngine::stateName(state()))));
|
|
||||||
} else if (HostOsInfo::isWindowsHost() && (state() == InferiorStopRequested
|
|
||||||
|| state() == InferiorShutdownRequested)) {
|
|
||||||
// FIXME: Breakpoints on Windows are exceptions which are thrown in newly
|
|
||||||
// created threads so we have to filter out the running threads messages when
|
|
||||||
// we request a stop.
|
|
||||||
} else {
|
} else {
|
||||||
notifyInferiorRunOk();
|
handleStopResponse(result);
|
||||||
|
m_pendingLogStreamOutput.clear();
|
||||||
|
m_pendingConsoleStreamOutput.clear();
|
||||||
|
}
|
||||||
|
} else if (asyncClass == "running") {
|
||||||
|
if (m_inUpdateLocals) {
|
||||||
|
showMessage(_("UNEXPECTED *running NOTIFICATION IGNORED"), LogWarning);
|
||||||
|
} else {
|
||||||
|
GdbMi threads = result["thread-id"];
|
||||||
|
threadsHandler()->notifyRunning(threads.data());
|
||||||
|
if (state() == InferiorRunOk || state() == InferiorSetupRequested) {
|
||||||
|
// We get multiple *running after thread creation and in Windows terminals.
|
||||||
|
showMessage(QString::fromLatin1("NOTE: INFERIOR STILL RUNNING IN STATE %1.").
|
||||||
|
arg(QLatin1String(DebuggerEngine::stateName(state()))));
|
||||||
|
} else if (HostOsInfo::isWindowsHost() && (state() == InferiorStopRequested
|
||||||
|
|| state() == InferiorShutdownRequested)) {
|
||||||
|
// FIXME: Breakpoints on Windows are exceptions which are thrown in newly
|
||||||
|
// created threads so we have to filter out the running threads messages when
|
||||||
|
// we request a stop.
|
||||||
|
} else {
|
||||||
|
notifyInferiorRunOk();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (asyncClass == "library-loaded") {
|
} else if (asyncClass == "library-loaded") {
|
||||||
// Archer has 'id="/usr/lib/libdrm.so.2",
|
// Archer has 'id="/usr/lib/libdrm.so.2",
|
||||||
@@ -1187,6 +1196,8 @@ void GdbEngine::handleResultRecord(DebuggerResponse *response)
|
|||||||
if (!(cmd.flags & Discardable))
|
if (!(cmd.flags & Discardable))
|
||||||
--m_nonDiscardableCount;
|
--m_nonDiscardableCount;
|
||||||
|
|
||||||
|
m_inUpdateLocals = (cmd.flags & InUpdateLocals);
|
||||||
|
|
||||||
if (cmd.callback)
|
if (cmd.callback)
|
||||||
cmd.callback(*response);
|
cmd.callback(*response);
|
||||||
|
|
||||||
@@ -4758,7 +4769,7 @@ void GdbEngine::doUpdateLocals(const UpdateParameters ¶ms)
|
|||||||
cmd.arg("resultvarname", m_resultVarName);
|
cmd.arg("resultvarname", m_resultVarName);
|
||||||
cmd.arg("partialVariable", params.partialVariable);
|
cmd.arg("partialVariable", params.partialVariable);
|
||||||
cmd.arg("sortStructMembers", boolSetting(SortStructMembers));
|
cmd.arg("sortStructMembers", boolSetting(SortStructMembers));
|
||||||
cmd.flags = Discardable;
|
cmd.flags = Discardable | InUpdateLocals;
|
||||||
cmd.callback = [this](const DebuggerResponse &r) { handleStackFrame(r); };
|
cmd.callback = [this](const DebuggerResponse &r) { handleStackFrame(r); };
|
||||||
runCommand(cmd);
|
runCommand(cmd);
|
||||||
|
|
||||||
@@ -4768,6 +4779,8 @@ void GdbEngine::doUpdateLocals(const UpdateParameters ¶ms)
|
|||||||
|
|
||||||
void GdbEngine::handleStackFrame(const DebuggerResponse &response)
|
void GdbEngine::handleStackFrame(const DebuggerResponse &response)
|
||||||
{
|
{
|
||||||
|
m_inUpdateLocals = false;
|
||||||
|
|
||||||
if (response.resultClass == ResultDone) {
|
if (response.resultClass == ResultDone) {
|
||||||
QByteArray out = response.consoleStreamOutput;
|
QByteArray out = response.consoleStreamOutput;
|
||||||
while (out.endsWith(' ') || out.endsWith('\n'))
|
while (out.endsWith(' ') || out.endsWith('\n'))
|
||||||
|
|||||||
@@ -171,7 +171,9 @@ private: ////////// Gdb Command Management //////////
|
|||||||
// This command needs to be send immediately.
|
// This command needs to be send immediately.
|
||||||
Immediate = 256,
|
Immediate = 256,
|
||||||
// This is a command that needs to be wrapped into -interpreter-exec console
|
// This is a command that needs to be wrapped into -interpreter-exec console
|
||||||
ConsoleCommand = 512
|
ConsoleCommand = 512,
|
||||||
|
// This is the UpdateLocals commannd during which we ignore notifications
|
||||||
|
InUpdateLocals = 1024
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag)
|
Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag)
|
||||||
|
|
||||||
@@ -432,6 +434,10 @@ protected:
|
|||||||
// For short-circuiting stack and thread list evaluation.
|
// For short-circuiting stack and thread list evaluation.
|
||||||
bool m_stackNeeded;
|
bool m_stackNeeded;
|
||||||
|
|
||||||
|
// For suppressing processing *stopped and *running responses
|
||||||
|
// while updating locals.
|
||||||
|
bool m_inUpdateLocals;
|
||||||
|
|
||||||
bool isQFatalBreakpoint(const BreakpointResponseId &id) const;
|
bool isQFatalBreakpoint(const BreakpointResponseId &id) const;
|
||||||
bool isHiddenBreakpoint(const BreakpointResponseId &id) const;
|
bool isHiddenBreakpoint(const BreakpointResponseId &id) const;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user