From d6b1a724a8f1b9d2826f38d06b4af4e4b2c70d3b Mon Sep 17 00:00:00 2001 From: Eric Callahan Date: Sat, 24 Dec 2022 07:44:06 -0500 Subject: [PATCH] eventloop: improve callback handling Wrap all callbacks in a coroutine that handles exceptions. This should eliminate "task not retreived" errors. Signed-off-by: Eric Callahan --- moonraker/eventloop.py | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/moonraker/eventloop.py b/moonraker/eventloop.py index 22b710b..695bc72 100644 --- a/moonraker/eventloop.py +++ b/moonraker/eventloop.py @@ -15,7 +15,6 @@ from typing import ( TYPE_CHECKING, Awaitable, Callable, - Coroutine, Optional, Tuple, TypeVar, @@ -67,11 +66,16 @@ class EventLoop: *args, **kwargs ) -> None: - if inspect.iscoroutinefunction(callback): - self.aioloop.create_task(callback(*args, **kwargs)) # type: ignore - else: - self.aioloop.call_soon( - functools.partial(callback, *args, **kwargs)) + async def _wrapper(): + try: + ret = callback(*args, **kwargs) + if inspect.isawaitable(ret): + await ret + except asyncio.CancelledError: + raise + except Exception: + logging.exception("Error Running Callback") + self.aioloop.create_task(_wrapper()) def delay_callback(self, delay: float, @@ -79,23 +83,14 @@ class EventLoop: *args, **kwargs ) -> asyncio.TimerHandle: - if inspect.iscoroutinefunction(callback): - return self.aioloop.call_later( - delay, self._async_callback, - functools.partial(callback, *args, **kwargs)) - else: - return self.aioloop.call_later( - delay, functools.partial(callback, *args, **kwargs)) + return self.aioloop.call_later( + delay, self.register_callback, + functools.partial(callback, *args, **kwargs) + ) def register_timer(self, callback: TimerCallback): return FlexTimer(self, callback) - def _async_callback(self, callback: Callable[[], Coroutine]) -> None: - # This wrapper delays creation of the coroutine object. In the - # event that a callback is cancelled this prevents "coroutine - # was never awaited" warnings in asyncio - self.aioloop.create_task(callback()) - def run_in_thread(self, callback: Callable[..., _T], *args