https://github.com/python/cpython/commit/374920a23d49130f446fe6369220bc548be57cd2
commit: 374920a23d49130f446fe6369220bc548be57cd2
branch: main
author: Timofei <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2026-07-08T00:53:17+05:30
summary:
gh-153133: Fix socket leak in error path of asyncio create_connection (#153134)
files:
A Misc/NEWS.d/next/Library/2026-07-05-17-39-16.gh-issue-153133.kKSH7g.rst
M Lib/asyncio/base_events.py
M Lib/test/test_asyncio/test_base_events.py
diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py
index 93bd7df993d8270..3836aaad326f62e 100644
--- a/Lib/asyncio/base_events.py
+++ b/Lib/asyncio/base_events.py
@@ -1219,21 +1219,26 @@ async def _create_connection_transport(
ssl_handshake_timeout=None,
ssl_shutdown_timeout=None, context=None):
- sock.setblocking(False)
- context = context if context is not None else
contextvars.copy_context()
-
- protocol = protocol_factory()
- waiter = self.create_future()
- if ssl:
- sslcontext = None if isinstance(ssl, bool) else ssl
- transport = self._make_ssl_transport(
- sock, protocol, sslcontext, waiter,
- server_side=server_side, server_hostname=server_hostname,
- ssl_handshake_timeout=ssl_handshake_timeout,
- ssl_shutdown_timeout=ssl_shutdown_timeout,
- context=context)
- else:
- transport = self._make_socket_transport(sock, protocol, waiter,
context=context)
+ try:
+ sock.setblocking(False)
+ context = context if context is not None else
contextvars.copy_context()
+
+ protocol = protocol_factory()
+ waiter = self.create_future()
+ if ssl:
+ sslcontext = None if isinstance(ssl, bool) else ssl
+ transport = self._make_ssl_transport(
+ sock, protocol, sslcontext, waiter,
+ server_side=server_side, server_hostname=server_hostname,
+ ssl_handshake_timeout=ssl_handshake_timeout,
+ ssl_shutdown_timeout=ssl_shutdown_timeout,
+ context=context)
+ else:
+ transport = self._make_socket_transport(sock, protocol,
waiter, context=context)
+ except:
+ # gh-153133: close the socket if the transport is never created.
+ sock.close()
+ raise
try:
await waiter
diff --git a/Lib/test/test_asyncio/test_base_events.py
b/Lib/test/test_asyncio/test_base_events.py
index fa3821e0783858c..b4fd7abed5963ea 100644
--- a/Lib/test/test_asyncio/test_base_events.py
+++ b/Lib/test/test_asyncio/test_base_events.py
@@ -1282,6 +1282,47 @@ def getaddrinfo(*args, **kw):
self.loop.run_until_complete(coro)
self.assertTrue(sock.close.called)
+ def test_create_connection_sock_transport_error_closes_sock(self):
+ # gh-153133: a user-provided socket is closed if the transport is
+ # never created.
+ sock = mock.Mock()
+ sock.type = socket.SOCK_STREAM
+
+ def factory():
+ raise ZeroDivisionError
+
+ coro = self.loop.create_connection(factory, sock=sock)
+ with self.assertRaises(ZeroDivisionError):
+ self.loop.run_until_complete(coro)
+ self.assertTrue(sock.close.called)
+
+ @patch_socket
+ def test_create_connection_transport_error_closes_sock(self, m_socket):
+ # gh-153133: an internally created socket is closed if the transport
+ # is never created.
+ sock = mock.Mock()
+ m_socket.socket.return_value = sock
+
+ def getaddrinfo(*args, **kw):
+ fut = self.loop.create_future()
+ addr = (socket.AF_INET, socket.SOCK_STREAM, 0, '',
+ ('127.0.0.1', 80))
+ fut.set_result([addr])
+ return fut
+ self.loop.getaddrinfo = getaddrinfo
+
+ async def sock_connect(sock, address):
+ return None
+
+ def factory():
+ raise ZeroDivisionError
+
+ with mock.patch.object(self.loop, 'sock_connect', sock_connect):
+ coro = self.loop.create_connection(factory, '127.0.0.1', 80)
+ with self.assertRaises(ZeroDivisionError):
+ self.loop.run_until_complete(coro)
+ self.assertTrue(sock.close.called)
+
@patch_socket
def test_create_connection_happy_eyeballs_empty_exceptions(self, m_socket):
# See gh-135836: Fix IndexError when Happy Eyeballs algorithm
diff --git
a/Misc/NEWS.d/next/Library/2026-07-05-17-39-16.gh-issue-153133.kKSH7g.rst
b/Misc/NEWS.d/next/Library/2026-07-05-17-39-16.gh-issue-153133.kKSH7g.rst
new file mode 100644
index 000000000000000..a7a68158ac895e3
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-07-05-17-39-16.gh-issue-153133.kKSH7g.rst
@@ -0,0 +1,2 @@
+Fix a socket leak in :meth:`asyncio.loop.create_connection` when the
+transport cannot be created.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]