Repository navigation
Closed
Closed
Copy link
Labels
stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-asynciotype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Description
Bug report
Bug description:
Bug description
BaseEventLoop._create_connection_transport() closes the socket only if await waiter fails:
try:
await waiter
except:
transport.close()
raiseIf sock.setblocking(), protocol_factory() or _make_*_transport() raises before the transport exists, the socket is never closed
Reproducer
import asyncio
import socket
async def main():
loop = asyncio.get_running_loop()
sock = socket.socket()
try:
await loop.create_connection(lambda: 1 / 0, sock=sock)
except ZeroDivisionError:
pass
print("leak: socket not closed" if sock.fileno() != -1 else "ok: closed")
sock.close()
asyncio.run(main())Expected: ok: closed but actually: leak: socket not closed
Proposed fix
Close the socket on error when the transport hasn't been created yet:
async def _create_connection_transport(
self, sock, protocol_factory, ssl,
server_hostname, server_side=False,
ssl_handshake_timeout=None,
ssl_shutdown_timeout=None, context=None):
transport = None
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)
await waiter
except:
if transport is None:
sock.close()
else:
transport.close()
raise
return transport, protocolI have a fix ready
CPython versions tested on:
CPython main branch
Operating systems tested on:
macOS
Linked PRs
Metadata
Metadata
Assignees
Labels
stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-asynciotype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Projects
- StatusShow more project fieldsDone
Activity
kumaraditya303 commentedon Jul 7, 2026
It is not really a leak because the GC would close the socket anyways if there are no refs from the transport.
deadlovelll commentedon Jul 7, 2026
hello! i dont fully agree with this, yes - gc can close it, but OTOH we can't rely on non-deterministic behavior.
In this case the raising exception keeps the socket alive by holding a ref, so it isn't promptly unreferenced
I got a little repro
if we run this we get:
Documentation also recommends to close sockets explicitly
kumaraditya303 commentedon Jul 7, 2026
Well, in practice all real world usage rely on GC to clear stuff, anyways I'll accept your change.
gh-153133: Fix socket leak in error path of asyncio create_connection (…
deadlovelll commentedon Jul 7, 2026
Thanks!
[3.15] gh-153133: Fix socket leak in error path of asyncio create_con…
[3.14] gh-153133: Fix socket leak in error path of asyncio create_con…