From 0869a2acc3a9bc7b15fbb847a11a040b98b87bff Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Sun, 12 Jun 2022 03:20:03 +0200 Subject: [PATCH] SNIClient: prevent hang on exit if waiting on devices from SNI --- SNIClient.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/SNIClient.py b/SNIClient.py index 009838db..32a0da4b 100644 --- a/SNIClient.py +++ b/SNIClient.py @@ -78,7 +78,10 @@ class SNIClientCommandProcessor(ClientCommandProcessor): snes_device_number = int(options[1]) self.ctx.snes_reconnect_address = None - asyncio.create_task(snes_connect(self.ctx, snes_address, snes_device_number), name="SNES Connect") + if self.ctx.snes_connect_task: + self.ctx.snes_connect_task.cancel() + self.ctx.snes_connect_task = asyncio.create_task(snes_connect(self.ctx, snes_address, snes_device_number), + name="SNES Connect") return True def _cmd_snes_close(self) -> bool: @@ -115,6 +118,7 @@ class Context(CommonContext): command_processor = SNIClientCommandProcessor game = "A Link to the Past" items_handling = None # set in game_watcher + snes_connect_task: typing.Optional[asyncio.Task] = None def __init__(self, snes_address, server_address, password): super(Context, self).__init__(server_address, password) @@ -181,6 +185,11 @@ class Context(CommonContext): if not currently_dead: self.death_state = DeathState.alive + async def shutdown(self): + await super(Context, self).shutdown() + if self.snes_connect_task: + await self.snes_connect_task + def on_package(self, cmd: str, args: dict): if cmd in {"Connected", "RoomUpdate"}: if "checked_locations" in args and args["checked_locations"]: @@ -653,17 +662,18 @@ async def get_snes_devices(ctx: Context) -> typing.List[str]: } await socket.send(dumps(DeviceList_Request)) - reply = loads(await socket.recv()) - devices = reply['Results'] if 'Results' in reply and len(reply['Results']) > 0 else None + reply: dict = loads(await socket.recv()) + devices: typing.List[str] = reply['Results'] if 'Results' in reply and len(reply['Results']) > 0 else [] if not devices: snes_logger.info('No SNES device found. Please connect a SNES device to SNI.') - while not devices: - await asyncio.sleep(1) + while not devices and not ctx.exit_event.is_set(): + await asyncio.sleep(0.1) await socket.send(dumps(DeviceList_Request)) reply = loads(await socket.recv()) - devices = reply['Results'] if 'Results' in reply and len(reply['Results']) > 0 else None - await verify_snes_app(socket) + devices = reply['Results'] if 'Results' in reply and len(reply['Results']) > 0 else [] + if devices: + await verify_snes_app(socket) await socket.close() return sorted(devices) @@ -1319,7 +1329,7 @@ async def main(): ctx.run_gui() ctx.run_cli() - snes_connect_task = asyncio.create_task(snes_connect(ctx, ctx.snes_address), name="SNES Connect") + ctx.snes_connect_task = asyncio.create_task(snes_connect(ctx, ctx.snes_address), name="SNES Connect") watcher_task = asyncio.create_task(game_watcher(ctx), name="GameWatcher") await ctx.exit_event.wait() @@ -1328,15 +1338,12 @@ async def main(): ctx.snes_reconnect_address = None if ctx.snes_socket is not None and not ctx.snes_socket.closed: await ctx.snes_socket.close() - if snes_connect_task: - snes_connect_task.cancel() await watcher_task await ctx.shutdown() def get_alttp_settings(romfile: str): lastSettings = Utils.get_adjuster_settings(GAME_ALTTP) - adjusted = False adjustedromfile = '' if lastSettings: choice = 'no'