From d02771f07a873bd269ed71ebe46f3353cb760b69 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Thu, 27 Aug 2026 12:37:46 -0500 Subject: [PATCH] cache the runtime ids in the ownership helper --- frigate/test/test_ownership.py | 14 ++++++++++++++ frigate/util/ownership.py | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/frigate/test/test_ownership.py b/frigate/test/test_ownership.py index 19087c7f6c..eeddb1f514 100644 --- a/frigate/test/test_ownership.py +++ b/frigate/test/test_ownership.py @@ -14,6 +14,9 @@ class FakePwEntry: # The devcontainer image exports FRIGATE_RUN_AS_ROOT, so any test that has to # reach past the escape-hatch check pins the variable instead of inheriting it. class TestGetRuntimeIds(unittest.TestCase): + def setUp(self) -> None: + ownership.get_runtime_ids.cache_clear() + @patch("frigate.util.ownership.os.geteuid", return_value=1000) def test_returns_none_when_not_root(self, _): assert ownership.get_runtime_ids() is None @@ -35,8 +38,19 @@ class TestGetRuntimeIds(unittest.TestCase): def test_returns_frigate_ids_as_root(self, *_): assert ownership.get_runtime_ids() == (1500, 1500) + @patch.dict("os.environ", {"FRIGATE_RUN_AS_ROOT": "false"}) + @patch("frigate.util.ownership.pwd.getpwnam", return_value=FakePwEntry()) + @patch("frigate.util.ownership.os.geteuid", return_value=0) + def test_caches_lookup(self, _geteuid, getpwnam): + assert ownership.get_runtime_ids() == (1500, 1500) + assert ownership.get_runtime_ids() == (1500, 1500) + getpwnam.assert_called_once() + class TestChownToRuntime(unittest.TestCase): + def setUp(self) -> None: + ownership.get_runtime_ids.cache_clear() + @patch("frigate.util.ownership.os.chown") @patch("frigate.util.ownership.get_runtime_ids", return_value=None) def test_noop_when_no_runtime_ids(self, _, chown): diff --git a/frigate/util/ownership.py b/frigate/util/ownership.py index 8ace34ca18..e1b9cc236c 100644 --- a/frigate/util/ownership.py +++ b/frigate/util/ownership.py @@ -1,5 +1,6 @@ """Helpers for aligning created files with the non-root runtime user.""" +import functools import logging import os import pwd @@ -9,12 +10,15 @@ logger = logging.getLogger(__name__) RUNTIME_USER = "frigate" +@functools.lru_cache(maxsize=1) def get_runtime_ids() -> tuple[int, int] | None: """Return (uid, gid) that services run as, or None when chown is not applicable. None when: not root (docker --user, so the host already mapped us), FRIGATE_RUN_AS_ROOT=true (escape hatch must not mutate ownership), or outside the Frigate container image (no frigate user). + The result is cached for the process lifetime because the runtime user + cannot change after boot. """ if os.geteuid() != 0: return None