Author: Charles Zablit
Date: 2026-06-26T17:57:29+01:00
New Revision: 049448403c7bfd140a212aefe3c422f3cad810ce

URL: 
https://github.com/llvm/llvm-project/commit/049448403c7bfd140a212aefe3c422f3cad810ce
DIFF: 
https://github.com/llvm/llvm-project/commit/049448403c7bfd140a212aefe3c422f3cad810ce.diff

LOG: [NFC][lldb] Split DomainSocket into a base + posix/windows impls (#205864)

Prepares for `AF_UNIX` domain-socket support on Windows by separating
the cross-platform socket logic from the one platform-specific
operation.

Every domain-socket operation is identical on POSIX and Windows (via
`<afunix.h>`), so it now lives in a single base class
`DomainSocket`. The one operation that is different is `CreatePair()`.
It lives in `DomainSocketPosix` / `DomainSocketWindows`. It's selected
for the host as `DomainSocketPlatform` through
`lldb/Host/DomainSocket.h`.

This is an NFC patch: POSIX behavior is unchanged, and while the shared
code now also compiles on Windows it stays unreachable there. A
follow-up commit enables it.

rdar://180736036

Added: 
    lldb/include/lldb/Host/DomainSocket.h
    lldb/include/lldb/Host/common/DomainSocket.h
    lldb/include/lldb/Host/posix/DomainSocketPosix.h
    lldb/include/lldb/Host/windows/DomainSocketWindows.h
    lldb/source/Host/common/DomainSocket.cpp
    lldb/source/Host/posix/DomainSocketPosix.cpp
    lldb/source/Host/windows/DomainSocketWindows.cpp

Modified: 
    lldb/include/lldb/Host/linux/AbstractSocket.h
    lldb/source/Host/CMakeLists.txt
    lldb/source/Host/common/Socket.cpp
    lldb/tools/lldb-server/lldb-platform.cpp
    lldb/unittests/TestingSupport/Host/SocketTestUtilities.h

Removed: 
    lldb/include/lldb/Host/posix/DomainSocket.h
    lldb/source/Host/posix/DomainSocket.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 
diff ers 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..988b8238a3cce 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,14 @@
 #include "llvm/Support/FileSystem.h"
 
 #include <cstddef>
-#include <fcntl.h>
 #include <memory>
+
+#ifdef _WIN32
+#include <afunix.h>
+#else
 #include <sys/socket.h>
 #include <sys/un.h>
+#endif
 
 using namespace lldb;
 using namespace lldb_private;
@@ -38,14 +42,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 +78,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..eddc7a955ad38
--- /dev/null
+++ b/lldb/source/Host/windows/DomainSocketWindows.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// 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/ADT/ScopeExit.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 remove_file =
+      llvm::make_scope_exit([&] { llvm::sys::fs::remove(path); });
+
+  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;
+  if (Status error =
+          listen_socket->Accept(std::chrono::seconds(1), accept_socket);
+      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 {


        
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to