mirror of
https://github.com/SteamDeckHomebrew/decky-loader.git
synced 2026-07-11 20:01:57 +00:00
use signals to shut down plugins instead of sending a socket message
should reduce or outright prevent shutdown stalls
This commit is contained in:
@@ -120,18 +120,25 @@ class PluginWrapper:
|
|||||||
start_time = time()
|
start_time = time()
|
||||||
if self.passive:
|
if self.passive:
|
||||||
return
|
return
|
||||||
|
self.log.info(f"Shutting down {self.name}")
|
||||||
|
|
||||||
_, pending = await wait([
|
pending: set[Task[None]] | None = None;
|
||||||
create_task(self._socket.write_single_line(dumps({ "stop": True, "uninstall": uninstall }, ensure_ascii=False)))
|
|
||||||
], timeout=1)
|
if uninstall:
|
||||||
|
_, pending = await wait([
|
||||||
|
create_task(self._socket.write_single_line(dumps({ "uninstall": uninstall }, ensure_ascii=False)))
|
||||||
|
], timeout=1)
|
||||||
|
|
||||||
|
self.terminate() # the plugin process will handle SIGTERM and shut down cleanly without a socket message
|
||||||
|
|
||||||
if hasattr(self, "_listener_task"):
|
if hasattr(self, "_listener_task"):
|
||||||
self._listener_task.cancel()
|
self._listener_task.cancel()
|
||||||
|
|
||||||
await self.kill_if_still_running()
|
await self.kill_if_still_running()
|
||||||
|
|
||||||
for pending_task in pending:
|
if pending:
|
||||||
pending_task.cancel()
|
for pending_task in pending:
|
||||||
|
pending_task.cancel()
|
||||||
|
|
||||||
self.log.info(f"Plugin {self.name} has been stopped in {time() - start_time:.1f}s")
|
self.log.info(f"Plugin {self.name} has been stopped in {time() - start_time:.1f}s")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -139,18 +146,14 @@ class PluginWrapper:
|
|||||||
|
|
||||||
async def kill_if_still_running(self):
|
async def kill_if_still_running(self):
|
||||||
start_time = time()
|
start_time = time()
|
||||||
sigtermed = False
|
|
||||||
while self.proc and self.proc.is_alive():
|
while self.proc and self.proc.is_alive():
|
||||||
elapsed_time = time() - start_time
|
elapsed_time = time() - start_time
|
||||||
if elapsed_time >= 5 and not sigtermed:
|
if elapsed_time >= 5:
|
||||||
sigtermed = True
|
self.log.warning(f"Plugin {self.name} still alive 5 seconds after stop request! Sending SIGKILL!")
|
||||||
self.log.warning(f"Plugin {self.name} still alive 5 seconds after stop request! Sending SIGTERM!")
|
|
||||||
self.terminate()
|
|
||||||
elif elapsed_time >= 10:
|
|
||||||
self.log.warning(f"Plugin {self.name} still alive 10 seconds after stop request! Sending SIGKILL!")
|
|
||||||
self.terminate(True)
|
self.terminate(True)
|
||||||
await sleep(0.1)
|
await sleep(0.1)
|
||||||
|
|
||||||
|
|
||||||
def terminate(self, kill: bool = False):
|
def terminate(self, kill: bool = False):
|
||||||
if self.proc and self.proc.is_alive():
|
if self.proc and self.proc.is_alive():
|
||||||
if kill:
|
if kill:
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ class SandboxedPlugin:
|
|||||||
self.author = author
|
self.author = author
|
||||||
self.api_version = api_version
|
self.api_version = api_version
|
||||||
self.shutdown_running = False
|
self.shutdown_running = False
|
||||||
|
self.uninstalling = False
|
||||||
|
|
||||||
self.log = getLogger("sandboxed_plugin")
|
self.log = getLogger("sandboxed_plugin")
|
||||||
|
|
||||||
@@ -161,13 +162,13 @@ class SandboxedPlugin:
|
|||||||
self.log.error("Failed to uninstall " + self.name + "!\n" + format_exc())
|
self.log.error("Failed to uninstall " + self.name + "!\n" + format_exc())
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def shutdown(self, uninstall: bool = False):
|
async def shutdown(self):
|
||||||
if not self.shutdown_running:
|
if not self.shutdown_running:
|
||||||
self.shutdown_running = True
|
self.shutdown_running = True
|
||||||
self.log.info(f"Calling Loader unload function for {self.name}.")
|
self.log.info(f"Calling Loader unload function for {self.name}.")
|
||||||
await self._unload()
|
await self._unload()
|
||||||
|
|
||||||
if uninstall:
|
if self.uninstalling:
|
||||||
self.log.info("Calling Loader uninstall function.")
|
self.log.info("Calling Loader uninstall function.")
|
||||||
await self._uninstall()
|
await self._uninstall()
|
||||||
|
|
||||||
@@ -180,8 +181,8 @@ class SandboxedPlugin:
|
|||||||
async def on_new_message(self, message : str) -> str|None:
|
async def on_new_message(self, message : str) -> str|None:
|
||||||
data = loads(message)
|
data = loads(message)
|
||||||
|
|
||||||
if "stop" in data:
|
if "uninstall" in data:
|
||||||
await self.shutdown(data.get('uninstall'))
|
self.uninstalling = data.get("uninstall")
|
||||||
|
|
||||||
d: SocketResponseDict = {"type": SocketMessageType.RESPONSE, "res": None, "success": True, "id": data["id"]}
|
d: SocketResponseDict = {"type": SocketMessageType.RESPONSE, "res": None, "success": True, "id": data["id"]}
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user