@@ -1437,20 +1437,20 @@ _dispatch_fd_entry_create_with_fd(dispatch_fd_t fd, uintptr_t hash)
1437
1437
int result = ioctlsocket ((SOCKET )fd , (long )FIONBIO , & value );
1438
1438
(void )dispatch_assume_zero (result );
1439
1439
} else {
1440
- // Try to make writing nonblocking, although pipes not coming
1441
- // from Foundation.Pipe may not have FILE_WRITE_ATTRIBUTES.
1440
+ // The _dispatch_pipe_monitor_thread expects pipes to be
1441
+ // PIPE_WAIT and exploits this assumption by using a blocking
1442
+ // 0-byte read as a synchronization mechanism.
1442
1443
DWORD dwPipeMode = 0 ;
1443
1444
if (GetNamedPipeHandleState ((HANDLE )fd , & dwPipeMode , NULL ,
1444
- NULL , NULL , NULL , 0 ) && !(dwPipeMode & PIPE_NOWAIT )) {
1445
- dwPipeMode |= PIPE_NOWAIT ;
1445
+ NULL , NULL , NULL , 0 ) && !(dwPipeMode & PIPE_WAIT )) {
1446
+ dwPipeMode |= PIPE_WAIT ;
1446
1447
if (!SetNamedPipeHandleState ((HANDLE )fd , & dwPipeMode ,
1447
1448
NULL , NULL )) {
1448
- // We may end up blocking on subsequent writes, but we
1449
- // don't have a good alternative.
1450
- // The WriteQuotaAvailable from NtQueryInformationFile
1451
- // erroneously returns 0 when there is a blocking read
1452
- // on the other end of the pipe.
1453
- _dispatch_fd_entry_debug ("failed to set PIPE_NOWAIT" ,
1449
+ // If setting the pipe to PIPE_WAIT fails, the
1450
+ // monitoring thread will spin constantly, saturating
1451
+ // a core, which is undesirable but non-fatal.
1452
+ // The semantics will still be correct in this case.
1453
+ _dispatch_fd_entry_debug ("failed to set PIPE_WAIT" ,
1454
1454
fd_entry );
1455
1455
}
1456
1456
}
0 commit comments