Index: lldb/trunk/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h =================================================================== --- lldb/trunk/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h +++ lldb/trunk/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: lldb/trunk/source/Host/posix/ConnectionFileDescriptorPosix.cpp =================================================================== --- lldb/trunk/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ lldb/trunk/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: lldb/trunk/tools/lldb-server/lldb-platform.cpp =================================================================== --- lldb/trunk/tools/lldb-server/lldb-platform.cpp +++ lldb/trunk/tools/lldb-server/lldb-platform.cpp @@ -19,6 +19,7 @@ #include #include #include +#include // C++ Includes @@ -30,6 +31,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" @@ -44,19 +46,19 @@ 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[] = { { "debug", no_argument, &g_debug, 1 }, { "verbose", no_argument, &g_verbose, 1 }, - { "stay-alive", no_argument, &g_stay_alive, 1 }, { "listen", required_argument, NULL, 'L' }, { "port-offset", required_argument, NULL, 'p' }, { "gdbserver-port", required_argument, NULL, 'P' }, { "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 +127,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 +249,17 @@ puts(output); } + std::unique_ptr listening_socket_up; + Socket *socket = nullptr; + printf ("Listening for a connection from %s...\n", listen_host_port.c_str()); + const bool children_inherit_listen_socket = false; + error = Socket::TcpListen(listen_host_port.c_str(), children_inherit_listen_socket, socket, NULL); + if (error.Fail()) + { + printf("error: %s\n", error.AsCString()); + exit(socket_error); + } + listening_socket_up.reset(socket); do { GDBRemoteCommunicationServerPlatform platform; @@ -258,51 +272,64 @@ platform.SetPortMap(std::move(gdbserver_portmap)); } - if (!listen_host_port.empty()) + const bool children_inherit_accept_socket = true; + socket = nullptr; + error = listening_socket_up->BlockingAccept(listen_host_port.c_str(), children_inherit_accept_socket, socket); + if (error.Fail()) + { + printf ("error: %s\n", error.AsCString()); + exit(socket_error); + } + printf ("Connection established.\n"); + if (g_server) { - std::unique_ptr conn_ap(new ConnectionFileDescriptor()); - if (conn_ap.get()) + // Collect child zombie processes. + while (waitpid(-1, nullptr, WNOHANG) > 0); + if (fork()) { - std::string connect_url ("listen://"); - connect_url.append(listen_host_port.c_str()); - - 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()); - } + // Parent will continue to listen for new connections. + continue; + } + else + { + // Child process will handle the connection and exit. + g_server = 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); + } while (g_server); fprintf(stderr, "lldb-server exiting...\n");