Fix thread leak in onvif discovery (#93742)

This commit is contained in:
J. Nick Koston 2023-05-29 10:06:13 -05:00 committed by GitHub
parent 3db59908ca
commit db931132a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 19 deletions

View File

@ -51,12 +51,15 @@ CONF_MANUAL_INPUT = "Manually configure ONVIF device"
def wsdiscovery() -> list[Service]:
"""Get ONVIF Profile S devices from network."""
discovery = WSDiscovery(ttl=4)
try:
discovery.start()
services = discovery.searchServices(
return discovery.searchServices(
scopes=[Scope("onvif://www.onvif.org/Profile/Streaming")]
)
finally:
discovery.stop()
return services
# Stop the threads started by WSDiscovery since otherwise there is a leak.
discovery._stopThreads() # pylint: disable=protected-access
async def async_discovery(hass: HomeAssistant) -> list[dict[str, Any]]:

View File

@ -60,10 +60,13 @@ def setup_mock_discovery(
with_mac=False,
two_devices=False,
with_hardware=True,
no_devices=False,
):
"""Prepare mock discovery result."""
services = []
for item in DISCOVERY:
if no_devices:
continue
service = MagicMock()
service.getXAddrs = MagicMock(
return_value=[
@ -92,7 +95,10 @@ def setup_mock_discovery(
scopes.append(scope)
service.getScopes = MagicMock(return_value=scopes)
services.append(service)
mock_discovery.return_value = services
mock_ws_discovery = MagicMock()
mock_ws_discovery.searchServices = MagicMock(return_value=services)
mock_discovery.return_value = mock_ws_discovery
async def test_flow_discovered_devices(hass: HomeAssistant) -> None:
@ -108,7 +114,7 @@ async def test_flow_discovered_devices(hass: HomeAssistant) -> None:
with patch(
"homeassistant.components.onvif.config_flow.get_device"
) as mock_onvif_camera, patch(
"homeassistant.components.onvif.config_flow.wsdiscovery"
"homeassistant.components.onvif.config_flow.WSDiscovery"
) as mock_discovery, patch(
"homeassistant.components.onvif.ONVIFDevice"
) as mock_device:
@ -178,7 +184,7 @@ async def test_flow_discovered_devices_ignore_configured_manual_input(
with patch(
"homeassistant.components.onvif.config_flow.get_device"
) as mock_onvif_camera, patch(
"homeassistant.components.onvif.config_flow.wsdiscovery"
"homeassistant.components.onvif.config_flow.WSDiscovery"
) as mock_discovery, patch(
"homeassistant.components.onvif.ONVIFDevice"
) as mock_device:
@ -217,12 +223,12 @@ async def test_flow_discovered_no_device(hass: HomeAssistant) -> None:
with patch(
"homeassistant.components.onvif.config_flow.get_device"
) as mock_onvif_camera, patch(
"homeassistant.components.onvif.config_flow.wsdiscovery"
"homeassistant.components.onvif.config_flow.WSDiscovery"
) as mock_discovery, patch(
"homeassistant.components.onvif.ONVIFDevice"
) as mock_device:
setup_mock_onvif_camera(mock_onvif_camera)
mock_discovery.return_value = []
setup_mock_discovery(mock_discovery, no_devices=True)
setup_mock_device(mock_device)
result = await hass.config_entries.flow.async_configure(
@ -259,7 +265,7 @@ async def test_flow_discovery_ignore_existing_and_abort(hass: HomeAssistant) ->
with patch(
"homeassistant.components.onvif.config_flow.get_device"
) as mock_onvif_camera, patch(
"homeassistant.components.onvif.config_flow.wsdiscovery"
"homeassistant.components.onvif.config_flow.WSDiscovery"
) as mock_discovery, patch(
"homeassistant.components.onvif.ONVIFDevice"
) as mock_device:
@ -302,7 +308,7 @@ async def test_flow_manual_entry(hass: HomeAssistant) -> None:
with patch(
"homeassistant.components.onvif.config_flow.get_device"
) as mock_onvif_camera, patch(
"homeassistant.components.onvif.config_flow.wsdiscovery"
"homeassistant.components.onvif.config_flow.WSDiscovery"
) as mock_discovery, patch(
"homeassistant.components.onvif.ONVIFDevice"
) as mock_device:
@ -359,7 +365,7 @@ async def test_flow_manual_entry_no_profiles(hass: HomeAssistant) -> None:
with patch(
"homeassistant.components.onvif.config_flow.get_device"
) as mock_onvif_camera, patch(
"homeassistant.components.onvif.config_flow.wsdiscovery"
"homeassistant.components.onvif.config_flow.WSDiscovery"
) as mock_discovery, patch(
"homeassistant.components.onvif.ONVIFDevice"
) as mock_device:
@ -399,7 +405,7 @@ async def test_flow_manual_entry_no_mac(hass: HomeAssistant) -> None:
with patch(
"homeassistant.components.onvif.config_flow.get_device"
) as mock_onvif_camera, patch(
"homeassistant.components.onvif.config_flow.wsdiscovery"
"homeassistant.components.onvif.config_flow.WSDiscovery"
) as mock_discovery, patch(
"homeassistant.components.onvif.ONVIFDevice"
) as mock_device:
@ -441,7 +447,7 @@ async def test_flow_manual_entry_fails(hass: HomeAssistant) -> None:
with patch(
"homeassistant.components.onvif.config_flow.get_device"
) as mock_onvif_camera, patch(
"homeassistant.components.onvif.config_flow.wsdiscovery"
"homeassistant.components.onvif.config_flow.WSDiscovery"
) as mock_discovery, patch(
"homeassistant.components.onvif.ONVIFDevice"
) as mock_device:
@ -549,7 +555,7 @@ async def test_flow_manual_entry_wrong_password(hass: HomeAssistant) -> None:
with patch(
"homeassistant.components.onvif.config_flow.get_device"
) as mock_onvif_camera, patch(
"homeassistant.components.onvif.config_flow.wsdiscovery"
"homeassistant.components.onvif.config_flow.WSDiscovery"
) as mock_discovery, patch(
"homeassistant.components.onvif.ONVIFDevice"
) as mock_device:
@ -826,7 +832,7 @@ async def test_flow_manual_entry_updates_existing_user_password(
with patch(
"homeassistant.components.onvif.config_flow.get_device"
) as mock_onvif_camera, patch(
"homeassistant.components.onvif.config_flow.wsdiscovery"
"homeassistant.components.onvif.config_flow.WSDiscovery"
) as mock_discovery, patch(
"homeassistant.components.onvif.ONVIFDevice"
) as mock_device:
@ -877,7 +883,7 @@ async def test_flow_manual_entry_wrong_port(hass: HomeAssistant) -> None:
with patch(
"homeassistant.components.onvif.config_flow.get_device"
) as mock_onvif_camera, patch(
"homeassistant.components.onvif.config_flow.wsdiscovery"
"homeassistant.components.onvif.config_flow.WSDiscovery"
) as mock_discovery, patch(
"homeassistant.components.onvif.ONVIFDevice"
) as mock_device: