@@ -1432,9 +1432,26 @@ _dispatch_fd_entry_create_with_fd(dispatch_fd_t fd, uintptr_t hash)
1432
1432
#if defined(_WIN32 )
1433
1433
DWORD dwType = GetFileType ((HANDLE )fd );
1434
1434
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
+
1438
1455
_dispatch_stream_init (fd_entry ,
1439
1456
_dispatch_get_default_queue (false));
1440
1457
} else {
@@ -2489,24 +2506,6 @@ _dispatch_operation_perform(dispatch_operation_t op)
2489
2506
}
2490
2507
bSuccess = TRUE;
2491
2508
} 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
- }
2510
2509
OVERLAPPED ovlOverlapped = {};
2511
2510
bSuccess = WriteFile (hFile , buf , (DWORD )len ,
2512
2511
(LPDWORD )& processed , & ovlOverlapped );
@@ -2523,6 +2522,9 @@ _dispatch_operation_perform(dispatch_operation_t op)
2523
2522
processed = 0 ;
2524
2523
}
2525
2524
}
2525
+ if (bSuccess && processed == 0 ) {
2526
+ err = EAGAIN ;
2527
+ }
2526
2528
} else {
2527
2529
bSuccess = WriteFile (hFile , buf , (DWORD )len ,
2528
2530
(LPDWORD )& processed , NULL );
0 commit comments