Skip to content

Commit ef7ded0

Browse files
z2ohcompnerd
authored andcommitted
Switch Win32 pipes to PIPE_WAIT
1 parent 34bc77c commit ef7ded0

File tree

2 files changed

+13
-10
lines changed

2 files changed

+13
-10
lines changed

src/event/event_windows.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,9 @@ _dispatch_pipe_monitor_thread(void *context)
277277
char cBuffer[1];
278278
DWORD dwNumberOfBytesTransferred;
279279
OVERLAPPED ov = {0};
280+
// Block on a 0-byte read; this will only resume when data is
281+
// available in the pipe. The pipe must be PIPE_WAIT or this thread
282+
// will spin.
280283
BOOL bSuccess = ReadFile(hPipe, cBuffer, /* nNumberOfBytesToRead */ 0,
281284
&dwNumberOfBytesTransferred, &ov);
282285
DWORD dwBytesAvailable;

src/io.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,20 +1463,20 @@ _dispatch_fd_entry_create_with_fd(dispatch_fd_t fd, uintptr_t hash)
14631463
int result = ioctlsocket((SOCKET)fd, (long)FIONBIO, &value);
14641464
(void)dispatch_assume_zero(result);
14651465
} else {
1466-
// Try to make writing nonblocking, although pipes not coming
1467-
// from Foundation.Pipe may not have FILE_WRITE_ATTRIBUTES.
1466+
// The _dispatch_pipe_monitor_thread expects pipes to be
1467+
// PIPE_WAIT and exploits this assumption by using a blocking
1468+
// 0-byte read as a synchronization mechanism.
14681469
DWORD dwPipeMode = 0;
14691470
if (GetNamedPipeHandleState((HANDLE)fd, &dwPipeMode, NULL,
1470-
NULL, NULL, NULL, 0) && !(dwPipeMode & PIPE_NOWAIT)) {
1471-
dwPipeMode |= PIPE_NOWAIT;
1471+
NULL, NULL, NULL, 0) && !(dwPipeMode & PIPE_WAIT)) {
1472+
dwPipeMode |= PIPE_WAIT;
14721473
if (!SetNamedPipeHandleState((HANDLE)fd, &dwPipeMode,
14731474
NULL, NULL)) {
1474-
// We may end up blocking on subsequent writes, but we
1475-
// don't have a good alternative.
1476-
// The WriteQuotaAvailable from NtQueryInformationFile
1477-
// erroneously returns 0 when there is a blocking read
1478-
// on the other end of the pipe.
1479-
_dispatch_fd_entry_debug("failed to set PIPE_NOWAIT",
1475+
// If setting the pipe to PIPE_WAIT fails, the
1476+
// monitoring thread will spin constantly, saturating
1477+
// a core, which is undesirable but non-fatal.
1478+
// The semantics will still be correct in this case.
1479+
_dispatch_fd_entry_debug("failed to set PIPE_WAIT",
14801480
fd_entry);
14811481
}
14821482
}

0 commit comments

Comments
 (0)