beanz updated this revision to Diff 95453.
beanz added a comment.

Removing code I accidentally left in that was from debugging, and moving some 
duplicated code that @labath spotted out of the ifdef.


https://reviews.llvm.org/D31823

Files:
  cmake/modules/LLDBConfig.cmake
  include/lldb/Host/Config.h
  include/lldb/Host/Config.h.cmake
  include/lldb/Host/MainLoop.h
  include/lldb/Host/Socket.h
  include/lldb/Host/common/TCPSocket.h
  include/lldb/Host/common/UDPSocket.h
  include/lldb/Host/linux/AbstractSocket.h
  include/lldb/Host/posix/DomainSocket.h
  include/lldb/Host/posix/MainLoopPosix.h
  lldb.xcodeproj/project.pbxproj
  source/Host/CMakeLists.txt
  source/Host/common/MainLoop.cpp
  source/Host/common/Socket.cpp
  source/Host/common/TCPSocket.cpp
  source/Host/common/UDPSocket.cpp
  source/Host/linux/AbstractSocket.cpp
  source/Host/posix/ConnectionFileDescriptorPosix.cpp
  source/Host/posix/DomainSocket.cpp
  source/Host/posix/MainLoopPosix.cpp
  source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
  tools/lldb-server/Acceptor.cpp
  unittests/Host/SocketTest.cpp
  unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp
  unittests/debugserver/RNBSocketTest.cpp

Index: unittests/debugserver/RNBSocketTest.cpp
===================================================================
--- unittests/debugserver/RNBSocketTest.cpp
+++ unittests/debugserver/RNBSocketTest.cpp
@@ -96,7 +96,7 @@
     ASSERT_EQ(bye, goodbye);
   } else {
     Socket *connected_socket;
-    err = server_socket->Accept(addr_wrap, false, connected_socket);
+    err = server_socket->Accept(connected_socket);
     if (err.Fail()) {
       llvm::errs() << err.AsCString();
       abort();
Index: unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp
===================================================================
--- unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp
+++ unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp
@@ -33,15 +33,14 @@
 void Connect(GDBRemoteCommunication &client, GDBRemoteCommunication &server) {
   bool child_processes_inherit = false;
   Error error;
-  TCPSocket listen_socket(child_processes_inherit, error);
+  TCPSocket listen_socket(true, child_processes_inherit);
   ASSERT_FALSE(error.Fail());
   error = listen_socket.Listen("127.0.0.1:0", 5);
   ASSERT_FALSE(error.Fail());
 
   Socket *accept_socket;
   std::future<Error> accept_error = std::async(std::launch::async, [&] {
-    return listen_socket.Accept("127.0.0.1:0", child_processes_inherit,
-                                accept_socket);
+    return listen_socket.Accept(accept_socket);
   });
 
   char connect_remote_address[64];
Index: unittests/Host/SocketTest.cpp
===================================================================
--- unittests/Host/SocketTest.cpp
+++ unittests/Host/SocketTest.cpp
@@ -44,8 +44,7 @@
                            const char *listen_remote_address,
                            bool child_processes_inherit, Socket **accept_socket,
                            Error *error) {
-    *error = listen_socket->Accept(listen_remote_address,
-                                   child_processes_inherit, *accept_socket);
+    *error = listen_socket->Accept(*accept_socket);
   }
 
   template <typename SocketType>
@@ -56,7 +55,7 @@
     bool child_processes_inherit = false;
     Error error;
     std::unique_ptr<SocketType> listen_socket_up(
-        new SocketType(child_processes_inherit, error));
+        new SocketType(true, child_processes_inherit));
     EXPECT_FALSE(error.Fail());
     error = listen_socket_up->Listen(listen_remote_address, 5);
     EXPECT_FALSE(error.Fail());
@@ -70,7 +69,7 @@
 
     std::string connect_remote_address = get_connect_addr(*listen_socket_up);
     std::unique_ptr<SocketType> connect_socket_up(
-        new SocketType(child_processes_inherit, error));
+        new SocketType(true, child_processes_inherit));
     EXPECT_FALSE(error.Fail());
     error = connect_socket_up->Connect(connect_remote_address);
     EXPECT_FALSE(error.Fail());
@@ -141,6 +140,20 @@
   EXPECT_STREQ("65535", port_str.c_str());
   EXPECT_EQ(65535, port);
   EXPECT_TRUE(error.Success());
+
+  EXPECT_TRUE(
+      Socket::DecodeHostAndPort("[::1]:12345", host_str, port_str, port, &error));
+  EXPECT_STREQ("::1", host_str.c_str());
+  EXPECT_STREQ("12345", port_str.c_str());
+  EXPECT_EQ(12345, port);
+  EXPECT_TRUE(error.Success());
+
+  EXPECT_TRUE(
+      Socket::DecodeHostAndPort("[abcd:12fg:AF58::1]:12345", host_str, port_str, port, &error));
+  EXPECT_STREQ("abcd:12fg:AF58::1", host_str.c_str());
+  EXPECT_STREQ("12345", port_str.c_str());
+  EXPECT_EQ(12345, port);
+  EXPECT_TRUE(error.Success());
 }
 
 #ifndef LLDB_DISABLE_POSIX
Index: tools/lldb-server/Acceptor.cpp
===================================================================
--- tools/lldb-server/Acceptor.cpp
+++ tools/lldb-server/Acceptor.cpp
@@ -62,8 +62,7 @@
 
 Error Acceptor::Accept(const bool child_processes_inherit, Connection *&conn) {
   Socket *conn_socket = nullptr;
-  auto error = m_listener_socket_up->Accept(
-      StringRef(m_name), child_processes_inherit, conn_socket);
+  auto error = m_listener_socket_up->Accept(conn_socket);
   if (error.Success())
     conn = new ConnectionFileDescriptor(conn_socket);
 
Index: source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
===================================================================
--- source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
+++ source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
@@ -67,7 +67,7 @@
 
 static Error FindUnusedPort(uint16_t &port) {
   Error error;
-  std::unique_ptr<TCPSocket> tcp_socket(new TCPSocket(false, error));
+  std::unique_ptr<TCPSocket> tcp_socket(new TCPSocket(true, false));
   if (error.Fail())
     return error;
 
Index: source/Host/posix/DomainSocket.cpp
===================================================================
--- source/Host/posix/DomainSocket.cpp
+++ source/Host/posix/DomainSocket.cpp
@@ -56,27 +56,32 @@
 
   return true;
 }
-}
-
-DomainSocket::DomainSocket(NativeSocket socket)
-    : Socket(socket, ProtocolUnixDomain, true) {}
+} // namespace
 
-DomainSocket::DomainSocket(bool child_processes_inherit, Error &error)
-    : DomainSocket(
-          CreateSocket(kDomain, kType, 0, child_processes_inherit, error)) {}
+DomainSocket::DomainSocket(bool should_close, bool child_processes_inherit)
+    : Socket(ProtocolUnixDomain, should_close, child_processes_inherit) {}
 
 DomainSocket::DomainSocket(SocketProtocol protocol,
-                           bool child_processes_inherit, Error &error)
-    : Socket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error),
-             protocol, true) {}
+                           bool child_processes_inherit)
+    : Socket(protocol, true, child_processes_inherit) {}
+
+DomainSocket::DomainSocket(NativeSocket socket,
+                           const DomainSocket &listen_socket)
+    : Socket(ProtocolUnixDomain, listen_socket.m_should_close_fd,
+             listen_socket.m_child_processes_inherit) {
+  m_socket = socket;
+}
 
 Error DomainSocket::Connect(llvm::StringRef name) {
   sockaddr_un saddr_un;
   socklen_t saddr_un_len;
   if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len))
     return Error("Failed to set socket address");
 
   Error error;
