[Lldb-commits] [lldb] 09531ed - [lldb] [llgs] Improve stdio forwarding in multiprocess+nonstop

Michał Górny via lldb-commits lldb-commits at lists.llvm.org
Fri Jul 15 13:12:23 PDT 2022


Author: Michał Górny
Date: 2022-07-15T21:50:39+02:00
New Revision: 09531ede6d5622da68941902072dbca517d31318

URL: https://github.com/llvm/llvm-project/commit/09531ede6d5622da68941902072dbca517d31318
DIFF: https://github.com/llvm/llvm-project/commit/09531ede6d5622da68941902072dbca517d31318.diff

LOG: [lldb] [llgs] Improve stdio forwarding in multiprocess+nonstop

Enable stdio forwarding when nonstop mode is enabled, and disable it
once it is disabled.  This makes it possible to cleanly handle stdio
forwarding while running multiple processes in non-stop mode.

Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.llvm.org/D128932

Added: 
    

Modified: 
    lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
    lldb/test/API/tools/lldb-server/TestGdbRemoteForkNonStop.py
    lldb/test/API/tools/lldb-server/main.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index be789bdf7da5..5804c13fe7b6 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -1113,14 +1113,16 @@ void GDBRemoteCommunicationServerLLGS::ProcessStateChanged(
     SendProcessOutput();
     // Then stop the forwarding, so that any late output (see llvm.org/pr25652)
     // does not interfere with our protocol.
-    StopSTDIOForwarding();
+    if (!m_non_stop)
+      StopSTDIOForwarding();
     HandleInferiorState_Stopped(process);
     break;
 
   case StateType::eStateExited:
     // Same as above
     SendProcessOutput();
-    StopSTDIOForwarding();
+    if (!m_non_stop)
+      StopSTDIOForwarding();
     HandleInferiorState_Exited(process);
     break;
 
@@ -1425,7 +1427,8 @@ GDBRemoteCommunication::PacketResult
 GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) {
   Log *log = GetLog(LLDBLog::Process);
 
-  StopSTDIOForwarding();
+  if (!m_non_stop)
+    StopSTDIOForwarding();
 
   if (m_debugged_processes.empty()) {
     LLDB_LOG(log, "No debugged process found.");
@@ -1451,7 +1454,8 @@ GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) {
 GDBRemoteCommunication::PacketResult
 GDBRemoteCommunicationServerLLGS::Handle_vKill(
     StringExtractorGDBRemote &packet) {
-  StopSTDIOForwarding();
+  if (!m_non_stop)
+    StopSTDIOForwarding();
 
   packet.SetFilePos(6); // vKill;
   uint32_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16);
@@ -3524,7 +3528,8 @@ GDBRemoteCommunicationServerLLGS::Handle_vRun(
 GDBRemoteCommunication::PacketResult
 GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) {
   Log *log = GetLog(LLDBLog::Process);
-  StopSTDIOForwarding();
+  if (!m_non_stop)
+    StopSTDIOForwarding();
 
   lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
 
@@ -3923,6 +3928,8 @@ GDBRemoteCommunicationServerLLGS::Handle_QNonStop(
   assert(packet_str.startswith("QNonStop:"));
   packet_str.consume_front("QNonStop:");
   if (packet_str == "0") {
+    if (m_non_stop)
+      StopSTDIOForwarding();
     for (auto &process_it : m_debugged_processes) {
       if (process_it.second.process_up->IsRunning()) {
         assert(m_non_stop);
@@ -3945,6 +3952,8 @@ GDBRemoteCommunicationServerLLGS::Handle_QNonStop(
     if (m_disabling_non_stop)
       return PacketResult::Success;
   } else if (packet_str == "1") {
+    if (!m_non_stop)
+      StartSTDIOForwarding();
     m_non_stop = true;
   } else
     return SendErrorResponse(Status("Invalid QNonStop packet"));
@@ -4238,9 +4247,10 @@ void GDBRemoteCommunicationServerLLGS::SetEnabledExtensions(
 
 GDBRemoteCommunication::PacketResult
 GDBRemoteCommunicationServerLLGS::SendContinueSuccessResponse() {
-  // TODO: how to handle forwarding in non-stop mode?
+  if (m_non_stop)
+    return SendOKResponse();
   StartSTDIOForwarding();
-  return m_non_stop ? SendOKResponse() : PacketResult::Success;
+  return PacketResult::Success;
 }
 
 void GDBRemoteCommunicationServerLLGS::AppendThreadIDToResponse(

diff  --git a/lldb/test/API/tools/lldb-server/TestGdbRemoteForkNonStop.py b/lldb/test/API/tools/lldb-server/TestGdbRemoteForkNonStop.py
index 7ba376485513..0868c32bdd32 100644
--- a/lldb/test/API/tools/lldb-server/TestGdbRemoteForkNonStop.py
+++ b/lldb/test/API/tools/lldb-server/TestGdbRemoteForkNonStop.py
@@ -112,3 +112,33 @@ def test_c_interspersed_nonstop(self):
     def test_vCont_interspersed_nonstop(self):
         self.resume_one_test(run_order=["parent", "child", "parent", "child"],
                              use_vCont=True, nonstop=True)
+
+    @add_test_categories(["fork"])
+    def test_c_both_nonstop(self):
+        lock1 = self.getBuildArtifact("lock1")
+        lock2 = self.getBuildArtifact("lock2")
+        parent_pid, parent_tid, child_pid, child_tid = (
+            self.start_fork_test(["fork", "process:sync:" + lock1, "print-pid",
+                                  "process:sync:" + lock2, "stop"],
+                                 nonstop=True))
+
+        self.test_sequence.add_log_lines([
+            "read packet: $Hcp{}.{}#00".format(parent_pid, parent_tid),
+            "send packet: $OK#00",
+            "read packet: $c#00",
+            "send packet: $OK#00",
+            "read packet: $Hcp{}.{}#00".format(child_pid, child_tid),
+            "send packet: $OK#00",
+            "read packet: $c#00",
+            "send packet: $OK#00",
+            {"direction": "send", "regex": "%Stop:T.*"},
+            # see the comment in TestNonStop.py, test_stdio
+            "read packet: $vStdio#00",
+            "read packet: $vStdio#00",
+            "send packet: $OK#00",
+            ], True)
+        ret = self.expect_gdbremote_sequence()
+        self.assertIn("PID: {}".format(int(parent_pid, 16)).encode(),
+                      ret["O_content"])
+        self.assertIn("PID: {}".format(int(child_pid, 16)).encode(),
+                      ret["O_content"])

diff  --git a/lldb/test/API/tools/lldb-server/main.cpp b/lldb/test/API/tools/lldb-server/main.cpp
index 21e46ef4e1b6..5d33ee6e1b0b 100644
--- a/lldb/test/API/tools/lldb-server/main.cpp
+++ b/lldb/test/API/tools/lldb-server/main.cpp
@@ -224,6 +224,8 @@ int main(int argc, char **argv) {
   int return_value = 0;
 
 #if !defined(_WIN32)
+  bool is_child = false;
+
   // Set the signal handler.
   sig_t sig_result = signal(SIGALRM, signal_handler);
   if (sig_result == SIG_ERR) {
@@ -324,10 +326,32 @@ int main(int argc, char **argv) {
       func_p();
 #if !defined(_WIN32) && !defined(TARGET_OS_WATCH) && !defined(TARGET_OS_TV)
     } else if (arg == "fork") {
-      assert (fork() != -1);
+      pid_t fork_pid = fork();
+      assert(fork_pid != -1);
+      is_child = fork_pid == 0;
     } else if (arg == "vfork") {
       if (vfork() == 0)
         _exit(0);
+    } else if (consume_front(arg, "process:sync:")) {
+      // this is only valid after fork
+      const char *filenames[] = {"parent", "child"};
+      std::string my_file = arg + "." + filenames[is_child];
+      std::string other_file = arg + "." + filenames[!is_child];
+
+      // indicate that we're ready
+      FILE *f = fopen(my_file.c_str(), "w");
+      assert(f);
+      fclose(f);
+
+      // wait for the other process to be ready
+      for (int i = 0; i < 5; ++i) {
+        f = fopen(other_file.c_str(), "r");
+        if (f)
+          break;
+        std::this_thread::sleep_for(std::chrono::milliseconds(125 * (1<<i)));
+      }
+      assert(f);
+      fclose(f);
 #endif
     } else if (consume_front(arg, "thread:new")) {
       std::promise<void> promise;


        


More information about the lldb-commits mailing list