Fix memory leak in onvif (#83006)

fixes https://github.com/home-assistant/core/issues/82504
This commit is contained in:
J. Nick Koston 2022-11-30 10:40:59 -10:00 committed by GitHub
parent 532ab12a48
commit 4239923ea2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 13 deletions

View File

@ -11,7 +11,7 @@ from httpx import RequestError
import onvif
from onvif import ONVIFCamera
from onvif.exceptions import ONVIFError
from zeep.exceptions import Fault
from zeep.exceptions import Fault, XMLParseError
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
@ -284,7 +284,7 @@ class ONVIFDevice:
snapshot = media_capabilities and media_capabilities.SnapshotUri
pullpoint = False
with suppress(ONVIFError, Fault, RequestError):
with suppress(ONVIFError, Fault, RequestError, XMLParseError):
pullpoint = await self.events.async_start()
ptz = False

View File

@ -5,6 +5,7 @@ import asyncio
from collections.abc import Callable
from contextlib import suppress
import datetime as dt
from logging import DEBUG, WARNING
from httpx import RemoteProtocolError, TransportError
from onvif import ONVIFCamera, ONVIFService
@ -20,7 +21,6 @@ from .parsers import PARSERS
UNHANDLED_TOPICS = set()
SUBSCRIPTION_ERRORS = (
XMLParseError,
Fault,
asyncio.TimeoutError,
TransportError,
@ -122,20 +122,32 @@ class EventManager:
if self._subscription:
# Suppressed. The subscription may no longer exist.
with suppress(*SUBSCRIPTION_ERRORS):
try:
await self._subscription.Unsubscribe()
except (XMLParseError, *SUBSCRIPTION_ERRORS) as err:
LOGGER.debug(
"Failed to unsubscribe ONVIF PullPoint subscription for '%s';"
" This is normal if the device restarted: %s",
self.unique_id,
err,
)
self._subscription = None
try:
restarted = await self.async_start()
except SUBSCRIPTION_ERRORS:
except (XMLParseError, *SUBSCRIPTION_ERRORS) as err:
restarted = False
# Device may not support subscriptions so log at debug level
# when we get an XMLParseError
LOGGER.log(
DEBUG if isinstance(err, XMLParseError) else WARNING,
"Failed to restart ONVIF PullPoint subscription for '%s'; "
"Retrying later: %s",
self.unique_id,
err,
)
if not restarted:
LOGGER.warning(
"Failed to restart ONVIF PullPoint subscription for '%s'. Retrying",
self.unique_id,
)
# Try again in a minute
self._unsub_refresh = async_call_later(self.hass, 60, self.async_restart)
elif self._listeners:
@ -154,8 +166,7 @@ class EventManager:
.isoformat(timespec="seconds")
.replace("+00:00", "Z")
)
with suppress(*SUBSCRIPTION_ERRORS):
await self._subscription.Renew(termination_time)
await self._subscription.Renew(termination_time)
def async_schedule_pull(self) -> None:
"""Schedule async_pull_messages to run."""
@ -178,8 +189,11 @@ class EventManager:
except RemoteProtocolError:
# Likely a shutdown event, nothing to see here
return
except SUBSCRIPTION_ERRORS as err:
LOGGER.warning(
except (XMLParseError, *SUBSCRIPTION_ERRORS) as err:
# Device may not support subscriptions so log at debug level
# when we get an XMLParseError
LOGGER.log(
DEBUG if isinstance(err, XMLParseError) else WARNING,
"Failed to fetch ONVIF PullPoint subscription messages for '%s': %s",
self.unique_id,
err,