+  m_socket = CreateSocket(kDomain, kType, 0, m_child_processes_inherit, error);
+  if (error.Fail())
+    return error;
   if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) <
       0)
     SetLastError(error);
@@ -93,6 +98,9 @@
   DeleteSocketFile(name);
 
   Error error;
+  m_socket = CreateSocket(kDomain, kType, 0, m_child_processes_inherit, error);
+  if (error.Fail())
+    return error;
   if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) ==
       0)
     if (::listen(GetNativeSocket(), backlog) == 0)
@@ -102,13 +110,12 @@
   return error;
 }
 
-Error DomainSocket::Accept(llvm::StringRef name, bool child_processes_inherit,
-                           Socket *&socket) {
+Error DomainSocket::Accept(Socket *&socket) {
   Error error;
   auto conn_fd = AcceptSocket(GetNativeSocket(), nullptr, nullptr,
-                              child_processes_inherit, error);
+                              m_child_processes_inherit, error);
   if (error.Success())
-    socket = new DomainSocket(conn_fd);
+    socket = new DomainSocket(conn_fd, *this);
 
   return error;
 }
Index: source/Host/posix/ConnectionFileDescriptorPosix.cpp
===================================================================
--- source/Host/posix/ConnectionFileDescriptorPosix.cpp
+++ source/Host/posix/ConnectionFileDescriptorPosix.cpp
@@ -218,7 +218,7 @@
           // assume we don't own it.
 
           std::unique_ptr<TCPSocket> tcp_socket;
-          tcp_socket.reset(new TCPSocket(fd, false));
+          tcp_socket.reset(new TCPSocket(fd, false, false));
           // Try and get a socket option from this file descriptor to
           // see if this is a socket and set m_is_socket accordingly.
           int resuse;
@@ -720,7 +720,7 @@
 
   listening_socket_up.reset(socket);
   socket = nullptr;
-  error = listening_socket_up->Accept(s, m_child_processes_inherit, socket);
+  error = listening_socket_up->Accept(socket);
   listening_socket_up.reset();
   if (error_ptr)
     *error_ptr = error;
Index: source/Host/linux/AbstractSocket.cpp
===================================================================
--- source/Host/linux/AbstractSocket.cpp
+++ source/Host/linux/AbstractSocket.cpp
@@ -14,8 +14,8 @@
 using namespace lldb;
 using namespace lldb_private;
 
-AbstractSocket::AbstractSocket(bool child_processes_inherit, Error &error)
-    : DomainSocket(ProtocolUnixAbstract, child_processes_inherit, error) {}
+AbstractSocket::AbstractSocket(bool child_processes_inherit)
+    : DomainSocket(ProtocolUnixAbstract, child_processes_inherit) {}
 
 size_t AbstractSocket::GetNameOffset() const { return 1; }
 
Index: source/Host/common/UDPSocket.cpp
===================================================================
--- source/Host/common/UDPSocket.cpp
+++ source/Host/common/UDPSocket.cpp
@@ -28,41 +28,31 @@
 const int kType = SOCK_DGRAM;
 
 static const char *g_not_supported_error = "Not supported";
-}
+} // namespace
 
-UDPSocket::UDPSocket(NativeSocket socket) : Socket(socket, ProtocolUdp, true) {}
+UDPSocket::UDPSocket(bool should_close, bool child_processes_inherit)
+    : Socket(ProtocolUdp, should_close, child_processes_inherit) {}
 
-UDPSocket::UDPSocket(bool child_processes_inherit, Error &error)
-    : UDPSocket(
-          CreateSocket(kDomain, kType, 0, child_processes_inherit, error)) {}
+UDPSocket::UDPSocket(NativeSocket socket, const UDPSocket &listen_socket)
+    : Socket(ProtocolUdp, listen_socket.m_should_close_fd,
+             listen_socket.m_child_processes_inherit) {
+  m_socket = socket;
+}
 
 size_t UDPSocket::Send(const void *buf, const size_t num_bytes) {
   return ::sendto(m_socket, static_cast<const char *>(buf), num_bytes, 0,
                   m_sockaddr, m_sockaddr.GetLength());
 }
 
 Error UDPSocket::Connect(llvm::StringRef name) {
-  return Error("%s", g_not_supported_error);
-}
-
-Error UDPSocket::Listen(llvm::StringRef name, int backlog) {
-  return Error("%s", g_not_supported_error);
-}
-
-Error UDPSocket::Accept(llvm::StringRef name, bool child_processes_inherit,
-                        Socket *&socket) {
-  return Error("%s", g_not_supported_error);
-}
-
-Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit,
-                         Socket *&socket) {
-  std::unique_ptr<UDPSocket> final_socket;
-
   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
   if (log)
     log->Printf("UDPSocket::%s (host/port = %s)", __FUNCTION__, name.data());
 
   Error error;
+  if (error.Fail())
+    return error;
+
   std::string host_str;
   std::string port_str;
   int32_t port = INT32_MIN;
@@ -94,44 +84,68 @@
   for (struct addrinfo *service_info_ptr = service_info_list;
        service_info_ptr != nullptr;
        service_info_ptr = service_info_ptr->ai_next) {
-    auto send_fd = CreateSocket(
+    m_socket = Socket::CreateSocket(
         service_info_ptr->ai_family, service_info_ptr->ai_socktype,
-        service_info_ptr->ai_protocol, child_processes_inherit, error);
+        service_info_ptr->ai_protocol, m_child_processes_inherit, error);
     if (error.Success()) {
-      final_socket.reset(new UDPSocket(send_fd));
-      final_socket->m_sockaddr = service_info_ptr;
+      m_sockaddr = service_info_ptr;
       break;
     } else
       continue;
   }
 
   ::freeaddrinfo(service_info_list);
 
-  if (!final_socket)
+  if (IsValid())
     return error;
 
   SocketAddress bind_addr;
 
   // Only bind to the loopback address if we are expecting a connection from
   // localhost to avoid any firewall issues.
-  const bool bind_addr_success = (host_str == "127.0.0.1" || host_str == "localhost")
-                                     ? bind_addr.SetToLocalhost(kDomain, port)
-                                     : bind_addr.SetToAnyAddress(kDomain, port);
+  const bool bind_addr_success =
+      (host_str == "127.0.0.1" || host_str == "localhost")
+          ? bind_addr.SetToLocalhost(kDomain, port)
+          : bind_addr.SetToAnyAddress(kDomain, port);
 
   if (!bind_addr_success) {
     error.SetErrorString("Failed to get hostspec to bind for");
     return error;
   }
 
   bind_addr.SetPort(0); // Let the source port # be determined dynamically
 
-  err = ::bind(final_socket->GetNativeSocket(), bind_addr, bind_addr.GetLength());
-
-  struct sockaddr_in source_info;
-  socklen_t address_len = sizeof (struct sockaddr_in);
-  err = ::getsockname(final_socket->GetNativeSocket(), (struct sockaddr *) &source_info, &address_len);
+  err = ::bind(m_socket, bind_addr, bind_addr.GetLength());
 
-  socket = final_socket.release();
   error.Clear();
   return error;
 }
+
+Error UDPSocket::Listen(llvm::StringRef name, int backlog) {
+  return Error(g_not_supported_error);
+}
+
+Error UDPSocket::Accept(Socket *&socket) {
+  return Error(g_not_supported_error);
+}
+
+Error UDPSocket::CreateSocket() {
+  Error error;
+  if (IsValid())
+    error = Close();
+  if (error.Fail())
+    return error;
+  m_socket =
+      Socket::CreateSocket(kDomain, kType, 0, m_child_processes_inherit, error);
+  return error;
+}
+
+Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit,
+                         Socket *&socket) {
+  std::unique_ptr<UDPSocket> final_socket(
+      new UDPSocket(true, child_processes_inherit));
+  Error error = final_socket->Connect(name);
+  if (!error.Fail())
+    socket = final_socket.release();
+  return error;
+}
Index: source/Host/common/TCPSocket.cpp
===================================================================
--- source/Host/common/TCPSocket.cpp
+++ source/Host/common/TCPSocket.cpp
@@ -14,38 +14,69 @@
 #include "lldb/Host/common/TCPSocket.h"
 
 #include "lldb/Host/Config.h"
