From c1b7aa084c275cb701ee5212fef0725c4cf2a915 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Thu, 13 Apr 2023 15:04:21 +0200 Subject: [PATCH] Fix race condition in deconz (#91328) * Fix race condition in deconz * Use a new separate test --- homeassistant/components/deconz/gateway.py | 10 +++++++-- tests/components/deconz/test_init.py | 26 ++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/deconz/gateway.py b/homeassistant/components/deconz/gateway.py index d977e8813da..f4af7337427 100644 --- a/homeassistant/components/deconz/gateway.py +++ b/homeassistant/components/deconz/gateway.py @@ -235,9 +235,15 @@ class DeconzGateway: ) -> None: """Handle signals of config entry being updated. - This is a static method because a class method (bound method), cannot be used with weak references. - Causes for this is either discovery updating host address or config entry options changing. + This is a static method because a class method (bound method), + cannot be used with weak references. + Causes for this is either discovery updating host address or + config entry options changing. """ + if entry.entry_id not in hass.data[DECONZ_DOMAIN]: + # A race condition can occur if multiple config entries are + # unloaded in parallel + return gateway = get_gateway_from_config_entry(hass, entry) if gateway.api.host != gateway.host: diff --git a/tests/components/deconz/test_init.py b/tests/components/deconz/test_init.py index e4c7139cd82..f456508a6f3 100644 --- a/tests/components/deconz/test_init.py +++ b/tests/components/deconz/test_init.py @@ -1,4 +1,5 @@ """Test deCONZ component setup process.""" +import asyncio from unittest.mock import patch from homeassistant.components.deconz import ( @@ -133,6 +134,31 @@ async def test_unload_entry_multiple_gateways( assert hass.data[DECONZ_DOMAIN][config_entry2.entry_id].master +async def test_unload_entry_multiple_gateways_parallel( + hass: HomeAssistant, aioclient_mock: AiohttpClientMocker +) -> None: + """Test race condition when unloading multiple config entries in parallel.""" + config_entry = await setup_deconz_integration(hass, aioclient_mock) + aioclient_mock.clear_requests() + + data = {"config": {"bridgeid": "01234E56789B"}} + with patch.dict(DECONZ_WEB_REQUEST, data): + config_entry2 = await setup_deconz_integration( + hass, + aioclient_mock, + entry_id="2", + unique_id="01234E56789B", + ) + + assert len(hass.data[DECONZ_DOMAIN]) == 2 + + await asyncio.gather( + config_entry.async_unload(hass), config_entry2.async_unload(hass) + ) + + assert len(hass.data[DECONZ_DOMAIN]) == 0 + + async def test_update_group_unique_id(hass: HomeAssistant) -> None: """Test successful migration of entry data.""" old_unique_id = "123"