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

Implemented the requested changes.


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

https://reviews.llvm.org/D128893

Files:
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
  lldb/test/API/tools/lldb-server/TestNonStop.py

Index: lldb/test/API/tools/lldb-server/TestNonStop.py
===================================================================
--- lldb/test/API/tools/lldb-server/TestNonStop.py
+++ lldb/test/API/tools/lldb-server/TestNonStop.py
@@ -366,3 +366,33 @@
              "send packet: $OK#00",
              ], True)
         self.expect_gdbremote_sequence()
+
+    @add_test_categories(["llgs"])
+    def test_leave_nonstop(self):
+        self.build()
+        self.set_inferior_startup_launch()
+        procs = self.prep_debug_monitor_and_inferior(
+                inferior_args=["thread:new", "thread:new", "stop", "sleep:15"])
+        self.test_sequence.add_log_lines(
+            ["read packet: $QNonStop:1#00",
+             "send packet: $OK#00",
+             # stop is used to synchronize starting threads
+             "read packet: $c#63",
+             "send packet: $OK#00",
+             {"direction": "send", "regex": "%Stop:T.*"},
+             "read packet: $c#63",
+             "send packet: $OK#00",
+             # verify that the threads are running now
+             "read packet: $?#00",
+             "send packet: $OK#00",
+             "read packet: $QNonStop:0#00",
+             "send packet: $OK#00",
+             # we should issue some random request now to verify that the stub
+             # did not send stop reasons -- we may verify whether notification
+             # queue was cleared while at it
+             "read packet: $vStopped#00",
+             "send packet: $Eff#00",
+             "read packet: $?#00",
+             {"direction": "send", "regex": "[$]T.*"},
+             ], True)
+        self.expect_gdbremote_sequence()
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -88,8 +88,9 @@
   struct DebuggedProcess {
     enum class Flag {
       vkilled = (1u << 0),
+      stopping_due_to_qnonstop = (1u << 1),
 
-      LLVM_MARK_AS_BITMASK_ENUM(vkilled)
+      LLVM_MARK_AS_BITMASK_ENUM(stopping_due_to_qnonstop)
     };
 
     std::unique_ptr<NativeProcessProtocol> process_up;
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -1920,6 +1920,24 @@
     bool force_synchronous) {
   Log *log = GetLog(LLDBLog::Process);
 
+  DebuggedProcess &process_info = m_debugged_processes.at(process.GetID());
+  if (bool(process_info.flags &
+           DebuggedProcess::Flag::stopping_due_to_qnonstop)) {
+    process_info.flags &= ~DebuggedProcess::Flag::stopping_due_to_qnonstop;
+
+    // Check if we are waiting for any more processes to stop.  If we are,
+    // do not send the OK response yet.
+    for (const auto &it : m_debugged_processes) {
+      if (bool(it.second.flags &
+               DebuggedProcess::Flag::stopping_due_to_qnonstop))
+        return PacketResult::Success;
+    }
+
+    // If all expected processes were stopped after a QNonStop:0 request,
+    // send the OK response.
+    return SendOKResponse();
+  }
+
   switch (process_state) {
   case eStateAttaching:
   case eStateLaunching:
@@ -3917,12 +3935,35 @@
 GDBRemoteCommunication::PacketResult
 GDBRemoteCommunicationServerLLGS::Handle_QNonStop(
     StringExtractorGDBRemote &packet) {
+  Log *log = GetLog(LLDBLog::Process);
+
   StringRef packet_str{packet.GetStringRef()};
   assert(packet_str.startswith("QNonStop:"));
   packet_str.consume_front("QNonStop:");
   if (packet_str == "0") {
+    bool any_running = false;
+    for (auto &process_it : m_debugged_processes) {
+      if (process_it.second.process_up->IsRunning()) {
+        Status error = process_it.second.process_up->Interrupt();
+        if (error.Fail()) {
+          LLDB_LOG(log,
+                   "while disabling nonstop, failed to halt process {0}: {1}",
+                   process_it.first, error);
+          return SendErrorResponse(0x41);
+        }
+        // we must not send stop reasons after QNonStop
+        process_it.second.flags |=
+            DebuggedProcess::Flag::stopping_due_to_qnonstop;
+        any_running = true;
+      }
+    }
+    m_stdio_notification_queue.clear();
+    m_stop_notification_queue.clear();
     m_non_stop = false;
-    // TODO: stop all threads
+    // If we are stopping anything, defer sending the OK response until we're
+    // done.
+    if (any_running)
+      return PacketResult::Success;
   } else if (packet_str == "1") {
     m_non_stop = true;
   } else
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to