diff --git a/bumble/device.py b/bumble/device.py index 9240fe93..962dad15 100644 --- a/bumble/device.py +++ b/bumble/device.py @@ -1163,6 +1163,7 @@ async def terminate(self) -> None: await self.device.send_sync_command( hci.HCI_LE_BIG_Terminate_Sync_Command(big_handle=self.big_handle) ) + self.device._remove_big_sync(self) self.state = BigSync.State.TERMINATED @@ -5933,14 +5934,19 @@ def on_big_sync_establishment( self.bis_links[bis_link.handle] = bis_link big_sync.emit(BigSync.Event.ESTABLISHMENT) + def _remove_big_sync(self, big_sync: BigSync) -> None: + if self.big_syncs.pop(big_sync.big_handle, None) is None: + return + for bis_link in big_sync.bis_links: + self.bis_links.pop(bis_link.handle, None) + @host_event_handler def on_big_sync_lost(self, big_handle: int, reason: int) -> None: - if not (big_sync := self.big_syncs.pop(big_handle, None)): + if not (big_sync := self.big_syncs.get(big_handle)): logger.warning('BIG %d not found', big_handle) return - for bis_link in big_sync.bis_links: - self.bis_links.pop(bis_link.handle, None) + self._remove_big_sync(big_sync) big_sync.state = BigSync.State.TERMINATED big_sync.emit(BigSync.Event.TERMINATION, reason) diff --git a/tests/device_test.py b/tests/device_test.py index ab40eeb2..ca812b43 100644 --- a/tests/device_test.py +++ b/tests/device_test.py @@ -1387,6 +1387,30 @@ async def test_big_and_big_sync(): assert len(big_sync.bis_links) == 2 await big_sync.terminate() + + # Terminating must clean up the BIG sync handle and its BIS links from the + # device, so that none are left behind as stale entries. + assert not two_devices.devices[1].big_syncs + assert not two_devices.devices[1].bis_links + + # next_big_handle() always picks the lowest unused handle (starting from + # DEVICE_MIN_BIG_HANDLE), so a re-sync must be able to allocate the same + # lowest handle again after the previous sync was cleaned up. + big_sync_2 = await two_devices.devices[1].create_big_sync( + pa_sync, + BigSyncParameters(big_sync_timeout=1000, bis=[1, 2]), + ) + assert len(big_sync_2.bis_links) == 2 + assert big_sync_2.big_handle == big_sync.big_handle + assert big_sync_2.big_handle in two_devices.devices[1].big_syncs + assert all( + bis_link.handle in two_devices.devices[1].bis_links + for bis_link in big_sync_2.bis_links + ) + await big_sync_2.terminate() + assert not two_devices.devices[1].big_syncs + assert not two_devices.devices[1].bis_links + await big.terminate()