-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[lldb] Fix qEcho message handling #145072
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Patch fixes the sync-on-timeout logic in lldb and switches to qEcho based ping, instead of qC. This fixes vRun message case, when there is no process yet and qC returns an error.
@llvm/pr-subscribers-lldb Author: None (eleviant) ChangesPatch fixes the sync-on-timeout logic in lldb and switches to qEcho based ping, instead of qC. This fixes vRun message case, when there is no process yet and qC returns an error. Full diff: https://github.com/llvm/llvm-project/pull/145072.diff 4 Files Affected:
diff --git a/lldb/packages/Python/lldbsuite/test/gdbclientutils.py b/lldb/packages/Python/lldbsuite/test/gdbclientutils.py
index 753de22b9cfee..b603c35c8df09 100644
--- a/lldb/packages/Python/lldbsuite/test/gdbclientutils.py
+++ b/lldb/packages/Python/lldbsuite/test/gdbclientutils.py
@@ -92,6 +92,9 @@ class MockGDBServerResponder:
class RESPONSE_DISCONNECT:
pass
+ class RESPONSE_NONE:
+ pass
+
def __init__(self):
self.packetLog = []
@@ -181,6 +184,8 @@ def respond(self, packet):
return self.qQueryGDBServer()
if packet == "qHostInfo":
return self.qHostInfo()
+ if packet.startswith("qEcho"):
+ return self.qEcho(int(packet.split(":")[1]))
if packet == "qGetWorkingDir":
return self.qGetWorkingDir()
if packet == "qOffsets":
@@ -237,6 +242,9 @@ def qProcessInfo(self):
def qHostInfo(self):
return "ptrsize:8;endian:little;"
+ def qEcho(self):
+ return "E04"
+
def qQueryGDBServer(self):
return "E04"
@@ -655,6 +663,8 @@ def _handlePacket(self, packet):
if not isinstance(response, list):
response = [response]
for part in response:
+ if part is MockGDBServerResponder.RESPONSE_NONE:
+ continue
if part is MockGDBServerResponder.RESPONSE_DISCONNECT:
raise self.TerminateConnectionException()
self._sendPacket(part)
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 2aea7c6b781d7..f244f7abe45e3 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -354,8 +354,9 @@ GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
disconnected = true;
Disconnect();
}
+ } else {
+ timed_out = true;
}
- timed_out = true;
break;
case eConnectionStatusSuccess:
// printf ("status = success but error = %s\n",
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index adbf06b9a19a0..d8130cae71ce6 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -406,7 +406,7 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
m_supports_qXfer_memory_map_read = eLazyBoolYes;
else if (x == "qXfer:siginfo:read+")
m_supports_qXfer_siginfo_read = eLazyBoolYes;
- else if (x == "qEcho")
+ else if (x == "qEcho+")
m_supports_qEcho = eLazyBoolYes;
else if (x == "QPassSignals+")
m_supports_QPassSignals = eLazyBoolYes;
diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py
index 08ac9290ee85a..49e589226b0ef 100644
--- a/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py
+++ b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py
@@ -356,6 +356,80 @@ def A(self, packet):
["vRun;%s;61726731;61726732;61726733" % (exe_hex,)]
)
+ def test_launch_lengthy_vRun(self):
+ class MyResponder(MockGDBServerResponder):
+ def __init__(self, *args, **kwargs):
+ self.started = False
+ return super().__init__(*args, **kwargs)
+
+ def qC(self):
+ if self.started:
+ return "QCp10.10"
+ else:
+ return "E42"
+
+ def qfThreadInfo(self):
+ if self.started:
+ return "mp10.10"
+ else:
+ return "E42"
+
+ def qsThreadInfo(self):
+ return "l"
+
+ def qEcho(self, num):
+ resp = "qEcho:" + str(num)
+ if num >= 2:
+ # We have launched our program
+ self.started = True
+ return [resp, "T13"]
+
+ return resp
+
+ def qSupported(self, client_supported):
+ return "PacketSize=3fff;QStartNoAckMode+;qEcho+;"
+
+ def qHostInfo(self):
+ return "default_packet_timeout:1;"
+
+ def vRun(self, packet):
+ return [self.RESPONSE_NONE]
+
+ def A(self, packet):
+ return "E28"
+
+ #self.runCmd("log enable -f /tmp/lldb.log gdb-remote all")
+ #self.runCmd("settings set plugin.process.gdb-remote.packet-timeout 1")
+ self.server.responder = MyResponder()
+
+ target = self.createTarget("a.yaml")
+ # NB: apparently GDB packets are using "/" on Windows too
+ exe_path = self.getBuildArtifact("a").replace(os.path.sep, "/")
+ exe_hex = binascii.b2a_hex(exe_path.encode()).decode()
+ process = self.connect(target)
+ lldbutil.expect_state_changes(
+ self, self.dbg.GetListener(), process, [lldb.eStateConnected]
+ )
+
+ process = target.Launch(
+ lldb.SBListener(),
+ ["arg1", "arg2", "arg3"], # argv
+ [], # envp
+ None, # stdin_path
+ None, # stdout_path
+ None, # stderr_path
+ None, # working_directory
+ 0, # launch_flags
+ True, # stop_at_entry
+ lldb.SBError(),
+ ) # error
+ self.assertTrue(process, PROCESS_IS_VALID)
+ self.assertEqual(process.GetProcessID(), 16)
+
+ self.assertPacketLogContains(
+ ["vRun;%s;61726731;61726732;61726733" % (exe_hex,)]
+ )
+
def test_launch_QEnvironment(self):
class MyResponder(MockGDBServerResponder):
def qC(self):
|
✅ With the latest revision this PR passed the Python code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, test addition is nice. Usually when I've seen lldb sending qC, something has gone off the rails enough that the debug session is dead, but I can see vRun being a particular instance where it might not be.
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/195/builds/10758 Here is the relevant piece of the build log for the reference
|
The buildbot lldb-remote-linux-ubuntu is still broken. |
Temporarily revert commit e066f35, because lldb tests randomly hang after it's been pushed.
Patch fixes the sync-on-timeout logic in lldb and switches to qEcho based ping, instead of qC. This fixes vRun message case, when there is no process yet and qC returns an error.
Temporarily revert commit e066f35, because lldb tests randomly hang after it's been pushed.
Patch fixes the sync-on-timeout logic in lldb and switches to qEcho based ping, instead of qC. This fixes vRun message case, when there is no process yet and qC returns an error.