@@ -1432,9 +1432,30 @@ _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
+ } else {
1440
+ // Try to make writing nonblocking, although pipes not coming
1441
+ // from Foundation.Pipe may not have FILE_WRITE_ATTRIBUTES.
1442
+ DWORD dwPipeMode = 0 ;
1443
+ if (GetNamedPipeHandleState ((HANDLE )fd , & dwPipeMode , NULL ,
1444
+ NULL , NULL , NULL , 0 ) && !(dwPipeMode & PIPE_NOWAIT )) {
1445
+ dwPipeMode |= PIPE_NOWAIT ;
1446
+ if (!SetNamedPipeHandleState ((HANDLE )fd , & dwPipeMode ,
1447
+ 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" ,
1454
+ fd_entry );
1455
+ }
1456
+ }
1457
+ }
1458
+
1438
1459
_dispatch_stream_init (fd_entry ,
1439
1460
_dispatch_get_default_queue (false));
1440
1461
} else {
@@ -2489,24 +2510,6 @@ _dispatch_operation_perform(dispatch_operation_t op)
2489
2510
}
2490
2511
bSuccess = TRUE;
2491
2512
} 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
2513
OVERLAPPED ovlOverlapped = {};
2511
2514
bSuccess = WriteFile (hFile , buf , (DWORD )len ,
2512
2515
(LPDWORD )& processed , & ovlOverlapped );
@@ -2523,6 +2526,10 @@ _dispatch_operation_perform(dispatch_operation_t op)
2523
2526
processed = 0 ;
2524
2527
}
2525
2528
}
2529
+ if (bSuccess && processed == 0 ) {
2530
+ err = EAGAIN ;
2531
+ goto error ;
2532
+ }
2526
2533
} else {
2527
2534
bSuccess = WriteFile (hFile , buf , (DWORD )len ,
2528
2535
(LPDWORD )& processed , NULL );
0 commit comments