Skip to content

Commit bb73164

Browse files
more fixes
1 parent 514b46e commit bb73164

4 files changed

Lines changed: 36 additions & 21 deletions

File tree

Doc/library/asyncio-eventloop.rst

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,8 +1312,13 @@ following:
13121312
* a character device, such as a terminal.
13131313

13141314
On Windows, where only :class:`ProactorEventLoop` implements these methods,
1315-
*pipe* must wrap a handle opened for overlapped I/O, since the handle has to
1316-
be associated with an I/O completion port.
1315+
*pipe* must wrap a handle opened for overlapped I/O (that is, created with the
1316+
``FILE_FLAG_OVERLAPPED`` flag), since the handle has to be associated with an
1317+
I/O completion port. Handles that were not opened for overlapped I/O are
1318+
rejected. In particular, the standard streams (:data:`sys.stdin`,
1319+
:data:`sys.stdout` and :data:`sys.stderr`), console handles, and the pipes
1320+
created by :func:`os.pipe` are **not** opened for overlapped I/O and therefore
1321+
cannot be used with these methods.
13171322

13181323
.. note::
13191324

Doc/library/asyncio-platforms.rst

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,8 @@ All event loops on Windows do not support the following methods:
6868
methods are not supported.
6969

7070
* :meth:`loop.connect_read_pipe` and :meth:`loop.connect_write_pipe` only
71-
accept a handle opened for overlapped I/O, which in practice means a named
72-
pipe such as those created by :func:`!asyncio.windows_utils.pipe`. A
73-
console handle cannot be associated with an I/O completion port, so
74-
:data:`sys.stdin`, :data:`sys.stdout` and :data:`sys.stderr` are not
75-
supported. See :ref:`Supported pipe objects <asyncio-pipe-objects>` for
76-
how such a handle is rejected, which differs between the two methods.
71+
accept a handle opened for overlapped I/O.
72+
See :ref:`Supported pipe objects <asyncio-pipe-objects>` for which objects are supported.
7773

7874
The resolution of the monotonic clock on Windows is usually around 15.6
7975
milliseconds. The best resolution is 0.5 milliseconds. The resolution depends on the

Lib/asyncio/proactor_events.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ def __init__(self, loop, sock, protocol, waiter=None,
6262
self._closing = False # Set when close() called.
6363
self._called_connection_lost = False
6464
self._eof_written = False
65+
self._empty_waiter = None
6566
if self._server is not None:
6667
self._server._attach(self)
6768
self._loop.call_soon(self._protocol.connection_made, self)
@@ -331,10 +332,6 @@ class _ProactorBaseWritePipeTransport(_ProactorBasePipeTransport,
331332

332333
_start_tls_compatible = True
333334

334-
def __init__(self, *args, **kw):
335-
super().__init__(*args, **kw)
336-
self._empty_waiter = None
337-
338335
def write(self, data):
339336
if not isinstance(data, (bytes, bytearray, memoryview)):
340337
raise TypeError(
@@ -465,7 +462,6 @@ class _ProactorDatagramTransport(_ProactorBasePipeTransport,
465462
def __init__(self, loop, sock, protocol, address=None,
466463
waiter=None, extra=None):
467464
self._address = address
468-
self._empty_waiter = None
469465
self._buffer_size = 0
470466
# We don't need to call _protocol.connection_made() since our base
471467
# constructor does it for us.

Lib/test/test_asyncio/test_windows_events.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -347,23 +347,22 @@ def connection_lost(self, exc):
347347

348348
async def run():
349349
transport, _ = await self.loop.connect_read_pipe(Proto, pipe)
350-
await lost
350+
exc = await lost
351351
transport.close()
352+
return exc
352353

353-
self.loop.run_until_complete(run())
354-
self.assertTrue(self.errors, 'no error reached the exception handler')
355-
self.assertIsInstance(self.errors[0]['exception'], OSError)
354+
exc = self.loop.run_until_complete(run())
355+
self.assertIsInstance(exc, OSError)
356356

357357
def check_write_rejected(self, pipe):
358358
self.addCleanup(pipe.close)
359359
with self.assertRaises(OSError):
360360
self.loop.run_until_complete(
361361
self.loop.connect_write_pipe(asyncio.BaseProtocol, pipe))
362362

363-
def test_overlapped_pipe(self):
364-
rhandle, whandle = windows_utils.pipe(overlapped=(True, True))
365-
rpipe = windows_utils.PipeHandle(rhandle)
366-
wpipe = windows_utils.PipeHandle(whandle)
363+
def check_accepted(self, rpipe, wpipe):
364+
self.addCleanup(rpipe.close)
365+
self.addCleanup(wpipe.close)
367366

368367
chunks = []
369368
lost = self.loop.create_future()
@@ -389,6 +388,15 @@ async def run():
389388
self.assertEqual(b''.join(chunks), b'spam')
390389
self.assertFalse(self.errors)
391390

391+
def test_overlapped_pipe(self):
392+
rhandle, whandle = windows_utils.pipe(duplex=True, overlapped=(True, True))
393+
self.check_accepted(windows_utils.PipeHandle(rhandle),
394+
windows_utils.PipeHandle(whandle))
395+
396+
def test_socketpair(self):
397+
rsock, wsock = socket.socketpair()
398+
self.check_accepted(rsock, wsock)
399+
392400
def test_read_non_overlapped_pipe(self):
393401
rhandle, whandle = windows_utils.pipe(overlapped=(False, False))
394402
self.addCleanup(windows_utils.PipeHandle(whandle).close)
@@ -409,6 +417,16 @@ def test_write_regular_file(self):
409417
self.addCleanup(os_helper.unlink, os_helper.TESTFN)
410418
self.check_write_rejected(open(os_helper.TESTFN, 'wb', 0))
411419

420+
def test_read_os_pipe(self):
421+
rfd, wfd = os.pipe()
422+
self.addCleanup(os.close, wfd)
423+
self.check_read_rejected(open(rfd, 'rb', 0))
424+
425+
def test_write_os_pipe(self):
426+
rfd, wfd = os.pipe()
427+
self.addCleanup(os.close, rfd)
428+
self.check_write_rejected(open(wfd, 'wb', 0))
429+
412430

413431
if __name__ == '__main__':
414432
unittest.main()

0 commit comments

Comments
 (0)