14
14
#include " llvm/Support/raw_socket_stream.h"
15
15
#include " llvm/Config/config.h"
16
16
#include " llvm/Support/Error.h"
17
+ #include " llvm/Support/FileSystem.h"
18
+
19
+ #include < atomic>
17
20
18
21
#ifndef _WIN32
19
22
#include < sys/socket.h>
@@ -45,7 +48,6 @@ WSABalancer::WSABalancer() {
45
48
}
46
49
47
50
WSABalancer::~WSABalancer () { WSACleanup (); }
48
-
49
51
#endif // _WIN32
50
52
51
53
static std::error_code getLastSocketErrorCode () {
@@ -56,117 +58,201 @@ static std::error_code getLastSocketErrorCode() {
56
58
#endif
57
59
}
58
60
61
+ static void closeFD (int FD) {
62
+ #ifdef _WIN32
63
+ // on windows ::close is a deprecated alias for _close
64
+ _close (FD);
65
+ #else
66
+ ::close (FD);
67
+ #endif
68
+ }
69
+
70
+ static void unlinkFile (StringRef Path) {
71
+ #ifdef _WIN32
72
+ // on windows ::unlink is a deprecated alias for _unlink
73
+ _unlink (Path.str ().c_str ());
74
+ #else
75
+ ::unlink (Path.str().c_str());
76
+ #endif
77
+ }
78
+
79
+ static sockaddr_un setSocketAddr (StringRef SocketPath) {
80
+ struct sockaddr_un Addr;
81
+ memset (&Addr, 0 , sizeof (Addr));
82
+ Addr.sun_family = AF_UNIX;
83
+ strncpy (Addr.sun_path , SocketPath.str ().c_str (), sizeof (Addr.sun_path ) - 1 );
84
+ return Addr;
85
+ }
86
+
87
+ static Expected<int > getSocketFD (StringRef SocketPath) {
88
+ #ifdef _WIN32
89
+ SOCKET MaybeSocket = socket (AF_UNIX, SOCK_STREAM, 0 );
90
+ if (MaybeSocket == INVALID_SOCKET) {
91
+ #else
92
+ int MaybeSocket = socket (AF_UNIX, SOCK_STREAM, 0 );
93
+ if (MaybeSocket == -1 ) {
94
+ #endif // _WIN32
95
+ return llvm::make_error<StringError>(getLastSocketErrorCode (),
96
+ " Create socket failed" );
97
+ }
98
+
99
+ struct sockaddr_un Addr = setSocketAddr (SocketPath);
100
+ if (::connect (MaybeSocket, (struct sockaddr *)&Addr, sizeof (Addr)) == -1 )
101
+ return llvm::make_error<StringError>(getLastSocketErrorCode (),
102
+ " Connect socket failed" );
103
+
104
+ #ifdef _WIN32
105
+ return _open_osfhandle (MaybeWinsocket, 0 );
106
+ #else
107
+ return MaybeSocket;
108
+ #endif // _WIN32
109
+ }
110
+
59
111
ListeningSocket::ListeningSocket (int SocketFD, StringRef SocketPath)
60
112
: FD (SocketFD), SocketPath (SocketPath) {}
61
113
62
114
ListeningSocket::ListeningSocket (ListeningSocket &&LS)
63
- : FD(LS.FD), SocketPath(LS.SocketPath) {
115
+ : FD (LS.FD .load ()), SocketPath (LS.SocketPath ) {
116
+
117
+ LS.SocketPath .clear ();
64
118
LS.FD = -1 ;
65
119
}
66
120
67
- Expected<ListeningSocket> ListeningSocket::createUnix (StringRef SocketPath,
68
- int MaxBacklog) {
121
+ Expected<ListeningSocket>
122
+ ListeningSocket::createListeningSocket (StringRef SocketPath, int MaxBacklog) {
123
+
124
+ // Handle instances where the target socket address already exists and
125
+ // differentiate between a preexisting file with and without a bound socket
126
+ //
127
+ // ::bind will return std::errc:address_in_use if a file at the socket address
128
+ // already exists (e.g., the file was not properly unlinked due to a crash)
129
+ // even if another socket has not yet binded to that address
130
+ if (llvm::sys::fs::exists (SocketPath)) {
131
+ Expected<int > MaybeFD = getSocketFD (SocketPath);
132
+ if (!MaybeFD) {
133
+
134
+ // Regardless of the error, notify the caller that a file already exists
135
+ // at the desired socket address. The file must be removed before ::bind
136
+ // can use the socket address
137
+ consumeError (MaybeFD.takeError ());
138
+ return llvm::make_error<StringError>(
139
+ std::make_error_code (std::errc::file_exists),
140
+ " Socket address unavailable" );
141
+ }
142
+ closeFD (std::move (*MaybeFD));
143
+
144
+ // Notify caller that the provided socket address already has a bound socket
145
+ return llvm::make_error<StringError>(
146
+ std::make_error_code (std::errc::address_in_use),
147
+ " Socket address unavailable" );
148
+ }
69
149
70
150
#ifdef _WIN32
71
151
WSABalancer _;
72
- SOCKET MaybeWinsocket = socket (AF_UNIX, SOCK_STREAM, 0 );
73
- if (MaybeWinsocket == INVALID_SOCKET) {
152
+ SOCKET MaybeSocket = socket (AF_UNIX, SOCK_STREAM, 0 );
153
+ if (MaybeSocket == INVALID_SOCKET) {
74
154
#else
75
- int MaybeWinsocket = socket (AF_UNIX, SOCK_STREAM, 0 );
76
- if (MaybeWinsocket == -1 ) {
155
+ int MaybeSocket = socket (AF_UNIX, SOCK_STREAM, 0 );
156
+ if (MaybeSocket == -1 ) {
77
157
#endif
78
158
return llvm::make_error<StringError>(getLastSocketErrorCode (),
79
159
" socket create failed" );
80
160
}
81
161
82
- struct sockaddr_un Addr;
83
- memset (&Addr, 0 , sizeof (Addr));
84
- Addr.sun_family = AF_UNIX;
85
- strncpy (Addr.sun_path , SocketPath.str ().c_str (), sizeof (Addr.sun_path ) - 1 );
86
-
87
- if (bind (MaybeWinsocket, (struct sockaddr *)&Addr, sizeof (Addr)) == -1 ) {
88
- std::error_code Err = getLastSocketErrorCode ();
89
- if (Err == std::errc::address_in_use)
90
- ::close (MaybeWinsocket);
91
- return llvm::make_error<StringError>(Err, " Bind error" );
162
+ struct sockaddr_un Addr = setSocketAddr (SocketPath);
163
+ if (::bind (MaybeSocket, (struct sockaddr *)&Addr, sizeof (Addr)) == -1 ) {
164
+ // Grab error code from call to ::bind before calling ::close
165
+ std::error_code EC = getLastSocketErrorCode ();
166
+ ::close (MaybeSocket);
167
+ return llvm::make_error<StringError>(EC, " Bind error" );
92
168
}
93
- if (listen (MaybeWinsocket, MaxBacklog) == -1 ) {
169
+
170
+ // Mark socket as passive so incoming connections can be accepted
171
+ if (::listen (MaybeSocket, MaxBacklog) == -1 )
94
172
return llvm::make_error<StringError>(getLastSocketErrorCode (),
95
173
" Listen error" );
96
- }
97
- int UnixSocket ;
174
+
175
+ int Socket ;
98
176
#ifdef _WIN32
99
- UnixSocket = _open_osfhandle (MaybeWinsocket, 0 );
177
+ Socket = _open_osfhandle (MaybeWinsocket, 0 );
100
178
#else
101
- UnixSocket = MaybeWinsocket ;
179
+ Socket = MaybeSocket ;
102
180
#endif // _WIN32
103
- return ListeningSocket{UnixSocket , SocketPath};
181
+ return ListeningSocket{Socket , SocketPath};
104
182
}
105
183
106
- Expected<std::unique_ptr<raw_socket_stream>> ListeningSocket::accept () {
184
+ Expected<std::unique_ptr<raw_socket_stream>>
185
+ ListeningSocket::accept (std::optional<std::chrono::microseconds> Timeout) {
186
+
187
+ int SelectStatus;
107
188
int AcceptFD;
189
+
108
190
#ifdef _WIN32
109
191
SOCKET WinServerSock = _get_osfhandle (FD);
110
- SOCKET WinAcceptSock = ::accept (WinServerSock, NULL , NULL );
111
- AcceptFD = _open_osfhandle (WinAcceptSock, 0 );
192
+ #endif
193
+
194
+ fd_set Readfds;
195
+ if (Timeout.has_value ()) {
196
+ timeval TV = {0 , Timeout.value ().count ()};
197
+ FD_ZERO (&Readfds);
198
+ #ifdef _WIN32
199
+ FD_SET (WinServerSock, &Readfds);
200
+ #else
201
+ FD_SET (FD, &Readfds);
202
+ #endif
203
+ SelectStatus = ::select (FD + 1 , &Readfds, NULL , NULL , &TV);
204
+ } else {
205
+ SelectStatus = 1 ;
206
+ }
207
+
208
+ if (SelectStatus == -1 )
209
+ return llvm::make_error<StringError>(getLastSocketErrorCode (),
210
+ " Select failed" );
211
+
212
+ if (SelectStatus) {
213
+ #ifdef _WIN32
214
+ SOCKET WinAcceptSock = ::accept (WinServerSock, NULL , NULL );
215
+ AcceptFD = _open_osfhandle (WinAcceptSock, 0 );
112
216
#else
113
- AcceptFD = ::accept (FD, NULL , NULL );
114
- #endif // _WIN32
217
+ AcceptFD = ::accept (FD, NULL , NULL );
218
+ #endif
219
+ } else
220
+ return llvm::make_error<StringError>(
221
+ std::make_error_code (std::errc::timed_out), " Accept timed out" );
222
+
115
223
if (AcceptFD == -1 )
116
224
return llvm::make_error<StringError>(getLastSocketErrorCode (),
117
225
" Accept failed" );
226
+
118
227
return std::make_unique<raw_socket_stream>(AcceptFD);
119
228
}
120
229
121
- ListeningSocket::~ListeningSocket () {
230
+ void ListeningSocket::shutdown () {
122
231
if (FD == -1 )
123
232
return ;
124
- ::close (FD);
125
- unlink (SocketPath.c_str ());
233
+ closeFD (FD);
234
+ unlinkFile (SocketPath);
235
+ FD = -1 ;
126
236
}
127
237
128
- static Expected<int > GetSocketFD (StringRef SocketPath) {
129
- #ifdef _WIN32
130
- SOCKET MaybeWinsocket = socket (AF_UNIX, SOCK_STREAM, 0 );
131
- if (MaybeWinsocket == INVALID_SOCKET) {
132
- #else
133
- int MaybeWinsocket = socket (AF_UNIX, SOCK_STREAM, 0 );
134
- if (MaybeWinsocket == -1 ) {
135
- #endif // _WIN32
136
- return llvm::make_error<StringError>(getLastSocketErrorCode (),
137
- " Create socket failed" );
138
- }
238
+ ListeningSocket::~ListeningSocket () { shutdown (); }
139
239
140
- struct sockaddr_un Addr;
141
- memset (&Addr, 0 , sizeof (Addr));
142
- Addr.sun_family = AF_UNIX;
143
- strncpy (Addr.sun_path , SocketPath.str ().c_str (), sizeof (Addr.sun_path ) - 1 );
144
-
145
- int status = connect (MaybeWinsocket, (struct sockaddr *)&Addr, sizeof (Addr));
146
- if (status == -1 ) {
147
- return llvm::make_error<StringError>(getLastSocketErrorCode (),
148
- " Connect socket failed" );
149
- }
150
- #ifdef _WIN32
151
- return _open_osfhandle (MaybeWinsocket, 0 );
152
- #else
153
- return MaybeWinsocket;
154
- #endif // _WIN32
155
- }
240
+ // ===----------------------------------------------------------------------===//
241
+ // raw_socket_stream
242
+ // ===----------------------------------------------------------------------===//
156
243
157
244
raw_socket_stream::raw_socket_stream (int SocketFD)
158
245
: raw_fd_stream (SocketFD, true ) {}
159
246
160
247
Expected<std::unique_ptr<raw_socket_stream>>
161
- raw_socket_stream::createConnectedUnix (StringRef SocketPath) {
248
+ raw_socket_stream::createConnectedSocket (StringRef SocketPath) {
162
249
#ifdef _WIN32
163
250
WSABalancer _;
164
251
#endif // _WIN32
165
- Expected<int > FD = GetSocketFD (SocketPath);
252
+ Expected<int > FD = getSocketFD (SocketPath);
166
253
if (!FD)
167
254
return FD.takeError ();
168
255
return std::make_unique<raw_socket_stream>(*FD);
169
256
}
170
257
171
258
raw_socket_stream::~raw_socket_stream () {}
172
-
0 commit comments