Skip to content

asyncio.start_server() leaves the transport open when a synchronous client callback raises #155928

Description

@yangbaechu

Bug report

Bug description:

When a synchronous client_connected_cb passed to asyncio.start_server() raises, the exception is reported by the event loop, but the server-side transport remains open.

import asyncio


async def main():
    loop = asyncio.get_running_loop()
    errors = []
    loop.set_exception_handler(lambda _, ctx: errors.append(ctx))

    connected = loop.create_future()

    def callback(reader, writer):
        connected.set_result(writer.transport)
        raise RuntimeError("boom")

    server = await asyncio.start_server(callback, "127.0.0.1", 0)
    _, client = await asyncio.open_connection(
        *server.sockets[0].getsockname()
    )

    transport = await connected
    print(len(errors), transport.is_closing())  # 1 False

    transport.close()
    client.close()
    server.close()
    await server.wait_closed()


asyncio.run(main())

The exception is reported once, but transport.is_closing() remains False.

Coroutine callbacks already close the transport when their task fails. The synchronous path should provide the same cleanup while preserving the existing exception reporting through Handle._run().

Related: #110894 and PR #111601.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytopic-asynciotype-bugAn unexpected behavior, bug, or error

    Projects

    • Status
      Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions