rupprecht created this revision.
rupprecht added reviewers: labath, clayborg.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.
rupprecht requested review of this revision.
Herald added a subscriber: JDevlieghere.

When running in an ipv6-only environment where `AF_INET` sockets are not 
available, many lldb tests (mostly gdb remote tests) fail because things like 
`127.0.0.1` don't work there.

This change is mostly a simple search-and-replace of `127.0.0.1` -> `localhost` 
until tests pass in an internal ipv6-only environment. A few places have been 
updated to dynamically retry with `AF_INET6` if creating a socket with 
`AF_INET` doesn't work.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D87333

Files:
  lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
  lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
  lldb/source/Target/Platform.cpp
  lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py
  lldb/test/API/tools/lldb-server/commandline/TestStubReverseConnect.py
  lldb/unittests/Host/SocketTest.cpp
  lldb/unittests/Host/SocketTestUtilities.cpp

Index: lldb/unittests/Host/SocketTestUtilities.cpp
===================================================================
--- lldb/unittests/Host/SocketTestUtilities.cpp
+++ lldb/unittests/Host/SocketTestUtilities.cpp
@@ -101,13 +101,14 @@
                              "Creating a canary {0} TCP socket failed: {1}.",
                              Proto, Err)
                              .str();
-  bool HasAddrNotAvail = false;
+  bool HasProtocolError = false;
   handleAllErrors(std::move(Err), [&](std::unique_ptr<llvm::ECError> ECErr) {
-    if (ECErr->convertToErrorCode() ==
-        std::make_error_code(std::errc::address_not_available))
-      HasAddrNotAvail = true;
+    std::error_code ec = ECErr->convertToErrorCode();
+    if (ec == std::make_error_code(std::errc::address_family_not_supported) ||
+        ec == std::make_error_code(std::errc::address_not_available))
+      HasProtocolError = true;
   });
