mgorny created this revision.
mgorny added reviewers: labath, krytarowski, emaste, jingham.
Herald added a subscriber: arichardson.
Herald added a project: All.
mgorny requested review of this revision.

Introduce the initial support for handling multiple ContinueDelegates
in GDBRemoteClientBase::SendContinuePacketAndWaitForResponse().  This
is the first step towards moving to a shared asynchronous thread serving
multiple ProcessGDBRemote instances.

The final goal is that every stop response will be passed through all
ContinueDelegates, and every delegate will decide whether it is
applicable to its process.  The additional `handled` parameter is used
to indicate that the correct delegate has been found and no further
delegates need to be invoked.

The next step is going to involve decoupling the async thread from
ProcessGDBRemote itself, and moving all the logic responsible for
updating the process status into ContinueDelegate API.

Sponsored by: The FreeBSD Foundation


https://reviews.llvm.org/D131837

Files:
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
  lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
  lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
  lldb/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp

Index: lldb/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp
===================================================================
--- lldb/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp
+++ lldb/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp
@@ -29,12 +29,23 @@
   unsigned stop_reply_called = 0;
   std::vector<std::string> structured_data_packets;
 
-  void HandleAsyncStdout(llvm::StringRef out) override { output += out; }
-  void HandleAsyncMisc(llvm::StringRef data) override { misc_data += data; }
-  void HandleStopReply() override { ++stop_reply_called; }
+  void HandleAsyncStdout(llvm::StringRef out, bool &handled) override {
+    output += out;
+    handled = true;
+  }
+  void HandleAsyncMisc(llvm::StringRef data, bool &handled) override {
+    misc_data += data;
+    handled = true;
+  }
+  void HandleStopReply(bool &handled) override {
+    ++stop_reply_called;
+    handled = true;
+  }
 
-  void HandleAsyncStructuredDataPacket(llvm::StringRef data) override {
+  void HandleAsyncStructuredDataPacket(llvm::StringRef data,
+                                       bool &handled) override {
     structured_data_packets.push_back(std::string(data));
+    handled = true;
   }
 };
 
@@ -63,9 +74,8 @@
   ListenerSP listener_sp = Listener::MakeListener("listener");
 
   StateType SendCPacket(StringExtractorGDBRemote &response) {
-    return client.SendContinuePacketAndWaitForResponse(delegate, LinuxSignals(),
-                                                       "c", g_timeout, 
-                                                       response);
+    return client.SendContinuePacketAndWaitForResponse(
+        {&delegate}, LinuxSignals(), "c", g_timeout, response);
   }
 
   void WaitForRunEvent() {
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
@@ -425,10 +425,11 @@
                                            lldb::user_id_t break_loc_id);
 
   // ContinueDelegate interface
-  void HandleAsyncStdout(llvm::StringRef out) override;
-  void HandleAsyncMisc(llvm::StringRef data) override;
-  void HandleStopReply() override;
-  void HandleAsyncStructuredDataPacket(llvm::StringRef data) override;
+  void HandleAsyncStdout(llvm::StringRef out, bool &handled) override;
+  void HandleAsyncMisc(llvm::StringRef data, bool &handled) override;
+  void HandleStopReply(bool &handled) override;
+  void HandleAsyncStructuredDataPacket(llvm::StringRef data,
+                                       bool &handled) override;
 
   void SetThreadPc(const lldb::ThreadSP &thread_sp, uint64_t index);
   using ModuleCacheKey = std::pair<std::string, std::string>;
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
@@ -3484,7 +3484,7 @@
 
             StateType stop_state =
                 GetGDBRemote().SendContinuePacketAndWaitForResponse(
-                    *this, *GetUnixSignals(),
+                    {this}, *GetUnixSignals(),
                     llvm::StringRef(continue_cstr, continue_cstr_len),
                     GetInterruptTimeout(), response);
 
@@ -4642,14 +4642,15 @@
   m_gdb_comm.ServeSymbolLookups(this);
 }
 
