https://github.com/charles-zablit updated https://github.com/llvm/llvm-project/pull/205864
>From 93690b77bb444b9323b1e2061d97dbcbc3c46039 Mon Sep 17 00:00:00 2001 From: Charles Zablit <[email protected]> Date: Thu, 25 Jun 2026 18:17:21 +0100 Subject: [PATCH 1/2] [NFC][lldb] Split DomainSocket into a base + posix/windows impls --- lldb/include/lldb/Host/DomainSocket.h | 30 ++++++++++ .../Host/{posix => common}/DomainSocket.h | 19 ++++-- lldb/include/lldb/Host/linux/AbstractSocket.h | 2 +- .../lldb/Host/posix/DomainSocketPosix.h | 29 +++++++++ .../lldb/Host/windows/DomainSocketWindows.h | 30 ++++++++++ lldb/source/Host/CMakeLists.txt | 4 +- .../Host/{posix => common}/DomainSocket.cpp | 59 ++++--------------- lldb/source/Host/common/Socket.cpp | 15 +++-- lldb/source/Host/posix/DomainSocketPosix.cpp | 54 +++++++++++++++++ .../Host/windows/DomainSocketWindows.cpp | 54 +++++++++++++++++ lldb/tools/lldb-server/lldb-platform.cpp | 4 +- .../TestingSupport/Host/SocketTestUtilities.h | 2 +- 12 files changed, 240 insertions(+), 62 deletions(-) create mode 100644 lldb/include/lldb/Host/DomainSocket.h rename lldb/include/lldb/Host/{posix => common}/DomainSocket.h (69%) create mode 100644 lldb/include/lldb/Host/posix/DomainSocketPosix.h create mode 100644 lldb/include/lldb/Host/windows/DomainSocketWindows.h rename lldb/source/Host/{posix => common}/DomainSocket.cpp (79%) create mode 100644 lldb/source/Host/posix/DomainSocketPosix.cpp create mode 100644 lldb/source/Host/windows/DomainSocketWindows.cpp diff --git a/lldb/include/lldb/Host/DomainSocket.h b/lldb/include/lldb/Host/DomainSocket.h new file mode 100644 index 0000000000000..d3e20c9b0ab3c --- /dev/null +++ b/lldb/include/lldb/Host/DomainSocket.h @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_HOST_DOMAINSOCKET_H +#define LLDB_HOST_DOMAINSOCKET_H + +#include "lldb/Host/common/DomainSocket.h" + +#if defined(_WIN32) +#include "lldb/Host/windows/DomainSocketWindows.h" +#else +#include "lldb/Host/posix/DomainSocketPosix.h" +#endif + +namespace lldb_private { + +#if defined(_WIN32) +using DomainSocketPlatform = DomainSocketWindows; +#else +using DomainSocketPlatform = DomainSocketPosix; +#endif + +} // namespace lldb_private + +#endif // LLDB_HOST_DOMAINSOCKET_H diff --git a/lldb/include/lldb/Host/posix/DomainSocket.h b/lldb/include/lldb/Host/common/DomainSocket.h similarity index 69% rename from lldb/include/lldb/Host/posix/DomainSocket.h rename to lldb/include/lldb/Host/common/DomainSocket.h index cfb31922367c5..4d2b657cf88e4 100644 --- a/lldb/include/lldb/Host/posix/DomainSocket.h +++ b/lldb/include/lldb/Host/common/DomainSocket.h @@ -1,4 +1,4 @@ -//===-- DomainSocket.h ------------------------------------------*- C++ -*-===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,14 +6,22 @@ // //===----------------------------------------------------------------------===// -#ifndef LLDB_HOST_POSIX_DOMAINSOCKET_H -#define LLDB_HOST_POSIX_DOMAINSOCKET_H +#ifndef LLDB_HOST_COMMON_DOMAINSOCKET_H +#define LLDB_HOST_COMMON_DOMAINSOCKET_H #include "lldb/Host/Socket.h" #include <string> #include <vector> namespace lldb_private { + +/// Cross-platform AF_UNIX domain-socket logic. +/// +/// Every operation on a domain socket (connect, listen, accept, name +/// lookup) is identical on POSIX and Windows, so it all lives here. The only +/// operation which differs between platforms is the CreatePair() factory: POSIX +/// has socketpair(2) while Windows must emulate it. That factory therefore +/// lives in the DomainSocketPosix / DomainSocketWindows implementation classes. class DomainSocket : public Socket { public: DomainSocket(NativeSocket socket, bool should_close); @@ -21,7 +29,6 @@ class DomainSocket : public Socket { using Pair = std::pair<std::unique_ptr<DomainSocket>, std::unique_ptr<DomainSocket>>; - static llvm::Expected<Pair> CreatePair(); Status Connect(llvm::StringRef name) override; Status Listen(llvm::StringRef name, int backlog) override; @@ -49,6 +56,6 @@ class DomainSocket : public Socket { private: DomainSocket(NativeSocket socket, const DomainSocket &listen_socket); }; -} +} // namespace lldb_private -#endif // LLDB_HOST_POSIX_DOMAINSOCKET_H +#endif // LLDB_HOST_COMMON_DOMAINSOCKET_H diff --git a/lldb/include/lldb/Host/linux/AbstractSocket.h b/lldb/include/lldb/Host/linux/AbstractSocket.h index c6a0e2f8af63b..3e1b228432141 100644 --- a/lldb/include/lldb/Host/linux/AbstractSocket.h +++ b/lldb/include/lldb/Host/linux/AbstractSocket.h @@ -9,7 +9,7 @@ #ifndef liblldb_AbstractSocket_h_ #define liblldb_AbstractSocket_h_ -#include "lldb/Host/posix/DomainSocket.h" +#include "lldb/Host/common/DomainSocket.h" namespace lldb_private { class AbstractSocket : public DomainSocket { diff --git a/lldb/include/lldb/Host/posix/DomainSocketPosix.h b/lldb/include/lldb/Host/posix/DomainSocketPosix.h new file mode 100644 index 0000000000000..1e37cd09cb9ec --- /dev/null +++ b/lldb/include/lldb/Host/posix/DomainSocketPosix.h @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_HOST_POSIX_DOMAINSOCKETPOSIX_H +#define LLDB_HOST_POSIX_DOMAINSOCKETPOSIX_H + +#include "lldb/Host/common/DomainSocket.h" + +namespace lldb_private { + +/// \class DomainSocketPosix DomainSocketPosix.h +/// "lldb/Host/posix/DomainSocketPosix.h" +/// POSIX implementation of the platform-specific parts of DomainSocket. +class DomainSocketPosix : public DomainSocket { +public: + using DomainSocket::DomainSocket; + + /// Create a connected pair of domain sockets using socketpair(2). + static llvm::Expected<Pair> CreatePair(); +}; + +} // namespace lldb_private + +#endif // LLDB_HOST_POSIX_DOMAINSOCKETPOSIX_H diff --git a/lldb/include/lldb/Host/windows/DomainSocketWindows.h b/lldb/include/lldb/Host/windows/DomainSocketWindows.h new file mode 100644 index 0000000000000..3b8f39bd12154 --- /dev/null +++ b/lldb/include/lldb/Host/windows/DomainSocketWindows.h @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_HOST_WINDOWS_DOMAINSOCKETWINDOWS_H +#define LLDB_HOST_WINDOWS_DOMAINSOCKETWINDOWS_H + +#include "lldb/Host/common/DomainSocket.h" + +namespace lldb_private { + +/// \class DomainSocketWindows DomainSocketWindows.h +/// "lldb/Host/windows/DomainSocketWindows.h" +/// Windows implementation of the platform-specific parts of DomainSocket. +class DomainSocketWindows : public DomainSocket { +public: + using DomainSocket::DomainSocket; + + /// Create a connected pair of domain sockets. Windows has no socketpair(2), + /// so this is emulated with a transient listening socket. + static llvm::Expected<Pair> CreatePair(); +}; + +} // namespace lldb_private + +#endif // LLDB_HOST_WINDOWS_DOMAINSOCKETWINDOWS_H diff --git a/lldb/source/Host/CMakeLists.txt b/lldb/source/Host/CMakeLists.txt index 28c639ee38215..57a833af97184 100644 --- a/lldb/source/Host/CMakeLists.txt +++ b/lldb/source/Host/CMakeLists.txt @@ -19,6 +19,7 @@ endmacro() add_host_subdirectory(common common/ConPTYUtils.cpp common/DiagnosticsRendering.cpp + common/DomainSocket.cpp common/FileAction.cpp common/FileCache.cpp common/File.cpp @@ -79,6 +80,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows") add_host_subdirectory(windows windows/ConnectionConPTYWindows.cpp windows/ConnectionGenericFileWindows.cpp + windows/DomainSocketWindows.cpp windows/FileSystem.cpp windows/FileWindows.cpp windows/Host.cpp @@ -100,7 +102,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows") endif() else() add_host_subdirectory(posix - posix/DomainSocket.cpp + posix/DomainSocketPosix.cpp posix/FilePosix.cpp posix/FileSystemPosix.cpp posix/HostInfoPosix.cpp diff --git a/lldb/source/Host/posix/DomainSocket.cpp b/lldb/source/Host/common/DomainSocket.cpp similarity index 79% rename from lldb/source/Host/posix/DomainSocket.cpp rename to lldb/source/Host/common/DomainSocket.cpp index 4f08c372d43cf..e80a26a1a409d 100644 --- a/lldb/source/Host/posix/DomainSocket.cpp +++ b/lldb/source/Host/common/DomainSocket.cpp @@ -1,4 +1,4 @@ -//===-- DomainSocket.cpp --------------------------------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Host/posix/DomainSocket.h" +#include "lldb/Host/common/DomainSocket.h" #include "lldb/Utility/LLDBLog.h" #ifdef __linux__ #include <lldb/Host/linux/AbstractSocket.h> @@ -17,10 +17,16 @@ #include "llvm/Support/FileSystem.h" #include <cstddef> -#include <fcntl.h> #include <memory> + +#ifdef _WIN32 +// clang-format off +#include <afunix.h> +// clang-format on +#else #include <sys/socket.h> #include <sys/un.h> +#endif using namespace lldb; using namespace lldb_private; @@ -38,14 +44,10 @@ static bool SetSockAddr(llvm::StringRef name, const size_t name_offset, memcpy(saddr_un->sun_path + name_offset, name.data(), name.size()); - // For domain sockets we can use SUN_LEN in order to calculate size of - // sockaddr_un, but for abstract sockets we have to calculate size manually - // because of leading null symbol. - if (name_offset == 0) - saddr_un_len = SUN_LEN(saddr_un); - else - saddr_un_len = - offsetof(struct sockaddr_un, sun_path) + name_offset + name.size(); + // Compute the address length explicitly rather than via SUN_LEN: that macro + // is not available on Windows. + saddr_un_len = + offsetof(struct sockaddr_un, sun_path) + name_offset + name.size(); #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ defined(__OpenBSD__) @@ -78,41 +80,6 @@ DomainSocket::DomainSocket(SocketProtocol protocol, NativeSocket socket, m_socket = socket; } -llvm::Expected<DomainSocket::Pair> DomainSocket::CreatePair() { - int sockets[2]; - int type = SOCK_STREAM; -#ifdef SOCK_CLOEXEC - type |= SOCK_CLOEXEC; -#endif - if (socketpair(AF_UNIX, type, 0, sockets) == -1) - return llvm::errorCodeToError(llvm::errnoAsErrorCode()); - -#ifndef SOCK_CLOEXEC - for (int s : sockets) { - int r = fcntl(s, F_SETFD, FD_CLOEXEC | fcntl(s, F_GETFD)); - assert(r == 0); - (void)r; - } -#endif - -#if defined(SO_NOSIGPIPE) - Log *log = GetLog(LLDBLog::Host); - if (Socket::SetOption(sockets[0], SOL_SOCKET, SO_NOSIGPIPE, 1) == -1) - LLDB_LOG(log, "failed to set NO_SIGPIPE on fd {0}: {1}", sockets[0], - llvm::sys::StrError()); - if (Socket::SetOption(sockets[1], SOL_SOCKET, SO_NOSIGPIPE, 1) == -1) - LLDB_LOG(log, "failed to set NO_SIGPIPE on fd {0}: {1}", sockets[1], - llvm::sys::StrError()); -#endif - - return Pair(std::unique_ptr<DomainSocket>( - new DomainSocket(ProtocolUnixDomain, sockets[0], - /*should_close=*/true)), - std::unique_ptr<DomainSocket>( - new DomainSocket(ProtocolUnixDomain, sockets[1], - /*should_close=*/true))); -} - Status DomainSocket::Connect(llvm::StringRef name) { sockaddr_un saddr_un; socklen_t saddr_un_len; diff --git a/lldb/source/Host/common/Socket.cpp b/lldb/source/Host/common/Socket.cpp index 810d63fc0390d..c0247509df1c1 100644 --- a/lldb/source/Host/common/Socket.cpp +++ b/lldb/source/Host/common/Socket.cpp @@ -24,9 +24,9 @@ #include "llvm/Support/Regex.h" #include "llvm/Support/WindowsError.h" -#if LLDB_ENABLE_POSIX -#include "lldb/Host/posix/DomainSocket.h" +#include "lldb/Host/DomainSocket.h" +#if LLDB_ENABLE_POSIX #include <arpa/inet.h> #include <netdb.h> #include <netinet/in.h> @@ -241,10 +241,17 @@ Socket::CreatePair(std::optional<SocketProtocol> protocol) { switch (protocol.value_or(kBestProtocol)) { case ProtocolTcp: return TCPSocket::CreatePair(); -#if LLDB_ENABLE_POSIX case ProtocolUnixDomain: +#if LLDB_ENABLE_POSIX + return DomainSocketPlatform::CreatePair(); +#else + return llvm::createStringError("unsupported protocol"); +#endif case ProtocolUnixAbstract: - return DomainSocket::CreatePair(); +#if LLDB_ENABLE_POSIX + return DomainSocketPlatform::CreatePair(); +#else + return llvm::createStringError("unsupported protocol"); #endif default: return llvm::createStringError("unsupported protocol"); diff --git a/lldb/source/Host/posix/DomainSocketPosix.cpp b/lldb/source/Host/posix/DomainSocketPosix.cpp new file mode 100644 index 0000000000000..77ea6c593bb38 --- /dev/null +++ b/lldb/source/Host/posix/DomainSocketPosix.cpp @@ -0,0 +1,54 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/posix/DomainSocketPosix.h" +#include "lldb/Utility/LLDBLog.h" + +#include "llvm/Support/Errno.h" +#include "llvm/Support/Error.h" + +#include <cassert> +#include <fcntl.h> +#include <memory> +#include <sys/socket.h> + +using namespace lldb; +using namespace lldb_private; + +llvm::Expected<DomainSocket::Pair> DomainSocketPosix::CreatePair() { + int sockets[2]; + int type = SOCK_STREAM; +#ifdef SOCK_CLOEXEC + type |= SOCK_CLOEXEC; +#endif + if (socketpair(AF_UNIX, type, 0, sockets) == -1) + return llvm::errorCodeToError(llvm::errnoAsErrorCode()); + +#ifndef SOCK_CLOEXEC + for (int s : sockets) { + int r = fcntl(s, F_SETFD, FD_CLOEXEC | fcntl(s, F_GETFD)); + assert(r == 0); + (void)r; + } +#endif + +#if defined(SO_NOSIGPIPE) + Log *log = GetLog(LLDBLog::Host); + if (Socket::SetOption(sockets[0], SOL_SOCKET, SO_NOSIGPIPE, 1) == -1) + LLDB_LOG(log, "failed to set NO_SIGPIPE on fd {0}: {1}", sockets[0], + llvm::sys::StrError()); + if (Socket::SetOption(sockets[1], SOL_SOCKET, SO_NOSIGPIPE, 1) == -1) + LLDB_LOG(log, "failed to set NO_SIGPIPE on fd {0}: {1}", sockets[1], + llvm::sys::StrError()); +#endif + + return Pair(std::unique_ptr<DomainSocket>(new DomainSocketPosix( + ProtocolUnixDomain, sockets[0], /*should_close=*/true)), + std::unique_ptr<DomainSocket>(new DomainSocketPosix( + ProtocolUnixDomain, sockets[1], /*should_close=*/true))); +} diff --git a/lldb/source/Host/windows/DomainSocketWindows.cpp b/lldb/source/Host/windows/DomainSocketWindows.cpp new file mode 100644 index 0000000000000..da2ee6dd16d61 --- /dev/null +++ b/lldb/source/Host/windows/DomainSocketWindows.cpp @@ -0,0 +1,54 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/windows/DomainSocketWindows.h" + +#include "llvm/Support/Error.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" + +#include <chrono> +#include <memory> + +using namespace lldb; +using namespace lldb_private; + +llvm::Expected<DomainSocket::Pair> DomainSocketWindows::CreatePair() { + // Windows has no socketpair(). Emulate it the same way TCPSocket::CreatePair + // does for loopback TCP: bind a listener to a unique temporary path, connect + // a client to it, and accept. AF_UNIX SOCK_STREAM connect() completes once + // the connection is queued (backlog >= 1), so a single thread can connect + // and then accept without deadlocking. + llvm::SmallString<128> model; + llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/true, model); + llvm::sys::path::append(model, "lldb-domain-socketpair-%%%%%%%%.sock"); + llvm::SmallString<128> path; + llvm::sys::fs::createUniquePath(model, path, /*MakeAbsolute=*/false); + + auto listen_socket = + std::make_unique<DomainSocketWindows>(/*should_close=*/true); + if (Status error = listen_socket->Listen(path, /*backlog=*/1); error.Fail()) + return error.takeError(); + + auto connect_socket = + std::make_unique<DomainSocketWindows>(/*should_close=*/true); + if (Status error = connect_socket->Connect(path); error.Fail()) + return error.takeError(); + + // The connection is already queued, so a short timeout is sufficient. + Socket *accept_socket = nullptr; + Status error = listen_socket->Accept(std::chrono::seconds(1), accept_socket); + // Once both ends are connected the bound socket file is no longer needed. + llvm::sys::fs::remove(path); + if (error.Fail()) + return error.takeError(); + + return Pair(std::move(connect_socket), + std::unique_ptr<DomainSocket>( + static_cast<DomainSocket *>(accept_socket))); +} diff --git a/lldb/tools/lldb-server/lldb-platform.cpp b/lldb/tools/lldb-server/lldb-platform.cpp index ec2ef053241ca..b1f03b36c578f 100644 --- a/lldb/tools/lldb-server/lldb-platform.cpp +++ b/lldb/tools/lldb-server/lldb-platform.cpp @@ -39,10 +39,8 @@ #include "lldb/Host/MainLoop.h" #include "lldb/Host/OptionParser.h" #include "lldb/Host/Socket.h" +#include "lldb/Host/common/DomainSocket.h" #include "lldb/Host/common/TCPSocket.h" -#if LLDB_ENABLE_POSIX -#include "lldb/Host/posix/DomainSocket.h" -#endif #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Status.h" diff --git a/lldb/unittests/TestingSupport/Host/SocketTestUtilities.h b/lldb/unittests/TestingSupport/Host/SocketTestUtilities.h index a7c9aee162e65..a03baf190dd33 100644 --- a/lldb/unittests/TestingSupport/Host/SocketTestUtilities.h +++ b/lldb/unittests/TestingSupport/Host/SocketTestUtilities.h @@ -22,7 +22,7 @@ #include "llvm/Testing/Support/Error.h" #if LLDB_ENABLE_POSIX -#include "lldb/Host/posix/DomainSocket.h" +#include "lldb/Host/common/DomainSocket.h" #endif namespace lldb_private { >From 75d807db8e24a4a78f908c89f2e69e4a08209862 Mon Sep 17 00:00:00 2001 From: Charles Zablit <[email protected]> Date: Fri, 26 Jun 2026 16:24:30 +0100 Subject: [PATCH 2/2] fixup! [NFC][lldb] Split DomainSocket into a base + posix/windows impls --- lldb/source/Host/windows/DomainSocketWindows.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lldb/source/Host/windows/DomainSocketWindows.cpp b/lldb/source/Host/windows/DomainSocketWindows.cpp index da2ee6dd16d61..eddc7a955ad38 100644 --- a/lldb/source/Host/windows/DomainSocketWindows.cpp +++ b/lldb/source/Host/windows/DomainSocketWindows.cpp @@ -8,6 +8,7 @@ #include "lldb/Host/windows/DomainSocketWindows.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" @@ -29,6 +30,8 @@ llvm::Expected<DomainSocket::Pair> DomainSocketWindows::CreatePair() { llvm::sys::path::append(model, "lldb-domain-socketpair-%%%%%%%%.sock"); llvm::SmallString<128> path; llvm::sys::fs::createUniquePath(model, path, /*MakeAbsolute=*/false); + auto remove_file = + llvm::make_scope_exit([&] { llvm::sys::fs::remove(path); }); auto listen_socket = std::make_unique<DomainSocketWindows>(/*should_close=*/true); @@ -42,10 +45,9 @@ llvm::Expected<DomainSocket::Pair> DomainSocketWindows::CreatePair() { // The connection is already queued, so a short timeout is sufficient. Socket *accept_socket = nullptr; - Status error = listen_socket->Accept(std::chrono::seconds(1), accept_socket); - // Once both ends are connected the bound socket file is no longer needed. - llvm::sys::fs::remove(path); - if (error.Fail()) + if (Status error = + listen_socket->Accept(std::chrono::seconds(1), accept_socket); + error.Fail()) return error.takeError(); return Pair(std::move(connect_socket), _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
