Skip to main content

Module cgroup_linux

Module cgroup_linux 

Source
Expand description

Linux tracker: one cgroup v2 per agent, under a systemd user scope srv puts itself in at startup with Delegate=yes, so srv may create and manage cgroups below it.

A cgroup holds every descendant of what it was given, whatever they do: setsid, double forks and reparenting don’t leave it (process groups and sessions can’t hold an agent’s tree: Claude Code and bashwrap each start new sessions). cgroup.kill ends all of them at once. See docs/analysis/agent-spawned-process-tracking-2026-10-07.md.

Structs§

CgroupTracker
One agent’s cgroup.

Constants§

CGROUP_FS 🔒

Statics§

ROOT 🔒
srv’s delegated scope directory, or None when it couldn’t get one (no cgroup v2, no systemd user manager): trackers then fall back.

Functions§

init
Move srv into its own delegated systemd user scope (agentmux-srv-<pid>.scope). Call once at startup, before any agent spawns. Idempotent; never fails startup.
join_before_exec
Make a child join procs (a cgroup.procs file) before it execs, so it is tracked before it runs any code of its own and before it can fork.
join_before_exec_pty
join_before_exec for a PTY spawn (portable-pty has no pre-exec hook): run the command through sh, which joins and then execs it, so the program starts already in the cgroup, as the same process.
kill_all 🔒
Kill everything in dir: cgroup.kill (kernel 5.14+), else SIGKILL each member until none is left.
own_cgroup 🔒
This process’s cgroup v2 path (/user.slice/…).
pids_in 🔒
populated 🔒
root
The directory per-agent cgroups are created in, once init succeeded.
setup 🔒
signal 🔒
start_transient_scope 🔒
Ask the user’s systemd manager for a transient scope holding this process, delegated to us (what systemd-run --user --scope -p Delegate=yes does).
usage_usec 🔒
usage_usec from a cpu.stat.