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

Dmitry Vasilyev via lldb-commits lldb-commits at lists.llvm.org
Wed Jul 31 06:13:06 PDT 2024


================
@@ -114,6 +120,218 @@ static Status save_socket_id_to_file(const std::string &socket_id,
   return status;
 }
 
+static GDBRemoteCommunicationServerPlatform::PortMap gdbserver_portmap;
+static std::mutex gdbserver_portmap_mutex;
+
+#if defined(_WIN32)
+static void SpawnProcessReaped(lldb::pid_t pid, int signal, int status) {
+  std::lock_guard<std::mutex> guard(gdbserver_portmap_mutex);
+  gdbserver_portmap.FreePortForProcess(pid);
+}
+
+static bool SpawnProcessParent(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) {
+  Log *log = GetLog(LLDBLog::Platform);
+  Pipe socket_pipe;
+  Status error = socket_pipe.CreateNew(true);
+  if (error.Fail()) {
+    LLDB_LOGF(log,
+              "lldb-platform parent: "
+              "cannot create pipe: %s",
+              error.AsCString());
+    return false;
+  }
+
+  ProcessLaunchInfo launch_info;
+  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("--accept"));
+  self_args.AppendArgument(llvm::to_string(socket_pipe.GetReadPipe()));
+  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(&SpawnProcessReaped);
+
+  // 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);
+
+  launch_info.AppendCloseFileAction(socket_pipe.GetWriteFileDescriptor());
+
+  // 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()) {
+    LLDB_LOGF(log,
+              "lldb-platform parent: "
+              "cannot launch child process for connection: %s",
+              error.AsCString());
+    return false;
+  }
+
+  lldb::pid_t childPid = launch_info.GetProcessID();
+  if (childPid == LLDB_INVALID_PROCESS_ID) {
+    LLDB_LOGF(log, "lldb-platform parent: "
+                   "cannot launch child process for connection: invalid pid");
+    return false;
+  }
+  LLDB_LOGF(log,
+            "lldb-platform parent: "
+            "launched '%s', pid=0x%x",
+            cmd.c_str(), childPid);
+
+  {
+    std::lock_guard<std::mutex> guard(gdbserver_portmap_mutex);
+    gdbserver_portmap.AssociatePortWithProcess(gdb_port, childPid);
+  }
+
+  if (socket_pipe.CanRead())
+    socket_pipe.CloseReadFileDescriptor();
+  if (!socket_pipe.CanWrite()) {
+    LLDB_LOGF(log, "lldb-platform parent: "
+                   "cannot write to socket_pipe");
+    Host::Kill(childPid, SIGTERM);
+    return false;
+  }
+
+  const TCPSocket &socket =
+      static_cast<const TCPSocket &>(*conn->GetReadObject());
+  NativeSocket nativeSocket = socket.GetNativeSocket();
+
+  WSAPROTOCOL_INFO protocol_info;
+  if (::WSADuplicateSocket(nativeSocket, childPid, &protocol_info) ==
+      SOCKET_ERROR) {
+    LLDB_LOGF(log,
+              "lldb-platform parent: "
+              "WSADuplicateSocket() failed, error: %d",
+              ::WSAGetLastError());
+    Host::Kill(childPid, SIGTERM);
+    return false;
+  }
+
+  size_t num_bytes;
+  error = socket_pipe.WriteWithTimeout(&protocol_info, sizeof(protocol_info),
+                                       std::chrono::seconds(2), num_bytes);
+  if (error.Fail()) {
+    LLDB_LOGF(log,
+              "lldb-platform parent: "
+              "socket_pipe.WriteWithTimeout(WSAPROTOCOL_INFO) failed: %s",
+              error.AsCString());
+    Host::Kill(childPid, SIGTERM);
+    return false;
+  }
+  if (num_bytes != sizeof(protocol_info)) {
+    LLDB_LOGF(log,
+              "lldb-platform parent: "
+              "socket_pipe.WriteWithTimeout(WSAPROTOCOL_INFO) failed: %d bytes",
+              num_bytes);
+    Host::Kill(childPid, SIGTERM);
+    return false;
+  }
+
+  socket_pipe.Close();
+
+  return true;
+}
+
+static bool SpawnProcessChild(pipe_t accept_fd,
+                              const std::string &listen_host_port,
+                              uint16_t port_offset,
+                              const lldb_private::Args &args) {
+  if (accept_fd == INVALID_HANDLE_VALUE)
+    return false;
+
+  Log *log = GetLog(LLDBLog::Platform);
+  if (!listen_host_port.empty()) {
+    LLDB_LOGF(log, "lldb-platform child: "
+                   "ambiguous parameters --listen and --accept");
+    exit(SOCKET_ERROR);
+  }
+
+  Pipe socket_pipe(accept_fd, LLDB_INVALID_PIPE);
+
+  WSAPROTOCOL_INFO protocol_info;
+  size_t num_bytes;
+  Status error =
+      socket_pipe.ReadWithTimeout(&protocol_info, sizeof(protocol_info),
+                                  std::chrono::seconds(2), num_bytes);
+  if (error.Fail()) {
+    LLDB_LOGF(log,
+              "lldb-platform child: "
+              "socket_pipe(0x%x).ReadWithTimeout(WSAPROTOCOL_INFO) failed: %s",
+              accept_fd, error.AsCString());
+    exit(SOCKET_ERROR);
+  }
+  if (num_bytes != sizeof(protocol_info)) {
+    LLDB_LOGF(log,
+              "lldb-platform child: "
+              "socket_pipe(0x%x).ReadWithTimeout(WSAPROTOCOL_INFO) failed: "
----------------
slydiman wrote:

Thanks. Updated.

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


More information about the lldb-commits mailing list