Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions bumble/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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)

Expand Down
24 changes: 24 additions & 0 deletions tests/device_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()


Expand Down
Loading