mgorny updated this revision to Diff 432910.
mgorny added a comment.

Split the main tests into two variants: one that assumes that server runs in 
all-stop mode (like lldb-server), the other assuming it runs in non-stop mode 
(like gdbserver on Linux).


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126614/new/

https://reviews.llvm.org/D126614

Files:
  lldb/packages/Python/lldbsuite/test/gdbclientutils.py
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
  lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
  lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
  lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td
  lldb/source/Target/Process.cpp
  lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py

Index: lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py
===================================================================
--- lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py
+++ lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py
@@ -585,3 +585,168 @@
         }
         self.do_siginfo_test("remote-freebsd", "basic_eh_frame.yaml",
                              data, expected)
+
+    def test_QNonStop_query(self):
+        class MyResponder(MockGDBServerResponder):
+            vStopped_counter = 0
+
+            def qSupported(self, client_supported):
+                return "QNonStop+;" + super().qSupported(client_supported)
+
+            def QNonStop(self, val):
+                assert val == 1
+                return "OK"
+
+            def qfThreadInfo(self):
+                return "m10,12"
+
+            def qsThreadInfo(self):
+                return "l"
+
+            def vStopped(self):
+                self.vStopped_counter += 1
+                return ("OK" if self.vStopped_counter % 2 == 0
+                        else "T00;thread:10")
+
+        self.dbg.HandleCommand(
+            "settings set plugin.process.gdb-remote.use-non-stop-protocol true")
+        self.addTearDownHook(lambda:
+            self.runCmd(
+                "settings set plugin.process.gdb-remote.use-non-stop-protocol "
+                "false"))
+        self.server.responder = MyResponder()
+        target = self.dbg.CreateTarget("")
+        process = self.connect(target)
+        self.assertPacketLogContains(["QNonStop:1", "vStopped"])
+
+    def test_QNonStop_run(self):
+        class MyResponder(MockGDBServerResponder):
+            vStopped_counter = 0
+
+            def qSupported(self, client_supported):
+                return "QNonStop+;" + super().qSupported(client_supported)
+
+            def QNonStop(self, val):
+                assert val == 1
+                return "OK"
+
+            def qfThreadInfo(self):
+                return "m10,12"
+
+            def qsThreadInfo(self):
+                return "l"
+
+            def vStopped(self):
+                self.vStopped_counter += 1
+                return ("OK" if self.vStopped_counter > 1
+                        else "T00;thread:10")
+
+            def cont(self):
+                self.vStopped_counter = 0
+                return ["OK", "%Stop:T02;thread:12"]
+
+            def vCtrlC(self):
+                return "OK"
+
+        self.dbg.HandleCommand(
+            "settings set plugin.process.gdb-remote.use-non-stop-protocol true")
+        self.addTearDownHook(lambda:
+            self.runCmd(
+                "settings set plugin.process.gdb-remote.use-non-stop-protocol "
+                "false"))
+        self.server.responder = MyResponder()
+        target = self.dbg.CreateTarget("")
+        process = self.connect(target)
+        self.assertPacketLogContains(["QNonStop:1"])
+
+        process.Continue()
+        self.assertPacketLogContains(["vStopped", "vCtrlC"])
+        self.assertEqual(process.GetSelectedThread().GetStopReason(),
+                         lldb.eStopReasonSignal)
+        self.assertEqual(process.GetSelectedThread().GetStopDescription(100),
+                         "signal SIGINT")
+
+    def test_QNonStop_run_non_stop_server(self):
+        class MyResponder(MockGDBServerResponder):
+            def qSupported(self, client_supported):
+                return "QNonStop+;" + super().qSupported(client_supported)
+
+            def QNonStop(self, val):
+                assert val == 1
+                return "OK"
+
+            def qfThreadInfo(self):
+                return "m10,12"
+
+            def qsThreadInfo(self):
+                return "l"
+
+            def vStopped(self):
+                return "OK"
+
+            def cont(self):
+                return ["OK", "%Stop:T02;thread:12"]
+
+            def vCtrlC(self):
+                return ["OK", "%Stop:T00;thread:10"]
+
+        self.dbg.HandleCommand(
+            "settings set plugin.process.gdb-remote.use-non-stop-protocol true")
+        self.addTearDownHook(lambda:
+            self.runCmd(
+                "settings set plugin.process.gdb-remote.use-non-stop-protocol "
+                "false"))
+        self.server.responder = MyResponder()
+        target = self.dbg.CreateTarget("")
+        process = self.connect(target)
+        self.assertPacketLogContains(["QNonStop:1"])
+
+        process.Continue()
+        self.assertPacketLogContains(["vStopped", "vCtrlC"])
+        self.assertEqual(process.GetSelectedThread().GetStopReason(),
+                         lldb.eStopReasonSignal)
+        self.assertEqual(process.GetSelectedThread().GetStopDescription(100),
+                         "signal SIGINT")
+
+    def test_QNonStop_vCtrlC(self):
+        class MyResponder(MockGDBServerResponder):
+            vStopped_counter = 0
+
+            def qSupported(self, client_supported):
+                return "QNonStop+;" + super().qSupported(client_supported)
+
+            def QNonStop(self, val):
+                assert val == 1
+                return "OK"
+
+            def qfThreadInfo(self):
+                return "m10,12"
+
+            def vStopped(self):
+                self.vStopped_counter += 1
+                return ("OK" if self.vStopped_counter % 2 == 0
+                        else "T00;thread:10")
+
+            def cont(self):
+                return ["OK"]
+
+            def vCtrlC(self):
+                return ["OK", "%Stop:T00;thread:10"]
+
+        self.dbg.HandleCommand(
+            "settings set plugin.process.gdb-remote.use-non-stop-protocol true")
+        self.addTearDownHook(lambda:
+            self.runCmd(
+                "settings set plugin.process.gdb-remote.use-non-stop-protocol "
+                "false"))
+        self.server.responder = MyResponder()
+        target = self.dbg.CreateTarget("")
+        process = self.connect(target)
+        self.assertPacketLogContains(["QNonStop:1"])
+
+        self.dbg.SetAsync(True)
+        process.Continue()
+        process.Stop()
+        self.assertPacketLogContains(["vStopped", "vCtrlC"])
+        self.assertEqual(process.GetSelectedThread().GetStopReason(),
+                         lldb.eStopReasonNone)
Index: lldb/source/Target/Process.cpp
===================================================================
--- lldb/source/Target/Process.cpp
+++ lldb/source/Target/Process.cpp
@@ -3095,7 +3095,7 @@
 }
 
 Status Process::Halt(bool clear_thread_plans, bool use_run_lock) {
-  if (!StateIsRunningState(m_public_state.GetValue()))
+  if (!StateIsRunningState(m_private_state.GetValue()))
     return Status("Process is not running.");
 
   // Don't clear the m_clear_thread_plans_on_stop, only set it to true if in
Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td
+++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td
@@ -9,6 +9,10 @@
     Global,
     DefaultStringValue<"">,
     Desc<"The file that provides the description for remote target registers.">;
+  def UseNonStopProtocol: Property<"use-non-stop-protocol", "Boolean">,
+    Global,
+    DefaultFalse,
+    Desc<"If true, LLDB will enable non-stop mode on the server and expect non-stop-style notifications from it. Note that LLDB currently requires that all threads are stopped anyway in non-stop mode.">;
   def UseSVR4: Property<"use-libraries-svr4", "Boolean">,
     Global,
     DefaultTrue,
Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -287,6 +287,7 @@
   int64_t m_breakpoint_pc_offset;
   lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach
   bool m_use_g_packet_for_reading;
+  bool m_use_non_stop_protocol;
 
   bool m_allow_flash_writes;
   using FlashRangeVector = lldb_private::RangeVector<lldb::addr_t, size_t>;
Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -164,6 +164,11 @@
     const uint32_t idx = ePropertyUseGPacketForReading;
     return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
   }
