diff options
-rw-r--r-- | Lib/asyncio/selector_events.py | 11 | ||||
-rw-r--r-- | Lib/test/test_asyncio/test_selector_events.py | 30 | ||||
-rw-r--r-- | Misc/NEWS | 6 |
3 files changed, 29 insertions, 18 deletions
diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index fb7ab2108e..9564d01dfa 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -569,6 +569,7 @@ class _SelectorTransport(transports._FlowControlMixin, self._loop.remove_reader(self._sock_fd) if not self._buffer: self._conn_lost += 1 + self._loop.remove_writer(self._sock_fd) self._loop.call_soon(self._call_connection_lost, None) # On Python 3.3 and older, objects with a destructor part of a reference @@ -662,6 +663,8 @@ class _SelectorSocketTransport(_SelectorTransport): logger.debug("%r resumes reading", self) def _read_ready(self): + if self._conn_lost: + return try: data = self._sock.recv(self.max_size) except (BlockingIOError, InterruptedError): @@ -721,6 +724,8 @@ class _SelectorSocketTransport(_SelectorTransport): def _write_ready(self): assert self._buffer, 'Data should not be empty' + if self._conn_lost: + return try: n = self._sock.send(self._buffer) except (BlockingIOError, InterruptedError): @@ -891,6 +896,8 @@ class _SelectorSslTransport(_SelectorTransport): logger.debug("%r resumes reading", self) def _read_ready(self): + if self._conn_lost: + return if self._write_wants_read: self._write_wants_read = False self._write_ready() @@ -923,6 +930,8 @@ class _SelectorSslTransport(_SelectorTransport): self.close() def _write_ready(self): + if self._conn_lost: + return if self._read_wants_write: self._read_wants_write = False self._read_ready() @@ -1000,6 +1009,8 @@ class _SelectorDatagramTransport(_SelectorTransport): return sum(len(data) for data, _ in self._buffer) def _read_ready(self): + if self._conn_lost: + return try: data, addr = self._sock.recvfrom(self.max_size) except (BlockingIOError, InterruptedError): diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 8ad55358b1..5dc6ff8e66 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -1087,17 +1087,6 @@ class SelectorSocketTransportTests(test_utils.TestCase): err, 'Fatal write error on socket transport') - @mock.patch('asyncio.base_events.logger') - def test_write_ready_exception_and_close(self, m_log): - self.sock.send.side_effect = OSError() - remove_writer = self.loop.remove_writer = mock.Mock() - - transport = self.socket_transport() - transport.close() - transport._buffer.extend(b'data') - transport._write_ready() - remove_writer.assert_called_with(self.sock_fd) - def test_write_eof(self): tr = self.socket_transport() self.assertTrue(tr.can_write_eof()) @@ -1121,6 +1110,14 @@ class SelectorSocketTransportTests(test_utils.TestCase): self.sock.shutdown.assert_called_with(socket.SHUT_WR) tr.close() + @mock.patch('asyncio.base_events.logger') + def test_transport_close_remove_writer(self, m_log): + remove_writer = self.loop.remove_writer = mock.Mock() + + transport = self.socket_transport() + transport.close() + remove_writer.assert_called_with(self.sock_fd) + @unittest.skipIf(ssl is None, 'No ssl module') class SelectorSslTransportTests(test_utils.TestCase): @@ -1175,7 +1172,7 @@ class SelectorSslTransportTests(test_utils.TestCase): self.sslsock.do_handshake.side_effect = exc with test_utils.disable_logger(): waiter = asyncio.Future(loop=self.loop) - transport = self.ssl_transport(waiter=waiter) + self.ssl_transport(waiter=waiter) self.assertTrue(waiter.done()) self.assertIs(exc, waiter.exception()) self.assertTrue(self.sslsock.close.called) @@ -1374,20 +1371,19 @@ class SelectorSslTransportTests(test_utils.TestCase): def test_write_ready_send_closing(self): self.sslsock.send.return_value = 4 transport = self._make_one() - transport.close() transport._buffer = list_to_buffer([b'data']) + transport.close() transport._write_ready() - self.assertFalse(self.loop.writers) self.protocol.connection_lost.assert_called_with(None) def test_write_ready_send_closing_empty_buffer(self): self.sslsock.send.return_value = 4 + call_soon = self.loop.call_soon = mock.Mock() transport = self._make_one() - transport.close() transport._buffer = list_to_buffer() + transport.close() transport._write_ready() - self.assertFalse(self.loop.writers) - self.protocol.connection_lost.assert_called_with(None) + call_soon.assert_called_with(transport._call_connection_lost, None) def test_write_ready_send_retry(self): transport = self._make_one() @@ -520,6 +520,10 @@ Library - Issue #27041: asyncio: Add loop.create_future method +- Issue #27223: asyncio: Fix _read_ready and _write_ready to respect + _conn_lost. + Patch by Ćukasz Langa. + IDLE ---- @@ -709,7 +713,7 @@ Tools/Demos Misc ---- -- Issue #17500, and https://github.com/python/pythondotorg/issues/945: Remove +- Issue #17500, and https://github.com/python/pythondotorg/issues/945: Remove unused and outdated icons. |