From 6cafc0ed030d392ec73d38936a25e118ac447f7e Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Wed, 18 Feb 2026 13:08:58 +1100 Subject: [PATCH] aioble/server: Fix _init_capture() guard to match _server_shutdown(). Signed-off-by: Andrew Leech --- micropython/bluetooth/aioble/aioble/server.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/micropython/bluetooth/aioble/aioble/server.py b/micropython/bluetooth/aioble/aioble/server.py index 5d5d7399b..1638784f4 100644 --- a/micropython/bluetooth/aioble/aioble/server.py +++ b/micropython/bluetooth/aioble/aioble/server.py @@ -100,13 +100,21 @@ def write(self, data, send_update=False): else: ble.gatts_write(self._value_handle, data, send_update) - # When the a capture-enabled characteristic is created, create the + # When a capture-enabled characteristic is created, create the # necessary events (if not already created). + # Guard on _capture_task (not _capture_queue) to match _server_shutdown() + # which guards on _capture_task. This ensures partial teardown (task gone + # but queue remains) self-heals instead of silently no-oping. @staticmethod def _init_capture(): - if hasattr(BaseCharacteristic, "_capture_queue"): + if hasattr(BaseCharacteristic, "_capture_task"): return - + # Clean up any partial state from incomplete shutdown + for attr in ("_capture_queue", "_capture_write_event", "_capture_consumed_event"): + try: + delattr(BaseCharacteristic, attr) + except AttributeError: + pass BaseCharacteristic._capture_queue = deque((), _WRITE_CAPTURE_QUEUE_LIMIT) BaseCharacteristic._capture_write_event = asyncio.ThreadSafeFlag() BaseCharacteristic._capture_consumed_event = asyncio.ThreadSafeFlag()