summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Ossman (ThinLinc team) <ossman@cendio.se>2024-02-28 01:27:44 (GMT)
committerGitHub <noreply@github.com>2024-02-28 01:27:44 (GMT)
commita355f60b032306651ca27bc53bbb82eb5106ff71 (patch)
tree5d5b332d9ef8ce85501bdf350f06f9d7298388ac
parent686ec17f506cddd0b14a8aad5849c15ffc20ed46 (diff)
downloadcpython-a355f60b032306651ca27bc53bbb82eb5106ff71.zip
cpython-a355f60b032306651ca27bc53bbb82eb5106ff71.tar.gz
cpython-a355f60b032306651ca27bc53bbb82eb5106ff71.tar.bz2
gh-114914: Avoid keeping dead StreamWriter alive (#115661)
In some cases we might cause a StreamWriter to stay alive even when the application has dropped all references to it. This prevents us from doing automatical cleanup, and complaining that the StreamWriter wasn't properly closed. Fortunately, the extra reference was never actually used for anything so we can just drop it.
-rw-r--r--Lib/asyncio/streams.py14
-rw-r--r--Lib/test/test_asyncio/test_streams.py25
-rw-r--r--Misc/NEWS.d/next/Library/2024-02-19-15-52-30.gh-issue-114914.M5-1d8.rst2
3 files changed, 31 insertions, 10 deletions
diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py
index df58b7a..3fe52db 100644
--- a/Lib/asyncio/streams.py
+++ b/Lib/asyncio/streams.py
@@ -201,7 +201,6 @@ class StreamReaderProtocol(FlowControlMixin, protocols.Protocol):
# is established.
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
@@ -214,10 +213,8 @@ class StreamReaderProtocol(FlowControlMixin, protocols.Protocol):
return None
return self._stream_reader_wr()
- def _replace_writer(self, writer):
+ def _replace_transport(self, transport):
loop = self._loop
- transport = writer.transport
- self._stream_writer = writer
self._transport = transport
self._over_ssl = transport.get_extra_info('sslcontext') is not None
@@ -239,11 +236,8 @@ class StreamReaderProtocol(FlowControlMixin, protocols.Protocol):
reader.set_transport(transport)
self._over_ssl = transport.get_extra_info('sslcontext') is not None
if self._client_connected_cb is not None:
- self._stream_writer = StreamWriter(transport, self,
- reader,
- self._loop)
- res = self._client_connected_cb(reader,
- self._stream_writer)
+ writer = StreamWriter(transport, self, reader, self._loop)
+ res = self._client_connected_cb(reader, writer)
if coroutines.iscoroutine(res):
def callback(task):
if task.cancelled():
@@ -405,7 +399,7 @@ class StreamWriter:
ssl_handshake_timeout=ssl_handshake_timeout,
ssl_shutdown_timeout=ssl_shutdown_timeout)
self._transport = new_transport
- protocol._replace_writer(self)
+ protocol._replace_transport(new_transport)
def __del__(self, warnings=warnings):
if not self._transport.is_closing():
diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py
index 2109905..bf123eb 100644
--- a/Lib/test/test_asyncio/test_streams.py
+++ b/Lib/test/test_asyncio/test_streams.py
@@ -1130,6 +1130,31 @@ os.close(fd)
self.assertEqual(messages, [])
+ def test_unclosed_server_resource_warnings(self):
+ async def inner(rd, wr):
+ fut.set_result(True)
+ with self.assertWarns(ResourceWarning) as cm:
+ del wr
+ gc.collect()
+ self.assertEqual(len(cm.warnings), 1)
+ self.assertTrue(str(cm.warnings[0].message).startswith("unclosed <StreamWriter"))
+
+ async def outer():
+ srv = await asyncio.start_server(inner, socket_helper.HOSTv4, 0)
+ async with srv:
+ addr = srv.sockets[0].getsockname()
+ with socket.create_connection(addr):
+ # Give the loop some time to notice the connection
+ await fut
+
+ messages = []
+ self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx))
+
+ fut = self.loop.create_future()
+ self.loop.run_until_complete(outer())
+
+ self.assertEqual(messages, [])
+
def _basetest_unhandled_exceptions(self, handle_echo):
port = socket_helper.find_unused_port()
diff --git a/Misc/NEWS.d/next/Library/2024-02-19-15-52-30.gh-issue-114914.M5-1d8.rst b/Misc/NEWS.d/next/Library/2024-02-19-15-52-30.gh-issue-114914.M5-1d8.rst
new file mode 100644
index 0000000..f7d392c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-02-19-15-52-30.gh-issue-114914.M5-1d8.rst
@@ -0,0 +1,2 @@
+Fix an issue where an abandoned :class:`StreamWriter` would not be garbage
+collected.