| //===----------------------------------------------------------------------===// | |
| // | |
| // 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::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))); | |
| } |