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 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 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; 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; 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/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 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() {