From 147c9039630afd2bc6a73f1a04d5e6526947d90b Mon Sep 17 00:00:00 2001 From: Alessandro Astone Date: Fri, 11 Oct 2024 15:40:10 +0200 Subject: [PATCH] fix(src): Close connections to API clients when shutting down This effectively re-implements asyncio.Server::close_clients which is only available in python3.13. In python3.12 asyncio.Server::wait_closed will hang unless these sockets are closed: https://github.com/python/cpython/issues/104344 Co-authored-by: Steffen Christgau --- src/wsdd.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/wsdd.py b/src/wsdd.py index 44762af..a5e3a22 100755 --- a/src/wsdd.py +++ b/src/wsdd.py @@ -1125,10 +1125,12 @@ def do_POST(self) -> None: class ApiServer: address_monitor: 'NetworkAddressMonitor' + clients: List[asyncio.StreamWriter] def __init__(self, aio_loop: asyncio.AbstractEventLoop, listen_address: bytes, address_monitor: 'NetworkAddressMonitor') -> None: self.server = None + self.clients = [] self.address_monitor = address_monitor # defer server creation @@ -1148,6 +1150,7 @@ async def create_server(self, aio_loop: asyncio.AbstractEventLoop, listen_addres self.on_connect, path=listen_address)) async def on_connect(self, read_stream: asyncio.StreamReader, write_stream: asyncio.StreamWriter) -> None: + self.clients.append(write_stream) while True: try: line = await read_stream.readline() @@ -1156,12 +1159,14 @@ async def on_connect(self, read_stream: asyncio.StreamReader, write_stream: asyn if not write_stream.is_closing(): await write_stream.drain() else: + self.clients.remove(write_stream) write_stream.close() return except UnicodeDecodeError as e: logger.debug('invalid input utf8', e) except Exception as e: logger.warning('exception in API client', e) + self.clients.remove(write_stream) write_stream.close() return @@ -1221,6 +1226,8 @@ async def cleanup(self) -> None: await self.create_task if self.server: self.server.close() + for client in self.clients: + client.close() await self.server.wait_closed()