+#include "lldb/Host/MainLoop.h"
 #include "lldb/Utility/Log.h"
 
+#include "llvm/Config/config.h"
+#include "llvm/Support/raw_ostream.h"
+
 #ifndef LLDB_DISABLE_POSIX
 #include <arpa/inet.h>
 #include <netinet/tcp.h>
 #include <sys/socket.h>
 #endif
 
+#if defined(LLVM_ON_WIN32)
+#include <winsock2.h>
+#endif
+
+#ifdef LLVM_ON_WIN32
+#define CLOSE_SOCKET closesocket
+#else
+#define CLOSE_SOCKET ::close
+#endif
+
 using namespace lldb;
 using namespace lldb_private;
 
 namespace {
-
-const int kDomain = AF_INET;
 const int kType = SOCK_STREAM;
 }
 
-TCPSocket::TCPSocket(NativeSocket socket, bool should_close)
-    : Socket(socket, ProtocolTcp, should_close) {}
+TCPSocket::TCPSocket(bool should_close, bool child_processes_inherit)
+    : Socket(ProtocolTcp, should_close, child_processes_inherit) {}
 
-TCPSocket::TCPSocket(bool child_processes_inherit, Error &error)
-    : TCPSocket(CreateSocket(kDomain, kType, IPPROTO_TCP,
-                             child_processes_inherit, error),
-                true) {}
+TCPSocket::TCPSocket(NativeSocket socket, const TCPSocket &listen_socket)
+    : Socket(ProtocolTcp, listen_socket.m_should_close_fd,
+             listen_socket.m_child_processes_inherit) {
+  m_socket = socket;
+}
+
+TCPSocket::TCPSocket(NativeSocket socket, bool should_close,
+                     bool child_processes_inherit)
+    : Socket(ProtocolTcp, should_close, child_processes_inherit) {
+  m_socket = socket;
+}
+
+TCPSocket::~TCPSocket() { CloseListenSockets(); }
+
+bool TCPSocket::IsValid() const {
+  return m_socket != kInvalidSocketValue || m_listen_sockets.size() != 0;
+}
 
 // Return the port number that is being used by the socket.
 uint16_t TCPSocket::GetLocalPortNumber() const {
   if (m_socket != kInvalidSocketValue) {
     SocketAddress sock_addr;
     socklen_t sock_addr_len = sock_addr.GetMaxLength();
     if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
       return sock_addr.GetPort();
+  } else if (!m_listen_sockets.empty()) {
+    SocketAddress sock_addr;
+    socklen_t sock_addr_len = sock_addr.GetMaxLength();
+    if (::getsockname(m_listen_sockets.begin()->first, sock_addr,
+                      &sock_addr_len) == 0)
+      return sock_addr.GetPort();
   }
   return 0;
 }
@@ -84,9 +115,18 @@
   return "";
 }
 
+Error TCPSocket::CreateSocket(int domain) {
+  Error error;
+  if (IsValid())
+    error = Close();
+  if (error.Fail())
+    return error;
+  m_socket = Socket::CreateSocket(domain, kType, IPPROTO_TCP,
+                                  m_child_processes_inherit, error);
+  return error;
+}
+
 Error TCPSocket::Connect(llvm::StringRef name) {
-  if (m_socket == kInvalidSocketValue)
-    return Error("Invalid socket");
 
   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION));
   if (log)
@@ -99,146 +139,133 @@
   if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
     return error;
 
-  struct sockaddr_in sa;
-  ::memset(&sa, 0, sizeof(sa));
-  sa.sin_family = kDomain;
-  sa.sin_port = htons(port);
-
-  int inet_pton_result = ::inet_pton(kDomain, host_str.c_str(), &sa.sin_addr);
-
-  if (inet_pton_result <= 0) {
-    struct hostent *host_entry = gethostbyname(host_str.c_str());
-    if (host_entry)
-      host_str = ::inet_ntoa(*(struct in_addr *)*host_entry->h_addr_list);
-    inet_pton_result = ::inet_pton(kDomain, host_str.c_str(), &sa.sin_addr);
-    if (inet_pton_result <= 0) {
-      if (inet_pton_result == -1)
-        SetLastError(error);
-      else
-        error.SetErrorStringWithFormat("invalid host string: '%s'",
-                                       host_str.c_str());
+  auto addresses =
+      lldb_private::SocketAddress::GetAddressInfo(host_str.c_str(), NULL);
+  for (auto address : addresses) {
+    error = CreateSocket(address.GetFamily());
+    if (error.Fail())
+      continue;
 
-      return error;
+    address.SetPort(port);
+
+    if (-1 == ::connect(GetNativeSocket(), &address.sockaddr(),
+                        address.GetLength())) {
+      continue;
     }
-  }
 
-  if (-1 ==
-      ::connect(GetNativeSocket(), (const struct sockaddr *)&sa, sizeof(sa))) {
-    SetLastError(error);
+    SetOptionNoDelay();
+
+    error.Clear();
     return error;
   }
 
-  // Keep our TCP packets coming without any delays.
-  SetOptionNoDelay();
-  error.Clear();
+  error.SetErrorString("Failed to connect port");
   return error;
 }
 
 Error TCPSocket::Listen(llvm::StringRef name, int backlog) {
-  Error error;
-
-  // enable local address reuse
-  SetOptionReuseAddress();
-
   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
   if (log)
     log->Printf("TCPSocket::%s (%s)", __FUNCTION__, name.data());
 
+  Error error;
   std::string host_str;
   std::string port_str;
   int32_t port = INT32_MIN;
   if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
     return error;
 
-  SocketAddress bind_addr;
+  auto addresses =
+      lldb_private::SocketAddress::GetAddressInfo(host_str.c_str(), NULL);
+  for (auto address : addresses) {
+    int fd = Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP,
+                                  m_child_processes_inherit, error);
+    if (error.Fail()) {
+      error.Clear();
+      continue;
+    }
 
-  // Only bind to the loopback address if we are expecting a connection from
-  // localhost to avoid any firewall issues.
-  const bool bind_addr_success = (host_str == "127.0.0.1")
-                                     ? bind_addr.SetToLocalhost(kDomain, port)
-                                     : bind_addr.SetToAnyAddress(kDomain, port);
+    // enable local address reuse
+    SetOptionReuseAddress();
 
-  if (!bind_addr_success) {
-    error.SetErrorString("Failed to bind port");
-    return error;
-  }
+    address.SetPort(port);
+
+    int err = ::bind(fd, &address.sockaddr(), address.GetLength());
+    if (-1 != err)
+      err = ::listen(fd, backlog);
 
-  int err = ::bind(GetNativeSocket(), bind_addr, bind_addr.GetLength());
-  if (err != -1)
-    err = ::listen(GetNativeSocket(), backlog);
+    if (-1 == err) {
+      CLOSE_SOCKET(fd);
+      continue;
+    }
 
-  if (err == -1)
-    SetLastError(error);
+    if (port == 0) {
+      socklen_t sa_len = address.GetLength();
+      if (getsockname(fd, &address.sockaddr(), &sa_len) == 0)
+        port = address.GetPort();
+    }
+    m_listen_sockets[fd] = address;
+  }
 
+  if (m_listen_sockets.size() == 0)
+    error.SetErrorString("Failed to connect port");
   return error;
 }
 
