[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()) {
+ Host::Kill(child_pid, SIGTERM);
+ return Status("cannot write to socket_pipe");
+ }
+
+ WSAPROTOCOL_INFO protocol_info;
+ if (::WSADuplicateSocket(socket, child_pid, &protocol_info) == SOCKET_ERROR) {
+ int last_error = ::WSAGetLastError();
+ Host::Kill(child_pid, SIGTERM);
+ return Status("WSADuplicateSocket() failed, error: %d", last_error);
+ }
+
+ size_t num_bytes;
+ error = socket_pipe.WriteWithTimeout(&protocol_info, sizeof(protocol_info),
+ std::chrono::seconds(2), num_bytes);
----------------
labath wrote:
2 seconds seems a bit on the low side. Since this fits in the pipe buffer, I guess it will never block in practice , but if it did, 2 seconds might not be enough on a loaded machine. I'd put 10s, just to prevent anyone from guessing if this is the source of the flakyness.
https://github.com/llvm/llvm-project/pull/101283
More information about the lldb-commits
mailing list