blob: eddc7a955ad3899b5bb20e8abf562dfa9f4aa4fd [file] [edit]
//===----------------------------------------------------------------------===//
//
// 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)));
}