fix(browser): skip the Chrome sweep when the host has no procfs

_terminate_owned_chrome() walked Path("/proc") unconditionally, so on macOS
and Windows iterdir() raised FileNotFoundError out of private-browser session
shutdown. src/tools/cookbook.py already guards the same kind of scan with
os.path.isdir("/proc").

The sweep only reclaims Chrome trees that agent-browser reparented, so it is
an optimisation rather than a correctness requirement: degrade to a no-op
rather than failing the whole shutdown path.

_PROC_ROOT is a module attribute so both branches are testable on either kind
of host. The procfs-present path had no coverage at all before this.
This commit is contained in:
Léo
2026-09-25 10:30:49 +02:00
parent 0e07d9a675
commit 8b85e11fb4
2 changed files with 57 additions and 1 deletions
+13 -1
View File
@@ -119,6 +119,12 @@ def _browser_pid_file_candidates(
)
return list(dict.fromkeys(candidates))
# Linux exposes one command line per pid under /proc; macOS and Windows do not.
# Kept as a module attribute so the procfs-dependent paths stay testable on a
# host that has no procfs, and on one that does.
_PROC_ROOT = Path("/proc")
_SCHOLARLY_METADATA_CUE_RE = re.compile(
r"\b(?:accept(?:ed|ance)?|publish(?:ed|ing|cation)?|venue|conference|"
r"journal|proceedings|doi)\b",
@@ -2316,8 +2322,14 @@ class PrivateBrowserTool:
except OSError:
return
profile_prefix = str(tmpdir / "agent-browser-chrome-")
if not _PROC_ROOT.is_dir():
# Without procfs there is no way to match a reparented Chrome by
# its command line, and the sweep is an optimisation rather than a
# correctness requirement. Leave those trees to the daemon's own
# lifecycle instead of failing the whole shutdown path.
return
pids: list[int] = []
for entry in Path("/proc").iterdir():
for entry in _PROC_ROOT.iterdir():
if not entry.name.isdigit():
continue
try: