Expand description
cgroup v2 memory awareness (read-only).
Best-effort, never required: a cloud-native unit reports the memory
budget its scheduler handed it so OOM risk is observable (logged at startup,
and exposed as a /metrics gauge). Reads the unified cgroup v2 interface
files directly under /sys/fs/cgroup; in a container with a cgroup
namespace (the target shape) that path is the unit’s own cgroup, so the
direct read is correct.
On a bare host it reflects the root cgroup (whole-host) — still informative.
Any missing file / cgroup v1 / parse failure degrades to None.
§Active enforcement (best-effort, opt-in, never required)
On top of the reads, when the operator opts in (--cgroup auto|<path> /
AGENTD_CGROUP) and the cgroup-v2 tree is writable, each supervised run is
placed in its own child cgroup so teardown can write cgroup.kill — the
kernel then SIGKILLs the entire subtree atomically, catching processes that
escaped the process group (setsid) which killpg + PR_SET_PDEATHSIG
would miss — the worst leak agentd can suffer, since such a process outlives
every other teardown mechanism. And under_memory_pressure
lets the spawn-admission gates backpressure when the unit is at its
memory.high soft limit. Every cgroup op is best-effort: if the tree isn’t
writable (no delegation, cgroup-v1, off-cgroup) the feature silently disables
and the run falls back to the PDEATHSIG + kill-ladder path — agentd stays
cgroup-aware, never cgroup-requiring.
Note: hard resource limits on the child (memory.max/pids.max) need the
parent to delegate controllers via cgroup.subtree_control, which fails
(EBUSY) whenever the parent cgroup holds processes directly — common for a
systemd unit without Delegate=yes. So limit-setting stays a deployment
concern (size the pod’s resources.limits); agentd adds the atomic teardown
backstop and the soft-pressure backpressure, which need no delegation.
Structs§
- Cgroup
Guard - A per-run child cgroup. Placing the root subagent here puts its whole subtree
in the cgroup (membership inherits across
fork), sokill_alltears the entire subtree down atomically. RAII:Dropkills + removes the cgroup. - Configured
- What
configuresettled on: the resolved parent dir (if armed) and whether requested hard limits will actually be enforced (controllers delegated). - Limits
- Normalised hard limits for a per-run leaf cgroup. Each field, when set, is the exact string written to the corresponding cgroup-v2 interface file.
- Memory
Snapshot - A point-in-time view of the unit’s cgroup v2 memory interface.
Functions§
- configure
- Resolve + probe the
--cgroupspec ONCE at startup, arming per-run child cgroups.specis"auto"(derive<own-cgroup>/agentdfrom/proc/self/cgroup) or an absolute path under/sys/fs/cgroup. Optionalmemory_max/pids_maxspecs request hard limits on each run’s leaf; this best-effort delegates the controllers to the parent so the limits can take effect. ReturnsNonewhen off / not writable (the feature stays dormant). Idempotent — the first call wins. - memory_
current memory.current— current charged usage in bytes.- memory_
high memory.high— the soft (throttling) limit;Nonewhen unset ("max").- memory_
max memory.max— the hard limit;Nonewhen unlimited ("max") or unreadable.- snapshot
- Read the current cgroup v2 memory snapshot (best-effort; never fails).
- under_
memory_ pressure - Whether the unit is at/over the backpressure fraction of its
memory.highsoft limit — a signal for the spawn-admission gates to refuse new subagents rather than push the cgroup into reclaim/OOM. Reads live each call;falsewhen no cgroup / nomemory.highset (can’t tell → don’t block).