From f14237c6a7369b349a32b81ec6a48c0b609046e3 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Thu, 22 Oct 2026 11:49:32 +0530 Subject: [PATCH] gh-159123: fix ResourceWarning flake in asyncio SSL handshake failure tests test_create_server_ssl_verify_failed, test_create_unix_server_ssl_verify_failed and test_create_server_ssl_match_failed stopped the loop as soon as the client handshake failed and then only called Server.close(), which closes the listening sockets but not the accepted server-side transport. If the TLS alert/EOF from the client reached the server socket in the last loop iteration, the transport's _call_connection_lost callback stayed queued when the loop was closed, leaving the socket open and emitting "unclosed transport <_SelectorSocketTransport closing fd=N>". Run the loop until Server.wait_closed() completes so the server-side transport of the failed handshake is closed before the loop is. --- Lib/test/test_asyncio/test_events.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index c59bc64e37df965..58556cc87409f7f 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1202,12 +1202,13 @@ def test_create_server_ssl_verify_failed(self): '(?i)certificate.verify.failed'): self.loop.run_until_complete(f_c) - # execute the loop to log the connection error - test_utils.run_briefly(self.loop) + # close connection: wait until the server-side transport of the + # failed handshake is closed as well, otherwise its socket may + # still be open when the loop is closed (gh-159123). + server.close() + self.loop.run_until_complete(server.wait_closed()) - # close connection self.assertIsNone(proto.transport) - server.close() @socket_helper.skip_unless_bind_unix_socket @unittest.skipIf(ssl is None, 'No ssl module') @@ -1232,12 +1233,13 @@ def test_create_unix_server_ssl_verify_failed(self): '(?i)certificate.verify.failed'): self.loop.run_until_complete(f_c) - # execute the loop to log the connection error - test_utils.run_briefly(self.loop) + # close connection: wait until the server-side transport of the + # failed handshake is closed as well, otherwise its socket may + # still be open when the loop is closed (gh-159123). + server.close() + self.loop.run_until_complete(server.wait_closed()) - # close connection self.assertIsNone(proto.transport) - server.close() @unittest.skipIf(ssl is None, 'No ssl module') def test_create_server_ssl_match_failed(self): @@ -1268,10 +1270,14 @@ def test_create_server_ssl_match_failed(self): with self.assertRaisesRegex(ssl.CertificateError, regex): self.loop.run_until_complete(f_c) - # close connection + # close connection: wait until the server-side transport of the + # failed handshake is closed as well, otherwise its socket may + # still be open when the loop is closed (gh-159123). + server.close() + self.loop.run_until_complete(server.wait_closed()) + # transport is None because TLS ALERT aborted the handshake self.assertIsNone(proto.transport) - server.close() @socket_helper.skip_unless_bind_unix_socket @unittest.skipIf(ssl is None, 'No ssl module')