ui: appmarks use effective cgroup via MainPID
This commit is contained in:
@@ -940,14 +940,77 @@ RU: Применяет policy-rules и проверяет health. При оши
|
||||
if p.returncode != 0:
|
||||
raise RuntimeError(f"systemd-run failed: {p.returncode}\n{out}".strip())
|
||||
|
||||
# EN: Some apps (e.g. Chrome wrappers) can return quickly; the transient scope
|
||||
# EN: may appear/disappear fast. Retry briefly to avoid race.
|
||||
# RU: Некоторые приложения (например, chrome-wrapper) быстро завершаются; scope
|
||||
# RU: может появиться/исчезнуть очень быстро. Делаем небольшой retry.
|
||||
cg = self._control_group_for_unit_retry(unit, timeout_sec=3.0)
|
||||
# EN: Some apps can be migrated into a different app scope by the desktop/session
|
||||
# EN: integration. Using unit ControlGroup is then incorrect. Prefer reading the
|
||||
# EN: effective cgroup from the unit MainPID (/proc/<pid>/cgroup) and fall back
|
||||
# EN: to systemctl ControlGroup only if needed.
|
||||
# RU: Некоторые приложения могут мигрировать в другой app scope (интеграция
|
||||
# RU: с desktop/session). Тогда ControlGroup юнита неверен. Предпочитаем читать
|
||||
# RU: реальный cgroup по MainPID (/proc/<pid>/cgroup) и только потом fallback
|
||||
# RU: на systemctl ControlGroup.
|
||||
cg = self._effective_cgroup_for_unit_retry(unit, timeout_sec=3.0)
|
||||
|
||||
return cg, out
|
||||
|
||||
def _effective_cgroup_for_unit_retry(self, unit: str, *, timeout_sec: float = 2.0) -> str:
|
||||
u = (unit or "").strip()
|
||||
if not u:
|
||||
raise ValueError("empty unit")
|
||||
|
||||
deadline = time.time() + max(0.2, float(timeout_sec or 0))
|
||||
last_pid_out = ""
|
||||
while time.time() < deadline:
|
||||
code, out = self._systemctl_user(["show", "-p", "MainPID", "--value", u])
|
||||
last_pid_out = out or ""
|
||||
if code == 0:
|
||||
try:
|
||||
pid = int((out or "").strip() or "0")
|
||||
except Exception:
|
||||
pid = 0
|
||||
if pid > 0:
|
||||
cg = self._cgroup_path_from_pid(pid)
|
||||
if cg:
|
||||
return cg
|
||||
low = (out or "").lower()
|
||||
if "could not be found" in low or "not found" in low:
|
||||
break
|
||||
time.sleep(0.1)
|
||||
|
||||
# Fallback: unit ControlGroup (may be wrong for migrated apps).
|
||||
try:
|
||||
cg = self._control_group_for_unit_retry(u, timeout_sec=1.0)
|
||||
if cg:
|
||||
return cg
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
raise RuntimeError(
|
||||
(
|
||||
"failed to query effective cgroup\n"
|
||||
+ (last_pid_out.strip() or "(no output)")
|
||||
+ "\n\n"
|
||||
+ "EN: Could not resolve unit MainPID->/proc/<pid>/cgroup.\n"
|
||||
+ "RU: Не удалось получить MainPID и прочитать /proc/<pid>/cgroup."
|
||||
).strip()
|
||||
)
|
||||
|
||||
def _cgroup_path_from_pid(self, pid: int) -> str:
|
||||
p = int(pid or 0)
|
||||
if p <= 0:
|
||||
return ""
|
||||
try:
|
||||
with open(f"/proc/{p}/cgroup", "r", encoding="utf-8", errors="replace") as f:
|
||||
for raw in f:
|
||||
line = (raw or "").strip()
|
||||
if not line:
|
||||
continue
|
||||
if line.startswith("0::"):
|
||||
cg = line[len("0::") :].strip()
|
||||
return cg
|
||||
except Exception:
|
||||
return ""
|
||||
return ""
|
||||
|
||||
def _control_group_for_unit_retry(self, unit: str, *, timeout_sec: float = 2.0) -> str:
|
||||
u = (unit or "").strip()
|
||||
if not u:
|
||||
@@ -1239,7 +1302,20 @@ RU: Применяет policy-rules и проверяет health. При оши
|
||||
cg = ""
|
||||
cg_id = 0
|
||||
try:
|
||||
cg = self._control_group_for_unit(unit)
|
||||
# Prefer effective cgroup via MainPID (/proc/<pid>/cgroup) for services.
|
||||
# Some GUI apps can migrate into a different app scope after launch.
|
||||
if unit.endswith(".service"):
|
||||
code, out = self._systemctl_user(["show", "-p", "MainPID", "--value", unit])
|
||||
if code == 0:
|
||||
try:
|
||||
pid = int((out or "").strip() or "0")
|
||||
except Exception:
|
||||
pid = 0
|
||||
if pid > 0:
|
||||
cg = self._cgroup_path_from_pid(pid)
|
||||
|
||||
if not cg:
|
||||
cg = self._control_group_for_unit(unit)
|
||||
cg_id = self._cgroup_inode_id(cg)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user