+
+  bool GetUseNonStopProtocol() const {
+    const uint32_t idx = ePropertyUseNonStopProtocol;
+    return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
+  }
 };
 
 static PluginProperties &GetGlobalPluginProperties() {
@@ -301,6 +306,8 @@
 
   m_use_g_packet_for_reading =
       GetGlobalPluginProperties().GetUseGPacketForReading();
+  m_use_non_stop_protocol =
+      GetGlobalPluginProperties().GetUseNonStopProtocol();
 }
 
 // Destructor
@@ -953,6 +960,8 @@
   m_gdb_comm.GetVContSupported('c');
   m_gdb_comm.GetVAttachOrWaitSupported();
   m_gdb_comm.EnableErrorStringInPacket();
+  if (m_use_non_stop_protocol)
+    m_gdb_comm.EnableNonStop();
 
   // First dispatch any commands from the platform:
   auto handle_cmds = [&] (const Args &args) ->  void {
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -321,6 +321,8 @@
 
   void EnableErrorStringInPacket();
 
+  void EnableNonStop();
+
   bool GetQXferLibrariesReadSupported();
 
   bool GetQXferLibrariesSVR4ReadSupported();
@@ -523,6 +525,8 @@
 
   bool GetSaveCoreSupported() const;
 
+  bool GetNonStopSupported() const;
+
 protected:
   LazyBool m_supports_not_sending_acks = eLazyBoolCalculate;
   LazyBool m_supports_thread_suffix = eLazyBoolCalculate;
@@ -563,6 +567,7 @@
   LazyBool m_supports_multiprocess = eLazyBoolCalculate;
   LazyBool m_supports_memory_tagging = eLazyBoolCalculate;
   LazyBool m_supports_qSaveCore = eLazyBoolCalculate;
+  LazyBool m_supports_QNonStop = eLazyBoolCalculate;
   LazyBool m_uses_native_signals = eLazyBoolCalculate;
 
   bool m_supports_qProcessInfoPID : 1, m_supports_qfProcessInfo : 1,
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -276,6 +276,7 @@
     m_avoid_g_packets = eLazyBoolCalculate;
     m_supports_multiprocess = eLazyBoolCalculate;
     m_supports_qSaveCore = eLazyBoolCalculate;
+    m_supports_QNonStop = eLazyBoolCalculate;
     m_supports_qXfer_auxv_read = eLazyBoolCalculate;
     m_supports_qXfer_libraries_read = eLazyBoolCalculate;
     m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
@@ -335,6 +336,7 @@
   m_supports_QPassSignals = eLazyBoolNo;
   m_supports_memory_tagging = eLazyBoolNo;
   m_supports_qSaveCore = eLazyBoolNo;
+  m_supports_QNonStop = eLazyBoolNo;
   m_uses_native_signals = eLazyBoolNo;
 
   m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if
@@ -384,6 +386,8 @@
         m_supports_memory_tagging = eLazyBoolYes;
       else if (x == "qSaveCore+")
         m_supports_qSaveCore = eLazyBoolYes;
+      else if (x == "QNonStop+")
+        m_supports_QNonStop = eLazyBoolYes;
       else if (x == "native-signals+")
         m_uses_native_signals = eLazyBoolYes;
       // Look for a list of compressions in the features list e.g.
@@ -530,6 +534,10 @@
   return m_supports_qSaveCore == eLazyBoolYes;
 }
 
