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
