From 62cdd3149c16b2156c1bd5863b8cf9d0f16cfb36 Mon Sep 17 00:00:00 2001 From: Simon Wrede Date: Sun, 9 Jan 2022 18:00:12 +0100 Subject: [PATCH 1/3] Added reference to task created by StreamReaderProtocol --- Lib/asyncio/streams.py | 3 ++- Lib/test/test_asyncio/test_streams.py | 19 +++++++++++++++++++ Misc/ACKS | 1 + .../2022-01-09-17-57-53.bpo-46309.BaLgD1.rst | 2 ++ 4 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2022-01-09-17-57-53.bpo-46309.BaLgD1.rst diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index 080d8a62cde1e2..d1226297fda27e 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -206,6 +206,7 @@ def __init__(self, stream_reader, client_connected_cb=None, loop=None): self._strong_reader = stream_reader self._reject_connection = False self._stream_writer = None + self._task = None self._transport = None self._client_connected_cb = client_connected_cb self._over_ssl = False @@ -241,7 +242,7 @@ def connection_made(self, transport): res = self._client_connected_cb(reader, self._stream_writer) if coroutines.iscoroutine(res): - self._loop.create_task(res) + self._task = self._loop.create_task(res) self._strong_reader = None def connection_lost(self, exc): diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index 227b2279e172c8..797865514e7baa 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -801,6 +801,25 @@ def test_streamreaderprotocol_constructor_use_global_loop(self): self.assertEqual(cm.warnings[0].filename, __file__) self.assertIs(protocol._loop, self.loop) + def test_streamreaderprotocol_task_reference(self): + # See http://bugs.python.org/issue46309 + messages = [] + self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx)) + + async def callback(*args): + await self.loop.create_future() + + async def test(): + reader = asyncio.StreamReader() + protocol = asyncio.StreamReaderProtocol(reader, callback) + transport = mock.Mock() + protocol.connection_made(transport) + await asyncio.sleep(0) + gc.collect() + + self.loop.run_until_complete(test()) + self.assertEqual(messages, []) + def test_drain_raises(self): # See http://bugs.python.org/issue25441 diff --git a/Misc/ACKS b/Misc/ACKS index 7f2e94dfa615f1..006efe1f8a5438 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1958,6 +1958,7 @@ Gordon Worley Darren Worrall Thomas Wouters Daniel Wozniak +Simon Wrede Marcin Niemira Wei Wu Heiko Wundram diff --git a/Misc/NEWS.d/next/Library/2022-01-09-17-57-53.bpo-46309.BaLgD1.rst b/Misc/NEWS.d/next/Library/2022-01-09-17-57-53.bpo-46309.BaLgD1.rst new file mode 100644 index 00000000000000..b22a2c91144066 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-01-09-17-57-53.bpo-46309.BaLgD1.rst @@ -0,0 +1,2 @@ +Added reference to task created in +:meth:`asyncio.streams.StreamReaderProtocol.connection_made`. From 11cc7894140613d39880183c52ec02829daeca29 Mon Sep 17 00:00:00 2001 From: Simon Wrede Date: Mon, 10 Jan 2022 20:25:04 +0100 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: Bar Harel --- Lib/asyncio/streams.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index d1226297fda27e..186e1436ca5035 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -206,7 +206,7 @@ def __init__(self, stream_reader, client_connected_cb=None, loop=None): self._strong_reader = stream_reader self._reject_connection = False self._stream_writer = None - self._task = None + self._connection_tasks = set() self._transport = None self._client_connected_cb = client_connected_cb self._over_ssl = False @@ -242,7 +242,9 @@ def connection_made(self, transport): res = self._client_connected_cb(reader, self._stream_writer) if coroutines.iscoroutine(res): - self._task = self._loop.create_task(res) + task = self._loop.create_task(res) + task.add_done_callback(self._connection_tasks.remove) + self._connection_tasks.add(task) self._strong_reader = None def connection_lost(self, exc): From 2a27d0c531344abf29bcaa10a3ac1a09495c1e1a Mon Sep 17 00:00:00 2001 From: Simon Wrede Date: Sat, 27 Aug 2022 10:25:27 +0200 Subject: [PATCH 3/3] Remove test and use single task reference instead of set --- Lib/asyncio/streams.py | 6 ++---- Lib/test/test_asyncio/test_streams.py | 19 ------------------- 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index 5f31cdb9cdf74d..c1d02ad9c1ac60 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -205,7 +205,7 @@ def __init__(self, stream_reader, client_connected_cb=None, loop=None): self._strong_reader = stream_reader self._reject_connection = False self._stream_writer = None - self._connection_tasks = set() + self._task = None self._transport = None self._client_connected_cb = client_connected_cb self._over_ssl = False @@ -248,9 +248,7 @@ def connection_made(self, transport): res = self._client_connected_cb(reader, self._stream_writer) if coroutines.iscoroutine(res): - task = self._loop.create_task(res) - task.add_done_callback(self._connection_tasks.remove) - self._connection_tasks.add(task) + self._task = self._loop.create_task(res) self._strong_reader = None def connection_lost(self, exc): diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index 97143dca08f4e5..098a0da344d0fb 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -864,25 +864,6 @@ def test_streamreaderprotocol_constructor_use_global_loop(self): self.assertEqual(cm.filename, __file__) self.assertIs(protocol._loop, self.loop) - def test_streamreaderprotocol_task_reference(self): - # See http://bugs.python.org/issue46309 - messages = [] - self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx)) - - async def callback(*args): - await self.loop.create_future() - - async def test(): - reader = asyncio.StreamReader() - protocol = asyncio.StreamReaderProtocol(reader, callback) - transport = mock.Mock() - protocol.connection_made(transport) - await asyncio.sleep(0) - gc.collect() - - self.loop.run_until_complete(test()) - self.assertEqual(messages, []) - def test_drain_raises(self): # See http://bugs.python.org/issue25441