subagent, bash: run each subagent run and bash task in its own cgroup
hive-subagent-daemon and hive-bash-daemon are now delegated their cgroup (Delegate=memory pids, DelegateSubgroup=daemon). At start each daemon enables memory+pids below its unit and creates runs/ (subagent) or tasks/ (bash). Each subagent run gets runs/<name>-<n>/ and each bash task tasks/<id>/, both with memory.oom.group=1, and the daemon removes the directory when the run ends. An OOM kill now takes one whole run instead of one process out of the daemon's shared cgroup, and never the daemon itself. Subagent runs get oom_score_adj +1000; bash tasks and both daemons stay at 0; the harness stays at -500. The unit-level OOMScoreAdjust=500 on the subagent daemon goes: it was both the daemon's own score and a floor no run below it could be lowered past. Bash tasks enter their cgroup from the existing pre_exec hook, writing to a cgroup.procs fd opened by the parent. hive-claude builds its Command itself and exposes neither a pre_exec hook nor the child's pid, so a subagent's claude (and an ACP agent's process) is started as the daemon's own binary with the run's cgroup in its environment; main() enters the cgroup, raises oom_score_adj and execs the real program, the trampoline swarm-review-classifier already uses. Both enter before the program executes, so nothing it forks starts outside the run's cgroup. Without a delegated `daemon` leaf (tests, a dev shell) each daemon logs one warning and runs everything in its own cgroup, as before. The shared helper is hive-agent-sock's run_cgroup module, the crate both daemons already use for what in-container plugins share. Closes #5007
This commit is contained in:
parent
baf282131f
commit
b31db6c7d9
14 changed files with 600 additions and 56 deletions
|
|
@ -539,8 +539,8 @@ in
|
|||
# A LOWER OOMScoreAdjust means LESS likely to be killed, so this
|
||||
# negative value puts the harness — and the agent's own `claude`,
|
||||
# which it spawns as a child and which therefore inherits the
|
||||
# value — last in line under memory pressure, behind
|
||||
# `hive-subagent-daemon`'s `+500` (see ./mcp.nix). Losing a
|
||||
# value — last in line under memory pressure, behind each subagent
|
||||
# run (+1000) and bash task (0) (see ./mcp.nix). Losing a
|
||||
# subagent costs one restartable task; losing this costs the
|
||||
# session that was supervising it. Not `-1000`, which would
|
||||
# exempt the harness entirely and leave the kernel with nothing
|
||||
|
|
|
|||
|
|
@ -338,6 +338,11 @@ in
|
|||
# take every running sibling task with it. `continue` scopes the
|
||||
# loss to the process the kernel chose.
|
||||
OOMPolicy = "continue";
|
||||
# The daemon runs each task in its own `tasks/<id>/` cgroup with
|
||||
# `memory.oom.group=1`, so an OOM kill takes one whole task. The
|
||||
# subgroup name is `DAEMON_SUBGROUP` in hive-agent-sock's `run_cgroup`.
|
||||
Delegate = "memory pids";
|
||||
DelegateSubgroup = "daemon";
|
||||
User = userName;
|
||||
Group = userName;
|
||||
};
|
||||
|
|
@ -436,18 +441,15 @@ in
|
|||
# `start`/`continue`/`status`/`interrupt` with no stdio fallback.
|
||||
Restart = "always";
|
||||
RestartSec = 3;
|
||||
# A HIGHER OOMScoreAdjust means MORE likely to be killed: the
|
||||
# kernel adds it to the badness score it derives from the
|
||||
# process's memory footprint, then kills the highest scorer. So
|
||||
# the positive value here and the negative one on `hive-agent`
|
||||
# put this unit first in line — a subagent turn can be retried,
|
||||
# the agent's own turn is the thing everything else hangs off.
|
||||
# `+500` against `hive-agent`'s `-500` is a full half of the
|
||||
# score range apart, enough that a fat subagent outranks a fatter
|
||||
# harness rather than merely tying with it. Every nested `claude`
|
||||
# inherits the value from the daemon, so the ordering covers the
|
||||
# whole subtree and not just this process.
|
||||
OOMScoreAdjust = 500;
|
||||
# The daemon runs each subagent run in its own `runs/<name>-<n>/`
|
||||
# cgroup with `memory.oom.group=1` and `oom_score_adj` +1000, so an
|
||||
# OOM kill takes one whole run, ahead of a bash task (0) and
|
||||
# `hive-agent` (-500). No `OOMScoreAdjust=` here: the daemon stays
|
||||
# at 0, and a unit value would also be the floor no run could go
|
||||
# below. The subgroup name is `DAEMON_SUBGROUP` in hive-agent-sock's
|
||||
# `run_cgroup`.
|
||||
Delegate = "memory pids";
|
||||
DelegateSubgroup = "daemon";
|
||||
# systemd's default is `stop`, which tears the whole unit down as
|
||||
# soon as the kernel kills *any* process in its cgroup — so one
|
||||
# over-large subagent takes the daemon and every sibling session
|
||||
|
|
|
|||
Loading…
Reference in a new issue