deadlovelll · GitHub

Bug report

Bug description:

Bug description

BaseEventLoop._create_connection_transport() closes the socket only if await waiter fails:

try:
    await waiter
except:
    transport.close()
    raise

If 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, protocol

I have a fix ready

CPython versions tested on:

CPython main branch

Operating systems tested on:

macOS

Linked PRs

Read the original on github.com ↗