LLVM: lib/Support/raw_socket_stream.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
15#include "llvm/Config/config.h"
18
19#include
20#include <fcntl.h>
21#include
22
23#ifndef _WIN32
24#include <poll.h>
25#include <sys/socket.h>
26#include <sys/un.h>
27#else
29
30
31
32#include <winsock2.h>
33#include <afunix.h>
34
35#include <io.h>
36#endif
37
38#if defined(HAVE_UNISTD_H)
39#include <unistd.h>
40#endif
41
42using namespace llvm;
43
44#ifdef _WIN32
45WSABalancer::WSABalancer() {
46 WSADATA WsaData;
47 ::memset(&WsaData, 0, sizeof(WsaData));
48 if (WSAStartup(MAKEWORD(2, 2), &WsaData) != 0) {
50 }
51}
52
53WSABalancer::~WSABalancer() { WSACleanup(); }
54#endif
55
57#ifdef _WIN32
58 return std::error_code(::WSAGetLastError(), std::system_category());
59#else
61#endif
62}
63
65 struct sockaddr_un Addr;
66 memset(&Addr, 0, sizeof(Addr));
67 Addr.sun_family = AF_UNIX;
68 strncpy(Addr.sun_path, SocketPath.str().c_str(), sizeof(Addr.sun_path) - 1);
69 return Addr;
70}
71
73#ifdef _WIN32
74 SOCKET Socket = socket(AF_UNIX, SOCK_STREAM, 0);
75 if (Socket == INVALID_SOCKET) {
76#else
77 int Socket = socket(AF_UNIX, SOCK_STREAM, 0);
78 if (Socket == -1) {
79#endif
81 "Create socket failed");
82 }
83
84#ifdef __CYGWIN__
85
86
87
88
89
90
91 setsockopt(Socket, SOL_SOCKET, SO_PEERCRED, NULL, 0);
92#endif
93 struct sockaddr_un Addr = setSocketAddr(SocketPath);
94 if (::connect(Socket, (struct sockaddr *)&Addr, sizeof(Addr)) == -1)
96 "Connect socket failed");
97
98#ifdef _WIN32
99 return _open_osfhandle(Socket, 0);
100#else
101 return Socket;
102#endif
103}
104
105ListeningSocket::ListeningSocket(int SocketFD, StringRef SocketPath,
106 int PipeFD[2])
107 : FD(SocketFD), SocketPath(SocketPath), PipeFD{PipeFD[0], PipeFD[1]} {}
108
109ListeningSocket::ListeningSocket(ListeningSocket &&LS)
110 : FD(LS.FD.load()), SocketPath(LS.SocketPath),
111 PipeFD{LS.PipeFD[0], LS.PipeFD[1]} {
112
113 LS.FD = -1;
114 LS.SocketPath.clear();
115 LS.PipeFD[0] = -1;
116 LS.PipeFD[1] = -1;
117}
118
120 int MaxBacklog) {
121
122
123
124
125
126
127
130 if (!MaybeFD) {
131
132
133
134
137 std::make_error_code(std::errc::file_exists),
138 "Socket address unavailable");
139 }
140 ::close(std::move(*MaybeFD));
141
142
144 std::make_error_code(std::errc::address_in_use),
145 "Socket address unavailable");
146 }
147
148#ifdef _WIN32
149 WSABalancer _;
150 SOCKET Socket = socket(AF_UNIX, SOCK_STREAM, 0);
151 if (Socket == INVALID_SOCKET)
152#else
153 int Socket = socket(AF_UNIX, SOCK_STREAM, 0);
154 if (Socket == -1)
155#endif
157 "socket create failed");
158
159#ifdef __CYGWIN__
160
161
162
163
164
165
166 setsockopt(Socket, SOL_SOCKET, SO_PEERCRED, NULL, 0);
167#endif
168 struct sockaddr_un Addr = setSocketAddr(SocketPath);
169 if (::bind(Socket, (struct sockaddr *)&Addr, sizeof(Addr)) == -1) {
170
172 ::close(Socket);
174 }
175
176
177 if (::listen(Socket, MaxBacklog) == -1)
179 "Listen error");
180
181 int PipeFD[2];
182#ifdef _WIN32
183
184 if (::_pipe(PipeFD, 1, 0) == -1)
185#else
186 if (::pipe(PipeFD) == -1)
187#endif
189 "pipe failed");
190
191#ifdef _WIN32
192 return ListeningSocket{_open_osfhandle(Socket, 0), SocketPath, PipeFD};
193#else
194 return ListeningSocket{Socket, SocketPath, PipeFD};
195#endif
196}
197
198
199
200
201
202
203
204
205
206
207static std::error_code
209 const std::function<int()> &getActiveFD,
210 const std::optional &CancelFD = std::nullopt) {
211 struct pollfd FD[2];
212 FD[0].events = POLLIN;
213#ifdef _WIN32
214 SOCKET WinServerSock = _get_osfhandle(getActiveFD());
215 FD[0].fd = WinServerSock;
216#else
217 FD[0].fd = getActiveFD();
218#endif
220 if (CancelFD.has_value()) {
221 FD[1].events = POLLIN;
222 FD[1].fd = CancelFD.value();
223 FDCount++;
224 }
225
226
227
228 auto Start = std::chrono::steady_clock::now();
229 auto RemainingTimeout = Timeout;
230 int PollStatus = 0;
231 do {
232
233
234 if (PollStatus != 0 && Timeout != std::chrono::milliseconds(-1)) {
235 auto TotalElapsedTime =
236 std::chrono::duration_caststd::chrono::milliseconds(
237 std::chrono::steady_clock::now() - Start);
238
239 if (TotalElapsedTime >= Timeout)
240 return std::make_error_code(std::errc::operation_would_block);
241
242 RemainingTimeout = Timeout - TotalElapsedTime;
243 }
244#ifdef _WIN32
245 PollStatus = WSAPoll(FD, FDCount, RemainingTimeout.count());
246 } while (PollStatus == SOCKET_ERROR &&
248#else
249 PollStatus = ::poll(FD, FDCount, RemainingTimeout.count());
250 } while (PollStatus == -1 &&
252#endif
253
254
255
256 if (getActiveFD() == -1 || (CancelFD.has_value() && FD[1].revents & POLLIN))
257 return std::make_error_code(std::errc::operation_canceled);
258#ifdef _WIN32
259 if (PollStatus == SOCKET_ERROR)
260#else
261 if (PollStatus == -1)
262#endif
264 if (PollStatus == 0)
265 return std::make_error_code(std::errc::timed_out);
266 if (FD[0].revents & POLLNVAL)
267 return std::make_error_code(std::errc::bad_file_descriptor);
268 return std::error_code();
269}
270
273 auto getActiveFD = [this]() -> int { return FD; };
275 if (TimeoutErr)
277
278 int AcceptFD;
279#ifdef _WIN32
280 SOCKET WinAcceptSock = ::accept(_get_osfhandle(FD), NULL, NULL);
281 AcceptFD = _open_osfhandle(WinAcceptSock, 0);
282#else
283 AcceptFD = ::accept(FD, NULL, NULL);
284#endif
285
286 if (AcceptFD == -1)
288 "Socket accept failed");
289 return std::make_unique<raw_socket_stream>(AcceptFD);
290}
291
293 int ObservedFD = FD.load();
294
295 if (ObservedFD == -1)
296 return;
297
298
299
300 if (!FD.compare_exchange_strong(ObservedFD, -1))
301 return;
302
303 ::close(ObservedFD);
304 ::unlink(SocketPath.c_str());
305
306
307 char Byte = 'A';
308 ssize_t written = ::write(PipeFD[1], &Byte, 1);
309
310
311 (void)written;
312}
313
316
317
318
319
320
321
322 if (PipeFD[0] != -1)
323 ::close(PipeFD[0]);
324 if (PipeFD[1] != -1)
325 ::close(PipeFD[1]);
326}
327
328
329
330
331
334
336
339#ifdef _WIN32
340 WSABalancer _;
341#endif
343 if (!FD)
344 return FD.takeError();
345 return std::make_unique<raw_socket_stream>(*FD);
346}
347
349 const std::chrono::milliseconds &Timeout) {
350 auto getActiveFD = [this]() -> int { return this->get_fd(); };
352
353 if (Err) {
355 return -1;
356 }
358}
AMDGPU Mark last scratch load
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
static LLVM_ABI Expected< ListeningSocket > createUnix(StringRef SocketPath, int MaxBacklog=llvm::hardware_concurrency().compute_thread_count())
Creates a listening socket bound to the specified file system path.
Definition raw_socket_stream.cpp:119
LLVM_ABI void shutdown()
Closes the FD, unlinks the socket file, and writes to PipeFD.
Definition raw_socket_stream.cpp:292
LLVM_ABI ~ListeningSocket()
Definition raw_socket_stream.cpp:314
LLVM_ABI Expected< std::unique_ptr< raw_socket_stream > > accept(const std::chrono::milliseconds &Timeout=std::chrono::milliseconds(-1))
Accepts an incoming connection on the listening socket.
Definition raw_socket_stream.cpp:272
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
int get_fd() const
Return the file descriptor.
void error_detected(std::error_code EC)
Set the flag indicating that an output error has been encountered.
LLVM_ABI raw_fd_stream(StringRef Filename, std::error_code &EC)
Open the specified file for reading/writing/seeking.
LLVM_ABI ssize_t read(char *Ptr, size_t Size)
This reads the Size bytes into a buffer pointed by Ptr.
static Expected< std::unique_ptr< raw_socket_stream > > createConnectedUnix(StringRef SocketPath)
Create a raw_socket_stream connected to the UNIX domain socket at SocketPath.
Definition raw_socket_stream.cpp:338
~raw_socket_stream() override
raw_socket_stream(int SocketFD)
Definition raw_socket_stream.cpp:332
ssize_t read(char *Ptr, size_t Size, const std::chrono::milliseconds &Timeout=std::chrono::milliseconds(-1))
Attempt to read from the raw_socket_stream's file descriptor.
Definition raw_socket_stream.cpp:348
LLVM_ABI bool exists(const basic_file_status &status)
Does file exist?
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
@ Timeout
Reached timeout while waiting for the owner to release the lock.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
LLVM_ABI Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue, Dwarf64StrOffsetsPromotion StrOffsetsOptValue)
std::error_code errnoAsErrorCode()
Helper to get errno as an std::error_code.
void consumeError(Error Err)
Consume a Error without doing anything.
static Expected< int > getSocketFD(StringRef SocketPath)
Definition raw_socket_stream.cpp:72
static std::error_code getLastSocketErrorCode()
Definition raw_socket_stream.cpp:56
static std::error_code manageTimeout(const std::chrono::milliseconds &Timeout, const std::function< int()> &getActiveFD, const std::optional< int > &CancelFD=std::nullopt)
Definition raw_socket_stream.cpp:208
static sockaddr_un setSocketAddr(StringRef SocketPath)
Definition raw_socket_stream.cpp:64