Modified local spawning in debugserver processes to use a new --reverse-connect option so that debugserver actually connects back to LLDB instead of LLDB connecting to debugserver.
This gets rid of our hacky "get_random_port()" which would grab a random port and tell debugserver to open that port. Now LLDB creates, binds, listens and accepts a connection by binding to port zero and sending the correctly bound port down as the host:port to connect back to.
Fixed the "ConnectionFileDescriptor" to be able to correctly listen for connections from a specified host, localhost, or any host. Prior to this fix "listen://" only accepted the following format:
listen://<port>
But now it can accept:
listen://<port> // Listen for connection from localhost on port <port>
listen://<host>:<port> // Listen for connection from <host> and <port>
listen://*:<port> // Listen for connection from any host on port <port>
llvm-svn: 196547
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index d53347a..04de58b 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -17,6 +17,7 @@
// C++ Includes
// Other libraries and framework includes
+#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
@@ -144,7 +145,9 @@
m_private_is_running (false),
m_history (512),
m_send_acks (true),
- m_is_platform (is_platform)
+ m_is_platform (is_platform),
+ m_listen_thread (LLDB_INVALID_HOST_THREAD),
+ m_listen_url ()
{
}
@@ -539,7 +542,56 @@
}
Error
-GDBRemoteCommunication::StartDebugserverProcess (const char *debugserver_url,
+GDBRemoteCommunication::StartListenThread (const char *hostname, in_port_t port)
+{
+ Error error;
+ if (IS_VALID_LLDB_HOST_THREAD(m_listen_thread))
+ {
+ error.SetErrorString("listen thread already running");
+ }
+ else
+ {
+ char listen_url[512];
+ if (hostname && hostname[0])
+ snprintf(listen_url, sizeof(listen_url), "listen://%s:%i", hostname ? hostname : "localhost", port);
+ else
+ snprintf(listen_url, sizeof(listen_url), "listen://%i", port);
+ m_listen_url = listen_url;
+ SetConnection(new ConnectionFileDescriptor());
+ m_listen_thread = Host::ThreadCreate (listen_url, GDBRemoteCommunication::ListenThread, this, &error);
+ }
+ return error;
+}
+
+bool
+GDBRemoteCommunication::JoinListenThread ()
+{
+ if (IS_VALID_LLDB_HOST_THREAD(m_listen_thread))
+ {
+ Host::ThreadJoin(m_listen_thread, NULL, NULL);
+ m_listen_thread = LLDB_INVALID_HOST_THREAD;
+ }
+ return true;
+}
+
+lldb::thread_result_t
+GDBRemoteCommunication::ListenThread (lldb::thread_arg_t arg)
+{
+ GDBRemoteCommunication *comm = (GDBRemoteCommunication *)arg;
+ Error error;
+ ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)comm->GetConnection ();
+
+ if (connection)
+ {
+ // Do the listen on another thread so we can continue on...
+ if (connection->Connect(comm->m_listen_url.c_str(), &error) != eConnectionStatusSuccess)
+ comm->SetConnection(NULL);
+ }
+ return NULL;
+}
+
+Error
+GDBRemoteCommunication::StartDebugserverProcess (const char *host_and_port,
lldb_private::ProcessLaunchInfo &launch_info,
uint16_t &port)
{
@@ -594,42 +646,69 @@
// Start args with "debugserver /file/path -r --"
debugserver_args.AppendArgument(debugserver_path);
- debugserver_args.AppendArgument(debugserver_url);
+
+ // If a host and port is supplied then use it
+ if (host_and_port)
+ debugserver_args.AppendArgument(host_and_port);
// use native registers, not the GDB registers
debugserver_args.AppendArgument("--native-regs");
// make debugserver run in its own session so signals generated by
// special terminal key sequences (^C) don't affect debugserver
debugserver_args.AppendArgument("--setsid");
-
- char named_pipe_path[PATH_MAX];
-
- // Create a temporary file to get the stdout/stderr and redirect the
- // output of the command into this file. We will later read this file
- // if all goes well and fill the data into "command_output_ptr"
- FileSpec tmpdir_file_spec;
- if (Host::GetLLDBPath (ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
- {
- tmpdir_file_spec.GetFilename().SetCString("debugserver-named-pipe.XXXXXX");
- strncpy(named_pipe_path, tmpdir_file_spec.GetPath().c_str(), sizeof(named_pipe_path));
- }
- else
- {
- strncpy(named_pipe_path, "/tmp/debugserver-named-pipe.XXXXXX", sizeof(named_pipe_path));
- }
- if (::mktemp (named_pipe_path))
+ char named_pipe_path[PATH_MAX];
+
+ if (host_and_port)
{
- if (::mkfifo(named_pipe_path, 0600) == 0)
+ // Create a temporary file to get the stdout/stderr and redirect the
+ // output of the command into this file. We will later read this file
+ // if all goes well and fill the data into "command_output_ptr"
+ FileSpec tmpdir_file_spec;
+ if (Host::GetLLDBPath (ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
{
- debugserver_args.AppendArgument("--named-pipe");
- debugserver_args.AppendArgument(named_pipe_path);
+ tmpdir_file_spec.GetFilename().SetCString("debugserver-named-pipe.XXXXXX");
+ strncpy(named_pipe_path, tmpdir_file_spec.GetPath().c_str(), sizeof(named_pipe_path));
+ }
+ else
+ {
+ strncpy(named_pipe_path, "/tmp/debugserver-named-pipe.XXXXXX", sizeof(named_pipe_path));
+ }
+
+ if (::mktemp (named_pipe_path))
+ {
+ if (::mkfifo(named_pipe_path, 0600) == 0)
+ {
+ debugserver_args.AppendArgument("--named-pipe");
+ debugserver_args.AppendArgument(named_pipe_path);
+ }
+ else
+ named_pipe_path[0] = '\0';
}
else
named_pipe_path[0] = '\0';
}
else
+ {
named_pipe_path[0] = '\0';
+
+ // No host and port given, so lets listen on our end and make the debugserver
+ // connect to us..
+ error = StartListenThread ("localhost", 0);
+ if (error.Fail())
+ return error;
+ ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection ();
+ port = connection->GetBoundPort(3);
+ assert (port != 0);
+ char port_cstr[32];
+ snprintf(port_cstr, sizeof(port_cstr), "localhost:%i", port);
+ // Send the host and port down that debugserver and specify an option
+ // so that it connects back to the port we are listening to in this process
+ debugserver_args.AppendArgument("--reverse-connect");
+ debugserver_args.AppendArgument(port_cstr);
+ }
+
+
const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
if (env_debugserver_log_file)
{
@@ -669,7 +748,11 @@
}
Host::Unlink(named_pipe_path);
}
-
+ else
+ {
+ // Make sure we actually connect with the debugserver...
+ JoinListenThread();
+ }
}
else
{