Skip to content

Read process arguments and environment through Platform - #2892

Merged
trissim merged 4 commits into
mainfrom
refactor/process-command-facts
Oct 23, 2026
Merged

trissim merged 4 commits into
mainfrom
refactor/process-command-facts

Conversation

@trissim

@trissim trissim commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Process command-line and environment decoding belongs to Platform. ProcessIdentity delegates both facts; the four consumer modules no longer open /proc themselves.

IMPL-13: owner_launch.py, owner_lifecycle.py, active_route.py and host_services repeated the same process read mechanism outside its owner. LinuxPlatform now owns both proc reads beside _stat. IMPL-12: SystemdUserService owns its service-specific missing-command refusal once.

LinuxPlatform.arguments (child_process.py:565) reads NUL-terminated argument words through os.fsdecode. Missing files and empty cmdline bytes raise ProcessLookupError(process.pid); _stat already classifies zombies as absent. Empty argv[0] remains a distinct value, and owner_lifecycle.py:107 retains its existing interpreter refusal. LinuxPlatform.environment (:574) decodes key/value entries at their first equals sign, preserving equals signs in values. Permission and other IO errors propagate.

ProcessIdentity.arguments/environment at child_process.py:250/253 delegate in one line each. DarwinPlatform.arguments/environment at :715/718 and Win32Platform at :913/916 explicitly raise NotImplementedError, per the commander's portability correction; no native readers or fallback paths were invented.

Consumers:

  • owner_launch.py:38/:41 reads the interpreter and environment; existing before/after process identity checks remain.
  • owner_lifecycle.py:106 reads argv[0], retaining its nonempty-interpreter check.
  • active_route.py:322 joins the argument tuple for display; its existing ProcessLookupError branch yields ExitedLockHolder. EmptyCommandLockHolder and the display-side choice are deleted.
  • SystemdUserService.running_arguments at host_services/init.py:200 calls ProcessIdentity.capture(pid).arguments() and translates ProcessLookupError into ServiceNotServingError from None. runtime at :207 calls that method.
  • SystemdConnectorService.from_process at host_services/connector.py:84 parses cls.running_arguments(pid)[2:]. Both duplicate inline checks and the unused connector ProcessIdentity import are deleted.
  • process_arguments is deleted without an alias.

Before, grep of proc command/environment reads on main:

origin/main:src/agent_comms/active_route.py:327:                command = Path(f'/proc/{pid}/cmdline').read_bytes().replace(b'\0', b' ').decode('utf-8', 'replace').strip()
origin/main:src/agent_comms/host_services/__init__.py:201:                          Path(f"/proc/{pid}/cmdline").read_bytes().split(b"\0")[:-1])
origin/main:src/agent_comms/owner_launch.py:40:        command = Path(f"/proc/{process.pid}/cmdline").read_bytes().split(b"\0", 1)[0]
origin/main:src/agent_comms/owner_launch.py:44:        raw = Path(f"/proc/{process.pid}/environ").read_bytes()
origin/main:src/agent_comms/owner_lifecycle.py:106:        command = Path(f"/proc/{process.pid}/cmdline").read_bytes().split(b"\0", 1)[0]

After:

src/agent_comms/child_process.py:567:            raw = Path(f"/proc/{process.pid}/cmdline").read_bytes()
src/agent_comms/child_process.py:576:            raw = Path(f"/proc/{process.pid}/environ").read_bytes()

Requested correction greps:

$ grep -rn "has no running command" src
src/agent_comms/host_services/__init__.py:204:            raise ServiceNotServingError(f"{cls.unit} has no running command") from None
$ grep -rn EmptyCommandLockHolder src tests
(no output; exit 1)

Source checks: owner/call declarations inspected through AST before edits; all changed modules parse; git diff --check is clean. Main including #2888/#2889 is merged. No new ProcessLookupError catch outside running_arguments and the existing active_route branch. tools/agent_resource_check.py and meminfo/pressure/locks reads are untouched.

Earlier head 9ecbe3a received 68 passed, 1 skipped on the review fork, as reported by commander. That result predates the empty-command correction. No tests were run by this unit.

Assumed: Linux proc cmdline records are NUL-terminated; empty raw bytes mean no live process of ours. Nonempty records may still contain an empty argv[0]. The explicit NotImplementedError portability correction supersedes the original Darwin/Windows wording. No process decision is replaced by a default argv.

Copilot AI balanced review requested due to automatic review settings October 23, 2026 20:30

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@trissim
trissim merged commit 5d331d0 into main Oct 23, 2026
6 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants