Skip to content

Commit

Permalink
Prevent Bluetooth reconnects from blocking shutdown (#104150)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdraco committed Nov 19, 2023
1 parent e7cec9b commit d3b4dd2
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 0 deletions.
3 changes: 3 additions & 0 deletions homeassistant/components/bluetooth/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ class BluetoothManager:
"storage",
"slot_manager",
"_debug",
"shutdown",
)

def __init__(
Expand Down Expand Up @@ -165,6 +166,7 @@ def __init__(
self.storage = storage
self.slot_manager = slot_manager
self._debug = _LOGGER.isEnabledFor(logging.DEBUG)
self.shutdown = False

@property
def supports_passive_scan(self) -> bool:
Expand Down Expand Up @@ -259,6 +261,7 @@ async def async_setup(self) -> None:
def async_stop(self, event: Event) -> None:
"""Stop the Bluetooth integration at shutdown."""
_LOGGER.debug("Stopping bluetooth manager")
self.shutdown = True
if self._cancel_unavailable_tracking:
self._cancel_unavailable_tracking()
self._cancel_unavailable_tracking = None
Expand Down
2 changes: 2 additions & 0 deletions homeassistant/components/bluetooth/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@ async def connect(self, **kwargs: Any) -> bool:
"""Connect to the specified GATT server."""
assert models.MANAGER is not None
manager = models.MANAGER
if manager.shutdown:
raise BleakError("Bluetooth is already shutdown")
if debug_logging := _LOGGER.isEnabledFor(logging.DEBUG):
_LOGGER.debug("%s: Looking for backend to connect", self.__address)
wrapped_backend = self._async_get_best_available_backend_and_device(manager)
Expand Down
23 changes: 23 additions & 0 deletions tests/components/bluetooth/test_wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import bleak
from bleak.backends.device import BLEDevice
from bleak.backends.scanner import AdvertisementData
from bleak.exc import BleakError
import pytest

from homeassistant.components.bluetooth import (
Expand Down Expand Up @@ -366,3 +367,25 @@ async def connect(self, *args, **kwargs):
assert await client.connect() is False
cancel_hci0()
cancel_hci1()


async def test_raise_after_shutdown(
hass: HomeAssistant,
two_adapters: None,
enable_bluetooth: None,
install_bleak_catcher,
mock_platform_client_that_raises_on_connect,
) -> None:
"""Ensure the slot gets released on connection exception."""
manager = _get_manager()
hci0_device_advs, cancel_hci0, cancel_hci1 = _generate_scanners_with_fake_devices(
hass
)
# hci0 has 2 slots, hci1 has 1 slot
with patch.object(manager, "shutdown", True):
ble_device = hci0_device_advs["00:00:00:00:00:01"][0]
client = bleak.BleakClient(ble_device)
with pytest.raises(BleakError, match="shutdown"):
await client.connect()
cancel_hci0()
cancel_hci1()

0 comments on commit d3b4dd2

Please sign in to comment.