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
Bug report
Bug description:
BaseEventLoop.create_datagram_endpoint(),connect_read_pipe()andconnect_write_pipe()create or take ownership of a socket/pipe and then runprotocol_factory()and transport creation. The only cleanup on those methods (except: transport.close()) covers the laterawait waiterstep, by which point the transport already owns the resource. Ifprotocol_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:
connect_read_pipe()/connect_write_pipe()leak the pipe the same way whenprotocol_factory()raises.CPython versions tested on:
CPython main
Operating systems tested on:
Linux, macOS
Linked PRs