https://github.com/dlgus8648 updated 
https://github.com/llvm/llvm-project/pull/202556

>From 3fc3e8f91128ad4f907e7f53ff41a50076c8c48e Mon Sep 17 00:00:00 2001
From: KIMRIHYEON <[email protected]>
Date: Tue, 9 Jun 2026 18:07:43 +0900
Subject: [PATCH 1/7] [lldb] Ignore async notification packets while waiting
 for a response

OpenOCD's gdbserver sends an async notification packet
("%oocd_keepalive:XX#cc") roughly every 500ms while a long memory
read/write is in progress. WaitForPacketNoLock() treated any non-invalid
packet returned by CheckForPacket() -- including a PacketType::Notify --
as the response to the pending request, so a keepalive arriving during a
memory write produced:

  unexpected response to GDB server memory write packet
  'M2ffff8,4:54430000': 'oocd_keepalive:00'

GDB has silently dropped unknown notifications received while waiting for
a packet since 7.0 (2009). Match that behaviour: drop notification
packets and keep waiting for the actual response. The LLDB client does
not otherwise consume '%' notifications, so this is safe.

Adds a unit test covering single and multiple notifications preceding the
response.

Fixes #197944.

Assisted-by: Claude Code (Anthropic)
---
 .../gdb-remote/GDBRemoteCommunication.cpp     | 24 +++++++++++++++++--
 .../gdb-remote/GDBRemoteCommunicationTest.cpp | 19 +++++++++++++++
 2 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 04f486882e2c2..56d1d8bc09fb1 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -242,7 +242,17 @@ 
GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
   Log *log = GetLog(GDBRLog::Packets);
 
   // Check for a packet from our cache first without trying any reading...
-  if (CheckForPacket(nullptr, 0, packet) != PacketType::Invalid)
+  // Async notification packets (e.g. OpenOCD's "oocd_keepalive", sent during
+  // long memory operations) are not responses to our request. GDB silently
+  // drops such notifications while waiting for a packet; do the same and keep
+  // looking for the actual response.
+  PacketType packet_type = CheckForPacket(nullptr, 0, packet);
+  while (packet_type == PacketType::Notify) {
+    LLDB_LOGF(log, "GDBRemoteCommunication::%s ignoring notification packet",
+              __FUNCTION__);
+    packet_type = CheckForPacket(nullptr, 0, packet);
+  }
+  if (packet_type != PacketType::Invalid)
     return PacketResult::Success;
 
   bool timed_out = false;
