diff options
Diffstat (limited to 'lldb/source/Host')
-rw-r--r-- | lldb/source/Host/CMakeLists.txt | 2 | ||||
-rw-r--r-- | lldb/source/Host/common/Socket.cpp | 35 | ||||
-rw-r--r-- | lldb/source/Host/common/TCPSocket.cpp | 248 | ||||
-rw-r--r-- | lldb/source/Host/common/UDPSocket.cpp | 84 | ||||
-rw-r--r-- | lldb/source/Host/linux/AbstractSocket.cpp | 4 | ||||
-rw-r--r-- | lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp | 4 | ||||
-rw-r--r-- | lldb/source/Host/posix/DomainSocket.cpp | 35 | ||||
-rw-r--r-- | lldb/source/Host/posix/MainLoopPosix.cpp (renamed from lldb/source/Host/common/MainLoop.cpp) | 144 |
8 files changed, 206 insertions, 350 deletions
diff --git a/lldb/source/Host/CMakeLists.txt b/lldb/source/Host/CMakeLists.txt index 2a73c30f852..f00d67420fa 100644 --- a/lldb/source/Host/CMakeLists.txt +++ b/lldb/source/Host/CMakeLists.txt @@ -15,7 +15,6 @@ add_host_subdirectory(common common/HostThread.cpp common/IOObject.cpp common/LockFileBase.cpp - common/MainLoop.cpp common/MonitoringProcessLauncher.cpp common/NativeBreakpoint.cpp common/NativeBreakpointList.cpp @@ -86,6 +85,7 @@ else() posix/HostProcessPosix.cpp posix/HostThreadPosix.cpp posix/LockFilePosix.cpp + posix/MainLoopPosix.cpp posix/PipePosix.cpp posix/ProcessLauncherPosixFork.cpp ) diff --git a/lldb/source/Host/common/Socket.cpp b/lldb/source/Host/common/Socket.cpp index 0589595bc7f..2a665ddacb6 100644 --- a/lldb/source/Host/common/Socket.cpp +++ b/lldb/source/Host/common/Socket.cpp @@ -18,8 +18,6 @@ #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" @@ -69,11 +67,9 @@ bool IsInterrupted() { } } -Socket::Socket(SocketProtocol protocol, bool should_close, - bool child_processes_inherit) +Socket::Socket(NativeSocket socket, SocketProtocol protocol, bool should_close) : IOObject(eFDTypeSocket, should_close), m_protocol(protocol), - m_socket(kInvalidSocketValue), - m_child_processes_inherit(child_processes_inherit) {} + m_socket(socket) {} Socket::~Socket() { Close(); } @@ -85,14 +81,14 @@ std::unique_ptr<Socket> Socket::Create(const SocketProtocol protocol, std::unique_ptr<Socket> socket_up; switch (protocol) { case ProtocolTcp: - socket_up = llvm::make_unique<TCPSocket>(true, child_processes_inherit); + socket_up.reset(new TCPSocket(child_processes_inherit, error)); break; case ProtocolUdp: - socket_up = llvm::make_unique<UDPSocket>(true, child_processes_inherit); + socket_up.reset(new UDPSocket(child_processes_inherit, error)); break; case ProtocolUnixDomain: #ifndef LLDB_DISABLE_POSIX - socket_up = llvm::make_unique<DomainSocket>(true, child_processes_inherit); + socket_up.reset(new DomainSocket(child_processes_inherit, error)); #else error.SetErrorString( "Unix domain sockets are not supported on this platform."); @@ -100,8 +96,7 @@ std::unique_ptr<Socket> Socket::Create(const SocketProtocol protocol, break; case ProtocolUnixAbstract: #ifdef __linux__ - socket_up = - llvm::make_unique<AbstractSocket>(child_processes_inherit); + socket_up.reset(new AbstractSocket(child_processes_inherit, error)); #else error.SetErrorString( "Abstract domain sockets are not supported on this platform."); @@ -150,7 +145,7 @@ Error Socket::TcpListen(llvm::StringRef host_and_port, return error; std::unique_ptr<TCPSocket> listen_socket( - new TCPSocket(child_processes_inherit, true)); + new TCPSocket(child_processes_inherit, error)); if (error.Fail()) return error; @@ -213,7 +208,7 @@ Error Socket::UnixDomainAccept(llvm::StringRef name, if (error.Fail()) return error; - error = listen_socket->Accept(socket); + error = listen_socket->Accept(name, child_processes_inherit, socket); return error; } @@ -245,22 +240,18 @@ Error Socket::UnixAbstractAccept(llvm::StringRef name, if (error.Fail()) return error; - error = listen_socket->Accept(socket); + error = listen_socket->Accept(name, child_processes_inherit, 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-9a-fA-F:]+.*\\]):([0-9]+)")); + static RegularExpression g_regex(llvm::StringRef("([^:]+):([0-9]+)")); RegularExpression::Match regex_match(2); if (g_regex.Execute(host_and_port, ®ex_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) { @@ -413,12 +404,12 @@ NativeSocket Socket::CreateSocket(const int domain, const int type, const int protocol, bool child_processes_inherit, Error &error) { error.Clear(); - auto socket_type = type; + auto socketType = type; #ifdef SOCK_CLOEXEC if (!child_processes_inherit) - socket_type |= SOCK_CLOEXEC; + socketType |= SOCK_CLOEXEC; #endif - auto sock = ::socket(domain, socket_type, protocol); + auto sock = ::socket(domain, socketType, protocol); if (sock == kInvalidSocketValue) SetLastError(error); diff --git a/lldb/source/Host/common/TCPSocket.cpp b/lldb/source/Host/common/TCPSocket.cpp index 2f7384bbb57..9a009280a90 100644 --- a/lldb/source/Host/common/TCPSocket.cpp +++ b/lldb/source/Host/common/TCPSocket.cpp @@ -14,55 +14,30 @@ #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 kType = SOCK_STREAM; -} -TCPSocket::TCPSocket(bool should_close, bool child_processes_inherit) - : Socket(ProtocolTcp, should_close, child_processes_inherit) {} - -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; +const int kDomain = AF_INET; +const int kType = SOCK_STREAM; } -TCPSocket::~TCPSocket() { CloseListenSockets(); } +TCPSocket::TCPSocket(NativeSocket socket, bool should_close) + : Socket(socket, ProtocolTcp, should_close) {} -bool TCPSocket::IsValid() const { - return m_socket != kInvalidSocketValue || m_listen_sockets.size() != 0; -} +TCPSocket::TCPSocket(bool child_processes_inherit, Error &error) + : TCPSocket(CreateSocket(kDomain, kType, IPPROTO_TCP, + child_processes_inherit, error), + true) {} // Return the port number that is being used by the socket. uint16_t TCPSocket::GetLocalPortNumber() const { @@ -71,12 +46,6 @@ uint16_t TCPSocket::GetLocalPortNumber() const { 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; } @@ -115,18 +84,9 @@ std::string TCPSocket::GetRemoteIPAddress() const { 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) @@ -139,133 +99,146 @@ Error TCPSocket::Connect(llvm::StringRef name) { if (!DecodeHostAndPort(name, host_str, port_str, port, &error)) return error; - auto addresses = - lldb_private::SocketAddress::GetAddressInfo(host_str.c_str(), NULL); - for (auto address : addresses) { - error = CreateSocket(address.GetFamily()); - if (error.Fail()) - continue; - - address.SetPort(port); + 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()); - if (-1 == ::connect(GetNativeSocket(), &address.sockaddr(), - address.GetLength())) { - continue; + return error; } + } - SetOptionNoDelay(); - - error.Clear(); + if (-1 == + ::connect(GetNativeSocket(), (const struct sockaddr *)&sa, sizeof(sa))) { + SetLastError(error); return error; } - error.SetErrorString("Failed to connect port"); + // Keep our TCP packets coming without any delays. + SetOptionNoDelay(); + error.Clear(); 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; - 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; - } - - // enable local address reuse - SetOptionReuseAddress(); + SocketAddress bind_addr; - address.SetPort(port); + // 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); - int err = ::bind(fd, &address.sockaddr(), address.GetLength()); - if (-1 != err) - err = ::listen(fd, backlog); + if (!bind_addr_success) { + error.SetErrorString("Failed to bind port"); + return error; + } - if (-1 == err) { - CLOSE_SOCKET(fd); - continue; - } + int err = ::bind(GetNativeSocket(), bind_addr, bind_addr.GetLength()); + if (err != -1) + err = ::listen(GetNativeSocket(), backlog); - 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 (err == -1) + SetLastError(error); - if (m_listen_sockets.size() == 0) - error.SetErrorString("Failed to connect port"); return error; } -void TCPSocket::CloseListenSockets() { - for (auto socket : m_listen_sockets) - CLOSE_SOCKET(socket.first); - m_listen_sockets.clear(); -} - -Error TCPSocket::Accept(Socket *&conn_socket) { +Error TCPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, + Socket *&conn_socket) { Error error; - if (m_listen_sockets.size() == 0) { - error.SetErrorString("No open listening sockets!"); + std::string host_str; + std::string port_str; + int32_t port; + if (!DecodeHostAndPort(name, host_str, port_str, port, &error)) return error; - } - 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()) + 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()); return error; + } } bool accept_connection = false; std::unique_ptr<TCPSocket> accepted_socket; + // Loop until we are happy with our connection while (!accept_connection) { - accept_loop.Run(); - + 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); + if (error.Fail()) - 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; + 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(); } - accept_connection = true; - accepted_socket.reset(new TCPSocket(sock, *this)); } if (!accepted_socket) @@ -275,7 +248,6 @@ Error TCPSocket::Accept(Socket *&conn_socket) { accepted_socket->SetOptionNoDelay(); error.Clear(); conn_socket = accepted_socket.release(); - CloseListenSockets(); return error; } diff --git a/lldb/source/Host/common/UDPSocket.cpp b/lldb/source/Host/common/UDPSocket.cpp index a32657aab0a..7ca62e7496b 100644 --- a/lldb/source/Host/common/UDPSocket.cpp +++ b/lldb/source/Host/common/UDPSocket.cpp @@ -28,16 +28,13 @@ const int kDomain = AF_INET; const int kType = SOCK_DGRAM; static const char *g_not_supported_error = "Not supported"; -} // namespace +} -UDPSocket::UDPSocket(bool should_close, bool child_processes_inherit) - : Socket(ProtocolUdp, should_close, child_processes_inherit) {} +UDPSocket::UDPSocket(NativeSocket socket) : Socket(socket, ProtocolUdp, true) {} -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; -} +UDPSocket::UDPSocket(bool child_processes_inherit, Error &error) + : UDPSocket( + CreateSocket(kDomain, kType, 0, child_processes_inherit, error)) {} size_t UDPSocket::Send(const void *buf, const size_t num_bytes) { return ::sendto(m_socket, static_cast<const char *>(buf), num_bytes, 0, @@ -45,14 +42,27 @@ size_t UDPSocket::Send(const void *buf, const size_t num_bytes) { } 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; @@ -84,11 +94,12 @@ Error UDPSocket::Connect(llvm::StringRef name) { for (struct addrinfo *service_info_ptr = service_info_list; service_info_ptr != nullptr; service_info_ptr = service_info_ptr->ai_next) { - m_socket = Socket::CreateSocket( + auto send_fd = CreateSocket( service_info_ptr->ai_family, service_info_ptr->ai_socktype, - service_info_ptr->ai_protocol, m_child_processes_inherit, error); + service_info_ptr->ai_protocol, child_processes_inherit, error); if (error.Success()) { - m_sockaddr = service_info_ptr; + final_socket.reset(new UDPSocket(send_fd)); + final_socket->m_sockaddr = service_info_ptr; break; } else continue; @@ -96,17 +107,16 @@ Error UDPSocket::Connect(llvm::StringRef name) { ::freeaddrinfo(service_info_list); - if (IsValid()) + if (!final_socket) 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"); @@ -115,37 +125,13 @@ Error UDPSocket::Connect(llvm::StringRef name) { bind_addr.SetPort(0); // Let the source port # be determined dynamically - err = ::bind(m_socket, bind_addr, bind_addr.GetLength()); + err = ::bind(final_socket->GetNativeSocket(), bind_addr, bind_addr.GetLength()); - error.Clear(); - return error; -} - -Error UDPSocket::Listen(llvm::StringRef name, int backlog) { - return Error("%s", g_not_supported_error); -} - -Error UDPSocket::Accept(Socket *&socket) { - return Error("%s", g_not_supported_error); -} + struct sockaddr_in source_info; + socklen_t address_len = sizeof (struct sockaddr_in); + err = ::getsockname(final_socket->GetNativeSocket(), (struct sockaddr *) &source_info, &address_len); -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(); + socket = final_socket.release(); + error.Clear(); return error; } diff --git a/lldb/source/Host/linux/AbstractSocket.cpp b/lldb/source/Host/linux/AbstractSocket.cpp index 2d6f6adaf1e..b6b59ae403d 100644 --- a/lldb/source/Host/linux/AbstractSocket.cpp +++ b/lldb/source/Host/linux/AbstractSocket.cpp @@ -14,8 +14,8 @@ using namespace lldb; using namespace lldb_private; -AbstractSocket::AbstractSocket(bool child_processes_inherit) - : DomainSocket(ProtocolUnixAbstract, child_processes_inherit) {} +AbstractSocket::AbstractSocket(bool child_processes_inherit, Error &error) + : DomainSocket(ProtocolUnixAbstract, child_processes_inherit, error) {} size_t AbstractSocket::GetNameOffset() const { return 1; } diff --git a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp index befc847d8a8..a3ac36558e3 100644 --- a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -218,7 +218,7 @@ ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path, // assume we don't own it. std::unique_ptr<TCPSocket> tcp_socket; - tcp_socket.reset(new TCPSocket(fd, false, false)); + tcp_socket.reset(new TCPSocket(fd, 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 @@ ConnectionFileDescriptor::SocketListenAndAccept(llvm::StringRef s, listening_socket_up.reset(socket); socket = nullptr; - error = listening_socket_up->Accept(socket); + error = listening_socket_up->Accept(s, m_child_processes_inherit, socket); listening_socket_up.reset(); if (error_ptr) *error_ptr = error; diff --git a/lldb/source/Host/posix/DomainSocket.cpp b/lldb/source/Host/posix/DomainSocket.cpp index 33c71268c2e..538979df2b6 100644 --- a/lldb/source/Host/posix/DomainSocket.cpp +++ b/lldb/source/Host/posix/DomainSocket.cpp @@ -56,21 +56,19 @@ bool SetSockAddr(llvm::StringRef name, const size_t name_offset, return true; } -} // namespace +} + +DomainSocket::DomainSocket(NativeSocket socket) + : Socket(socket, ProtocolUnixDomain, true) {} -DomainSocket::DomainSocket(bool should_close, bool child_processes_inherit) - : Socket(ProtocolUnixDomain, should_close, child_processes_inherit) {} +DomainSocket::DomainSocket(bool child_processes_inherit, Error &error) + : DomainSocket( + CreateSocket(kDomain, kType, 0, child_processes_inherit, error)) {} DomainSocket::DomainSocket(SocketProtocol protocol, - 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; -} + bool child_processes_inherit, Error &error) + : Socket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error), + protocol, true) {} Error DomainSocket::Connect(llvm::StringRef name) { sockaddr_un saddr_un; @@ -79,9 +77,6 @@ Error DomainSocket::Connect(llvm::StringRef name) { 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); @@ -98,9 +93,6 @@ Error DomainSocket::Listen(llvm::StringRef name, int backlog) { 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) @@ -110,12 +102,13 @@ Error DomainSocket::Listen(llvm::StringRef name, int backlog) { return error; } -Error DomainSocket::Accept(Socket *&socket) { +Error DomainSocket::Accept(llvm::StringRef name, bool child_processes_inherit, + Socket *&socket) { Error error; auto conn_fd = AcceptSocket(GetNativeSocket(), nullptr, nullptr, - m_child_processes_inherit, error); + child_processes_inherit, error); if (error.Success()) - socket = new DomainSocket(conn_fd, *this); + socket = new DomainSocket(conn_fd); return error; } diff --git a/lldb/source/Host/common/MainLoop.cpp b/lldb/source/Host/posix/MainLoopPosix.cpp index d73a80581b1..a73187e730f 100644 --- a/lldb/source/Host/common/MainLoop.cpp +++ b/lldb/source/Host/posix/MainLoopPosix.cpp @@ -1,4 +1,4 @@ -//===-- MainLoop.cpp --------------------------------------------*- C++ -*-===// +//===-- MainLoopPosix.cpp ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,47 +7,14 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Config/config.h" - -#include "lldb/Host/MainLoop.h" +#include "lldb/Host/posix/MainLoopPosix.h" #include "lldb/Utility/Error.h" #include <algorithm> #include <cassert> #include <cerrno> #include <csignal> +#include <sys/select.h> #include <vector> -#include <time.h> - -#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 SIGNAL_POLLING_UNSUPPORTED -#ifdef LLVM_ON_WIN32 -typedef int sigset_t; -typedef int siginfo_t; -#endif - -int ppoll(struct pollfd *fds, size_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; @@ -59,20 +26,14 @@ static void SignalHandler(int signo, siginfo_t *info, void *) { g_signal_flags[signo] = 1; } -MainLoop::~MainLoop() { +MainLoopPosix::~MainLoopPosix() { assert(m_read_fds.size() == 0); assert(m_signals.size() == 0); } -MainLoop::ReadHandleUP -MainLoop::RegisterReadObject(const IOObjectSP &object_sp, +MainLoopPosix::ReadHandleUP +MainLoopPosix::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; @@ -92,13 +53,9 @@ MainLoop::RegisterReadObject(const IOObjectSP &object_sp, // We shall block the signal, then install the signal handler. The signal will // be unblocked in // the Run() function to check for signal delivery. -MainLoop::SignalHandleUP -MainLoop::RegisterSignal(int signo, const Callback &callback, +MainLoopPosix::SignalHandleUP +MainLoopPosix::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; @@ -131,19 +88,15 @@ MainLoop::RegisterSignal(int signo, const Callback &callback, g_signal_flags[signo] = 0; return SignalHandleUP(new SignalHandle(*this, signo)); -#endif } -void MainLoop::UnregisterReadObject(IOObject::WaitableHandle handle) { +void MainLoopPosix::UnregisterReadObject(IOObject::WaitableHandle handle) { bool erased = m_read_fds.erase(handle); UNUSED_IF_ASSERT_DISABLED(erased); assert(erased); } -void MainLoop::UnregisterSignal(int signo) { -#if SIGNAL_POLLING_UNSUPPORTED - Error("Signal polling is not supported on this platform."); -#else +void MainLoopPosix::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()); @@ -157,26 +110,14 @@ void MainLoop::UnregisterSignal(int signo) { nullptr); m_signals.erase(it); -#endif } -Error MainLoop::Run() { +Error MainLoopPosix::Run() { std::vector<int> signals; - 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 sigset_t sigmask; - std::vector<struct pollfd> read_fds; - read_fds.reserve(m_read_fds.size()); -#endif + std::vector<int> read_fds; + fd_set read_fd_set; + m_terminate_request = false; // run until termination or until we run out of things to listen to while (!m_terminate_request && (!m_read_fds.empty() || !m_signals.empty())) { @@ -184,51 +125,28 @@ Error MainLoop::Run() { // listen to, we // will store the *real* list of events separately. signals.clear(); - -#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 read_fds.clear(); + FD_ZERO(&read_fd_set); + int nfds = 0; -#if !SIGNAL_POLLING_UNSUPPORTED 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); + } + for (const auto &sig : m_signals) { signals.push_back(sig.first); sigdelset(&sigmask, sig.first); } -#endif - for (const auto &fd : m_read_fds) { - struct pollfd pfd; - pfd.fd = fd.first; - pfd.events = POLLIN; - pfd.revents = 0; - read_fds.push_back(pfd); - } - - if (ppoll(read_fds.data(), read_fds.size(), nullptr, &sigmask) == -1 && + if (pselect(nfds, &read_fd_set, nullptr, nullptr, nullptr, &sigmask) == + -1 && errno != EINTR) return Error(errno, eErrorTypePOSIX); -#endif for (int sig : signals) { if (g_signal_flags[sig] == 0) @@ -245,19 +163,15 @@ Error MainLoop::Run() { return Error(); } -#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; + for (int fd : read_fds) { + if (!FD_ISSET(fd, &read_fd_set)) + continue; // Not ready - auto it = m_read_fds.find(fd.fd); -#endif + auto it = m_read_fds.find(fd); 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) |