From d73682ee8a1a983e3644ca58ddf6a9f8a1e84a69 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 25 Nov 2025 11:34:01 +0100 Subject: [PATCH] Fix blocking I/O in DockerInfo cpu realtime check (#6344) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The support_cpu_realtime property was performing blocking filesystem I/O (Path.exists()) in async context, causing BlockingError e.g. when the audio plugin started. Changes: - Convert support_cpu_realtime from property to dataclass field - Make DockerInfo.new() async to properly handle I/O operations - Run Path.exists() check in executor thread during initialization - Store result as immutable field to avoid repeated filesystem access Fixes SUPERVISOR-15WC 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude --- supervisor/docker/manager.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/supervisor/docker/manager.py b/supervisor/docker/manager.py index 3f9e8faf3..55101fb16 100644 --- a/supervisor/docker/manager.py +++ b/supervisor/docker/manager.py @@ -76,15 +76,25 @@ class DockerInfo: storage: str = attr.ib() logging: str = attr.ib() cgroup: str = attr.ib() + support_cpu_realtime: bool = attr.ib() @staticmethod - def new(data: dict[str, Any]): + async def new(data: dict[str, Any]) -> DockerInfo: """Create a object from docker info.""" + # Check if CONFIG_RT_GROUP_SCHED is loaded (blocking I/O in executor) + cpu_rt_file_exists = await asyncio.get_running_loop().run_in_executor( + None, Path("/sys/fs/cgroup/cpu/cpu.rt_runtime_us").exists + ) + cpu_rt_supported = ( + cpu_rt_file_exists and os.environ.get(ENV_SUPERVISOR_CPU_RT) == "1" + ) + return DockerInfo( AwesomeVersion(data.get("ServerVersion", "0.0.0")), data.get("Driver", "unknown"), data.get("LoggingDriver", "unknown"), data.get("CgroupVersion", "1"), + cpu_rt_supported, ) @property @@ -95,13 +105,6 @@ class DockerInfo: except AwesomeVersionCompareException: return False - @property - def support_cpu_realtime(self) -> bool: - """Return true, if CONFIG_RT_GROUP_SCHED is loaded.""" - if not Path("/sys/fs/cgroup/cpu/cpu.rt_runtime_us").exists(): - return False - return bool(os.environ.get(ENV_SUPERVISOR_CPU_RT) == "1") - @dataclass(frozen=True, slots=True) class PullProgressDetail: @@ -234,7 +237,7 @@ class DockerAPI(CoreSysAttributes): timeout=900, ), ) - self._info = DockerInfo.new(self.dockerpy.info()) + self._info = await DockerInfo.new(self.dockerpy.info()) await self.config.read_data() self._network = await DockerNetwork(self.dockerpy).post_init( self.config.enable_ipv6, self.config.mtu