summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2016-08-12 16:46:18 +0000
committerGreg Clayton <gclayton@apple.com>2016-08-12 16:46:18 +0000
commitc6c420fca14d9eac716c2099514bcfcaea94809c (patch)
tree22239e938218c4fa3d60d967aa4fff42936121eb /lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
parent623c4c1572ab07864ad9efd37e672eca60707675 (diff)
downloadbcm5719-llvm-c6c420fca14d9eac716c2099514bcfcaea94809c.tar.gz
bcm5719-llvm-c6c420fca14d9eac716c2099514bcfcaea94809c.zip
Switch over to using socketpair for local debugserver connections as they are twice as fast as TCP sockets (on macOS at least).
This change opens a socket pair and passes the second socket pair file descriptor down to the debugserver binary using a new option: "--fd=N" where N is the file descriptor. This file descriptor gets passed via posix_spawn() so that there is no need to do any bind/listen or bind/accept calls and eliminates the hanshake unix socket that is used to pass the result of the actual port that ends up being used so it can save time on launch as well as being faster. This is currently only enabled on __APPLE__ builds. Other OSs should try modifying the #define from ProcessGDBRemote.cpp but the first person will need to port the --fd option over to lldb-server. Any OSs that enable USE_SOCKETPAIR_FOR_LOCAL_CONNECTION in their native builds can use the socket pair stuff. The #define is Apple only right now, but looks like: #if defined (__APPLE__) #define USE_SOCKETPAIR_FOR_LOCAL_CONNECTION 1 #endif <rdar://problem/27814880> llvm-svn: 278524
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp')
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp76
1 files changed, 52 insertions, 24 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 07ec61f2544..eb82dc1eba3 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -16,6 +16,7 @@
#include <netinet/in.h>
#include <sys/mman.h> // for mmap
#endif
+#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
@@ -64,6 +65,7 @@
#include "lldb/Target/TargetList.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Target/SystemRuntime.h"
+#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/PseudoTerminal.h"
// Project includes
@@ -3602,6 +3604,23 @@ ProcessGDBRemote::EstablishConnectionIfNeeded (const ProcessInfo &process_info)
}
return error;
}
+#if defined (__APPLE__)
+#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
Error
ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info)
@@ -3624,30 +3643,34 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info
false);
debugserver_launch_info.SetUserID(process_info.GetUserID());
-#if defined (__APPLE__) && (defined (__arm__) || defined (__arm64__) || defined (__aarch64__))
- // On iOS, still do a local connection using a random port
- const char *hostname = "127.0.0.1";
- uint16_t port = get_random_port ();
-#else
- // Set hostname being NULL to do the reverse connect where debugserver
- // will bind to port zero and it will communicate back to us the port
- // that we will connect to
- const char *hostname = nullptr;
- uint16_t port = 0;
-#endif
- StreamString url_str;
- const char* url = nullptr;
- if (hostname != nullptr)
+ int communication_fd = -1;
+#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
+ // Auto close the sockets we might open up unless everything goes OK. This
+ // helps us not leak file descriptors when things go wrong.
+ lldb_utility::CleanUp <int, int> our_socket(-1, -1, close);
+ lldb_utility::CleanUp <int, int> gdb_socket(-1, -1, close);
+
+ // Use a socketpair on Apple for now until other platforms can verify it
+ // works and is fast enough
{
- url_str.Printf("%s:%u", hostname, port);
- url = url_str.GetData();
+ int sockets[2]; /* the pair of socket descriptors */
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1)
+ {
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ our_socket.set(sockets[0]);
+ gdb_socket.set(sockets[1]);
}
- error = m_gdb_comm.StartDebugserverProcess (url,
- GetTarget().GetPlatform().get(),
- debugserver_launch_info,
- &port);
+ // Don't let any child processes inherit our communication socket
+ SetCloexecFlag(our_socket.get());
+ communication_fd = gdb_socket.get();
+#endif
+
+ error = m_gdb_comm.StartDebugserverProcess(nullptr, GetTarget().GetPlatform().get(), debugserver_launch_info, nullptr, nullptr, communication_fd);
if (error.Success ())
m_debugserver_pid = debugserver_launch_info.GetProcessID();
@@ -3655,7 +3678,14 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info
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
+ m_gdb_comm.SetConnection(new ConnectionFileDescriptor(our_socket.release(), true));
+#endif
StartAsyncThread ();
+ }
if (error.Fail())
{
@@ -3669,13 +3699,11 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info
if (m_gdb_comm.IsConnected())
{
// Finish the connection process by doing the handshake without connecting (send NULL URL)
- ConnectToDebugserver (NULL);
+ ConnectToDebugserver(NULL);
}
else
{
- StreamString connect_url;
- connect_url.Printf("connect://%s:%u", hostname, port);
- error = ConnectToDebugserver (connect_url.GetString().c_str());
+ error.SetErrorString("connection failed");
}
}
OpenPOWER on IntegriCloud