mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 00:45:18 +03:00
624c185094
Summary: This commit introduces a few types from the watchman codebase: `FileDescriptor` which is on posix systems represents a file descriptor, and on Windows is a HANDLE (which can be a file, pipe or socket descriptor). `Pipe` is a convenience struct that holds the read and write ends of a Pipe. Note that we have a conceptual class with a windows specific Pipe type under eden/fs/win/utils/Pipe.h; I remove that in the next diff in the stack. There are a couple of differences from the watchman code Reviewed By: chadaustin Differential Revision: D23287819 fbshipit-source-id: 6ca90ba345037c6c3e308f588d690a899c9866a5
104 lines
2.4 KiB
C++
104 lines
2.4 KiB
C++
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This software may be used and distributed according to the terms of the
|
|
* GNU General Public License version 2.
|
|
*/
|
|
|
|
#include "eden/fs/utils/Pipe.h"
|
|
#include <fcntl.h>
|
|
#include <folly/String.h>
|
|
#ifndef _WIN32
|
|
#include <sys/socket.h>
|
|
#include <unistd.h>
|
|
#else
|
|
#include <event2/util.h> // @manual
|
|
#endif
|
|
#include <system_error>
|
|
|
|
namespace facebook {
|
|
namespace eden {
|
|
|
|
Pipe::Pipe(bool nonBlocking) {
|
|
#ifdef _WIN32
|
|
HANDLE readPipe;
|
|
HANDLE writePipe;
|
|
auto sec = SECURITY_ATTRIBUTES{};
|
|
|
|
sec.nLength = sizeof(sec);
|
|
sec.bInheritHandle = FALSE; // O_CLOEXEC equivalent
|
|
constexpr DWORD kPipeSize = 64 * 1024;
|
|
|
|
if (!CreatePipe(&readPipe, &writePipe, &sec, kPipeSize)) {
|
|
throw std::system_error(
|
|
GetLastError(), std::system_category(), "CreatePipe failed");
|
|
}
|
|
read = FileDescriptor(
|
|
reinterpret_cast<intptr_t>(readPipe), FileDescriptor::FDType::Pipe);
|
|
write = FileDescriptor(
|
|
reinterpret_cast<intptr_t>(writePipe), FileDescriptor::FDType::Pipe);
|
|
|
|
#else
|
|
int fds[2];
|
|
int res;
|
|
#if FOLLY_HAVE_PIPE2
|
|
res = pipe2(fds, (nonBlocking ? O_NONBLOCK : 0) | O_CLOEXEC);
|
|
#else
|
|
res = pipe(fds);
|
|
#endif
|
|
|
|
if (res) {
|
|
throw std::system_error(
|
|
errno,
|
|
std::system_category(),
|
|
std::string("pipe error: ") + folly::errnoStr(errno));
|
|
}
|
|
read = FileDescriptor(fds[0], FileDescriptor::FDType::Pipe);
|
|
write = FileDescriptor(fds[1], FileDescriptor::FDType::Pipe);
|
|
|
|
#if !FOLLY_HAVE_PIPE2
|
|
read.setCloExec();
|
|
write.setCloExec();
|
|
if (nonBlocking) {
|
|
read.setNonBlock();
|
|
write.setNonBlock();
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
SocketPair::SocketPair(bool nonBlocking) {
|
|
FileDescriptor::system_handle_type pair[2];
|
|
#ifdef _WIN32
|
|
// The win32 libevent implementation will attempt to use unix domain sockets
|
|
// if available, but will fall back to using loopback TCP sockets.
|
|
auto r = evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair);
|
|
#else
|
|
auto r = ::socketpair(
|
|
AF_UNIX,
|
|
#ifdef SOCK_NONBLOCK
|
|
SOCK_NONBLOCK |
|
|
#endif
|
|
#ifdef SOCK_CLOEXEC
|
|
SOCK_CLOEXEC |
|
|
#endif
|
|
SOCK_STREAM,
|
|
0,
|
|
pair);
|
|
#endif
|
|
folly::checkUnixError(r, "socketpair failed");
|
|
|
|
read = FileDescriptor(pair[0], FileDescriptor::FDType::Socket);
|
|
write = FileDescriptor(pair[1], FileDescriptor::FDType::Socket);
|
|
|
|
read.setCloExec();
|
|
write.setCloExec();
|
|
if (nonBlocking) {
|
|
read.setNonBlock();
|
|
write.setNonBlock();
|
|
}
|
|
}
|
|
|
|
} // namespace eden
|
|
} // namespace facebook
|