From 56fc030abd83942b24ec9f3093d4608b216bc549 Mon Sep 17 00:00:00 2001 From: Paul Robertson Date: Wed, 30 Sep 2026 08:20:25 +1300 Subject: [PATCH 1/2] fix(utils): log fire-and-forget background task failures --- sendspin/utils.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/sendspin/utils.py b/sendspin/utils.py index d259ed8..9455819 100644 --- a/sendspin/utils.py +++ b/sendspin/utils.py @@ -3,6 +3,7 @@ from __future__ import annotations import asyncio +import logging import platform import sys import uuid @@ -13,6 +14,8 @@ from aiosendspin.models.core import DeviceInfo +logger = logging.getLogger(__name__) + _T = TypeVar("_T") # Check if eager_start is supported (Python 3.12+) @@ -61,11 +64,27 @@ def create_task( TASKS.add(task) task.add_done_callback(TASKS.discard) - task.add_done_callback(lambda t: t.exception() if not t.cancelled() else None) + task.add_done_callback(_log_task_exception) return task +def _log_task_exception(task: asyncio.Task[Any]) -> None: + """Log a fire-and-forget background task failure instead of swallowing it. + + Retrieving the exception suppresses "exception was never retrieved" + warnings, but the previous lambda then discarded it — every background + failure (hook/amixer/PulseAudio volume errors included) was invisible. + """ + if task.cancelled(): + return + exc = task.exception() + if exc is not None: + logger.error( + "Background task %r failed", task.get_name(), exc_info=exc + ) + + def _detect_mac_address() -> str | None: """Return a stable hardware MAC address, or None if only a synthesized one is available. From c12ce85c7cab7f6356a0321bcd5ecc9c4b6af8c2 Mon Sep 17 00:00:00 2001 From: Paul Robertson Date: Sun, 4 Oct 2026 20:00:08 +0000 Subject: [PATCH 2/2] style: apply ruff format --- sendspin/utils.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sendspin/utils.py b/sendspin/utils.py index 9455819..c4dace3 100644 --- a/sendspin/utils.py +++ b/sendspin/utils.py @@ -80,9 +80,7 @@ def _log_task_exception(task: asyncio.Task[Any]) -> None: return exc = task.exception() if exc is not None: - logger.error( - "Background task %r failed", task.get_name(), exc_info=exc - ) + logger.error("Background task %r failed", task.get_name(), exc_info=exc) def _detect_mac_address() -> str | None: