diff options
| author | AAGaming <aagaming@riseup.net> | 2024-08-07 16:14:18 -0400 |
|---|---|---|
| committer | AAGaming <aagaming@riseup.net> | 2024-08-07 16:14:18 -0400 |
| commit | 65b6883dcc42944607eb0efa1f28e41f57335313 (patch) | |
| tree | 38db3185d6720552daa978149279928d271df19a /backend | |
| parent | 166c7ea8a7ea74d9a61d84ebe16556cec9e7cc83 (diff) | |
| download | decky-loader-65b6883dcc42944607eb0efa1f28e41f57335313.tar.gz decky-loader-65b6883dcc42944607eb0efa1f28e41f57335313.zip | |
handle crashloops and disable decky for the user
Diffstat (limited to 'backend')
| -rw-r--r-- | backend/decky_loader/helpers.py | 3 | ||||
| -rw-r--r-- | backend/decky_loader/main.py | 29 | ||||
| -rw-r--r-- | backend/decky_loader/utilities.py | 6 |
3 files changed, 35 insertions, 3 deletions
diff --git a/backend/decky_loader/helpers.py b/backend/decky_loader/helpers.py index 2e0fe45f..8ca77632 100644 --- a/backend/decky_loader/helpers.py +++ b/backend/decky_loader/helpers.py @@ -52,6 +52,9 @@ async def csrf_middleware(request: Request, handler: Handler): return await handler(request) return Response(text='Forbidden', status=403) +def create_inject_script(script: str) -> str: + return "try{if (window.deckyHasLoaded){setTimeout(() => SteamClient.Browser.RestartJSContext(), 100)}else{window.deckyHasLoaded = true;(async()=>{try{await import('http://localhost:1337/frontend/%s?v=%s')}catch(e){console.error(e)};})();}}catch(e){console.error(e)}" % (script, get_loader_version(), ) + # Get the default homebrew path unless a home_path is specified. home_path argument is deprecated def get_homebrew_path() -> str: return localplatform.get_unprivileged_path() diff --git a/backend/decky_loader/main.py b/backend/decky_loader/main.py index 5033126e..c268b387 100644 --- a/backend/decky_loader/main.py +++ b/backend/decky_loader/main.py @@ -15,6 +15,7 @@ from asyncio import AbstractEventLoop, CancelledError, Task, all_tasks, current_ from logging import basicConfig, getLogger from os import path from traceback import format_exc +from time import time import aiohttp_cors # pyright: ignore [reportMissingTypeStubs] # Partial imports @@ -25,7 +26,7 @@ from setproctitle import getproctitle, setproctitle, setthreadtitle # local modules from .browser import PluginBrowser -from .helpers import (REMOTE_DEBUGGER_UNIT, csrf_middleware, get_csrf_token, get_loader_version, +from .helpers import (REMOTE_DEBUGGER_UNIT, create_inject_script, csrf_middleware, get_csrf_token, get_loader_version, mkdir_as_user, get_system_pythonpaths, get_effective_user_id) from .injector import get_gamepadui_tab, Tab @@ -75,6 +76,9 @@ class PluginManager: self.plugin_browser = PluginBrowser(plugin_path, self.plugin_loader.plugins, self.plugin_loader, self.settings) self.utilities = Utilities(self) self.updater = Updater(self) + self.last_webhelper_exit: float = 0 + self.webhelper_crash_count: int = 0 + self.inject_fallback: bool = False jinja_setup(self.web_app) @@ -96,6 +100,21 @@ class PluginManager: self.cors.add(route) # pyright: ignore [reportUnknownMemberType] self.web_app.add_routes([static("/static", path.join(path.dirname(__file__), 'static'))]) + async def handle_crash(self): + new_time = time() + if (new_time - self.last_webhelper_exit < 60): + self.webhelper_crash_count += 1 + logger.warn(f"webhelper crashed within a minute from last crash! crash count: {self.webhelper_crash_count}") + else: + self.webhelper_crash_count = 0 + self.last_webhelper_exit = new_time + + # should never happen + if (self.webhelper_crash_count > 4): + await self.updater.do_shutdown() + # Give up + exit(0) + async def shutdown(self, _: Application): try: logger.info(f"Shutting down...") @@ -187,6 +206,7 @@ class PluginManager: # If this is a forceful disconnect the loop will just stop without any failure message. In this case, injector.py will handle this for us so we don't need to close the socket. # This is because of https://github.com/aio-libs/aiohttp/blob/3ee7091b40a1bc58a8d7846e7878a77640e96996/aiohttp/client_ws.py#L321 logger.info("CEF has disconnected...") + await self.handle_crash() # At this point the loop starts again and we connect to the freshly started Steam client once it is ready. except Exception: if not self.reinject: @@ -194,6 +214,7 @@ class PluginManager: logger.error("Exception while reading page events " + format_exc()) await tab.close_websocket() self.js_ctx_tab = None + await self.handle_crash() pass # while True: # await sleep(5) @@ -211,7 +232,11 @@ class PluginManager: await restart_webhelper() await sleep(1) # To give CEF enough time to close down the websocket return # We'll catch the next tab in the main loop - await tab.evaluate_js("try{if (window.deckyHasLoaded){setTimeout(() => SteamClient.Browser.RestartJSContext(), 100)}else{window.deckyHasLoaded = true;(async()=>{try{await import('http://localhost:1337/frontend/index.js?v=%s')}catch(e){console.error(e)};})();}}catch(e){console.error(e)}" % (get_loader_version(), ), False, False, False) + await tab.evaluate_js(create_inject_script("index.js" if self.webhelper_crash_count < 3 else "fallback.js"), False, False, False) + if self.webhelper_crash_count > 2: + self.reinject = False + await sleep(1) + await self.updater.do_shutdown() except: logger.info("Failed to inject JavaScript into tab\n" + format_exc()) pass diff --git a/backend/decky_loader/utilities.py b/backend/decky_loader/utilities.py index 17226ebc..4962da32 100644 --- a/backend/decky_loader/utilities.py +++ b/backend/decky_loader/utilities.py @@ -21,7 +21,7 @@ if TYPE_CHECKING: from .main import PluginManager from .injector import inject_to_tab, get_gamepadui_tab, close_old_tabs, get_tab from . import helpers -from .localplatform.localplatform import ON_WINDOWS, service_stop, service_start, get_home_path, get_username, get_use_cef_close_workaround, close_cef_socket +from .localplatform.localplatform import ON_WINDOWS, service_stop, service_start, get_home_path, get_username, get_use_cef_close_workaround, close_cef_socket, restart_webhelper class FilePickerObj(TypedDict): file: Path @@ -77,6 +77,7 @@ class Utilities: context.ws.add_route("utilities/get_tab_id", self.get_tab_id) context.ws.add_route("utilities/get_user_info", self.get_user_info) context.ws.add_route("utilities/http_request", self.http_request_legacy) + context.ws.add_route("utilities/restart_webhelper", self.restart_webhelper) context.ws.add_route("utilities/close_cef_socket", self.close_cef_socket) context.ws.add_route("utilities/_call_legacy_utility", self._call_legacy_utility) @@ -291,6 +292,9 @@ class Utilities: if get_use_cef_close_workaround(): await close_cef_socket() + async def restart_webhelper(self): + await restart_webhelper() + async def filepicker_ls(self, path: str | None = None, include_files: bool = True, |
