From 20baecf6ed1b8582c6bd0a247e3cbe2f900271b2 Mon Sep 17 00:00:00 2001 From: Randy Scott Date: Wed, 22 Oct 2025 20:43:00 -0500 Subject: [PATCH] fix: ble: Race condition in receive for notifications Fix a race condition relating to BLE notifications. If the notification arrives before the `receive()` method is called, the notification will be lost and the transfer will time out. This happens because `self._notify_condition.notify()` does nothing without a pending `self._notify_condition.wait()`. Only wait for notifications if the buffer does not contain enough data for the header. --- smpclient/transport/ble.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/smpclient/transport/ble.py b/smpclient/transport/ble.py index 4b66f77..f46d7ad 100644 --- a/smpclient/transport/ble.py +++ b/smpclient/transport/ble.py @@ -159,13 +159,9 @@ async def receive(self) -> bytes: # self._notify_condition is used to synchronize access to self._buffer. async with self._notify_condition: # wait for the header - logger.debug(f"Waiting for notify on {SMP_CHARACTERISTIC_UUID=}") - await self._notify_or_disconnect() - - if len(self._buffer) < smphdr.Header.SIZE: # pragma: no cover - raise SMPBLETransportException( - f"Buffer contents not big enough for SMP header: {self._buffer=}" - ) + while len(self._buffer) < smphdr.Header.SIZE: + logger.debug(f"Waiting for notify on {SMP_CHARACTERISTIC_UUID=}") + await self._notify_or_disconnect() header: Final = smphdr.Header.loads(self._buffer[: smphdr.Header.SIZE]) logger.debug(f"Received {header=}")