@@ -1432,9 +1432,26 @@ _dispatch_fd_entry_create_with_fd(dispatch_fd_t fd, uintptr_t hash)
14321432#if defined(_WIN32 )
14331433 DWORD dwType = GetFileType ((HANDLE )fd );
14341434 if (dwType == FILE_TYPE_PIPE ) {
1435- unsigned long value = 1 ;
1436- int result = ioctlsocket ((SOCKET )fd , (long )FIONBIO , & value );
1437- (void )dispatch_assume_zero (result );
1435+ if (_dispatch_handle_is_socket ((HANDLE )fd )) {
1436+ unsigned long value = 1 ;
1437+ int result = ioctlsocket ((SOCKET )fd , (long )FIONBIO , & value );
1438+ (void )dispatch_assume_zero (result );
1439+ }
1440+ else {
1441+ // Try to make writing nonblocking, although pipes not coming
1442+ // from Foundation.Pipe may not have FILE_WRITE_ATTRIBUTES.
1443+ DWORD pipe_mode = PIPE_NOWAIT ;
1444+ if (!SetNamedPipeHandleState ((HANDLE )fd , & pipe_mode , NULL ,
1445+ NULL )) {
1446+ // We may end up blocking on subsequent writes, but we
1447+ // don't have a good alternative. The WriteQuotaAvailable
1448+ // from NtQueryInformationFile erroneously returns 0 when
1449+ // there is a blocking read on the other end of the pipe.
1450+ _dispatch_fd_entry_debug ("failed to set PIPE_NOWAIT" ,
1451+ fd_entry );
1452+ }
1453+ }
1454+
14381455 _dispatch_stream_init (fd_entry ,
14391456 _dispatch_get_default_queue (false));
14401457 } else {
@@ -2489,24 +2506,6 @@ _dispatch_operation_perform(dispatch_operation_t op)
24892506 }
24902507 bSuccess = TRUE;
24912508 } else if (GetFileType (hFile ) == FILE_TYPE_PIPE ) {
2492- // Unfortunately there isn't a good way to achieve O_NONBLOCK
2493- // semantics when writing to a pipe. SetNamedPipeHandleState()
2494- // can allow pipes to be switched into a "no wait" mode, but
2495- // that doesn't work on most pipe handles because Windows
2496- // doesn't consistently create pipes with FILE_WRITE_ATTRIBUTES
2497- // access. The best we can do is to try to query the write quota
2498- // and then write as much as we can.
2499- IO_STATUS_BLOCK iosb ;
2500- FILE_PIPE_LOCAL_INFORMATION fpli ;
2501- NTSTATUS status = _dispatch_NtQueryInformationFile (hFile , & iosb ,
2502- & fpli , sizeof (fpli ), FilePipeLocalInformation );
2503- if (NT_SUCCESS (status )) {
2504- if (fpli .WriteQuotaAvailable == 0 ) {
2505- err = EAGAIN ;
2506- goto error ;
2507- }
2508- len = MIN (len , fpli .WriteQuotaAvailable );
2509- }
25102509 OVERLAPPED ovlOverlapped = {};
25112510 bSuccess = WriteFile (hFile , buf , (DWORD )len ,
25122511 (LPDWORD )& processed , & ovlOverlapped );
@@ -2523,6 +2522,9 @@ _dispatch_operation_perform(dispatch_operation_t op)
25232522 processed = 0 ;
25242523 }
25252524 }
2525+ if (bSuccess && processed == 0 ) {
2526+ err = EAGAIN ;
2527+ }
25262528 } else {
25272529 bSuccess = WriteFile (hFile , buf , (DWORD )len ,
25282530 (LPDWORD )& processed , NULL );
0 commit comments