diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index 50badd6b247..d6531f88a74 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -208,9 +208,6 @@ class FlowControlMixin(protocols.Protocol): self._drain_waiter = waiter await waiter - def _get_close_waiter(self, stream): - raise NotImplementedError - class StreamReaderProtocol(FlowControlMixin, protocols.Protocol): """Helper class to adapt between Protocol and StreamReader. @@ -268,9 +265,6 @@ class StreamReaderProtocol(FlowControlMixin, protocols.Protocol): return False return True - def _get_close_waiter(self, stream): - return self._closed - def __del__(self): # Prevent reports about unhandled exceptions. # Better than self._closed._log_traceback = False hack @@ -326,7 +320,7 @@ class StreamWriter: return self._transport.is_closing() async def wait_closed(self): - await self._protocol._get_close_waiter(self) + await self._protocol._closed def get_extra_info(self, name, default=None): return self._transport.get_extra_info(name, default) @@ -344,12 +338,13 @@ class StreamWriter: if exc is not None: raise exc if self._transport.is_closing(): - # Wait for protocol.connection_lost() call - # Raise connection closing error if any, - # ConnectionResetError otherwise - fut = self._protocol._get_close_waiter(self) - await fut - raise ConnectionResetError('Connection lost') + # Yield to the event loop so connection_lost() may be + # called. Without this, _drain_helper() would return + # immediately, and code that calls + # write(...); await drain() + # in a loop would never call connection_lost(), so it + # would not see an error when the socket is closed. + await sleep(0, loop=self._loop) await self._protocol._drain_helper() diff --git a/Lib/asyncio/subprocess.py b/Lib/asyncio/subprocess.py index ecacc1a66db..90fc00de833 100644 --- a/Lib/asyncio/subprocess.py +++ b/Lib/asyncio/subprocess.py @@ -25,7 +25,6 @@ class SubprocessStreamProtocol(streams.FlowControlMixin, self._transport = None self._process_exited = False self._pipe_fds = [] - self._stdin_closed = self._loop.create_future() def __repr__(self): info = [self.__class__.__name__] @@ -77,10 +76,6 @@ class SubprocessStreamProtocol(streams.FlowControlMixin, if pipe is not None: pipe.close() self.connection_lost(exc) - if exc is None: - self._stdin_closed.set_result(None) - else: - self._stdin_closed.set_exception(exc) return if fd == 1: reader = self.stdout @@ -107,10 +102,6 @@ class SubprocessStreamProtocol(streams.FlowControlMixin, self._transport.close() self._transport = None - def _get_close_waiter(self, stream): - if stream is self.stdin: - return self._stdin_closed - class Process: def __init__(self, transport, protocol, loop): diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index 2e5fc61bce2..63fa13f79e2 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -99,29 +99,6 @@ class StreamTests(test_utils.TestCase): self._basetest_open_connection_no_loop_ssl(conn_fut) - @unittest.skipIf(ssl is None, 'No ssl module') - def test_drain_on_closed_writer_ssl(self): - - async def inner(httpd): - reader, writer = await asyncio.open_connection( - *httpd.address, - ssl=test_utils.dummy_ssl_context()) - - messages = [] - self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx)) - writer.write(b'GET / HTTP/1.0\r\n\r\n') - data = await reader.read() - self.assertTrue(data.endswith(b'\r\n\r\nTest message')) - - writer.close() - with self.assertRaises(ConnectionResetError): - await writer.drain() - - self.assertEqual(messages, []) - - with test_utils.run_test_server(use_ssl=True) as httpd: - self.loop.run_until_complete(inner(httpd)) - def _basetest_open_connection_error(self, open_connection_fut): reader, writer = self.loop.run_until_complete(open_connection_fut) writer._protocol.connection_lost(ZeroDivisionError()) diff --git a/Misc/NEWS.d/next/Library/2019-05-05-09-45-44.bpo-36801.XrlFFs.rst b/Misc/NEWS.d/next/Library/2019-05-05-09-45-44.bpo-36801.XrlFFs.rst deleted file mode 100644 index 43e51fe5ca9..00000000000 --- a/Misc/NEWS.d/next/Library/2019-05-05-09-45-44.bpo-36801.XrlFFs.rst +++ /dev/null @@ -1 +0,0 @@ -Properly handle SSL connection closing in asyncio StreamWriter.drain() call.