From 2be906d59bee65ab691832069cc1e1274b1e7b28 Mon Sep 17 00:00:00 2001 From: itay azolay Date: Sun, 1 Dec 2019 13:12:51 +0200 Subject: [PATCH 01/12] Fixing pause_reading called in connection made is ignored added is_reading() for unix transports --- Lib/asyncio/selector_events.py | 3 +-- Lib/asyncio/unix_events.py | 20 +++++++++++++++++-- Lib/test/test_asyncio/test_selector_events.py | 12 +++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 00e3244bfb294c..18c9421a6a2176 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -728,9 +728,8 @@ def get_write_buffer_size(self): return len(self._buffer) def _add_reader(self, fd, callback, *args): - if self._closing: + if not self.is_reading(): return - self._loop._add_reader(fd, callback, *args) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index d8f653045aee4c..a095bbce75180c 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -460,13 +460,18 @@ def __init__(self, loop, pipe, protocol, waiter=None, extra=None): self._loop.call_soon(self._protocol.connection_made, self) # only start reading when connection_made() has been called - self._loop.call_soon(self._loop._add_reader, + self._loop.call_soon(self._add_reader, self._fileno, self._read_ready) if waiter is not None: # only wake up the waiter when connection_made() has been called self._loop.call_soon(futures._set_result_unless_cancelled, waiter, None) + def _add_reader(self, fd, callback, *args): + if not self.is_reading(): + return + self._loop._add_reader(fd, callback, *args) + def __repr__(self): info = [self.__class__.__name__] if self._pipe is None: @@ -531,6 +536,9 @@ def get_protocol(self): def is_closing(self): return self._closing + def is_reading(self): + return not self._paused and not self._closing + def close(self): if not self._closing: self._close(None) @@ -601,7 +609,7 @@ def __init__(self, loop, pipe, protocol, waiter=None, extra=None): # works for pipes and sockets. (Exception: OS X 10.4? Issue #19294.) if is_socket or (is_fifo and not sys.platform.startswith("aix")): # only start reading when connection_made() has been called - self._loop.call_soon(self._loop._add_reader, + self._loop.call_soon(self._add_reader, self._fileno, self._read_ready) if waiter is not None: @@ -609,6 +617,11 @@ def __init__(self, loop, pipe, protocol, waiter=None, extra=None): self._loop.call_soon(futures._set_result_unless_cancelled, waiter, None) + def _add_reader(self, fd, callback, *args): + if not self.is_reading(): + return + self._loop._add_reader(fd, callback, *args) + def __repr__(self): info = [self.__class__.__name__] if self._pipe is None: @@ -729,6 +742,9 @@ def get_protocol(self): def is_closing(self): return self._closing + def is_reading(self): + return not self._paused and not self._closing + def close(self): if self._pipe is not None and not self._closing: # write_eof is all what we needed to close the write pipe diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 1613c753c26ee5..43a41e8fc32e07 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -554,6 +554,18 @@ def test_pause_resume_reading(self): self.assertFalse(tr.is_reading()) self.loop.assert_no_reader(7) + def test_pause_reading_connection_made(self): + tr = self.socket_transport() + tr.pause_reading() + test_utils.run_briefly(self.loop) + self.assertFalse(tr.is_reading()) + self.loop.assert_no_reader(7, tr._read_ready) + + tr.resume_reading() + self.assertTrue(tr.is_reading()) + self.loop.assert_reader(7, tr._read_ready) + + def test_read_eof_received_error(self): transport = self.socket_transport() transport.close = mock.Mock() From 8b1f17be0a2298e1ac08eca845cd3aebfb9556ae Mon Sep 17 00:00:00 2001 From: itay azolay Date: Sun, 1 Dec 2019 13:31:14 +0200 Subject: [PATCH 02/12] Revert changes to unix_events --- Lib/asyncio/unix_events.py | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index a095bbce75180c..d8f653045aee4c 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -460,18 +460,13 @@ def __init__(self, loop, pipe, protocol, waiter=None, extra=None): self._loop.call_soon(self._protocol.connection_made, self) # only start reading when connection_made() has been called - self._loop.call_soon(self._add_reader, + self._loop.call_soon(self._loop._add_reader, self._fileno, self._read_ready) if waiter is not None: # only wake up the waiter when connection_made() has been called self._loop.call_soon(futures._set_result_unless_cancelled, waiter, None) - def _add_reader(self, fd, callback, *args): - if not self.is_reading(): - return - self._loop._add_reader(fd, callback, *args) - def __repr__(self): info = [self.__class__.__name__] if self._pipe is None: @@ -536,9 +531,6 @@ def get_protocol(self): def is_closing(self): return self._closing - def is_reading(self): - return not self._paused and not self._closing - def close(self): if not self._closing: self._close(None) @@ -609,7 +601,7 @@ def __init__(self, loop, pipe, protocol, waiter=None, extra=None): # works for pipes and sockets. (Exception: OS X 10.4? Issue #19294.) if is_socket or (is_fifo and not sys.platform.startswith("aix")): # only start reading when connection_made() has been called - self._loop.call_soon(self._add_reader, + self._loop.call_soon(self._loop._add_reader, self._fileno, self._read_ready) if waiter is not None: @@ -617,11 +609,6 @@ def __init__(self, loop, pipe, protocol, waiter=None, extra=None): self._loop.call_soon(futures._set_result_unless_cancelled, waiter, None) - def _add_reader(self, fd, callback, *args): - if not self.is_reading(): - return - self._loop._add_reader(fd, callback, *args) - def __repr__(self): info = [self.__class__.__name__] if self._pipe is None: @@ -742,9 +729,6 @@ def get_protocol(self): def is_closing(self): return self._closing - def is_reading(self): - return not self._paused and not self._closing - def close(self): if self._pipe is not None and not self._closing: # write_eof is all what we needed to close the write pipe From 9db5d28dac05363ed3bb4d8c41f98405e190a542 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2019 12:58:32 +0000 Subject: [PATCH 03/12] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst b/Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst new file mode 100644 index 00000000000000..a37fb9e4e54450 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst @@ -0,0 +1 @@ +fix pause_reading is for one message when called in connection_made \ No newline at end of file From 92d8ca7cea35acef23439c8050f706799d559e2b Mon Sep 17 00:00:00 2001 From: itay azolay Date: Sun, 1 Dec 2019 22:14:18 +0200 Subject: [PATCH 04/12] fix _add_reader in SelectorTransport --- Lib/asyncio/selector_events.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 18c9421a6a2176..0419893cd1ade4 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -728,7 +728,7 @@ def get_write_buffer_size(self): return len(self._buffer) def _add_reader(self, fd, callback, *args): - if not self.is_reading(): + if self._closing: return self._loop._add_reader(fd, callback, *args) @@ -788,6 +788,11 @@ def resume_reading(self): if self._loop.get_debug(): logger.debug("%r resumes reading", self) + def _add_reader(self, fd, callback, *args): + if not self.is_reading(): + return + self._loop._add_reader(fd, callback, *args) + def _read_ready(self): self._read_ready_cb() From 7acf410d211f15d48099441f6bd5dbed03eaa25f Mon Sep 17 00:00:00 2001 From: itay azolay Date: Sun, 1 Dec 2019 22:31:09 +0200 Subject: [PATCH 05/12] fix tests --- Lib/test/test_asyncio/test_selector_events.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 43a41e8fc32e07..f8f35686462731 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -559,12 +559,16 @@ def test_pause_reading_connection_made(self): tr.pause_reading() test_utils.run_briefly(self.loop) self.assertFalse(tr.is_reading()) - self.loop.assert_no_reader(7, tr._read_ready) + self.loop.assert_no_reader(7) tr.resume_reading() self.assertTrue(tr.is_reading()) self.loop.assert_reader(7, tr._read_ready) + tr.close() + self.assertFalse(tr.is_reading()) + self.loop.assert_no_reader(7) + def test_read_eof_received_error(self): transport = self.socket_transport() From a16f4d380cecda223d60791935e821174d2a44a9 Mon Sep 17 00:00:00 2001 From: itay azolay Date: Thu, 9 Jan 2020 22:45:49 +0200 Subject: [PATCH 06/12] Added functionality to unix_events --- Lib/asyncio/unix_events.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index d8f653045aee4c..ef8909e47ad3ca 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -460,12 +460,16 @@ def __init__(self, loop, pipe, protocol, waiter=None, extra=None): self._loop.call_soon(self._protocol.connection_made, self) # only start reading when connection_made() has been called - self._loop.call_soon(self._loop._add_reader, + self._loop.call_soon(self._add_reader, self._fileno, self._read_ready) if waiter is not None: # only wake up the waiter when connection_made() has been called self._loop.call_soon(futures._set_result_unless_cancelled, waiter, None) + def _add_reader(self, fd, callback): + if not self.is_reading(): + return + self._loop._add_reader(fd, callback) def __repr__(self): info = [self.__class__.__name__] From c4b3444f9bb487e951266bbc8e97a1d82ab7dd07 Mon Sep 17 00:00:00 2001 From: itay azolay Date: Fri, 10 Jan 2020 00:37:05 +0200 Subject: [PATCH 07/12] fix tests and added is_reading() to unixReadPipeTransport --- Lib/asyncio/selector_events.py | 2 +- Lib/asyncio/unix_events.py | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 0419893cd1ade4..6413ce0de1b29c 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -773,7 +773,7 @@ def is_reading(self): return not self._paused and not self._closing def pause_reading(self): - if self._closing or self._paused: + if not self.is_reading(): return self._paused = True self._loop._remove_reader(self._sock_fd) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index ef8909e47ad3ca..b58e2b39c584a3 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -466,11 +466,15 @@ def __init__(self, loop, pipe, protocol, waiter=None, extra=None): # only wake up the waiter when connection_made() has been called self._loop.call_soon(futures._set_result_unless_cancelled, waiter, None) + def _add_reader(self, fd, callback): if not self.is_reading(): return self._loop._add_reader(fd, callback) + def is_reading(self): + return not self._paused and not self._closing + def __repr__(self): info = [self.__class__.__name__] if self._pipe is None: @@ -511,7 +515,7 @@ def _read_ready(self): self._loop.call_soon(self._call_connection_lost, None) def pause_reading(self): - if self._closing or self._paused: + if not self.is_reading(): return self._paused = True self._loop._remove_reader(self._fileno) From 9da5fce8e2fc7a506c60a6b2e18283ddbb213cc4 Mon Sep 17 00:00:00 2001 From: itay azolay Date: Sun, 12 Jan 2020 18:42:34 +0200 Subject: [PATCH 08/12] Move ReadTransport SelectorSocketTransport override to SelectorTransport parent class --- Lib/asyncio/selector_events.py | 48 ++++++++++++++++------------------ 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 6413ce0de1b29c..99bea57e66f555 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -624,6 +624,8 @@ def __init__(self, loop, sock, protocol, extra=None, server=None): self._buffer = self._buffer_factory() self._conn_lost = 0 # Set when call to connection_lost scheduled. self._closing = False # Set when close() called. + self._paused = False # Set when pause_reading() called + if self._server is not None: self._server._attach() loop._transports[self._sock_fd] = self @@ -669,6 +671,25 @@ def get_protocol(self): def is_closing(self): return self._closing + def is_reading(self): + return not self.is_closing() and not self._paused + + def pause_reading(self): + if not self.is_reading(): + return + self._paused = True + self._loop._remove_reader(self._sock_fd) + if self._loop.get_debug(): + logger.debug("%r pauses reading", self) + + def resume_reading(self): + if self._closing or not self._paused: + return + self._paused = False + self._add_reader(self._sock_fd, self._read_ready) + if self._loop.get_debug(): + logger.debug("%r resumes reading", self) + def close(self): if self._closing: return @@ -728,7 +749,7 @@ def get_write_buffer_size(self): return len(self._buffer) def _add_reader(self, fd, callback, *args): - if self._closing: + if not self.is_reading(): return self._loop._add_reader(fd, callback, *args) @@ -744,7 +765,6 @@ def __init__(self, loop, sock, protocol, waiter=None, self._read_ready_cb = None super().__init__(loop, sock, protocol, extra, server) self._eof = False - self._paused = False self._empty_waiter = None # Disable the Nagle algorithm -- small writes will be @@ -769,30 +789,6 @@ def set_protocol(self, protocol): super().set_protocol(protocol) - def is_reading(self): - return not self._paused and not self._closing - - def pause_reading(self): - if not self.is_reading(): - return - self._paused = True - self._loop._remove_reader(self._sock_fd) - if self._loop.get_debug(): - logger.debug("%r pauses reading", self) - - def resume_reading(self): - if self._closing or not self._paused: - return - self._paused = False - self._add_reader(self._sock_fd, self._read_ready) - if self._loop.get_debug(): - logger.debug("%r resumes reading", self) - - def _add_reader(self, fd, callback, *args): - if not self.is_reading(): - return - self._loop._add_reader(fd, callback, *args) - def _read_ready(self): self._read_ready_cb() From b9722e9bf71fcb4440f7ffb155093d1287cf6ffb Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Thu, 20 Apr 2023 06:44:58 -0700 Subject: [PATCH 09/12] Improve wording in NEWS file. --- .../Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst b/Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst index a37fb9e4e54450..1851da19278099 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst @@ -1 +1 @@ -fix pause_reading is for one message when called in connection_made \ No newline at end of file +Fix :func:`_UnixReadPipeTransport.pause_reading` to make it work when called from :func;`connection_made`. From 93ee980f56e462f26fbd0141bbca5499bef01487 Mon Sep 17 00:00:00 2001 From: Oleg Iarygin Date: Thu, 20 Apr 2023 17:53:40 +0400 Subject: [PATCH 10/12] Update Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst --- .../Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst b/Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst index 1851da19278099..f0b4ee643f77b2 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst @@ -1 +1 @@ -Fix :func:`_UnixReadPipeTransport.pause_reading` to make it work when called from :func;`connection_made`. +Fix :func:`_UnixReadPipeTransport.pause_reading` to make it work when called from :func:`connection_made`. From dbbeeddd405e6cac1c16151878e493a5b7e614b5 Mon Sep 17 00:00:00 2001 From: Itay Azolay Date: Sat, 22 Apr 2023 18:32:43 +0300 Subject: [PATCH 11/12] Refactor pause reading to be called from within connection made add Proactor events tests --- Lib/test/test_asyncio/test_proactor_events.py | 13 +++++++++++++ Lib/test/test_asyncio/test_selector_events.py | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index 6cb7dc300c5331..c42856e578b8cc 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -447,6 +447,19 @@ def monkey(): self.assertFalse(tr.is_reading()) + def test_pause_reading_connection_made(self): + tr = self.socket_transport() + self.protocol.connection_made.side_effect = lambda _: tr.pause_reading() + test_utils.run_briefly(self.loop) + self.assertFalse(tr.is_reading()) + self.loop.assert_no_reader(7) + + tr.resume_reading() + self.assertTrue(tr.is_reading()) + + tr.close() + self.assertFalse(tr.is_reading()) + def pause_writing_transport(self, high): tr = self.socket_transport() diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index ed3b0d2506492e..47693ea4d3ce2e 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -549,7 +549,7 @@ def test_pause_resume_reading(self): def test_pause_reading_connection_made(self): tr = self.socket_transport() - tr.pause_reading() + self.protocol.connection_made.side_effect = lambda _: tr.pause_reading() test_utils.run_briefly(self.loop) self.assertFalse(tr.is_reading()) self.loop.assert_no_reader(7) From 17d036bd79edd058e1684bcdb486e70f0422261c Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Tue, 25 Apr 2023 18:23:42 +0530 Subject: [PATCH 12/12] fixup news --- .../Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst b/Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst index f0b4ee643f77b2..13c054fdd68276 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst @@ -1 +1 @@ -Fix :func:`_UnixReadPipeTransport.pause_reading` to make it work when called from :func:`connection_made`. +Fix :func:`!pause_reading` to work when called from :func:`!connection_made` in :mod:`asyncio`.