-  if (HasAddrNotAvail) {
+  if (HasProtocolError) {
     GTEST_LOG_(WARNING)
         << llvm::formatv(
                "Assuming the host does not support {0}. Skipping test.", Proto)
Index: lldb/unittests/Host/SocketTest.cpp
===================================================================
--- lldb/unittests/Host/SocketTest.cpp
+++ lldb/unittests/Host/SocketTest.cpp
@@ -14,12 +14,24 @@
 
 using namespace lldb_private;
 
-class SocketTest : public testing::Test {
+struct SocketTestParams {
+  bool is_ipv6;
+  std::string localhost_ip;
+};
+
+class SocketTest : public testing::TestWithParam<SocketTestParams> {
 public:
   SubsystemRAII<Socket> subsystems;
+
+protected:
+  bool HostSupportsProtocol() const {
+    if (GetParam().is_ipv6)
+      return HostSupportsIPv6();
+    return HostSupportsIPv4();
+  }
 };
 
-TEST_F(SocketTest, DecodeHostAndPort) {
+TEST_P(SocketTest, DecodeHostAndPort) {
   std::string host_str;
   std::string port_str;
   int32_t port;
@@ -86,7 +98,7 @@
 }
 
 #if LLDB_ENABLE_POSIX
-TEST_F(SocketTest, DomainListenConnectAccept) {
+TEST_P(SocketTest, DomainListenConnectAccept) {
   llvm::SmallString<64> Path;
   std::error_code EC = llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", Path);
   ASSERT_FALSE(EC);
@@ -102,18 +114,22 @@
 }
 #endif
 
-TEST_F(SocketTest, TCPListen0ConnectAccept) {
+TEST_P(SocketTest, TCPListen0ConnectAccept) {
+  if (!HostSupportsProtocol())
+    return;
   std::unique_ptr<TCPSocket> socket_a_up;
   std::unique_ptr<TCPSocket> socket_b_up;
-  CreateTCPConnectedSockets("127.0.0.1", &socket_a_up, &socket_b_up);
+  CreateTCPConnectedSockets(GetParam().localhost_ip, &socket_a_up,
+                            &socket_b_up);
 }
 
-TEST_F(SocketTest, TCPGetAddress) {
+TEST_P(SocketTest, TCPGetAddress) {
   std::unique_ptr<TCPSocket> socket_a_up;
   std::unique_ptr<TCPSocket> socket_b_up;
-  if (!HostSupportsIPv4())
+  if (!HostSupportsProtocol())
     return;
-  CreateTCPConnectedSockets("127.0.0.1", &socket_a_up, &socket_b_up);
+  CreateTCPConnectedSockets(GetParam().localhost_ip, &socket_a_up,
+                            &socket_b_up);
 
   EXPECT_EQ(socket_a_up->GetLocalPortNumber(),
             socket_b_up->GetRemotePortNumber());
@@ -121,11 +137,16 @@
             socket_a_up->GetRemotePortNumber());
   EXPECT_NE(socket_a_up->GetLocalPortNumber(),
             socket_b_up->GetLocalPortNumber());
-  EXPECT_STREQ("127.0.0.1", socket_a_up->GetRemoteIPAddress().c_str());
-  EXPECT_STREQ("127.0.0.1", socket_b_up->GetRemoteIPAddress().c_str());
+  EXPECT_STREQ(GetParam().localhost_ip.c_str(),
+               socket_a_up->GetRemoteIPAddress().c_str());
+  EXPECT_STREQ(GetParam().localhost_ip.c_str(),
+               socket_b_up->GetRemoteIPAddress().c_str());
 }
 
-TEST_F(SocketTest, UDPConnect) {
+TEST_P(SocketTest, UDPConnect) {
+  // UDPSocket::Connect() creates sockets with AF_INET (IPv4).
+  if (!HostSupportsIPv4())
+    return;
   llvm::Expected<std::unique_ptr<UDPSocket>> socket =
       UDPSocket::Connect("127.0.0.1:0", /*child_processes_inherit=*/false);
 
@@ -133,7 +154,9 @@
   EXPECT_TRUE(socket.get()->IsValid());
 }
 
-TEST_F(SocketTest, TCPListen0GetPort) {
+TEST_P(SocketTest, TCPListen0GetPort) {
+  if (!HostSupportsIPv4())
+    return;
   Predicate<uint16_t> port_predicate;
   port_predicate.SetValue(0, eBroadcastNever);
   llvm::Expected<std::unique_ptr<TCPSocket>> sock =
@@ -143,12 +166,13 @@
   EXPECT_NE(sock.get()->GetLocalPortNumber(), 0);
 }
 
-TEST_F(SocketTest, TCPGetConnectURI) {
+TEST_P(SocketTest, TCPGetConnectURI) {
   std::unique_ptr<TCPSocket> socket_a_up;
   std::unique_ptr<TCPSocket> socket_b_up;
-  if (!HostSupportsIPv4())
+  if (!HostSupportsProtocol())
     return;
-  CreateTCPConnectedSockets("127.0.0.1", &socket_a_up, &socket_b_up);
+  CreateTCPConnectedSockets(GetParam().localhost_ip, &socket_a_up,
+                            &socket_b_up);
 
   llvm::StringRef scheme;
   llvm::StringRef hostname;
@@ -160,7 +184,8 @@
   EXPECT_EQ(port, socket_a_up->GetRemotePortNumber());
 }
 
-TEST_F(SocketTest, UDPGetConnectURI) {
+TEST_P(SocketTest, UDPGetConnectURI) {
+  // UDPSocket::Connect() creates sockets with AF_INET (IPv4).
   if (!HostSupportsIPv4())
     return;
   llvm::Expected<std::unique_ptr<UDPSocket>> socket =
@@ -177,7 +202,7 @@
 }
 
 #if LLDB_ENABLE_POSIX
-TEST_F(SocketTest, DomainGetConnectURI) {
+TEST_P(SocketTest, DomainGetConnectURI) {
   llvm::SmallString<64> domain_path;
   std::error_code EC =
       llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", domain_path);
@@ -202,3 +227,13 @@
   EXPECT_EQ(path, domain_path);
 }
 #endif
+
+INSTANTIATE_TEST_CASE_P(
+    SocketTests, SocketTest,
+    testing::Values(SocketTestParams{/*is_ipv6=*/false,
+                                     /*localhost_ip=*/"127.0.0.1"},
+                    SocketTestParams{/*is_ipv6=*/true, /*localhost_ip=*/"::1"}),
+    // Prints "SocketTests/SocketTest.DecodeHostAndPort/ipv4" etc. in test logs.
+    [](const testing::TestParamInfo<SocketTestParams> &info) {
+      return info.param.is_ipv6 ? "ipv6" : "ipv4";
+    });
Index: lldb/test/API/tools/lldb-server/commandline/TestStubReverseConnect.py
===================================================================
--- lldb/test/API/tools/lldb-server/commandline/TestStubReverseConnect.py
+++ lldb/test/API/tools/lldb-server/commandline/TestStubReverseConnect.py
@@ -1,5 +1,6 @@
 from __future__ import print_function
 
+import errno
 import gdbremote_testcase
 import lldbgdbserverutils
 import re
@@ -24,11 +25,16 @@
         self.listener_port = self.listener_socket.getsockname()[1]
 
     def create_listener_socket(self):
-        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        try:
+            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        except OSError as e:
+            if e.errno != errno.EAFNOSUPPORT:
+                raise
+            sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
         self.assertIsNotNone(sock)
 
         sock.settimeout(self.DEFAULT_TIMEOUT)
-        sock.bind(("127.0.0.1", 0))
+        sock.bind(("localhost", 0))
         sock.listen(1)
 
         def tear_down_listener():
@@ -49,7 +55,7 @@
         else:
             self.debug_monitor_extra_args = appended_stub_args
 
-        self.stub_hostname = "127.0.0.1"
+        self.stub_hostname = "localhost"
         self.port = self.listener_port
 
         triple = self.dbg.GetSelectedPlatform().GetTriple()
Index: lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py
===================================================================
--- lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py
+++ lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py
@@ -1,3 +1,4 @@
+import errno
 import os
 import os.path
 import threading
@@ -317,12 +318,17 @@
     def __init__(self, port = 0):
         self.responder = MockGDBServerResponder()
         self.port = port
-        self._socket = socket.socket()
+        try:
+            self._socket = socket.socket(family=socket.AF_INET)
+        except OSError as e:
+            if e.errno != errno.EAFNOSUPPORT:
+                raise
+            self._socket = socket.socket(family=socket.AF_INET6)
 
     def start(self):
         # Block until the socket is up, so self.port is available immediately.
         # Then start a thread that waits for a client connection.
-        addr = ("127.0.0.1", self.port)
+        addr = ("localhost", self.port)
         self._socket.bind(addr)
         self.port = self._socket.getsockname()[1]
         self._socket.listen(1)
Index: lldb/source/Target/Platform.cpp
===================================================================
--- lldb/source/Target/Platform.cpp
+++ lldb/source/Target/Platform.cpp
@@ -811,7 +811,7 @@
 
 const char *Platform::GetHostname() {
   if (IsHost())
-    return "127.0.0.1";
+    return "localhost";
 
   if (m_name.empty())
     return nullptr;
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -192,7 +192,7 @@
   // on m_bytes.  The checksum was for the compressed packet.
   bool DecompressPacket();
 
-  Status StartListenThread(const char *hostname = "127.0.0.1",
+  Status StartListenThread(const char *hostname = "localhost",
                            uint16_t port = 0);
 
   bool JoinListenThread();
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -1048,7 +1048,7 @@
       } else {
         // No host and port given, so lets listen on our end and make the
         // debugserver connect to us..
-        error = StartListenThread("127.0.0.1", 0);
+        error = StartListenThread("localhost", 0);
         if (error.Fail()) {
           LLDB_LOGF(log,
                     "GDBRemoteCommunication::%s() unable to start listen "
@@ -1063,7 +1063,7 @@
         uint16_t port_ = connection->GetListeningPort(std::chrono::seconds(10));
         if (port_ > 0) {
           char port_cstr[32];
-          snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", port_);
+          snprintf(port_cstr, sizeof(port_cstr), "localhost:%i", port_);
           // Send the host and port down that debugserver and specify an option
           // so that it connects back to the port we are listening to in this
           // process
@@ -1072,7 +1072,7 @@
           if (port)
             *port = port_;
         } else {
-          error.SetErrorString("failed to bind to port 0 on 127.0.0.1");
+          error.SetErrorString("failed to bind to port 0 on localhost");
           LLDB_LOGF(log, "GDBRemoteCommunication::%s() failed: %s",
                     __FUNCTION__, error.AsCString());
           return error;
@@ -1234,7 +1234,7 @@
   const int backlog = 5;
   TCPSocket listen_socket(true, child_processes_inherit);
   if (llvm::Error error =
-          listen_socket.Listen("127.0.0.1:0", backlog).ToError())
+          listen_socket.Listen("localhost:0", backlog).ToError())
     return error;
 
   Socket *accept_socket;
@@ -1243,7 +1243,7 @@
 
   llvm::SmallString<32> remote_addr;
   llvm::raw_svector_ostream(remote_addr)
-      << "connect://127.0.0.1:" << listen_socket.GetLocalPortNumber();
+      << "connect://localhost:" << listen_socket.GetLocalPortNumber();
 
   std::unique_ptr<ConnectionFileDescriptor> conn_up(
       new ConnectionFileDescriptor());
Index: lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
===================================================================
--- lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -537,7 +537,7 @@
     // localhost, so we will need the remote debugserver to accept connections
     // only from localhost, no matter what our current hostname is
     launch_result =
-        m_gdb_client.LaunchGDBServer("127.0.0.1", pid, port, socket_name);
+        m_gdb_client.LaunchGDBServer("localhost", pid, port, socket_name);
   } else {
     // All other hosts should use their actual hostname
     launch_result =
Index: lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
+++ lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
@@ -318,7 +318,12 @@
             raise _ConnectionRefused()  # Got EOF, connection dropped.
 
     def create_socket(self):
-        sock = socket.socket()
+        try:
+            sock = socket.socket(family=socket.AF_INET)
+        except OSError as e:
+            if e.errno != errno.EAFNOSUPPORT:
+                raise
+            sock = socket.socket(family=socket.AF_INET6)
         logger = self.logger
 
         triple = self.dbg.GetSelectedPlatform().GetTriple()
@@ -379,7 +384,7 @@
                 ["*:{}".format(self.port)]
         else:
             commandline_args = self.debug_monitor_extra_args + \
-                ["127.0.0.1:{}".format(self.port)]
+                ["localhost:{}".format(self.port)]
 
         if attach_pid:
             commandline_args += ["--attach=%d" % attach_pid]
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to