-
Notifications
You must be signed in to change notification settings - Fork 468
Switch Win32 pipes to PIPE_WAIT #853
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1437,20 +1437,20 @@ _dispatch_fd_entry_create_with_fd(dispatch_fd_t fd, uintptr_t hash) | |
int result = ioctlsocket((SOCKET)fd, (long)FIONBIO, &value); | ||
(void)dispatch_assume_zero(result); | ||
} else { | ||
// Try to make writing nonblocking, although pipes not coming | ||
// from Foundation.Pipe may not have FILE_WRITE_ATTRIBUTES. | ||
// The _dispatch_pipe_monitor_thread expects pipes to be | ||
// PIPE_WAIT and exploits this assumption by using a blocking | ||
// 0-byte read as a synchronization mechanism. | ||
DWORD dwPipeMode = 0; | ||
if (GetNamedPipeHandleState((HANDLE)fd, &dwPipeMode, NULL, | ||
NULL, NULL, NULL, 0) && !(dwPipeMode & PIPE_NOWAIT)) { | ||
dwPipeMode |= PIPE_NOWAIT; | ||
NULL, NULL, NULL, 0) && !(dwPipeMode & PIPE_WAIT)) { | ||
dwPipeMode |= PIPE_WAIT; | ||
if (!SetNamedPipeHandleState((HANDLE)fd, &dwPipeMode, | ||
NULL, NULL)) { | ||
Comment on lines
1444
to
1448
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Why wouldn't we try to "fix" the pipe in that case? If my understanding is correct that ownership of the pipe is transferred to libdispatch, it makes sense to me that we should try to make it conform to the expected semantics. |
||
// We may end up blocking on subsequent writes, but we | ||
// don't have a good alternative. | ||
// The WriteQuotaAvailable from NtQueryInformationFile | ||
// erroneously returns 0 when there is a blocking read | ||
// on the other end of the pipe. | ||
_dispatch_fd_entry_debug("failed to set PIPE_NOWAIT", | ||
// If setting the pipe to PIPE_WAIT fails, the | ||
// monitoring thread will spin constantly, saturating | ||
// a core, which is undesirable but non-fatal. | ||
// The semantics will still be correct in this case. | ||
_dispatch_fd_entry_debug("failed to set PIPE_WAIT", | ||
fd_entry); | ||
} | ||
} | ||
|
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.
_dispatch_pipe_monitor_thread
is the reader and this code is for the writer. We shouldn't assume that the reader thread is using libdispatch. We could just assert that it's not NOWAIT and comment that the writer is misbehaved if NOWAIT is set, regardless of what the reader does.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.
Hmm, I'm not following.
_dispatch_pipe_monitor_thread
isn't actually the reader, it just waits until data is available on the pipe and then signals to the real reader that data is available. I don't think you can get around using_dispatch_pipe_monitor_thread
if you are writing data through a Win32 pipe on libdispatch, so I think the comment is relevant here.