@@ -258,7 +268,17 @@ 
GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
                      error, bytes_read);
 
     if (bytes_read > 0) {
-      if (CheckForPacket(buffer, bytes_read, packet) != PacketType::Invalid)
+      // Drop any async notification packets (see above) and keep waiting for
+      // the actual response. Once the freshly-read bytes have been consumed,
+      // re-check the cache for any further buffered packets.
+      packet_type = CheckForPacket(buffer, bytes_read, packet);
+      while (packet_type == PacketType::Notify) {
+        LLDB_LOGF(log,
+                  "GDBRemoteCommunication::%s ignoring notification packet",
+                  __FUNCTION__);
+        packet_type = CheckForPacket(nullptr, 0, packet);
+      }
+      if (packet_type != PacketType::Invalid)
         return PacketResult::Success;
     } else {
       switch (status) {
diff --git a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationTest.cpp 
b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationTest.cpp
index e96d587b10e25..2491ace98565b 100644
--- a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationTest.cpp
+++ b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationTest.cpp
@@ -75,6 +75,25 @@ TEST_F(GDBRemoteCommunicationTest, ReadPacket) {
   }
 }
 
+// Test that async notification packets received while waiting for a response
+// are silently dropped and that we keep looking for the actual response.
+// OpenOCD sends a "%oocd_keepalive:XX#cc" notification during long memory
+// operations; like GDB (since 7.0), LLDB must ignore it rather than mistake it
+// for the response. See https://github.com/llvm/llvm-project/issues/197944.
+TEST_F(GDBRemoteCommunicationTest, ReadPacketIgnoresNotifications) {
+  StringExtractorGDBRemote response;
+
+  // A single notification ahead of the response.
+  ASSERT_TRUE(Write("%oocd_keepalive:00#54$OK#9a"));
+  ASSERT_EQ(PacketResult::Success, client.ReadPacket(response));
+  EXPECT_EQ("OK", response.GetStringRef());
+
+  // Several notifications ahead of the response.
+  ASSERT_TRUE(Write("%oocd_keepalive:01#55%oocd_keepalive:02#56$OK#9a"));
+  ASSERT_EQ(PacketResult::Success, client.ReadPacket(response));
+  EXPECT_EQ("OK", response.GetStringRef());
+}
+
 // Test that packets with incorrect RLE sequences do not cause a crash and
 // reported as invalid.
 TEST_F(GDBRemoteCommunicationTest, CheckForPacket) {

>From 72b80166d1359ab60a49e4662946b36e2a0d723d Mon Sep 17 00:00:00 2001
From: KIMRIHYEON <[email protected]>
Date: Tue, 9 Jun 2026 20:45:13 +0900
Subject: [PATCH 2/7] Address review comments

- Add a unit test asserting ReadPacket fails (times out) when only a
  notification packet is received, rather than returning it.
- Drop a redundant sentence from the notification-handling comment.
---
 .../Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp    | 3 +--
 .../Process/gdb-remote/GDBRemoteCommunicationTest.cpp        | 5 +++++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 56d1d8bc09fb1..6228095c3763a 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -269,8 +269,7 @@ 
GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
 
     if (bytes_read > 0) {
       // Drop any async notification packets (see above) and keep waiting for
-      // the actual response. Once the freshly-read bytes have been consumed,
-      // re-check the cache for any further buffered packets.
+      // the actual response.
       packet_type = CheckForPacket(buffer, bytes_read, packet);
       while (packet_type == PacketType::Notify) {
         LLDB_LOGF(log,
diff --git a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationTest.cpp 
b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationTest.cpp
index 2491ace98565b..b7bf541fdb7f8 100644
--- a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationTest.cpp
+++ b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationTest.cpp
@@ -92,6 +92,11 @@ TEST_F(GDBRemoteCommunicationTest, 
ReadPacketIgnoresNotifications) {
   ASSERT_TRUE(Write("%oocd_keepalive:01#55%oocd_keepalive:02#56$OK#9a"));
   ASSERT_EQ(PacketResult::Success, client.ReadPacket(response));
   EXPECT_EQ("OK", response.GetStringRef());
+
+  // A notification with no response following it is dropped, and the read
+  // fails (times out) rather than returning the notification.
+  ASSERT_TRUE(Write("%oocd_keepalive:03#57"));
+  EXPECT_EQ(PacketResult::ErrorReplyTimeout, client.ReadPacket(response));
 }
 
 // Test that packets with incorrect RLE sequences do not cause a crash and

>From 6a1840630acd7f2bd12ae658a0e97ec98ffd35f8 Mon Sep 17 00:00:00 2001
From: KIMRIHYEON <[email protected]>
Date: Thu, 11 Jun 2026 13:35:41 +0900
Subject: [PATCH 3/7] Add a test for a notification arriving in a separate read

Cover the case raised in review where the async notification and the
actual response do not arrive in the same read: send the notification on
its own, then send the response from another thread after a short delay so
it lands in a later read once the client is already waiting again. Verifies
that the client drops the notification and keeps reading for the real
response instead of giving up once the receive buffer briefly drains.

Assisted-by: Claude Code (Anthropic)
---
 .../gdb-remote/GDBRemoteCommunicationTest.cpp | 29 +++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationTest.cpp 
b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationTest.cpp
index b7bf541fdb7f8..094ead3881709 100644
--- a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationTest.cpp
+++ b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationTest.cpp
@@ -10,6 +10,9 @@
 #include "lldb/Host/ConnectionFileDescriptor.h"
 #include "llvm/Testing/Support/Error.h"
 
+#include <chrono>
+#include <thread>
+
 using namespace lldb_private::process_gdb_remote;
 using namespace lldb_private;
 using namespace lldb;
@@ -99,6 +102,32 @@ TEST_F(GDBRemoteCommunicationTest, 
ReadPacketIgnoresNotifications) {
   EXPECT_EQ(PacketResult::ErrorReplyTimeout, client.ReadPacket(response));
 }
 
+// Test the case where the notification and the actual response do NOT arrive
+// together in a single read: the notification is sent first, and the response
+// follows only after the client has already consumed the notification and gone
+// back to waiting. The notification must still be dropped and the client must
+// keep reading until the real response arrives, rather than giving up once the
+// receive buffer briefly drains.
+TEST_F(GDBRemoteCommunicationTest, ReadPacketIgnoresNotificationsAcrossReads) {
+  StringExtractorGDBRemote response;
+
+  // Send the notification on its own. The client should read it, drop it, and
+  // block on the next read with the buffer empty.
+  ASSERT_TRUE(Write("%oocd_keepalive:00#54"));
+
+  // Send the response from another thread after a short delay, so it lands in
+  // a separate read once the client is already waiting again.
+  std::thread responder([this] {
+    std::this_thread::sleep_for(std::chrono::milliseconds(200));
+    Write("$OK#9a");
+  });
+
+  EXPECT_EQ(PacketResult::Success, client.ReadPacket(response));
+  EXPECT_EQ("OK", response.GetStringRef());
+
+  responder.join();
+}
+
 // Test that packets with incorrect RLE sequences do not cause a crash and
 // reported as invalid.
 TEST_F(GDBRemoteCommunicationTest, CheckForPacket) {

>From 07c2a22ac5dc5b925eacedcf52f6854f4cabc176 Mon Sep 17 00:00:00 2001
From: KIMRIHYEON <[email protected]>
Date: Mon, 15 Jun 2026 14:43:36 +0900
Subject: [PATCH 4/7] Document the eConnectionStatusSuccess case in
 WaitForPacketNoLock

Explain why a zero-byte read with a success status is not treated as a
failure: it can happen on a non-socket connection when the read returns
EAGAIN, and we must keep looping for the actual response (e.g. after
dropping async notification packets). Requested in review.

Assisted-by: Claude Code (Anthropic)
---
 .../Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp    | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 6228095c3763a..94506da0345a8 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -376,6 +376,11 @@ 
GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
         }
         break;
       case eConnectionStatusSuccess:
+        // Read() can return zero bytes with a success status (e.g. a spurious
+        // readable wakeup that yields EAGAIN on a non-socket connection). That
+        // is neither EOF nor an error, so keep looping -- we may still be
+        // waiting for the actual response, for instance after dropping the
+        // async notification packets handled above.
         // printf ("status = success but error = %s\n",
         // error.AsCString("<invalid>"));
         break;

>From a619fc1f074e798475b4138d3e8d3ed1bb2a8623 Mon Sep 17 00:00:00 2001
From: KIMRIHYEON <[email protected]>
Date: Mon, 15 Jun 2026 22:24:52 +0900
Subject: [PATCH 5/7] Extract notification-draining loop into
 GetNextNonNotifyPacket

The loop that drops async notification packets while looking for the next
real packet was duplicated at the two CheckForPacket() call sites in
WaitForPacketNoLock(). Factor it into a GetNextNonNotifyPacket() helper so
the behaviour -- and the comment explaining it -- lives in one place.
No functional change. Requested in review.

Assisted-by: Claude Code (Anthropic)
---
 .../gdb-remote/GDBRemoteCommunication.cpp     | 42 +++++++++----------
 .../gdb-remote/GDBRemoteCommunication.h       |  5 +++
 2 files changed, 26 insertions(+), 21 deletions(-)

diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 94506da0345a8..6a06de99c2b54 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -232,6 +232,24 @@ 
GDBRemoteCommunication::ReadPacket(StringExtractorGDBRemote &response,
   }
 }
 
+GDBRemoteCommunication::PacketType
+GDBRemoteCommunication::GetNextNonNotifyPacket(
+    const uint8_t *src, size_t src_len, StringExtractorGDBRemote &packet) {
+  // Async notification packets (e.g. OpenOCD's "oocd_keepalive", sent during
+  // long memory operations) are not responses to our request. GDB silently
+  // drops unknown notifications while waiting for a packet; do the same and
+  // keep looking for the actual response. After the freshly-read bytes are
+  // consumed, drain any further buffered packets from the cache.
+  Log *log = GetLog(GDBRLog::Packets);
+  PacketType packet_type = CheckForPacket(src, src_len, packet);
+  while (packet_type == PacketType::Notify) {
+    LLDB_LOGF(log, "GDBRemoteCommunication::%s ignoring notification packet",
+              __FUNCTION__);
+    packet_type = CheckForPacket(nullptr, 0, packet);
+  }
+  return packet_type;
+}
+
 GDBRemoteCommunication::PacketResult
 GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
                                             Timeout<std::micro> timeout,
@@ -242,17 +260,7 @@ 
GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
   Log *log = GetLog(GDBRLog::Packets);
 
   // Check for a packet from our cache first without trying any reading...
-  // Async notification packets (e.g. OpenOCD's "oocd_keepalive", sent during
-  // long memory operations) are not responses to our request. GDB silently
-  // drops such notifications while waiting for a packet; do the same and keep
-  // looking for the actual response.
-  PacketType packet_type = CheckForPacket(nullptr, 0, packet);
-  while (packet_type == PacketType::Notify) {
-    LLDB_LOGF(log, "GDBRemoteCommunication::%s ignoring notification packet",
-              __FUNCTION__);
-    packet_type = CheckForPacket(nullptr, 0, packet);
-  }
-  if (packet_type != PacketType::Invalid)
+  if (GetNextNonNotifyPacket(nullptr, 0, packet) != PacketType::Invalid)
     return PacketResult::Success;
 
   bool timed_out = false;
@@ -268,16 +276,8 @@ 
GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
                      error, bytes_read);
 
     if (bytes_read > 0) {
-      // Drop any async notification packets (see above) and keep waiting for
-      // the actual response.
-      packet_type = CheckForPacket(buffer, bytes_read, packet);
-      while (packet_type == PacketType::Notify) {
-        LLDB_LOGF(log,
-                  "GDBRemoteCommunication::%s ignoring notification packet",
-                  __FUNCTION__);
-        packet_type = CheckForPacket(nullptr, 0, packet);
-      }
-      if (packet_type != PacketType::Invalid)
+      if (GetNextNonNotifyPacket(buffer, bytes_read, packet) !=
+          PacketType::Invalid)
         return PacketResult::Success;
     } else {
       switch (status) {
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index 35bf5eb2e3f0d..b1c235891f465 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -119,6 +119,11 @@ class GDBRemoteCommunication : public Communication {
   PacketType CheckForPacket(const uint8_t *src, size_t src_len,
                             StringExtractorGDBRemote &packet);
 
+  // Like CheckForPacket, but silently drops any async notification packets and
+  // returns the type of the next non-notification packet. See the definition.
+  PacketType GetNextNonNotifyPacket(const uint8_t *src, size_t src_len,
+                                    StringExtractorGDBRemote &packet);
+
   bool GetSendAcks() { return m_send_acks; }
 
   // Set the global packet timeout.

>From a69dd955b78e54a841296e6ce4fe7976d3517c2f Mon Sep 17 00:00:00 2001
From: KIMRIHYEON <[email protected]>
Date: Tue, 16 Jun 2026 07:01:42 +0900
Subject: [PATCH 6/7] Clarify the GetNextNonNotifyPacket comment

The previous wording said it would "drain any further buffered packets from
the cache", which is misleading: the loop does not empty the cache. Reword
to explain that CheckForPacket() returns one packet per call, so the loop
passes nullptr/0 to read each subsequent buffered packet, skipping
notifications until a non-notification packet (or Invalid) is returned.
Requested in review.

Assisted-by: Claude Code (Anthropic)
---
 .../Process/gdb-remote/GDBRemoteCommunication.cpp    | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 6a06de99c2b54..4db163d330a25 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -235,11 +235,13 @@ 
GDBRemoteCommunication::ReadPacket(StringExtractorGDBRemote &response,
 GDBRemoteCommunication::PacketType
 GDBRemoteCommunication::GetNextNonNotifyPacket(
     const uint8_t *src, size_t src_len, StringExtractorGDBRemote &packet) {
-  // Async notification packets (e.g. OpenOCD's "oocd_keepalive", sent during
-  // long memory operations) are not responses to our request. GDB silently
-  // drops unknown notifications while waiting for a packet; do the same and
-  // keep looking for the actual response. After the freshly-read bytes are
-  // consumed, drain any further buffered packets from the cache.
+  // Return the type of the next packet that is not an async notification.
+  // Notification packets (e.g. OpenOCD's "oocd_keepalive", sent during long
+  // memory operations) are not responses to our request; like GDB, silently
+  // drop them and keep looking for the actual response. CheckForPacket()
+  // appends src/src_len to its buffer and returns one packet per call, so the
+  // loop passes nullptr/0 to read each subsequent buffered packet until a
+  // non-notification packet (or PacketType::Invalid) is returned.
   Log *log = GetLog(GDBRLog::Packets);
   PacketType packet_type = CheckForPacket(src, src_len, packet);
   while (packet_type == PacketType::Notify) {

>From 8b7b18ba833141b916e6afcfa64aba71edc37d97 Mon Sep 17 00:00:00 2001
From: KIMRIHYEON <[email protected]>
Date: Mon, 22 Jun 2026 18:37:17 +0900
Subject: [PATCH 7/7] [lldb] Add an API test for ignoring notification packets

Add a gdb-remote client API test that performs a memory read against a mock
GDB server which sends multiple async notification packets before the real
response, exercising LLDB's notification handling. Also extends
gdbclientutils so the mock server can frame '%' notification packets, not
just '$' packets.

Based on a test case provided by David Spickett.

Assisted-by: Claude Code (Anthropic)
---
 .../Python/lldbsuite/test/gdbclientutils.py   | 15 +++--
 .../TestIgnoringNotifications.py              | 67 +++++++++++++++++++
 2 files changed, 76 insertions(+), 6 deletions(-)
 create mode 100644 
lldb/test/API/functionalities/gdb_remote_client/TestIgnoringNotifications.py

diff --git a/lldb/packages/Python/lldbsuite/test/gdbclientutils.py 
b/lldb/packages/Python/lldbsuite/test/gdbclientutils.py
index 4c40299f3256d..b789452bac174 100644
--- a/lldb/packages/Python/lldbsuite/test/gdbclientutils.py
+++ b/lldb/packages/Python/lldbsuite/test/gdbclientutils.py
@@ -22,15 +22,18 @@ def checksum(message):
     return check % 256
 
 
-def frame_packet(message):
+def frame_packet(message, prefix):
     """
     Create a framed packet that's ready to send over the GDB connection
     channel.
 
-    Framing includes surrounding the message between $ and #, and appending
-    a two character hex checksum.
+    Framing means:
+    * Attaching the prefix. Which is usually '$' but for notifications will be
+      '%'.
+    * Appending a '#'.
+    * Adding a two character hex checksum.
     """
-    return "$%s#%02x" % (message, checksum(message))
+    return "%s%s#%02x" % (prefix, message, checksum(message))
 
 
 def escape_binary(message):
@@ -694,9 +697,9 @@ def _parsePacket(self):
         self._receivedDataOffset = 0
         return packet
 
-    def _sendPacket(self, packet: str):
+    def _sendPacket(self, packet: str, prefix="$"):
         assert self._socket is not None
-        framed_packet = seven.bitcast_to_bytes(frame_packet(packet))
+        framed_packet = seven.bitcast_to_bytes(frame_packet(packet, prefix))
         self._socket.sendall(framed_packet)
 
     def _handlePacket(self, packet):
diff --git 
a/lldb/test/API/functionalities/gdb_remote_client/TestIgnoringNotifications.py 
b/lldb/test/API/functionalities/gdb_remote_client/TestIgnoringNotifications.py
new file mode 100644
index 0000000000000..4867d301c440a
--- /dev/null
+++ 
b/lldb/test/API/functionalities/gdb_remote_client/TestIgnoringNotifications.py
@@ -0,0 +1,67 @@
+"""
+Test that LLDB ignores notification packets (those beginning with '%')
+when waiting for a response to a '$' packet.
+
+OpenOCD is one debug server that uses notification packets to reset
+the connection timeout if a memory read takes too long. So that's what
+we test here, but it should apply to any exchange.
+"""
+
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from lldbsuite.test.gdbclientutils import *
+from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase
+
+
+class NotifyingServerResponder(MockGDBServerResponder):
+    def readMemory(self, addr, length):
+        return "01" * length
+
+
+class NotifyingServer(MockGDBServer):
+    def __init__(self, socket):
+        self._socket = socket
+        self.responder = NotifyingServerResponder()
+        self.sent_notification = False
+
+    def _sendPacket(self, packet: str, prefix="$"):
+        # In theory we could add notifies before all packets, but it always
+        # goes through the same code and just makes the test take longer.
+        if packet == "01010101":
+            # Send more than one to make sure we clear them all to find
+            # the real response.
+            super()._sendPacket("this_is_a_notification", prefix="%")
+            super()._sendPacket("this_is_a_2nd_notification", prefix="%")
+            self.sent_notification = True
+
+        super()._sendPacket(packet)
+
+
+class TestIgnoringNotifications(GDBRemoteTestBase):
+    def setUp(self):
+        TestBase.setUp(self)
+        self.server = NotifyingServer(self.server_socket_class())
+        self.server.start()
+
+    @skipIfLLVMTargetMissing("AArch64")
+    def test(self):
+        target = self.createTarget("basic_eh_frame-aarch64.yaml")
+
+        if self.TraceOn():
+            self.runCmd("log enable gdb-remote packets")
+            self.addTearDownHook(lambda: self.runCmd("log disable gdb-remote 
packets"))
+
+        process = self.connect(target)
+        lldbutil.expect_state_changes(
+            self, self.dbg.GetListener(), process, [lldb.eStateStopped]
+        )
+
+        # Disabling cache is not required but makes debugging this test easier.
+        self.runCmd("settings set target.process.disable-memory-cache true")
+
+        # Should succeed despite getting a notification before the real result.
+        self.expect("memory read --format hex 0x1234 0x1238", 
substrs=["0x01010101"])
+
+        # Check we didn't succeed because lldb got memory in some other way.
+        self.assertTrue(self.server.sent_notification)

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to