uvloop icon indicating copy to clipboard operation
uvloop copied to clipboard

Server.serve_forever() isn't cancelled when Server.close() is called

Open gurnec opened this issue 1 year ago • 0 comments

  • uvloop version: 0.19.0
  • Python version: 3.10.12 (3.10.12-1~22.04.3)
  • Platform: Ubuntu 22.04.4
  • Can you reproduce the bug with PYTHONASYNCIODEBUG in env?: Yes
  • Does uvloop behave differently from vanilla asyncio? How?: Yes, described below.

With stock asyncio, after awaiting on Server.serve_forever(), calling Server.close() causes the await statement to throw CancelledError. With uvloop's implementation, the listening socket is correctly closed, however the await statement blocks indefinitely.

Example:

async def run_server():
    async with await asyncio.start_server(lambda r,w: w.close(), '127.0.0.1', 8080) as server:
        server.get_loop().add_signal_handler(15, lambda: server.close())
        try:
            await server.serve_forever()
        except asyncio.CancelledError:
            print('Shutting down')

uvloop.run(run_server())

The uvloop version closes the listening socket in response to SIGTERM, but never exits. The stock version prints Shutting down and exits.

Here's the CPython source where this is implemented:

https://github.com/python/cpython/blob/v3.8.18/Lib/asyncio/base_events.py#L341-L344

Thanks for taking a look!

gurnec avatar Mar 14 '24 14:03 gurnec