-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[llvm][Support] ListeningSocket::accept returns operation_canceled if FD is set to -1 #89479
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
… return operation canceled if FD equals -1
@llvm/pr-subscribers-llvm-support Author: Connor Sughrue (cpsughrue) ChangesIf Full diff: https://github.com/llvm/llvm-project/pull/89479.diff 1 Files Affected:
diff --git a/llvm/lib/Support/raw_socket_stream.cpp b/llvm/lib/Support/raw_socket_stream.cpp
index 14e2308df4d7ed..ff14b3b6e09c19 100644
--- a/llvm/lib/Support/raw_socket_stream.cpp
+++ b/llvm/lib/Support/raw_socket_stream.cpp
@@ -200,21 +200,32 @@ ListeningSocket::accept(std::chrono::milliseconds Timeout) {
while (PollStatus == -1 && (Timeout.count() == -1 || ElapsedTime < Timeout)) {
if (Timeout.count() != -1)
RemainingTime -= ElapsedTime.count();
-
auto Start = std::chrono::steady_clock::now();
+
#ifdef _WIN32
PollStatus = WSAPoll(FDs, 2, RemainingTime);
- if (PollStatus == SOCKET_ERROR) {
#else
PollStatus = ::poll(FDs, 2, RemainingTime);
+#endif
+ // If FD equals -1 then ListeningSocket::shutdown has been called and it is
+ // appropriate to return operation_canceled. ListeningSocket::shutdown
+ // copies FD's value to ObservedFD then sets FD to -1 before canceling
+ // ::poll by calling close on ObservedFD and writing to the pipe.
+ if (FD.load() == -1)
+ return llvm::make_error<StringError>(
+ std::make_error_code(std::errc::operation_canceled),
+ "Accept canceled");
+
+#if _WIN32
+ if (PollStatus == SOCKET_ERROR) {
+#else
if (PollStatus == -1) {
#endif
- // Ignore error if caused by interupting signal
std::error_code PollErrCode = getLastSocketErrorCode();
+ // Ignore EINTR (signal occured before any request event) and retry
if (PollErrCode != std::errc::interrupted)
return llvm::make_error<StringError>(PollErrCode, "FD poll failed");
}
-
if (PollStatus == 0)
return llvm::make_error<StringError>(
std::make_error_code(std::errc::timed_out),
@@ -222,13 +233,7 @@ ListeningSocket::accept(std::chrono::milliseconds Timeout) {
if (FDs[0].revents & POLLNVAL)
return llvm::make_error<StringError>(
- std::make_error_code(std::errc::bad_file_descriptor),
- "File descriptor closed by another thread");
-
- if (FDs[1].revents & POLLIN)
- return llvm::make_error<StringError>(
- std::make_error_code(std::errc::operation_canceled),
- "Accept canceled");
+ std::make_error_code(std::errc::bad_file_descriptor));
auto Stop = std::chrono::steady_clock::now();
ElapsedTime +=
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks correct with some minor comments, but it would be good to figure out why the existing shutdown test already returned std::errc::operation_canceled
, but the module build daemon was seeing std::errc::bad_file_descriptor
on shutdown.
Still trying to figure out the root cause but the jist of the issue is that the below code does not fail
The raw_socket_stream FILE_DESCRIPTOR_CLOSED test should fail but wrapping a gtest macro in llvm::handleAllErrors seems to "silence" it. EDIT: The gtest macros don't use exception but rather either return |
Another important note. The code
results in two instances of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
If
::poll
returns andFD
equals -1, thenListeningSocket::shutdown
has been called. So, regardless of any other information that could be gleaned fromFDs.revents
orPollStatus
, it is appropriate to returnstd::errc::operation_canceled
.ListeningSocket::shutdown
copiesFD
's value toObservedFD
then setsFD
to -1 before canceling::poll
by calling::close(ObservedFD)
and writing to the pipe.