diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py +++ b/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] diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp --- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/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 = diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/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(); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/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 conn_up( new ConnectionFileDescriptor()); diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp --- a/lldb/source/Target/Platform.cpp +++ b/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; diff --git a/lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py b/lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py --- a/lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py +++ b/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) diff --git a/lldb/test/API/tools/lldb-server/commandline/TestStubReverseConnect.py b/lldb/test/API/tools/lldb-server/commandline/TestStubReverseConnect.py --- a/lldb/test/API/tools/lldb-server/commandline/TestStubReverseConnect.py +++ b/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() diff --git a/lldb/unittests/Host/SocketTest.cpp b/lldb/unittests/Host/SocketTest.cpp --- a/lldb/unittests/Host/SocketTest.cpp +++ b/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 { public: SubsystemRAII 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 socket_a_up; std::unique_ptr 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 socket_a_up; std::unique_ptr 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> 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 port_predicate; port_predicate.SetValue(0, eBroadcastNever); llvm::Expected> sock = @@ -143,12 +166,13 @@ EXPECT_NE(sock.get()->GetLocalPortNumber(), 0); } -TEST_F(SocketTest, TCPGetConnectURI) { +TEST_P(SocketTest, TCPGetConnectURI) { std::unique_ptr socket_a_up; std::unique_ptr 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> 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 &info) { + return info.param.is_ipv6 ? "ipv6" : "ipv4"; + }); diff --git a/lldb/unittests/Host/SocketTestUtilities.cpp b/lldb/unittests/Host/SocketTestUtilities.cpp --- a/lldb/unittests/Host/SocketTestUtilities.cpp +++ b/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 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)