[Lldb-commits] [lldb] [lldb] Updated lldb-server to spawn the child process and share socket (PR #101283)

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Wed Aug 7 05:57:57 PDT 2024


================
@@ -114,6 +126,175 @@ static Status save_socket_id_to_file(const std::string &socket_id,
   return status;
 }
 
+static void client_handle(GDBRemoteCommunicationServerPlatform &platform,
+                          const lldb_private::Args &args) {
+  if (!platform.IsConnected())
+    return;
+
+  if (args.GetArgumentCount() > 0) {
+    lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+    std::optional<uint16_t> port;
+    std::string socket_name;
+    Status error = platform.LaunchGDBServer(args,
+                                            "", // hostname
+                                            pid, port, socket_name);
+    if (error.Success())
+      platform.SetPendingGdbServer(pid, *port, socket_name);
+    else
+      fprintf(stderr, "failed to start gdbserver: %s\n", error.AsCString());
+  }
+
+  bool interrupt = false;
+  bool done = false;
+  Status error;
+  while (!interrupt && !done) {
+    if (platform.GetPacketAndSendResponse(std::nullopt, error, interrupt,
+                                          done) !=
+        GDBRemoteCommunication::PacketResult::Success)
+      break;
+  }
+
+  printf("Disconnected.\n");
+}
+
+static GDBRemoteCommunicationServerPlatform::PortMap gdbserver_portmap;
+static std::mutex gdbserver_portmap_mutex;
+
+static void spawn_process_reaped(lldb::pid_t pid, int signal, int status) {
+  std::lock_guard<std::mutex> guard(gdbserver_portmap_mutex);
+  gdbserver_portmap.FreePortForProcess(pid);
+}
+
+static Status spawn_process(const char *progname, Connection *conn,
+                            uint16_t gdb_port, uint16_t port_offset,
+                            const lldb_private::Args &args,
+                            const std::string &log_file,
+                            const StringRef log_channels) {
+  Status error;
+  const TCPSocket &tcpSocket =
+      static_cast<const TCPSocket &>(*conn->GetReadObject());
+  NativeSocket socket = tcpSocket.GetNativeSocket();
+
+  ProcessLaunchInfo launch_info;
+
+  fd_t fd;
+#ifdef _WIN32
+  // Create a pipe to transfer WSAPROTOCOL_INFO to the child process.
+  Pipe socket_pipe;
+  error = socket_pipe.CreateNew(true);
+  if (error.Fail())
+    return error;
+
+  // Seems it will not work anyway. ProcessLauncherWindows ignores FileActions.
+  // And it is necessary to pass HANDLE instead of FD on Widows.
+  launch_info.AppendCloseFileAction(socket_pipe.GetWriteFileDescriptor());
+
+  fd = socket_pipe.GetReadPipe();
+#else
+  fd = socket;
+#endif
+
+  FileSpec self_spec(progname, FileSpec::Style::native);
+  launch_info.SetExecutableFile(self_spec, true);
+  Args &self_args = launch_info.GetArguments();
+  self_args.AppendArgument(llvm::StringRef("platform"));
+  self_args.AppendArgument(llvm::StringRef("--fd"));
+  self_args.AppendArgument(llvm::to_string(fd));
+  if (gdb_port) {
+    self_args.AppendArgument(llvm::StringRef("--gdbserver-port"));
+    self_args.AppendArgument(llvm::to_string(gdb_port));
+  }
+  if (port_offset > 0) {
+    self_args.AppendArgument(llvm::StringRef("--port-offset"));
+    self_args.AppendArgument(llvm::to_string(port_offset));
+  }
+  if (!log_file.empty()) {
+    self_args.AppendArgument(llvm::StringRef("--log-file"));
+    self_args.AppendArgument(log_file);
+  }
+  if (!log_channels.empty()) {
+    self_args.AppendArgument(llvm::StringRef("--log-channels"));
+    self_args.AppendArgument(log_channels);
+  }
+  if (args.GetArgumentCount() > 0) {
+    self_args.AppendArgument("--");
+    self_args.AppendArguments(args);
+  }
+
+  launch_info.SetLaunchInSeparateProcessGroup(false);
+  launch_info.SetMonitorProcessCallback(&spawn_process_reaped);
+
+  // Copy the current environment.
+  // WSASocket(FROM_PROTOCOL_INFO) will fail in the child process
+  // with the error WSAEPROVIDERFAILEDINIT if the SystemRoot is missing
+  // in the environment.
+  launch_info.GetEnvironment() = Host::GetEnvironment();
+
+  launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO);
+
+  // Close STDIN, STDOUT and STDERR.
+  launch_info.AppendCloseFileAction(STDIN_FILENO);
+  launch_info.AppendCloseFileAction(STDOUT_FILENO);
+  launch_info.AppendCloseFileAction(STDERR_FILENO);
+
+  // Redirect STDIN, STDOUT and STDERR to "/dev/null".
+  launch_info.AppendSuppressFileAction(STDIN_FILENO, true, false);
+  launch_info.AppendSuppressFileAction(STDOUT_FILENO, false, true);
+  launch_info.AppendSuppressFileAction(STDERR_FILENO, false, true);
+
+  std::string cmd;
+  self_args.GetCommandString(cmd);
+
+  error = Host::LaunchProcess(launch_info);
+  if (error.Fail())
+    return error;
+
+  lldb::pid_t child_pid = launch_info.GetProcessID();
+  if (child_pid == LLDB_INVALID_PROCESS_ID)
+    return Status("invalid pid");
+
+  LLDB_LOG(GetLog(LLDBLog::Platform), "lldb-platform launched '{0}', pid={1}",
+           cmd, child_pid);
+
+  {
+    std::lock_guard<std::mutex> guard(gdbserver_portmap_mutex);
+    gdbserver_portmap.AssociatePortWithProcess(gdb_port, child_pid);
+  }
+
+#ifdef _WIN32
+  // Transfer WSAPROTOCOL_INFO to the child process.
+  if (socket_pipe.CanRead())
+    socket_pipe.CloseReadFileDescriptor();
+  if (!socket_pipe.CanWrite()) {
----------------
labath wrote:

When can these fail? I would expect these to always hold and not even be worthy of an assert..

https://github.com/llvm/llvm-project/pull/101283


More information about the lldb-commits mailing list