Skip to content

asyncio leaks the socket/pipe in create_datagram_endpoint and connect_read_pipe/connect_write_pipe when transport creation fails #156400

Description

@tonghuaroot

Bug report

Bug description:

BaseEventLoop.create_datagram_endpoint(), connect_read_pipe() and connect_write_pipe() create or take ownership of a socket/pipe and then run protocol_factory() and transport creation. The only cleanup on those methods (except: transport.close()) covers the later await waiter step, by which point the transport already owns the resource. If protocol_factory() or _make_*_transport() raises, the socket or pipe is never closed and leaks until garbage collection.

This is the same problem gh-153133 fixed for create_connection(); these three loop methods were not covered.

Reproducer:

import asyncio, warnings

async def main():
    loop = asyncio.get_running_loop()
    try:
        await loop.create_datagram_endpoint(lambda: 1 / 0,
                                             local_addr=('127.0.0.1', 0))
    except ZeroDivisionError:
        pass

warnings.simplefilter('error', ResourceWarning)
asyncio.run(main())   # ResourceWarning: unclosed <socket.socket ...>

connect_read_pipe() / connect_write_pipe() leak the pipe the same way when protocol_factory() raises.

CPython versions tested on:

CPython main

Operating systems tested on:

Linux, macOS

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytopic-asyncio

    Projects

    Status
    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions