[Lldb-commits] [lldb] [lldb] Use Socket::CreatePair for launching debugserver (PR #145017)
Pavel Labath via lldb-commits
lldb-commits at lists.llvm.org
Mon Jun 23 02:02:02 PDT 2025
https://github.com/labath updated https://github.com/llvm/llvm-project/pull/145017
>From c4923f70478b5274e114642841fd9d3683b67d39 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Fri, 20 Jun 2025 10:29:23 +0200
Subject: [PATCH] [lldb] Use Socket::CreatePair for launching debugserver
This lets get rid of platform-specific code in ProcessGDBRemote and use the
same code path (module differences in socket types) everywhere. It also unlocks
further cleanups in the debugserver launching code.
---
.../Process/gdb-remote/ProcessGDBRemote.cpp | 145 +++++++-----------
1 file changed, 55 insertions(+), 90 deletions(-)
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index f18bdd5175f2e..4e3569a5e7987 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -3447,115 +3447,80 @@ ProcessGDBRemote::EstablishConnectionIfNeeded(const ProcessInfo &process_info) {
}
return error;
}
-#if !defined(_WIN32)
-#define USE_SOCKETPAIR_FOR_LOCAL_CONNECTION 1
-#endif
-
-#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
-static bool SetCloexecFlag(int fd) {
-#if defined(FD_CLOEXEC)
- int flags = ::fcntl(fd, F_GETFD);
- if (flags == -1)
- return false;
- return (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0);
-#else
- return false;
-#endif
-}
-#endif
Status ProcessGDBRemote::LaunchAndConnectToDebugserver(
const ProcessInfo &process_info) {
using namespace std::placeholders; // For _1, _2, etc.
- Status error;
- if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID) {
- // If we locate debugserver, keep that located version around
- static FileSpec g_debugserver_file_spec;
+ if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
+ return Status();
- ProcessLaunchInfo debugserver_launch_info;
- // Make debugserver run in its own session so signals generated by special
- // terminal key sequences (^C) don't affect debugserver.
- debugserver_launch_info.SetLaunchInSeparateProcessGroup(true);
+ ProcessLaunchInfo debugserver_launch_info;
+ // Make debugserver run in its own session so signals generated by special
+ // terminal key sequences (^C) don't affect debugserver.
+ debugserver_launch_info.SetLaunchInSeparateProcessGroup(true);
- const std::weak_ptr<ProcessGDBRemote> this_wp =
- std::static_pointer_cast<ProcessGDBRemote>(shared_from_this());
- debugserver_launch_info.SetMonitorProcessCallback(
- std::bind(MonitorDebugserverProcess, this_wp, _1, _2, _3));
- debugserver_launch_info.SetUserID(process_info.GetUserID());
+ const std::weak_ptr<ProcessGDBRemote> this_wp =
+ std::static_pointer_cast<ProcessGDBRemote>(shared_from_this());
+ debugserver_launch_info.SetMonitorProcessCallback(
+ std::bind(MonitorDebugserverProcess, this_wp, _1, _2, _3));
+ debugserver_launch_info.SetUserID(process_info.GetUserID());
#if defined(__APPLE__)
- // On macOS 11, we need to support x86_64 applications translated to
- // arm64. We check whether a binary is translated and spawn the correct
- // debugserver accordingly.
- int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID,
- static_cast<int>(process_info.GetProcessID()) };
- struct kinfo_proc processInfo;
- size_t bufsize = sizeof(processInfo);
- if (sysctl(mib, (unsigned)(sizeof(mib)/sizeof(int)), &processInfo,
- &bufsize, NULL, 0) == 0 && bufsize > 0) {
- if (processInfo.kp_proc.p_flag & P_TRANSLATED) {
- FileSpec rosetta_debugserver("/Library/Apple/usr/libexec/oah/debugserver");
- debugserver_launch_info.SetExecutableFile(rosetta_debugserver, false);
- }
+ // On macOS 11, we need to support x86_64 applications translated to
+ // arm64. We check whether a binary is translated and spawn the correct
+ // debugserver accordingly.
+ int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID,
+ static_cast<int>(process_info.GetProcessID())};
+ struct kinfo_proc processInfo;
+ size_t bufsize = sizeof(processInfo);
+ if (sysctl(mib, (unsigned)(sizeof(mib) / sizeof(int)), &processInfo, &bufsize,
+ NULL, 0) == 0 &&
+ bufsize > 0) {
+ if (processInfo.kp_proc.p_flag & P_TRANSLATED) {
+ FileSpec rosetta_debugserver(
+ "/Library/Apple/usr/libexec/oah/debugserver");
+ debugserver_launch_info.SetExecutableFile(rosetta_debugserver, false);
}
+ }
#endif
- shared_fd_t communication_fd = SharedSocket::kInvalidFD;
-#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
- // Use a socketpair on non-Windows systems for security and performance
- // reasons.
- int sockets[2]; /* the pair of socket descriptors */
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) {
- error = Status::FromErrno();
- return error;
- }
+ llvm::Expected<Socket::Pair> socket_pair = Socket::CreatePair();
+ if (!socket_pair)
+ return Status::FromError(socket_pair.takeError());
- int our_socket = sockets[0];
- int gdb_socket = sockets[1];
- auto cleanup_our = llvm::make_scope_exit([&]() { close(our_socket); });
- auto cleanup_gdb = llvm::make_scope_exit([&]() { close(gdb_socket); });
+ Status error;
+ SharedSocket shared_socket(socket_pair->first.get(), error);
+ if (error.Fail())
+ return error;
- // Don't let any child processes inherit our communication socket
- SetCloexecFlag(our_socket);
- communication_fd = gdb_socket;
-#endif
+ error = m_gdb_comm.StartDebugserverProcess(
+ nullptr, GetTarget().GetPlatform().get(), debugserver_launch_info,
+ nullptr, nullptr, shared_socket.GetSendableFD());
- error = m_gdb_comm.StartDebugserverProcess(
- nullptr, GetTarget().GetPlatform().get(), debugserver_launch_info,
- nullptr, nullptr, communication_fd);
+ if (error.Fail()) {
+ Log *log = GetLog(GDBRLog::Process);
- if (error.Success())
- m_debugserver_pid = debugserver_launch_info.GetProcessID();
- else
- m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
-
- if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) {
-#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
- // Our process spawned correctly, we can now set our connection to use
- // our end of the socket pair
- cleanup_our.release();
- m_gdb_comm.SetConnection(
- std::make_unique<ConnectionFileDescriptor>(our_socket, true));
-#endif
- StartAsyncThread();
- }
+ LLDB_LOGF(log, "failed to start debugserver process: %s",
+ error.AsCString());
+ return error;
+ }
- if (error.Fail()) {
- Log *log = GetLog(GDBRLog::Process);
+ m_debugserver_pid = debugserver_launch_info.GetProcessID();
+ shared_socket.CompleteSending(m_debugserver_pid);
- LLDB_LOGF(log, "failed to start debugserver process: %s",
- error.AsCString());
- return error;
- }
+ // Our process spawned correctly, we can now set our connection to use
+ // our end of the socket pair
+ m_gdb_comm.SetConnection(std::make_unique<ConnectionFileDescriptor>(
+ socket_pair->second.release()));
+ StartAsyncThread();
- if (m_gdb_comm.IsConnected()) {
- // Finish the connection process by doing the handshake without
- // connecting (send NULL URL)
- error = ConnectToDebugserver("");
- } else {
- error = Status::FromErrorString("connection failed");
- }
+ if (m_gdb_comm.IsConnected()) {
+ // Finish the connection process by doing the handshake without
+ // connecting (send NULL URL)
+ error = ConnectToDebugserver("");
+ } else {
+ error = Status::FromErrorString("connection failed");
}
return error;
}
More information about the lldb-commits
mailing list