@@ -178,7 +178,7 @@ Expected<ListeningSocket> ListeningSocket::createUnix(StringRef SocketPath,
178
178
}
179
179
180
180
Expected<std::unique_ptr<raw_socket_stream>>
181
- ListeningSocket::accept (std::optional<std:: chrono::milliseconds> Timeout) {
181
+ ListeningSocket::accept (std::chrono::milliseconds Timeout) {
182
182
183
183
struct pollfd FDs[2 ];
184
184
FDs[0 ].events = POLLIN;
@@ -191,15 +191,14 @@ ListeningSocket::accept(std::optional<std::chrono::milliseconds> Timeout) {
191
191
FDs[1 ].events = POLLIN;
192
192
FDs[1 ].fd = PipeFD[0 ];
193
193
194
- std::chrono::milliseconds OriginalTimeout =
195
- Timeout. value_or ( std::chrono::milliseconds (- 1 ));
196
- int RemainingTime = OriginalTimeout .count ();
194
+ // Keep track of how much time has passed in case poll is interupted by a
195
+ // signal and needs to be recalled
196
+ int RemainingTime = Timeout .count ();
197
197
std::chrono::milliseconds ElapsedTime = std::chrono::milliseconds (0 );
198
-
199
198
int PollStatus = -1 ;
200
- while (PollStatus == - 1 &&
201
- (RemainingTime == -1 || ElapsedTime < OriginalTimeout )) {
202
- if (RemainingTime != -1 )
199
+
200
+ while (PollStatus == - 1 && (Timeout. count () == -1 || ElapsedTime < Timeout )) {
201
+ if (Timeout. count () != -1 )
203
202
RemainingTime -= ElapsedTime.count ();
204
203
205
204
auto Start = std::chrono::steady_clock::now ();
@@ -213,7 +212,7 @@ ListeningSocket::accept(std::optional<std::chrono::milliseconds> Timeout) {
213
212
// Ignore error if caused by interupting signal
214
213
std::error_code PollErrCode = getLastSocketErrorCode ();
215
214
if (PollErrCode != std::errc::interrupted)
216
- return llvm::make_error<StringError>(PollErrCode, " poll failed" );
215
+ return llvm::make_error<StringError>(PollErrCode, " FD poll failed" );
217
216
}
218
217
219
218
if (PollStatus == 0 )
@@ -226,9 +225,14 @@ ListeningSocket::accept(std::optional<std::chrono::milliseconds> Timeout) {
226
225
std::make_error_code (std::errc::bad_file_descriptor),
227
226
" File descriptor closed by another thread" );
228
227
229
- auto End = std::chrono::steady_clock::now ();
228
+ if (FDs[1 ].revents & POLLIN)
229
+ return llvm::make_error<StringError>(
230
+ std::make_error_code (std::errc::operation_canceled),
231
+ " Accept canceled" );
232
+
233
+ auto Stop = std::chrono::steady_clock::now ();
230
234
ElapsedTime +=
231
- std::chrono::duration_cast<std::chrono::milliseconds>(End - Start);
235
+ std::chrono::duration_cast<std::chrono::milliseconds>(Stop - Start);
232
236
}
233
237
234
238
int AcceptFD;
@@ -241,24 +245,27 @@ ListeningSocket::accept(std::optional<std::chrono::milliseconds> Timeout) {
241
245
242
246
if (AcceptFD == -1 )
243
247
return llvm::make_error<StringError>(getLastSocketErrorCode (),
244
- " accept failed" );
248
+ " Socket accept failed" );
245
249
return std::make_unique<raw_socket_stream>(AcceptFD);
246
250
}
247
251
248
252
void ListeningSocket::shutdown () {
249
253
int ObservedFD = FD.load ();
254
+
250
255
if (ObservedFD == -1 )
251
256
return ;
257
+
258
+ // If FD equals ObservedFD set FD to -1; If FD doesn't equal ObservedFD then
259
+ // another thread is responsible for shutdown so return
252
260
if (!FD.compare_exchange_strong (ObservedFD, -1 ))
253
261
return ;
254
- ::close (FD);
262
+
263
+ ::close (ObservedFD);
255
264
::unlink (SocketPath.c_str());
256
265
257
266
// Ensure ::poll returns if shutdown is called by a seperate thread
258
267
char Byte = ' A' ;
259
268
::write (PipeFD[1 ], &Byte, 1 );
260
-
261
- FD = -1 ;
262
269
}
263
270
264
271
ListeningSocket::~ListeningSocket () {
@@ -267,6 +274,8 @@ ListeningSocket::~ListeningSocket() {
267
274
// Close the pipe's FDs in the destructor instead of within
268
275
// ListeningSocket::shutdown to avoid unnecessary synchronization issues that
269
276
// would occur as PipeFD's values would have to be changed to -1
277
+ //
278
+ // The move constructor sets PipeFD to -1
270
279
if (PipeFD[0 ] != -1 )
271
280
::close (PipeFD[0 ]);
272
281
if (PipeFD[1 ] != -1 )
0 commit comments