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