diff options
| author | AAGaming <aagaming@riseup.net> | 2024-07-04 01:27:13 -0400 |
|---|---|---|
| committer | AAGaming <aagaming@riseup.net> | 2024-07-04 01:27:13 -0400 |
| commit | a45df8566ed207d126e5992bb7c870acd09a1864 (patch) | |
| tree | 52f63323244cd72ec9cd774144e131e4ed05fb51 /backend | |
| parent | 2b2a1d9e39addd03c357a1ba08f6241b980a2759 (diff) | |
| download | decky-loader-a45df8566ed207d126e5992bb7c870acd09a1864.tar.gz decky-loader-a45df8566ed207d126e5992bb7c870acd09a1864.zip | |
fix plugin uninstalls
Diffstat (limited to 'backend')
| -rw-r--r-- | backend/decky_loader/browser.py | 5 | ||||
| -rw-r--r-- | backend/decky_loader/localplatform/localsocket.py | 2 | ||||
| -rw-r--r-- | backend/decky_loader/plugin/plugin.py | 6 | ||||
| -rw-r--r-- | backend/decky_loader/plugin/sandboxed_plugin.py | 27 | ||||
| -rw-r--r-- | backend/decky_loader/wsrouter.py | 6 |
5 files changed, 32 insertions, 14 deletions
diff --git a/backend/decky_loader/browser.py b/backend/decky_loader/browser.py index 28a591a0..af23ed0c 100644 --- a/backend/decky_loader/browser.py +++ b/backend/decky_loader/browser.py @@ -147,8 +147,9 @@ class PluginBrowser: except Exception as e: logger.error(f"Plugin {name} in {plugin_dir} was not uninstalled") logger.error(f"Error at {str(e)}", exc_info=e) - if self.loader.watcher: - self.loader.watcher.disabled = False + finally: + if self.loader.watcher: + self.loader.watcher.disabled = False async def _install(self, artifact: str, name: str, version: str, hash: str): await self.loader.ws.emit("loader/plugin_download_start", name) diff --git a/backend/decky_loader/localplatform/localsocket.py b/backend/decky_loader/localplatform/localsocket.py index 96dbbab6..c0b4faa1 100644 --- a/backend/decky_loader/localplatform/localsocket.py +++ b/backend/decky_loader/localplatform/localsocket.py @@ -88,6 +88,8 @@ class UnixSocket: except asyncio.IncompleteReadError as err: line.extend(err.partial) break + except asyncio.CancelledError: + break else: break diff --git a/backend/decky_loader/plugin/plugin.py b/backend/decky_loader/plugin/plugin.py index f4b01ad3..a9a9ce29 100644 --- a/backend/decky_loader/plugin/plugin.py +++ b/backend/decky_loader/plugin/plugin.py @@ -109,7 +109,7 @@ class PluginWrapper: def start(self): if self.passive: return self - self.proc = Process(target=self.sandboxed_plugin.initialize, args=[self._socket], daemon=True) + self.proc = Process(target=self.sandboxed_plugin.initialize, args=[self._socket]) self.proc.start() self._listener_task = create_task(self._response_listener()) return self @@ -121,9 +121,11 @@ class PluginWrapper: if hasattr(self, "_socket"): await self._socket.write_single_line(dumps({ "stop": True, "uninstall": uninstall }, ensure_ascii=False)) await self._socket.close_socket_connection() + if self.proc: + self.proc.join() + await self.kill_if_still_running() if hasattr(self, "_listener_task"): self._listener_task.cancel() - await self.kill_if_still_running() async def kill_if_still_running(self): time = 0 diff --git a/backend/decky_loader/plugin/sandboxed_plugin.py b/backend/decky_loader/plugin/sandboxed_plugin.py index 07b04e7d..32330a9a 100644 --- a/backend/decky_loader/plugin/sandboxed_plugin.py +++ b/backend/decky_loader/plugin/sandboxed_plugin.py @@ -1,12 +1,12 @@ from os import path, environ -from signal import SIG_IGN, SIGINT, SIGTERM, signal +from signal import SIG_IGN, SIGINT, SIGTERM, getsignal, signal from importlib.util import module_from_spec, spec_from_file_location from json import dumps, loads from logging import getLogger from sys import exit, path as syspath, modules as sysmodules from traceback import format_exc from asyncio import (get_event_loop, new_event_loop, - set_event_loop, sleep) + set_event_loop) from setproctitle import setproctitle, setthreadtitle from .messages import SocketResponseDict, SocketMessageType @@ -19,6 +19,8 @@ from typing import List, TypeVar, Any DataType = TypeVar("DataType") +original_term_handler = getsignal(SIGTERM) + class SandboxedPlugin: def __init__(self, name: str, @@ -46,6 +48,8 @@ class SandboxedPlugin: self._socket = socket try: + # Ignore signals meant for parent Process + # TODO SURELY there's a better way to do this. signal(SIGINT, SIG_IGN) signal(SIGTERM, SIG_IGN) @@ -120,7 +124,14 @@ class SandboxedPlugin: except: self.log.error("Failed to start " + self.name + "!\n" + format_exc()) exit(0) - get_event_loop().run_forever() + try: + get_event_loop().run_forever() + except SystemExit: + pass + except: + self.log.error("Loop exited for " + self.name + "!\n" + format_exc()) + finally: + get_event_loop().close() async def _unload(self): try: @@ -156,6 +167,8 @@ class SandboxedPlugin: data = loads(message) if "stop" in data: + # Incase the loader needs to terminate our process soon + signal(SIGTERM, original_term_handler) self.log.info(f"Calling Loader unload function for {self.name}.") await self._unload() @@ -163,10 +176,10 @@ class SandboxedPlugin: self.log.info("Calling Loader uninstall function.") await self._uninstall() - get_event_loop().stop() - while get_event_loop().is_running(): - await sleep(0.1) - get_event_loop().close() + self.log.debug("Stopping event loop") + + loop = get_event_loop() + loop.call_soon_threadsafe(loop.stop) exit(0) d: SocketResponseDict = {"type": SocketMessageType.RESPONSE, "res": None, "success": True, "id": data["id"]} diff --git a/backend/decky_loader/wsrouter.py b/backend/decky_loader/wsrouter.py index b513723f..8d20a24d 100644 --- a/backend/decky_loader/wsrouter.py +++ b/backend/decky_loader/wsrouter.py @@ -1,6 +1,6 @@ from logging import getLogger -from asyncio import AbstractEventLoop, create_task +from asyncio import AbstractEventLoop from aiohttp import WSCloseCode, WSMsgType, WSMessage from aiohttp.web import Application, WebSocketResponse, Request, Response, get @@ -114,10 +114,10 @@ class WSRouter: # do stuff with the message if data["route"] in self.routes: self.logger.debug(f'Started PY call {data["route"]} ID {data["id"]}') - create_task(self._call_route(data["route"], data["args"], data["id"])) + self.loop.create_task(self._call_route(data["route"], data["args"], data["id"])) else: error = {"error":f'Route {data["route"]} does not exist.', "name": "RouteNotFoundError", "traceback": None} - create_task(self.write({"type": MessageType.ERROR.value, "id": data["id"], "error": error})) + self.loop.create_task(self.write({"type": MessageType.ERROR.value, "id": data["id"], "error": error})) case _: self.logger.error("Unknown message type", data) finally: |