-void ProcessGDBRemote::HandleAsyncStdout(llvm::StringRef out) {
+void ProcessGDBRemote::HandleAsyncStdout(llvm::StringRef out, bool &handled) {
   AppendSTDOUT(out.data(), out.size());
+  handled = true;
 }
 
 static const char *end_delimiter = "--end--;";
 static const int end_delimiter_len = 8;
 
-void ProcessGDBRemote::HandleAsyncMisc(llvm::StringRef data) {
+void ProcessGDBRemote::HandleAsyncMisc(llvm::StringRef data, bool &handled) {
   std::string input = data.str(); // '1' to move beyond 'A'
   if (m_partial_profile_data.length() > 0) {
     m_partial_profile_data.append(input);
@@ -4672,6 +4673,8 @@
     // Last incomplete chunk.
     m_partial_profile_data = input.substr(pos);
   }
+
+  handled = true;
 }
 
 std::string ProcessGDBRemote::HarmonizeThreadIdsForProfileData(
@@ -4750,7 +4753,8 @@
   return output_stream.str();
 }
 
-void ProcessGDBRemote::HandleStopReply() {
+void ProcessGDBRemote::HandleStopReply(bool &handled) {
+  handled = true;
   if (GetStopID() != 0)
     return;
 
@@ -4854,10 +4858,12 @@
   return json_sp;
 }
 
-void ProcessGDBRemote::HandleAsyncStructuredDataPacket(llvm::StringRef data) {
+void ProcessGDBRemote::HandleAsyncStructuredDataPacket(llvm::StringRef data,
+                                                       bool &handled) {
   auto structured_data_sp = ParseStructuredDataPacket(data);
   if (structured_data_sp)
     RouteAsyncStructuredData(structured_data_sp);
+  handled = true;
 }
 
 class CommandObjectProcessGDBRemoteSpeedTest : public CommandObjectParsed {
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
@@ -20,15 +20,16 @@
 public:
   struct ContinueDelegate {
     virtual ~ContinueDelegate();
-    virtual void HandleAsyncStdout(llvm::StringRef out) = 0;
-    virtual void HandleAsyncMisc(llvm::StringRef data) = 0;
-    virtual void HandleStopReply() = 0;
+    virtual void HandleAsyncStdout(llvm::StringRef out, bool &handled) = 0;
+    virtual void HandleAsyncMisc(llvm::StringRef data, bool &handled) = 0;
+    virtual void HandleStopReply(bool &handled) = 0;
 
     /// Process asynchronously-received structured data.
     ///
     /// \param[in] data
     ///   The complete data packet, expected to start with JSON-async.
-    virtual void HandleAsyncStructuredDataPacket(llvm::StringRef data) = 0;
+    virtual void HandleAsyncStructuredDataPacket(llvm::StringRef data,
+                                                 bool &handled) = 0;
   };
 
   GDBRemoteClientBase(const char *comm_name, const char *listener_name);
@@ -38,7 +39,7 @@
   bool Interrupt(std::chrono::seconds interrupt_timeout);
 
   lldb::StateType SendContinuePacketAndWaitForResponse(
-      ContinueDelegate &delegate, const UnixSignals &signals,
+      llvm::ArrayRef<ContinueDelegate *> delegates, const UnixSignals &signals,
       llvm::StringRef payload, std::chrono::seconds interrupt_timeout,
       StringExtractorGDBRemote &response);
 
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
@@ -37,7 +37,7 @@
       m_is_running(false), m_should_stop(false) {}
 
 StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
-    ContinueDelegate &delegate, const UnixSignals &signals,
+    llvm::ArrayRef<ContinueDelegate *> delegates, const UnixSignals &signals,
     llvm::StringRef payload, std::chrono::seconds interrupt_timeout,
     StringExtractorGDBRemote &response) {
   Log *log = GetLog(GDBRLog::Process);
@@ -113,15 +113,31 @@
     case 'O': {
       std::string inferior_stdout;
       response.GetHexByteString(inferior_stdout);
-      delegate.HandleAsyncStdout(inferior_stdout);
+      for (auto delegate : delegates) {
+        bool handled = false;
+        delegate->HandleAsyncStdout(inferior_stdout, handled);
+        if (handled)
+          break;
+      }
       break;
     }
     case 'A':
-      delegate.HandleAsyncMisc(
-          llvm::StringRef(response.GetStringRef()).substr(1));
+      for (auto delegate : delegates) {
+        bool handled = false;
+        delegate->HandleAsyncMisc(
+            llvm::StringRef(response.GetStringRef()).substr(1), handled);
+        if (handled)
+          break;
+      }
       break;
     case 'J':
-      delegate.HandleAsyncStructuredDataPacket(response.GetStringRef());
+      for (auto delegate : delegates) {
+        bool handled = false;
+        delegate->HandleAsyncStructuredDataPacket(response.GetStringRef(),
+                                                  handled);
+        if (handled)
+          break;
+      }
       break;
     case 'T':
     case 'S':
@@ -140,7 +156,12 @@
       m_continue_packet = 'c';
       cont_lock.unlock();
 
-      delegate.HandleStopReply();
+      for (auto delegate : delegates) {
+        bool handled = false;
+        delegate->HandleStopReply(handled);
+        if (handled)
+          break;
+      }
       if (should_stop)
         return eStateStopped;
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to