+bool GDBRemoteCommunicationClient::GetNonStopSupported() const {
+  return m_supports_QNonStop == eLazyBoolYes;
+}
+
 StructuredData::ObjectSP GDBRemoteCommunicationClient::GetThreadsInfo() {
   // Get information on all threads at one using the "jThreadsInfo" packet
   StructuredData::ObjectSP object_sp;
@@ -579,6 +587,18 @@
   }
 }
 
+void GDBRemoteCommunicationClient::EnableNonStop() {
+  if (!GetNonStopSupported())
+    return;
+
+  StringExtractorGDBRemote response;
+  if (SendPacketAndWaitForResponse("QNonStop:1", response) ==
+      PacketResult::Success) {
+    if (response.IsOKResponse())
+      SetNonStopProtocol(true);
+  }
+}
+
 bool GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported() {
   if (m_supports_jLoadedDynamicLibrariesInfos == eLazyBoolCalculate) {
     StringExtractorGDBRemote response;
@@ -2747,8 +2767,13 @@
 
 bool GDBRemoteCommunicationClient::GetStopReply(
     StringExtractorGDBRemote &response) {
-  if (SendPacketAndWaitForResponse("?", response) == PacketResult::Success)
+  if (SendPacketAndWaitForResponse("?", response) == PacketResult::Success) {
+    if (GetNonStopProtocol()) {
+      if (!DrainNotificationQueue("vStopped"))
+        return false;  // TODO: better error handling
+    }
     return response.IsNormalResponse();
+  }
   return false;
 }
 
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
@@ -59,6 +59,12 @@
       std::chrono::seconds interrupt_timeout,
       llvm::function_ref<void(llvm::StringRef)> output_callback);
 
+  bool GetNonStopProtocol() { return m_non_stop_protocol; }
+
+  void SetNonStopProtocol(bool enabled) { m_non_stop_protocol = enabled; }
+
+  bool DrainNotificationQueue(llvm::StringRef command);
+
   class Lock {
   public:
     // If interrupt_timeout == 0 seconds, only take the lock if the target is
@@ -133,6 +139,9 @@
 
   /// Whether we should resume after a stop.
   bool m_should_stop;
+
+  /// Whether non-stop protocol should be used.
+  bool m_non_stop_protocol = false;
   /// @}
 
   /// This handles the synchronization between individual async threads. For
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
@@ -52,13 +52,13 @@
   if (!cont_lock)
     return eStateInvalid;
   OnRunPacketSent(true);
-  // The main ReadPacket loop wakes up at computed_timeout intervals, just to 
+  // The main ReadPacket loop wakes up at computed_timeout intervals, just to
   // check that the connection hasn't dropped.  When we wake up we also check
   // whether there is an interrupt request that has reached its endpoint.
-  // If we want a shorter interrupt timeout that kWakeupInterval, we need to 
+  // If we want a shorter interrupt timeout that kWakeupInterval, we need to
   // choose the shorter interval for the wake up as well.
-  std::chrono::seconds computed_timeout = std::min(interrupt_timeout, 
-                                                   kWakeupInterval);
+  std::chrono::seconds computed_timeout =
+      std::min(interrupt_timeout, kWakeupInterval);
   for (;;) {
     PacketResult read_result = ReadPacket(response, computed_timeout, false);
     // Reset the computed_timeout to the default value in case we are going
@@ -79,7 +79,8 @@
         // time left till the interrupt timeout.  But don't wait longer
         // than our wakeup timeout.
         auto new_wait = m_interrupt_endpoint - cur_time;
-        computed_timeout = std::min(kWakeupInterval,
+        computed_timeout = std::min(
+            kWakeupInterval,
             std::chrono::duration_cast<std::chrono::seconds>(new_wait));
         continue;
       }
@@ -95,10 +96,72 @@
     if (response.Empty())
       return eStateInvalid;
 
-    const char stop_type = response.GetChar();
     LLDB_LOGF(log, "GDBRemoteClientBase::%s () got packet: %s", __FUNCTION__,
               response.GetStringRef().data());
 
+    // We do not currently support full asynchronous communication.  Instead,
+    // when in non-stop mode, we:
+    // 1) get the "OK" response to the continue packet
+    // 2) wait for the asynchronous %Stop notification
+    // 3) drain the notification queue
+    // 4) issue a "vCtrlC" command to ensure that all threads stop
+    // 5) repeat 1-3 for the response to this packet
+
+    if (response.IsOKResponse())
+      continue;
+    // TODO: get a proper mechanism for async notifications
+    if (response.GetStringRef().startswith("Stop:")) {
+      response.Reset(response.GetStringRef().substr(5));
+
+      if (!DrainNotificationQueue("vStopped"))
+        return eStateInvalid;
+
+      switch (response.GetStringRef()[0]) {
+      case 'W':
+      case 'X':
+        // Do not attempt to stop the process if it exited already.
+        break;
+      default:
+        StringExtractorGDBRemote stop_response;
+        if (SendPacketAndWaitForResponseNoLock("vCtrlC", stop_response) !=
+            PacketResult::Success) {
+          LLDB_LOGF(log, "GDBRemoteClientBase::%s () vCtrlC failed",
+                    __FUNCTION__);
+          return eStateInvalid;
+        }
+
+        LLDB_LOGF(log, "GDBRemoteClientBase::%s () vCtrlC response: %s",
+                  __FUNCTION__, stop_response.GetStringRef().data());
+        if (stop_response.IsUnsupportedResponse()) {
+          LLDB_LOGF(log, "GDBRemoteClientBase::%s () vCtrlC unsupported",
+                    __FUNCTION__);
+          return eStateInvalid;
+        }
+        if (!stop_response.IsOKResponse()) {
+          LLDB_LOGF(log, "GDBRemoteClientBase::%s () vCtrlC failed",
+                    __FUNCTION__);
+          return eStateInvalid;
+        }
+
+        // vCtrlC may not do anything, so timeout if we don't get notification
+        if (ReadPacket(stop_response, milliseconds(500), false) ==
+            PacketResult::Success) {
+          if (!stop_response.GetStringRef().startswith("Stop:")) {
+            LLDB_LOGF(log,
+                      "GDBRemoteClientBase::%s () unexpected response "
+                      "after vCtrlC",
+                      __FUNCTION__);
+            return eStateInvalid;
+          }
+
+          if (!DrainNotificationQueue("vStopped"))
+            return eStateInvalid;
+        }
+      }
+    }
+
+    const char stop_type = response.GetChar();
+
     switch (stop_type) {
     case 'W':
     case 'X':
@@ -283,6 +346,30 @@
     BroadcastEvent(eBroadcastBitRunPacketSent, nullptr);
 }
 
+bool GDBRemoteClientBase::DrainNotificationQueue(llvm::StringRef command) {
+  Log *log = GetLog(GDBRLog::Process);
+  for (;;) {
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponseNoLock(command, response) ==
+        PacketResult::Success) {
+      if (response.IsUnsupportedResponse()) {
+        LLDB_LOGF(log, "GDBRemoteClientBase::%s () %s unsupported",
+                  __FUNCTION__, command.data());
+        return false;
+      }
+
+      LLDB_LOGF(log, "GDBRemoteClientBase::%s () %s response: %s", __FUNCTION__,
+                command.data(), response.GetStringRef().data());
+      if (response.IsOKResponse())
+        return true;
+    } else {
+      LLDB_LOGF(log, "GDBRemoteClientBase::%s () sending %s failed",
+                __FUNCTION__, command.data());
+      return false;
+    }
+  }
+}
+
 ///////////////////////////////////////
 // GDBRemoteClientBase::ContinueLock //
 ///////////////////////////////////////
@@ -358,18 +445,23 @@
     if (m_comm.m_async_count == 1) {
       // The sender has sent the continue packet and we are the first async
       // packet. Let's interrupt it.
-      const char ctrl_c = '\x03';
-      ConnectionStatus status = eConnectionStatusSuccess;
-      size_t bytes_written = m_comm.Write(&ctrl_c, 1, status, nullptr);
-      if (bytes_written == 0) {
+      bool success;
+      if (m_comm.GetNonStopProtocol())
+        success = m_comm.SendPacketNoLock("vCtrlC") == PacketResult::Success;
+      else {
+        const char ctrl_c = '\x03';
+        ConnectionStatus status = eConnectionStatusSuccess;
+        success = m_comm.Write(&ctrl_c, 1, status, nullptr) != 0;
+      }
+      if (!success) {
         --m_comm.m_async_count;
         LLDB_LOGF(log, "GDBRemoteClientBase::Lock::Lock failed to send "
                        "interrupt packet");
         return;
       }
       m_comm.m_interrupt_endpoint = steady_clock::now() + m_interrupt_timeout;
-      if (log)
-        log->PutCString("GDBRemoteClientBase::Lock::Lock sent packet: \\x03");
+      if (log && !m_comm.GetNonStopProtocol())
+          log->PutCString("GDBRemoteClientBase::Lock::Lock sent packet: \\x03");
     }
     m_comm.m_cv.wait(lock, [this] { return !m_comm.m_is_running; });
     m_did_interrupt = true;
Index: lldb/packages/Python/lldbsuite/test/gdbclientutils.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/gdbclientutils.py
+++ lldb/packages/Python/lldbsuite/test/gdbclientutils.py
@@ -26,7 +26,11 @@
     Framing includes surrounding the message between $ and #, and appending
     a two character hex checksum.
     """
-    return "$%s#%02x" % (message, checksum(message))
+    prefix = "$"
+    if message.startswith("%"):
+        prefix = "%"
+        message = message[1:]
+    return "%s%s#%02x" % (prefix, message, checksum(message))
 
 
 def escape_binary(message):
@@ -200,6 +204,12 @@
         if packet.startswith("qRegisterInfo"):
             regnum = int(packet[len("qRegisterInfo"):], 16)
             return self.qRegisterInfo(regnum)
+        if packet.startswith("QNonStop:"):
+            return self.QNonStop(int(packet.split(":", 1)[1]))
+        if packet == "vStopped":
+            return self.vStopped()
+        if packet == "vCtrlC":
+            return self.vCtrlC()
         if packet == "k":
             return self.k()
 
@@ -333,6 +343,15 @@
     def qRegisterInfo(self, num):
         return ""
 
+    def QNonStop(self, enabled):
+        return ""
+
+    def vStopped(self):
+        return ""
+
+    def vCtrlC(self):
+        return ""
+
     def k(self):
         return ["W01", self.RESPONSE_DISCONNECT]
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to