@@ -1750,7 +1750,15 @@ _Py_read(int fd, void *buf, size_t count)
1750
1750
Py_BEGIN_ALLOW_THREADS
1751
1751
errno = 0 ;
1752
1752
#ifdef MS_WINDOWS
1753
+ _doserrno = 0 ;
1753
1754
n = read (fd , buf , (int )count );
1755
+ // read() on a non-blocking empty pipe fails with EINVAL, which is
1756
+ // mapped from the Windows error code ERROR_NO_DATA.
1757
+ if (n < 0 && errno == EINVAL ) {
1758
+ if (_doserrno == ERROR_NO_DATA ) {
1759
+ errno = EAGAIN ;
1760
+ }
1761
+ }
1754
1762
#else
1755
1763
n = read (fd , buf , count );
1756
1764
#endif
@@ -1804,6 +1812,50 @@ _Py_write_impl(int fd, const void *buf, size_t count, int gil_held)
1804
1812
}
1805
1813
}
1806
1814
}
1815
+
1816
+ // In non-blocking mode, a write that exceeds the available size of a pipe
1817
+ // fails without writing anything. Limiting writes to the pipe size allows
1818
+ // a buffered write to succeed eventually, as the pipe is read.
1819
+ HANDLE hfile = _Py_get_osfhandle (fd );
1820
+ if (hfile == INVALID_HANDLE_VALUE ) {
1821
+ return -1 ;
1822
+ }
1823
+ DWORD mode , pipe_size ;
1824
+ if (gil_held ) {
1825
+ Py_BEGIN_ALLOW_THREADS
1826
+ if (GetFileType (hfile ) == FILE_TYPE_PIPE &&
1827
+ GetNamedPipeHandleStateW (hfile , & mode , NULL , NULL , NULL ,
1828
+ NULL , 0 ) &&
1829
+ mode & PIPE_NOWAIT )
1830
+ {
1831
+ // GetNamedPipeInfo() requires FILE_READ_ATTRIBUTES access.
1832
+ // CreatePipe() includes this access for the write handle.
1833
+ if (!GetNamedPipeInfo (hfile , NULL , NULL , & pipe_size , NULL )) {
1834
+ pipe_size = 4096 ;
1835
+ }
1836
+ if (count > pipe_size ) {
1837
+ count = pipe_size ;
1838
+ }
1839
+ }
1840
+ Py_END_ALLOW_THREADS
1841
+ }
1842
+ else {
1843
+ if (GetFileType (hfile ) == FILE_TYPE_PIPE &&
1844
+ GetNamedPipeHandleStateW (hfile , & mode , NULL , NULL , NULL ,
1845
+ NULL , 0 ) &&
1846
+ mode & PIPE_NOWAIT )
1847
+ {
1848
+ // GetNamedPipeInfo() requires FILE_READ_ATTRIBUTES access.
1849
+ // CreatePipe() includes this access for the write handle.
1850
+ if (!GetNamedPipeInfo (hfile , NULL , NULL , & pipe_size , NULL )) {
1851
+ pipe_size = 4096 ;
1852
+ }
1853
+ if (count > pipe_size ) {
1854
+ count = pipe_size ;
1855
+ }
1856
+ }
1857
+ }
1858
+
1807
1859
#endif
1808
1860
if (count > _PY_WRITE_MAX ) {
1809
1861
count = _PY_WRITE_MAX ;
@@ -1814,7 +1866,13 @@ _Py_write_impl(int fd, const void *buf, size_t count, int gil_held)
1814
1866
Py_BEGIN_ALLOW_THREADS
1815
1867
errno = 0 ;
1816
1868
#ifdef MS_WINDOWS
1869
+ _doserrno = 0 ;
1817
1870
n = write (fd , buf , (int )count );
1871
+ // write() on a non-blocking pipe fails with ENOSPC on Windows if
1872
+ // the pipe lacks available space for the entire buffer.
1873
+ if (n < 0 && errno == ENOSPC && _doserrno == 0 ) {
1874
+ errno = EAGAIN ;
1875
+ }
1818
1876
#else
1819
1877
n = write (fd , buf , count );
1820
1878
#endif
@@ -1829,7 +1887,13 @@ _Py_write_impl(int fd, const void *buf, size_t count, int gil_held)
1829
1887
do {
1830
1888
errno = 0 ;
1831
1889
#ifdef MS_WINDOWS
1890
+ _doserrno = 0 ;
1832
1891
n = write (fd , buf , (int )count );
1892
+ // write() on a non-blocking pipe fails with ENOSPC on Windows if
1893
+ // the pipe lacks available space for the entire buffer.
1894
+ if (n < 0 && errno == ENOSPC && _doserrno == 0 ) {
1895
+ errno = EAGAIN ;
1896
+ }
1833
1897
#else
1834
1898
n = write (fd , buf , count );
1835
1899
#endif
0 commit comments