summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/asyncio/unix_events.py14
-rw-r--r--Lib/test/test_asyncio/test_events.py35
2 files changed, 45 insertions, 4 deletions
diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py
index aad1068..666706f 100644
--- a/Lib/asyncio/unix_events.py
+++ b/Lib/asyncio/unix_events.py
@@ -329,14 +329,17 @@ class _UnixReadPipeTransport(transports.ReadTransport):
elif self._closing:
info.append('closing')
info.append('fd=%s' % self._fileno)
- if self._pipe is not None:
+ selector = getattr(self._loop, '_selector', None)
+ if self._pipe is not None and selector is not None:
polling = selector_events._test_selector_event(
- self._loop._selector,
+ selector,
self._fileno, selectors.EVENT_READ)
if polling:
info.append('polling')
else:
info.append('idle')
+ elif self._pipe is not None:
+ info.append('open')
else:
info.append('closed')
return '<%s>' % ' '.join(info)
@@ -454,9 +457,10 @@ class _UnixWritePipeTransport(transports._FlowControlMixin,
elif self._closing:
info.append('closing')
info.append('fd=%s' % self._fileno)
- if self._pipe is not None:
+ selector = getattr(self._loop, '_selector', None)
+ if self._pipe is not None and selector is not None:
polling = selector_events._test_selector_event(
- self._loop._selector,
+ selector,
self._fileno, selectors.EVENT_WRITE)
if polling:
info.append('polling')
@@ -465,6 +469,8 @@ class _UnixWritePipeTransport(transports._FlowControlMixin,
bufsize = self.get_write_buffer_size()
info.append('bufsize=%s' % bufsize)
+ elif self._pipe is not None:
+ info.append('open')
else:
info.append('closed')
return '<%s>' % ' '.join(info)
diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py
index 4b4e3c0..d52213c 100644
--- a/Lib/test/test_asyncio/test_events.py
+++ b/Lib/test/test_asyncio/test_events.py
@@ -1368,6 +1368,41 @@ class EventLoopTestsMixin:
@unittest.skipUnless(sys.platform != 'win32',
"Don't support pipes for Windows")
+ def test_unclosed_pipe_transport(self):
+ # This test reproduces the issue #314 on GitHub
+ loop = self.create_event_loop()
+ read_proto = MyReadPipeProto(loop=loop)
+ write_proto = MyWritePipeProto(loop=loop)
+
+ rpipe, wpipe = os.pipe()
+ rpipeobj = io.open(rpipe, 'rb', 1024)
+ wpipeobj = io.open(wpipe, 'w', 1024)
+
+ @asyncio.coroutine
+ def connect():
+ read_transport, _ = yield from loop.connect_read_pipe(
+ lambda: read_proto, rpipeobj)
+ write_transport, _ = yield from loop.connect_write_pipe(
+ lambda: write_proto, wpipeobj)
+ return read_transport, write_transport
+
+ # Run and close the loop without closing the transports
+ read_transport, write_transport = loop.run_until_complete(connect())
+ loop.close()
+
+ # These 'repr' calls used to raise an AttributeError
+ # See Issue #314 on GitHub
+ self.assertIn('open', repr(read_transport))
+ self.assertIn('open', repr(write_transport))
+
+ # Clean up (avoid ResourceWarning)
+ rpipeobj.close()
+ wpipeobj.close()
+ read_transport._pipe = None
+ write_transport._pipe = None
+
+ @unittest.skipUnless(sys.platform != 'win32',
+ "Don't support pipes for Windows")
# select, poll and kqueue don't support character devices (PTY) on Mac OS X
# older than 10.6 (Snow Leopard)
@support.requires_mac_ver(10, 6)