Index: include/lldb/Host/posix/ConnectionFileDescriptorPosix.h =================================================================== --- include/lldb/Host/posix/ConnectionFileDescriptorPosix.h +++ include/lldb/Host/posix/ConnectionFileDescriptorPosix.h @@ -38,6 +38,8 @@ ConnectionFileDescriptor(int fd, bool owns_fd); + ConnectionFileDescriptor(Socket* socket); + virtual ~ConnectionFileDescriptor(); bool IsConnected() const override; @@ -104,6 +106,8 @@ std::string m_uri; private: + void InitializeSocket(Socket* socket); + DISALLOW_COPY_AND_ASSIGN(ConnectionFileDescriptor); }; Index: source/Host/posix/ConnectionFileDescriptorPosix.cpp =================================================================== --- source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -81,6 +81,17 @@ OpenCommandPipe(); } +ConnectionFileDescriptor::ConnectionFileDescriptor(Socket* socket) + : Connection() + , m_pipe() + , m_mutex(Mutex::eMutexTypeRecursive) + , m_shutting_down(false) + , m_waiting_for_accept(false) + , m_child_processes_inherit(false) +{ + InitializeSocket(socket); +} + ConnectionFileDescriptor::~ConnectionFileDescriptor() { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); @@ -758,15 +769,7 @@ if (error.Fail()) return eConnectionStatusError; - m_write_sp.reset(socket); - m_read_sp = m_write_sp; - if (error.Fail()) - { - return eConnectionStatusError; - } - StreamString strm; - strm.Printf("connect://%s:%u",socket->GetRemoteIPAddress().c_str(), socket->GetRemotePortNumber()); - m_uri.swap(strm.GetString()); + InitializeSocket(socket); return eConnectionStatusSuccess; } @@ -831,3 +834,13 @@ { m_child_processes_inherit = child_processes_inherit; } + +void +ConnectionFileDescriptor::InitializeSocket(Socket* socket) +{ + m_write_sp.reset(socket); + m_read_sp = m_write_sp; + StreamString strm; + strm.Printf("connect://%s:%u",socket->GetRemoteIPAddress().c_str(), socket->GetRemotePortNumber()); + m_uri.swap(strm.GetString()); +} Index: tools/lldb-server/lldb-platform.cpp =================================================================== --- tools/lldb-server/lldb-platform.cpp +++ tools/lldb-server/lldb-platform.cpp @@ -30,6 +30,7 @@ #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/HostGetOpt.h" #include "lldb/Host/OptionParser.h" +#include "lldb/Host/Socket.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h" @@ -45,6 +46,7 @@ static int g_debug = 0; static int g_verbose = 0; static int g_stay_alive = 0; +static int g_server = 0; static struct option g_long_options[] = { @@ -57,6 +59,7 @@ { "min-gdbserver-port", required_argument, NULL, 'm' }, { "max-gdbserver-port", required_argument, NULL, 'M' }, { "lldb-command", required_argument, NULL, 'c' }, + { "server", no_argument, &g_server, 1 }, { NULL, 0, NULL, 0 } }; @@ -125,6 +128,7 @@ std::vector lldb_commands; bool show_usage = false; int option_error = 0; + int socket_error = -1; std::string short_options(OptionParser::GetShortOptionString(g_long_options)); @@ -246,6 +250,7 @@ puts(output); } + std::unique_ptr listening_socket_up; do { GDBRemoteCommunicationServerPlatform platform; @@ -257,50 +262,72 @@ { platform.SetPortMap(std::move(gdbserver_portmap)); } - - if (!listen_host_port.empty()) + Socket *socket = nullptr; + if (!listening_socket_up) { - std::unique_ptr conn_ap(new ConnectionFileDescriptor()); - if (conn_ap.get()) + printf ("Listening for a connection from %s...\n", listen_host_port.c_str()); + Error error = Socket::TcpListen(listen_host_port.c_str(), false, socket, NULL); + if (error.Fail()) { - std::string connect_url ("listen://"); - connect_url.append(listen_host_port.c_str()); + printf("error: %s\n", error.AsCString()); + exit(socket_error); + } + listening_socket_up.reset(socket); + socket = nullptr; + } - printf ("Listening for a connection from %s...\n", listen_host_port.c_str()); - if (conn_ap->Connect(connect_url.c_str(), &error) == eConnectionStatusSuccess) - { - printf ("Connection established.\n"); - platform.SetConnection (conn_ap.release()); - } - else - { - printf ("error: %s\n", error.AsCString()); - } + error = listening_socket_up->BlockingAccept(listen_host_port.c_str(), true, socket); + if (error.Fail()) + { + printf ("error: %s\n", error.AsCString()); + exit(socket_error); + } + printf ("Connection established.\n"); + if (g_server) + { + if (fork()) + { + // Parent will continue to listen for new connections + continue; + } + else + { + // Child process will handle the connection and exit. + g_stay_alive = 0; + // Listening socket is owned by parent process. + listening_socket_up.release(); } + } + else + { + // If not running as a server, this process will not accept + // connections while a connection is active. + listening_socket_up.reset(); + } + platform.SetConnection (new ConnectionFileDescriptor(socket)); - if (platform.IsConnected()) + if (platform.IsConnected()) + { + // After we connected, we need to get an initial ack from... + if (platform.HandshakeWithClient(&error)) { - // After we connected, we need to get an initial ack from... - if (platform.HandshakeWithClient(&error)) + bool interrupt = false; + bool done = false; + while (!interrupt && !done) { - bool interrupt = false; - bool done = false; - while (!interrupt && !done) - { - if (platform.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done) != GDBRemoteCommunication::PacketResult::Success) - break; - } - - if (error.Fail()) - { - fprintf(stderr, "error: %s\n", error.AsCString()); - } + if (platform.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done) != GDBRemoteCommunication::PacketResult::Success) + break; } - else + + if (error.Fail()) { - fprintf(stderr, "error: handshake with client failed\n"); + fprintf(stderr, "error: %s\n", error.AsCString()); } } + else + { + fprintf(stderr, "error: handshake with client failed\n"); + } } } while (g_stay_alive);