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
Bug report
Bug description:
When a synchronous
client_connected_cbpassed toasyncio.start_server()raises, the exception is reported by the event loop, but the server-side transport remains open.The exception is reported once, but
transport.is_closing()remainsFalse.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