-Error TCPSocket::Accept(llvm::StringRef name, bool child_processes_inherit,
-                        Socket *&conn_socket) {
+void TCPSocket::CloseListenSockets() {
+  for (auto socket : m_listen_sockets)
+  CLOSE_SOCKET(socket.first);
+  m_listen_sockets.clear();
+}
+
+Error TCPSocket::Accept(Socket *&conn_socket) {
   Error error;
-  std::string host_str;
-  std::string port_str;
-  int32_t port;
-  if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
+  if (m_listen_sockets.size() == 0) {
+    error.SetErrorString("No open listening sockets!");
     return error;
+  }
 
-  const sa_family_t family = kDomain;
-  const int socktype = kType;
-  const int protocol = IPPROTO_TCP;
-  SocketAddress listen_addr;
-  if (host_str.empty())
-    listen_addr.SetToLocalhost(family, port);
-  else if (host_str.compare("*") == 0)
-    listen_addr.SetToAnyAddress(family, port);
-  else {
-    if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family,
-                                 socktype, protocol)) {
-      error.SetErrorStringWithFormat("unable to resolve hostname '%s'",
-                                     host_str.c_str());
+  int sock = -1;
+  int listen_sock = -1;
+  lldb_private::SocketAddress AcceptAddr;
+  MainLoop accept_loop;
+  std::vector<MainLoopBase::ReadHandleUP> handles;
+  for (auto socket : m_listen_sockets) {
+    auto fd = socket.first;
+    auto inherit = this->m_child_processes_inherit;
+    auto io_sp = IOObjectSP(new TCPSocket(socket.first, false, inherit));
+    handles.emplace_back(accept_loop.RegisterReadObject(
+        io_sp, [fd, inherit, &sock, &AcceptAddr, &error,
+                        &listen_sock](MainLoopBase &loop) {
+          socklen_t sa_len = AcceptAddr.GetMaxLength();
+          sock = AcceptSocket(fd, &AcceptAddr.sockaddr(), &sa_len, inherit,
+                              error);
+          listen_sock = fd;
+          loop.RequestTermination();
+        }, error));
+    if (error.Fail())
       return error;
-    }
   }
 
   bool accept_connection = false;
   std::unique_ptr<TCPSocket> accepted_socket;
-
   // Loop until we are happy with our connection
   while (!accept_connection) {
-    struct sockaddr_in accept_addr;
-    ::memset(&accept_addr, 0, sizeof accept_addr);
-#if !(defined(__linux__) || defined(_WIN32))
-    accept_addr.sin_len = sizeof accept_addr;
-#endif
-    socklen_t accept_addr_len = sizeof accept_addr;
-
-    int sock = AcceptSocket(GetNativeSocket(), (struct sockaddr *)&accept_addr,
-                            &accept_addr_len, child_processes_inherit, error);
-
+    accept_loop.Run();
+    
     if (error.Fail())
-      break;
-
-    bool is_same_addr = true;
-#if !(defined(__linux__) || (defined(_WIN32)))
-    is_same_addr = (accept_addr_len == listen_addr.sockaddr_in().sin_len);
-#endif
-    if (is_same_addr)
-      is_same_addr = (accept_addr.sin_addr.s_addr ==
-                      listen_addr.sockaddr_in().sin_addr.s_addr);
-
-    if (is_same_addr ||
-        (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY)) {
-      accept_connection = true;
-      accepted_socket.reset(new TCPSocket(sock, true));
-    } else {
-      const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr;
-      const uint8_t *listen_ip =
-          (const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr;
-      ::fprintf(stderr, "error: rejecting incoming connection from %u.%u.%u.%u "
-                        "(expecting %u.%u.%u.%u)\n",
-                accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3],
-                listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]);
-      accepted_socket.reset();
+        return error;
+
+    lldb_private::SocketAddress &AddrIn = m_listen_sockets[listen_sock];
+    if (!AddrIn.IsAnyAddr() && AcceptAddr != AddrIn) {
+      CLOSE_SOCKET(sock);
+      llvm::errs() << llvm::formatv(
+          "error: rejecting incoming connection from {0} (expecting {1})",
+          AcceptAddr.GetIPAddress(), AddrIn.GetIPAddress());
+      continue;
     }
+    accept_connection = true;
+    accepted_socket.reset(new TCPSocket(sock, *this));
   }
 
   if (!accepted_socket)
@@ -248,6 +275,7 @@
   accepted_socket->SetOptionNoDelay();
   error.Clear();
   conn_socket = accepted_socket.release();
+  CloseListenSockets();
   return error;
 }
 
Index: source/Host/common/Socket.cpp
===================================================================
--- source/Host/common/Socket.cpp
+++ source/Host/common/Socket.cpp
@@ -18,6 +18,8 @@
 #include "lldb/Utility/Log.h"
 #include "lldb/Utility/RegularExpression.h"
 
+#include "llvm/ADT/STLExtras.h"
+
 #ifndef LLDB_DISABLE_POSIX
 #include "lldb/Host/posix/DomainSocket.h"
 
@@ -67,9 +69,11 @@
 }
 }
 
-Socket::Socket(NativeSocket socket, SocketProtocol protocol, bool should_close)
+Socket::Socket(SocketProtocol protocol, bool should_close,
+               bool child_processes_inherit)
     : IOObject(eFDTypeSocket, should_close), m_protocol(protocol),
-      m_socket(socket) {}
+      m_socket(kInvalidSocketValue),
+      m_child_processes_inherit(child_processes_inherit) {}
 
 Socket::~Socket() { Close(); }
 
@@ -81,22 +85,23 @@
   std::unique_ptr<Socket> socket_up;
   switch (protocol) {
   case ProtocolTcp:
-    socket_up.reset(new TCPSocket(child_processes_inherit, error));
+    socket_up = llvm::make_unique<TCPSocket>(true, child_processes_inherit);
     break;
   case ProtocolUdp:
-    socket_up.reset(new UDPSocket(child_processes_inherit, error));
+    socket_up = llvm::make_unique<UDPSocket>(true, child_processes_inherit);
     break;
   case ProtocolUnixDomain:
 #ifndef LLDB_DISABLE_POSIX
-    socket_up.reset(new DomainSocket(child_processes_inherit, error));
+    socket_up = llvm::make_unique<DomainSocket>(true, child_processes_inherit);
 #else
     error.SetErrorString(
         "Unix domain sockets are not supported on this platform.");
 #endif
     break;
   case ProtocolUnixAbstract:
 #ifdef __linux__
-    socket_up.reset(new AbstractSocket(child_processes_inherit, error));
+    socket_up =
+        llvm::make_unique<AbstractSocket>(true, child_processes_inherit);
 #else
     error.SetErrorString(
         "Abstract domain sockets are not supported on this platform.");
@@ -145,7 +150,7 @@
     return error;
 
   std::unique_ptr<TCPSocket> listen_socket(
-      new TCPSocket(child_processes_inherit, error));
+      new TCPSocket(child_processes_inherit, true));
   if (error.Fail())
     return error;
 
@@ -208,7 +213,7 @@
   if (error.Fail())
     return error;
 
-  error = listen_socket->Accept(name, child_processes_inherit, socket);
+  error = listen_socket->Accept(socket);
   return error;
 }
 
@@ -240,18 +245,22 @@
   if (error.Fail())
     return error;
 
-  error = listen_socket->Accept(name, child_processes_inherit, socket);
+  error = listen_socket->Accept(socket);
   return error;
 }
 
 bool Socket::DecodeHostAndPort(llvm::StringRef host_and_port,
                                std::string &host_str, std::string &port_str,
                                int32_t &port, Error *error_ptr) {
-  static RegularExpression g_regex(llvm::StringRef("([^:]+):([0-9]+)"));
+  static RegularExpression g_regex(
+      llvm::StringRef("([^:]+|\\[[0-9a-fA-F:]+.*\\]):([0-9]+)"));
   RegularExpression::Match regex_match(2);
   if (g_regex.Execute(host_and_port, &regex_match)) {
     if (regex_match.GetMatchAtIndex(host_and_port.data(), 1, host_str) &&
         regex_match.GetMatchAtIndex(host_and_port.data(), 2, port_str)) {
+      // IPv6 addresses are wrapped in [] when specified with ports
+      if (host_str.front() == '[' && host_str.back() == ']')
+        host_str = host_str.substr(1, host_str.size() - 2);
       bool ok = false;
       port = StringConvert::ToUInt32(port_str.c_str(), UINT32_MAX, 10, &ok);
       if (ok && port <= UINT16_MAX) {
@@ -404,12 +413,12 @@
                                   const int protocol,
                                   bool child_processes_inherit, Error &error) {
   error.Clear();
-  auto socketType = type;
+  auto socket_type = type;
 #ifdef SOCK_CLOEXEC
   if (!child_processes_inherit)
-    socketType |= SOCK_CLOEXEC;
+    socket_type |= SOCK_CLOEXEC;
 #endif
-  auto sock = ::socket(domain, socketType, protocol);
+  auto sock = ::socket(domain, socket_type, protocol);
   if (sock == kInvalidSocketValue)
     SetLastError(error);
 
Index: source/Host/common/MainLoop.cpp
===================================================================
--- source/Host/common/MainLoop.cpp
+++ source/Host/common/MainLoop.cpp
@@ -1,21 +1,51 @@
-//===-- MainLoopPosix.cpp ---------------------------------------*- C++ -*-===//
+//===-- MainLoop.cpp --------------------------------------------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 
-#include "lldb/Host/posix/MainLoopPosix.h"
+#include "llvm/Config/config.h"
+
+#include "lldb/Host/MainLoop.h"
 #include "lldb/Utility/Error.h"
 #include <algorithm>
 #include <cassert>
 #include <cerrno>
 #include <csignal>
 #include <sys/select.h>
 #include <vector>
 
+#if HAVE_SYS_EVENT_H
+#include <sys/event.h>
+#elif defined(LLVM_ON_WIN32)
+#include <winsock2.h>
+#else
+#include <poll.h>
+#endif
+
+#ifdef LLVM_ON_WIN32
+#define POLL WSAPoll
+#else
+#define POLL poll
+#endif
+
+#if !HAVE_PPOLL && !HAVE_SYS_EVENT_H
+#define SIGNAL_POLLING_UNSUPPORTED 1
+
+int ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts,
+          const sigset_t *) {
+  int timeout =
+      (timeout_ts == nullptr)
+          ? -1
+          : (timeout_ts->tv_sec * 1000 + timeout_ts->tv_nsec / 1000000);
+  return POLL(fds, nfds, timeout);
+}
+
+#endif
+
 using namespace lldb;
 using namespace lldb_private;
 
@@ -26,14 +56,20 @@
   g_signal_flags[signo] = 1;
 }
 
-MainLoopPosix::~MainLoopPosix() {
+MainLoop::~MainLoop() {
   assert(m_read_fds.size() == 0);
   assert(m_signals.size() == 0);
 }
 
-MainLoopPosix::ReadHandleUP
-MainLoopPosix::RegisterReadObject(const IOObjectSP &object_sp,
+MainLoop::ReadHandleUP
+MainLoop::RegisterReadObject(const IOObjectSP &object_sp,
                                   const Callback &callback, Error &error) {
+#ifdef LLVM_ON_WIN32
+  if (object_sp->GetFdType() != IOObject:: eFDTypeSocket) {
+    error.SetErrorString("MainLoop: non-socket types unsupported on Windows");
+    return nullptr;
+  }
+#endif
   if (!object_sp || !object_sp->IsValid()) {
     error.SetErrorString("IO object is not valid.");
     return nullptr;
@@ -53,9 +89,13 @@
 // We shall block the signal, then install the signal handler. The signal will
 // be unblocked in
 // the Run() function to check for signal delivery.
-MainLoopPosix::SignalHandleUP
-MainLoopPosix::RegisterSignal(int signo, const Callback &callback,
+MainLoop::SignalHandleUP
+MainLoop::RegisterSignal(int signo, const Callback &callback,
                               Error &error) {
+#ifdef SIGNAL_POLLING_UNSUPPORTED
+  error.SetErrorString("Signal polling is not supported on this platform.");
+  return nullptr;
+#else
   if (m_signals.find(signo) != m_signals.end()) {
     error.SetErrorStringWithFormat("Signal %d already monitored.", signo);
     return nullptr;
@@ -88,15 +128,16 @@
   g_signal_flags[signo] = 0;
 
   return SignalHandleUP(new SignalHandle(*this, signo));
+#endif
 }
 
-void MainLoopPosix::UnregisterReadObject(IOObject::WaitableHandle handle) {
+void MainLoop::UnregisterReadObject(IOObject::WaitableHandle handle) {
   bool erased = m_read_fds.erase(handle);
   UNUSED_IF_ASSERT_DISABLED(erased);
   assert(erased);
 }
 
-void MainLoopPosix::UnregisterSignal(int signo) {
+void MainLoop::UnregisterSignal(int signo) {
   // We undo the actions of RegisterSignal on a best-effort basis.
   auto it = m_signals.find(signo);
   assert(it != m_signals.end());
@@ -112,41 +153,72 @@
   m_signals.erase(it);
 }
 
-Error MainLoopPosix::Run() {
+Error MainLoop::Run() {
   std::vector<int> signals;
   sigset_t sigmask;
-  std::vector<int> read_fds;
-  fd_set read_fd_set;
   m_terminate_request = false;
+  signals.reserve(m_signals.size());
+  
+#if HAVE_SYS_EVENT_H
+  int queue_id = kqueue();
+  if (queue_id < 0)
+    Error("kqueue failed with error %d\n", queue_id);
+
+  std::vector<struct kevent> events;
+  events.reserve(m_read_fds.size() + m_signals.size());
+#else
+  std::vector<struct pollfd> read_fds;
+  read_fds.reserve(m_read_fds.size());
+#endif
 
   // run until termination or until we run out of things to listen to
   while (!m_terminate_request && (!m_read_fds.empty() || !m_signals.empty())) {
     // To avoid problems with callbacks changing the things we're supposed to
     // listen to, we
     // will store the *real* list of events separately.
     signals.clear();
     read_fds.clear();
-    FD_ZERO(&read_fd_set);
-    int nfds = 0;
 
+#if HAVE_SYS_EVENT_H
+    events.resize(m_read_fds.size() + m_signals.size());
+    int i = 0;
+    for (auto &fd: m_read_fds) {
+      EV_SET(&events[i++], fd.first, EVFILT_READ, EV_ADD, 0, 0, 0);
+    }
+
+    for (const auto &sig : m_signals) {
+      signals.push_back(sig.first);
+      EV_SET(&events[i++], sig.first, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
+    }
+
+    struct kevent event_list[4];
+    int num_events =
+        kevent(queue_id, events.data(), events.size(), event_list, 4, NULL);
+
+    if (num_events < 0)
+      return Error("kevent() failed with error %d\n", num_events);
+
+#else
     if (int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask))
       return Error("pthread_sigmask failed with error %d\n", ret);
 
     for (const auto &fd : m_read_fds) {
-      read_fds.push_back(fd.first);
-      FD_SET(fd.first, &read_fd_set);
-      nfds = std::max(nfds, fd.first + 1);
+      struct pollfd pfd;
+      pfd.fd = fd.first;
+      pfd.events = POLLIN;
+      pfd.revents = 0;
+      read_fds.push_back(pfd);
     }
 
     for (const auto &sig : m_signals) {
       signals.push_back(sig.first);
       sigdelset(&sigmask, sig.first);
     }
 
-    if (pselect(nfds, &read_fd_set, nullptr, nullptr, nullptr, &sigmask) ==
-            -1 &&
+    if (ppoll(read_fds.data(), read_fds.size(), nullptr, &sigmask) == -1 &&
         errno != EINTR)
       return Error(errno, eErrorTypePOSIX);
+#endif
 
     for (int sig : signals) {
       if (g_signal_flags[sig] == 0)
@@ -163,15 +235,19 @@
         return Error();
     }
 
-    for (int fd : read_fds) {
-      if (!FD_ISSET(fd, &read_fd_set))
-        continue; // Not ready
+#if HAVE_SYS_EVENT_H
+    for (int i = 0; i < num_events; ++i) {
+      auto it = m_read_fds.find(event_list[i].ident);
+#else
+    for (auto fd : read_fds) {
+      if ((fd.revents & POLLIN) == 0)
+        continue;
 
-      auto it = m_read_fds.find(fd);
+      auto it = m_read_fds.find(fd.fd);
+#endif
       if (it == m_read_fds.end())
         continue; // File descriptor must have gotten unregistered in the
                   // meantime
-
       it->second(*this); // Do the work
 
       if (m_terminate_request)
Index: source/Host/CMakeLists.txt
===================================================================
--- source/Host/CMakeLists.txt
+++ source/Host/CMakeLists.txt
@@ -15,6 +15,7 @@
   common/HostThread.cpp
   common/IOObject.cpp
   common/LockFileBase.cpp
+  common/MainLoop.cpp
   common/MonitoringProcessLauncher.cpp
   common/NativeBreakpoint.cpp
   common/NativeBreakpointList.cpp
@@ -85,7 +86,6 @@
     posix/HostProcessPosix.cpp
     posix/HostThreadPosix.cpp
     posix/LockFilePosix.cpp
-    posix/MainLoopPosix.cpp
     posix/PipePosix.cpp
     posix/ProcessLauncherPosixFork.cpp
     )
Index: lldb.xcodeproj/project.pbxproj
===================================================================
--- lldb.xcodeproj/project.pbxproj
+++ lldb.xcodeproj/project.pbxproj
@@ -665,7 +665,6 @@
 		26FFC19D14FC072100087D58 /* DynamicLoaderPOSIXDYLD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26FFC19714FC072100087D58 /* DynamicLoaderPOSIXDYLD.cpp */; };
 		304B2E461CAAA57B007829FE /* ClangUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3032B1B61CAAA3D1004BE1AB /* ClangUtil.cpp */; };
 		30B38A001CAAA6D7009524E3 /* ClangUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 3032B1B91CAAA400004BE1AB /* ClangUtil.h */; };
-		30DED5DE1B4ECB49004CC508 /* MainLoopPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 30DED5DC1B4ECB17004CC508 /* MainLoopPosix.cpp */; };
 		332CCB181AFF41620034D4C4 /* SBLanguageRuntime.h in Headers */ = {isa = PBXBuildFile; fileRef = 3392EBB71AFF402200858B9F /* SBLanguageRuntime.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		33E5E8471A674FB60024ED68 /* StringConvert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33E5E8411A672A240024ED68 /* StringConvert.cpp */; };
 		3F8160A61AB9F7DD001DA9DF /* Logging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F8160A51AB9F7DD001DA9DF /* Logging.cpp */; };
@@ -976,6 +975,8 @@
 		B2A58724143119D50092BFBA /* SBWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2A58723143119D50092BFBA /* SBWatchpoint.cpp */; };
 		B2B7CCEB15D1BD6700EEFB57 /* CommandObjectWatchpointCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2B7CCEA15D1BD6600EEFB57 /* CommandObjectWatchpointCommand.cpp */; };
 		B2B7CCF015D1C20F00EEFB57 /* WatchpointOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2B7CCEF15D1C20F00EEFB57 /* WatchpointOptions.cpp */; };
+		D67521361EA17C3900439694 /* MainLoop.cpp in CopyFiles */ = {isa = PBXBuildFile; fileRef = D67521351EA17C3900439694 /* MainLoop.cpp */; };
+		D67521381EA17C4200439694 /* MainLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D67521351EA17C3900439694 /* MainLoop.cpp */; };
 		E769331C1A94D15400C73337 /* lldb-gdbserver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D6F3F4183E7F9300194858 /* lldb-gdbserver.cpp */; };
 		E769331E1A94D18100C73337 /* lldb-server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E769331D1A94D18100C73337 /* lldb-server.cpp */; };
 		E7723D441AC4A7FB002BA082 /* RegisterContextPOSIXCore_arm64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E7723D421AC4A7FB002BA082 /* RegisterContextPOSIXCore_arm64.cpp */; };
@@ -1187,6 +1188,7 @@
 			dstPath = "$(DEVELOPER_INSTALL_DIR)/usr/share/man/man1";
 			dstSubfolderSpec = 0;
 			files = (
+				D67521361EA17C3900439694 /* MainLoop.cpp in CopyFiles */,
 				AF90106515AB7D3600FF120D /* lldb.1 in CopyFiles */,
 			);
 			runOnlyForDeploymentPostprocessing = 1;
@@ -2317,7 +2319,6 @@
 		26FFC19814FC072100087D58 /* DynamicLoaderPOSIXDYLD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderPOSIXDYLD.h; sourceTree = "<group>"; };
 		3032B1B61CAAA3D1004BE1AB /* ClangUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangUtil.cpp; path = source/Symbol/ClangUtil.cpp; sourceTree = "<group>"; };
 		3032B1B91CAAA400004BE1AB /* ClangUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangUtil.h; path = include/lldb/Symbol/ClangUtil.h; sourceTree = "<group>"; };
-		30DED5DC1B4ECB17004CC508 /* MainLoopPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MainLoopPosix.cpp; sourceTree = "<group>"; };
 		33064C991A5C7A330033D415 /* UriParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UriParser.cpp; path = source/Utility/UriParser.cpp; sourceTree = "<group>"; };
 		3392EBB71AFF402200858B9F /* SBLanguageRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBLanguageRuntime.h; path = include/lldb/API/SBLanguageRuntime.h; sourceTree = "<group>"; };
 		33E5E8411A672A240024ED68 /* StringConvert.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringConvert.cpp; sourceTree = "<group>"; };
@@ -3047,6 +3048,7 @@
 		B2B7CCED15D1BFB700EEFB57 /* WatchpointOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WatchpointOptions.h; path = include/lldb/Breakpoint/WatchpointOptions.h; sourceTree = "<group>"; };
 		B2B7CCEF15D1C20F00EEFB57 /* WatchpointOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WatchpointOptions.cpp; path = source/Breakpoint/WatchpointOptions.cpp; sourceTree = "<group>"; };
 		B2D3033612EFA5C500F84EB3 /* InstructionUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InstructionUtils.h; path = Utility/InstructionUtils.h; sourceTree = "<group>"; };
+		D67521351EA17C3900439694 /* MainLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MainLoop.cpp; sourceTree = "<group>"; };
 		E73A15A41B548EC500786197 /* GDBRemoteSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GDBRemoteSignals.cpp; path = Utility/GDBRemoteSignals.cpp; sourceTree = "<group>"; };
 		E73A15A51B548EC500786197 /* GDBRemoteSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GDBRemoteSignals.h; path = Utility/GDBRemoteSignals.h; sourceTree = "<group>"; };
 		E769331D1A94D18100C73337 /* lldb-server.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "lldb-server.cpp"; path = "tools/lldb-server/lldb-server.cpp"; sourceTree = "<group>"; };
@@ -5661,7 +5663,6 @@
 			children = (
 				2579065E1BD0488D00178368 /* DomainSocket.cpp */,
 				255EFF751AFABA950069F277 /* LockFilePosix.cpp */,
-				30DED5DC1B4ECB17004CC508 /* MainLoopPosix.cpp */,
 				AFDFDFD019E34D3400EAE509 /* ConnectionFileDescriptorPosix.cpp */,
 				3FDFDDC5199D37ED009756A7 /* FileSystem.cpp */,
 				3FDFE53019A292F0009756A7 /* HostInfoPosix.cpp */,
@@ -5896,6 +5897,7 @@
 		69A01E1A1236C5D400C660B5 /* common */ = {
 			isa = PBXGroup;
 			children = (
+				D67521351EA17C3900439694 /* MainLoop.cpp */,
 				2579065A1BD0488100178368 /* TCPSocket.cpp */,
 				2579065B1BD0488100178368 /* UDPSocket.cpp */,
 				255EFF731AFABA720069F277 /* LockFileBase.cpp */,
@@ -7284,6 +7286,7 @@
 				AE6897281B94F6DE0018845D /* DWARFASTParserGo.cpp in Sources */,
 				945261C41B9A11FC00BF138D /* LibCxxUnorderedMap.cpp in Sources */,
 				26CEB5F218762056008F575A /* CommandObjectGUI.cpp in Sources */,
+				D67521381EA17C4200439694 /* MainLoop.cpp in Sources */,
 				2689008013353E2200698AC0 /* CommandInterpreter.cpp in Sources */,
 				AF77E0A41A033D360096C0EA /* RegisterContextPOSIX_powerpc.cpp in Sources */,
 				4CDB8D6D1DBA91B6006C5B13 /* LibStdcppUniquePointer.cpp in Sources */,
@@ -7776,7 +7779,6 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				30DED5DE1B4ECB49004CC508 /* MainLoopPosix.cpp in Sources */,
 				E769331C1A94D15400C73337 /* lldb-gdbserver.cpp in Sources */,
 				26DC6A1D1337FECA00FF7998 /* lldb-platform.cpp in Sources */,
 				E769331E1A94D18100C73337 /* lldb-server.cpp in Sources */,
Index: include/lldb/Host/posix/MainLoopPosix.h
===================================================================
--- include/lldb/Host/posix/MainLoopPosix.h
+++ /dev/null
@@ -1,104 +0,0 @@
-//===-- MainLoopPosix.h -----------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef lldb_Host_posix_MainLoopPosix_h_
-#define lldb_Host_posix_MainLoopPosix_h_
-
-#include "lldb/Host/MainLoopBase.h"
-
-#include "llvm/ADT/DenseMap.h"
-
-namespace lldb_private {
-
-// Posix implementation of the MainLoopBase class. It can monitor file
-// descriptors for
-// readability using pselect. In addition to the common base, this class
-// provides the ability to
-// invoke a given handler when a signal is received.
-//
-// Since this class is primarily intended to be used for single-threaded
-// processing, it does not
-// attempt to perform any internal synchronisation and any concurrent accesses
-// must be protected
-// externally. However, it is perfectly legitimate to have more than one
-// instance of this class
-// running on separate threads, or even a single thread (with some limitations
-// on signal
-// monitoring).
-// TODO: Add locking if this class is to be used in a multi-threaded context.
-class MainLoopPosix : public MainLoopBase {
-private:
-  class SignalHandle;
-
-public:
-  typedef std::unique_ptr<SignalHandle> SignalHandleUP;
-
-  ~MainLoopPosix() override;
-
-  ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp,
-                                  const Callback &callback,
-                                  Error &error) override;
-
-  // Listening for signals from multiple MainLoopPosix instances is perfectly
-  // safe as long as they
-  // don't try to listen for the same signal. The callback function is invoked
-  // when the control
-  // returns to the Run() function, not when the hander is executed. This means
-  // that you can
-  // treat the callback as a normal function and perform things which would not
-  // be safe in a
-  // signal handler. However, since the callback is not invoked synchronously,
-  // you cannot use
-  // this mechanism to handle SIGSEGV and the like.
-  SignalHandleUP RegisterSignal(int signo, const Callback &callback,
-                                Error &error);
-
-  Error Run() override;
-
-  // This should only be performed from a callback. Do not attempt to terminate
-  // the processing
-  // from another thread.
-  // TODO: Add synchronization if we want to be terminated from another thread.
-  void RequestTermination() override { m_terminate_request = true; }
-
-protected:
-  void UnregisterReadObject(IOObject::WaitableHandle handle) override;
-
-  void UnregisterSignal(int signo);
-
-private:
-  class SignalHandle {
-  public:
-    ~SignalHandle() { m_mainloop.UnregisterSignal(m_signo); }
-
-  private:
-    SignalHandle(MainLoopPosix &mainloop, int signo)
-        : m_mainloop(mainloop), m_signo(signo) {}
-
-    MainLoopPosix &m_mainloop;
-    int m_signo;
-
-    friend class MainLoopPosix;
-    DISALLOW_COPY_AND_ASSIGN(SignalHandle);
-  };
-
-  struct SignalInfo {
-    Callback callback;
-    struct sigaction old_action;
-    bool was_blocked : 1;
-  };
-
-  llvm::DenseMap<IOObject::WaitableHandle, Callback> m_read_fds;
-  llvm::DenseMap<int, SignalInfo> m_signals;
-  bool m_terminate_request : 1;
-};
-
-} // namespace lldb_private
-
-#endif // lldb_Host_posix_MainLoopPosix_h_
Index: include/lldb/Host/posix/DomainSocket.h
===================================================================
--- include/lldb/Host/posix/DomainSocket.h
+++ include/lldb/Host/posix/DomainSocket.h
@@ -15,22 +15,20 @@
 namespace lldb_private {
 class DomainSocket : public Socket {
 public:
-  DomainSocket(bool child_processes_inherit, Error &error);
+  DomainSocket(bool should_close, bool child_processes_inherit);
 
   Error Connect(llvm::StringRef name) override;
   Error Listen(llvm::StringRef name, int backlog) override;
-  Error Accept(llvm::StringRef name, bool child_processes_inherit,
-               Socket *&socket) override;
+  Error Accept(Socket *&socket) override;
 
 protected:
-  DomainSocket(SocketProtocol protocol, bool child_processes_inherit,
-               Error &error);
+  DomainSocket(SocketProtocol protocol, bool child_processes_inherit);
 
   virtual size_t GetNameOffset() const;
   virtual void DeleteSocketFile(llvm::StringRef name);
 
 private:
-  DomainSocket(NativeSocket socket);
+  DomainSocket(NativeSocket socket, const DomainSocket &listen_socket);
 };
 }
 
Index: include/lldb/Host/linux/AbstractSocket.h
===================================================================
--- include/lldb/Host/linux/AbstractSocket.h
+++ include/lldb/Host/linux/AbstractSocket.h
@@ -15,7 +15,7 @@
 namespace lldb_private {
 class AbstractSocket : public DomainSocket {
 public:
-  AbstractSocket(bool child_processes_inherit, Error &error);
+  AbstractSocket(bool child_processes_inherit);
 
 protected:
   size_t GetNameOffset() const override;
Index: include/lldb/Host/common/UDPSocket.h
===================================================================
--- include/lldb/Host/common/UDPSocket.h
+++ include/lldb/Host/common/UDPSocket.h
@@ -15,19 +15,20 @@
 namespace lldb_private {
 class UDPSocket : public Socket {
 public:
-  UDPSocket(bool child_processes_inherit, Error &error);
+  UDPSocket(bool should_close, bool child_processes_inherit);
 
   static Error Connect(llvm::StringRef name, bool child_processes_inherit,
                        Socket *&socket);
 
 private:
-  UDPSocket(NativeSocket socket);
+  UDPSocket(NativeSocket socket, const UDPSocket &listen_socket);
 
   size_t Send(const void *buf, const size_t num_bytes) override;
   Error Connect(llvm::StringRef name) override;
   Error Listen(llvm::StringRef name, int backlog) override;
-  Error Accept(llvm::StringRef name, bool child_processes_inherit,
-               Socket *&socket) override;
+  Error Accept(Socket *&socket) override;
+
+  Error CreateSocket();
 
   SocketAddress m_sockaddr;
 };
Index: include/lldb/Host/common/TCPSocket.h
===================================================================
--- include/lldb/Host/common/TCPSocket.h
+++ include/lldb/Host/common/TCPSocket.h
@@ -11,12 +11,16 @@
 #define liblldb_TCPSocket_h_
 
 #include "lldb/Host/Socket.h"
+#include "lldb/Host/SocketAddress.h"
+#include <map>
 
 namespace lldb_private {
 class TCPSocket : public Socket {
 public:
-  TCPSocket(NativeSocket socket, bool should_close);
-  TCPSocket(bool child_processes_inherit, Error &error);
+  TCPSocket(bool should_close, bool child_processes_inherit);
+  TCPSocket(NativeSocket socket, bool should_close,
+            bool child_processes_inherit);
+  ~TCPSocket();
 
   // returns port number or 0 if error
   uint16_t GetLocalPortNumber() const;
@@ -37,8 +41,18 @@
 
   Error Connect(llvm::StringRef name) override;
   Error Listen(llvm::StringRef name, int backlog) override;
-  Error Accept(llvm::StringRef name, bool child_processes_inherit,
-               Socket *&conn_socket) override;
+  Error Accept(Socket *&conn_socket) override;
+
+  Error CreateSocket(int domain);
+
+  bool IsValid() const override;
+
+private:
+  TCPSocket(NativeSocket socket, const TCPSocket &listen_socket);
+
+  void CloseListenSockets();
+
+  std::map<int, SocketAddress> m_listen_sockets;
 };
 }
 
Index: include/lldb/Host/Socket.h
===================================================================
--- include/lldb/Host/Socket.h
+++ include/lldb/Host/Socket.h
@@ -57,8 +57,7 @@
 
   virtual Error Connect(llvm::StringRef name) = 0;
   virtual Error Listen(llvm::StringRef name, int backlog) = 0;
-  virtual Error Accept(llvm::StringRef name, bool child_processes_inherit,
-                       Socket *&socket) = 0;
+  virtual Error Accept(Socket *&socket) = 0;
 
   // Initialize a Tcp Socket object in listening mode.  listen and accept are
   // implemented
@@ -103,7 +102,8 @@
                                 int32_t &port, Error *error_ptr);
 
 protected:
-  Socket(NativeSocket socket, SocketProtocol protocol, bool should_close);
+  Socket(SocketProtocol protocol, bool should_close,
+         bool m_child_process_inherit);
 
   virtual size_t Send(const void *buf, const size_t num_bytes);
 
@@ -117,6 +117,7 @@
 
   SocketProtocol m_protocol;
   NativeSocket m_socket;
+  bool m_child_processes_inherit;
 };
 
 } // namespace lldb_private
Index: include/lldb/Host/MainLoop.h
===================================================================
--- include/lldb/Host/MainLoop.h
+++ include/lldb/Host/MainLoop.h
@@ -10,16 +10,88 @@
 #ifndef lldb_Host_MainLoop_h_
 #define lldb_Host_MainLoop_h_
 
-#ifdef _WIN32
 #include "lldb/Host/MainLoopBase.h"
+
+#include "llvm/ADT/DenseMap.h"
+
 namespace lldb_private {
-typedef MainLoopBase MainLoop;
-}
-#else
-#include "lldb/Host/posix/MainLoopPosix.h"
-namespace lldb_private {
-typedef MainLoopPosix MainLoop;
-}
-#endif
+
+// Implementation of the MainLoopBase class. It can monitor file descriptors for
+// readability using ppoll, kqueue, poll or WSAPoll. On Windows it only supports
+// polling sockets, and will not work on generic file handles or pipes. On
+// systems without kqueue or ppoll handling singnals is not supported. In
+// addition to the common base, this class provides the ability to invoke a
+// given handler when a signal is received.
+//
+// Since this class is primarily intended to be used for single-threaded
+// processing, it does not attempt to perform any internal synchronisation and
+// any concurrent accesses must be protected  externally. However, it is
+// perfectly legitimate to have more than one instance of this class running on
+// separate threads, or even a single thread (with some limitations on signal
+// monitoring).
+// TODO: Add locking if this class is to be used in a multi-threaded context.
+class MainLoop : public MainLoopBase {
+private:
+  class SignalHandle;
+
+public:
+  typedef std::unique_ptr<SignalHandle> SignalHandleUP;
+
+  ~MainLoop() override;
+
+  ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp,
+                                  const Callback &callback,
+                                  Error &error) override;
+
+  // Listening for signals from multiple MainLoop instances is perfectly safe as
+  // long as they don't try to listen for the same signal. The callback function
+  // is invoked when the control returns to the Run() function, not when the
+  // hander is executed. This mean that you can treat the callback as a normal
+  // function and perform things which would not be safe in a signal handler.
+  // However, since the callback is not invoked synchronously, you cannot use
+  // this mechanism to handle SIGSEGV and the like.
+  SignalHandleUP RegisterSignal(int signo, const Callback &callback,
+                                Error &error);
+
+  Error Run() override;
+
+  // This should only be performed from a callback. Do not attempt to terminate
+  // the processing from another thread.
+  // TODO: Add synchronization if we want to be terminated from another thread.
+  void RequestTermination() override { m_terminate_request = true; }
+
+protected:
+  void UnregisterReadObject(IOObject::WaitableHandle handle) override;
+
+  void UnregisterSignal(int signo);
+
+private:
+  class SignalHandle {
+  public:
+    ~SignalHandle() { m_mainloop.UnregisterSignal(m_signo); }
+
+  private:
+    SignalHandle(MainLoop &mainloop, int signo)
+        : m_mainloop(mainloop), m_signo(signo) {}
+
+    MainLoop &m_mainloop;
+    int m_signo;
+
+    friend class MainLoop;
+    DISALLOW_COPY_AND_ASSIGN(SignalHandle);
+  };
+
+  struct SignalInfo {
+    Callback callback;
+    struct sigaction old_action;
+    bool was_blocked : 1;
+  };
+
+  llvm::DenseMap<IOObject::WaitableHandle, Callback> m_read_fds;
+  llvm::DenseMap<int, SignalInfo> m_signals;
+  bool m_terminate_request : 1;
+};
+
+} // namespace lldb_private
 
 #endif // lldb_Host_MainLoop_h_
Index: include/lldb/Host/Config.h.cmake
===================================================================
--- include/lldb/Host/Config.h.cmake
+++ include/lldb/Host/Config.h.cmake
@@ -16,4 +16,6 @@
 
 #cmakedefine01 HAVE_SYS_EVENT_H
 
+#cmakedefine01 HAVE_PPOLL
+
 #endif // #ifndef LLDB_HOST_CONFIG_H
Index: include/lldb/Host/Config.h
===================================================================
--- include/lldb/Host/Config.h
+++ include/lldb/Host/Config.h
@@ -18,6 +18,8 @@
 
 #define HAVE_SYS_EVENT_H 1
 
+#define HAVE_PPOLL 0
+
 #else
 
 #error This file is only used by the Xcode build.
Index: cmake/modules/LLDBConfig.cmake
===================================================================
--- cmake/modules/LLDBConfig.cmake
+++ cmake/modules/LLDBConfig.cmake
@@ -432,6 +432,7 @@
 endif()
 
 find_package(Backtrace)
+check_symbol_exists(ppoll poll.h HAVE_PPOLL)
 
 check_include_file(termios.h HAVE_TERMIOS_H)
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to