diff --git a/CHANGELOG.md b/CHANGELOG.md index 532b24f1..6e5f80bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - fix(voice): remove the gap between sentences - fix(core): change the power-off menu item icon - closes #151 - refactor(core): migrate `ubo_app/services.py` to `typings/ubo_handle.pyi` as it was only providing types +- fix(core): make sure app exits gracefully before shutdown/reboot and atexit callbacks run - closes #150 ## Version 0.15.5 diff --git a/ubo_app/load_services.py b/ubo_app/load_services.py index 2f94a69d..7cac3e83 100644 --- a/ubo_app/load_services.py +++ b/ubo_app/load_services.py @@ -346,7 +346,7 @@ async def shutdown(self: UboServiceThread) -> None: if not tasks: break for task in tasks: - with contextlib.suppress(asyncio.TimeoutError): + with contextlib.suppress(BaseException): await asyncio.wait_for(task, timeout=SERVICES_LOOP_GRACE_PERIOD) logger.debug('Stopping event loop', extra={'thread_': self}) diff --git a/ubo_app/service.py b/ubo_app/service.py index 4f397d9a..f9a55ef4 100644 --- a/ubo_app/service.py +++ b/ubo_app/service.py @@ -83,7 +83,7 @@ async def shutdown(self: WorkerThread) -> None: if not tasks: break for task in tasks: - with contextlib.suppress(asyncio.TimeoutError): + with contextlib.suppress(BaseException): await asyncio.wait_for(task, timeout=MAIN_LOOP_GRACE_PERIOD) logger.debug('Stopping event loop', extra={'thread_': self}) diff --git a/ubo_app/side_effects.py b/ubo_app/side_effects.py index 09e24a7c..e6e30232 100644 --- a/ubo_app/side_effects.py +++ b/ubo_app/side_effects.py @@ -8,7 +8,6 @@ from pathlib import Path from typing import TYPE_CHECKING -from kivy.clock import Clock from redux import FinishAction from ubo_app.store.core import PowerOffEvent, RebootEvent @@ -40,12 +39,13 @@ def power_off() -> None: if IS_RPI: def power_off_system(*_: list[object]) -> None: + atexit.unregister(power_off_system) + atexit._run_exitfuncs() # noqa: SLF001 subprocess.run( # noqa: S603 ['/usr/bin/env', 'systemctl', 'poweroff', '-i'], check=True, ) - Clock.schedule_once(power_off_system, 5) atexit.register(power_off_system) @@ -55,12 +55,13 @@ def reboot() -> None: if IS_RPI: def reboot_system(*_: list[object]) -> None: + atexit.unregister(reboot_system) + atexit._run_exitfuncs() # noqa: SLF001 subprocess.run( # noqa: S603 ['/usr/bin/env', 'systemctl', 'reboot', '-i'], check=True, ) - Clock.schedule_once(reboot_system, 5) atexit.register(reboot_system)