From 53393afe8d25b72ed8d0f9ba08f3ef38cde51baa Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Mon, 28 Apr 2025 23:48:47 +0200 Subject: [PATCH] Revert "Recreate aiohttp session on connectivity check (#5332)" (#5851) This reverts commit 1504278223a8d852d3b11de25f676fa8d6501a70. It turns out that recreating the session can cause race conditions, e.g. with API checks triggered by proxied requests running alongside. These manifest in the following error: AttributeError: 'NoneType' object has no attribute 'connect' ... File "supervisor/homeassistant/api.py", line 187, in check_api_state if state := await self.get_api_state(): File "supervisor/homeassistant/api.py", line 171, in get_api_state data = await self.get_core_state() File "supervisor/homeassistant/api.py", line 145, in get_core_state return await self._get_json("api/core/state") File "supervisor/homeassistant/api.py", line 132, in _get_json async with self.make_request("get", path) as resp: File "contextlib.py", line 214, in __aenter__ return await anext(self.gen) File "supervisor/homeassistant/api.py", line 106, in make_request async with getattr(self.sys_websession, method)( File "aiohttp/client.py", line 1425, in __aenter__ self._resp: _RetType = await self._coro File "aiohttp/client.py", line 703, in _request conn = await self._connector.connect( The only reason for the _connection in the aiohttp client to be None is when close() gets called on the session. The only place this is being done is the connectivity check. So it seems that between fetching the session from the `sys_websession` property) and actually using the connector, a connectivity check has been run which then causes the above stack trace. Let's not mess with the lifetime of the ClientSession object and simply revert the change. Another solution for the original problem needs to be found. --- supervisor/coresys.py | 18 +++++------------- supervisor/supervisor.py | 2 -- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/supervisor/coresys.py b/supervisor/coresys.py index 2e3fcbe78..46abeec3a 100644 --- a/supervisor/coresys.py +++ b/supervisor/coresys.py @@ -68,7 +68,7 @@ class CoreSys: # External objects self._loop: asyncio.BaseEventLoop = asyncio.get_running_loop() - self._websession = None + self._websession: aiohttp.ClientSession = aiohttp.ClientSession() # Global objects self._config: CoreConfig = CoreConfig() @@ -101,8 +101,10 @@ class CoreSys: self._bus: Bus | None = None self._mounts: MountManager | None = None - # Setup aiohttp session - self.create_websession() + # Set default header for aiohttp + self._websession._default_headers = MappingProxyType( + {aiohttp.hdrs.USER_AGENT: SERVER_SOFTWARE} + ) # Task factory attributes self._set_task_context: list[Callable[[Context], Context]] = [] @@ -582,16 +584,6 @@ class CoreSys: return self.loop.run_in_executor(None, funct, *args) - def create_websession(self) -> None: - """Create a new aiohttp session.""" - if self._websession: - self.create_task(self._websession.close()) - - # Create session and set default header for aiohttp - self._websession: aiohttp.ClientSession = aiohttp.ClientSession( - headers=MappingProxyType({aiohttp.hdrs.USER_AGENT: SERVER_SOFTWARE}) - ) - def _create_context(self) -> Context: """Create a new context for a task.""" context = copy_context() diff --git a/supervisor/supervisor.py b/supervisor/supervisor.py index 9ddc7829c..99b85d4e9 100644 --- a/supervisor/supervisor.py +++ b/supervisor/supervisor.py @@ -292,8 +292,6 @@ class Supervisor(CoreSysAttributes): "https://checkonline.home-assistant.io/online.txt", timeout=timeout ) except (ClientError, TimeoutError): - # Need to recreate the websession to avoid stale connection checks - self.coresys.create_websession() self.connectivity = False else: self.connectivity = True