Skip to content

fix(cmd/flynn): cap a command's memory at half of RAM by default - #662

Merged
ion-alpha-dev merged 1 commit into
mainfrom
fix/default-command-memory-cap
Nov 3, 2026
Merged

ion-alpha-dev merged 1 commit into
mainfrom
fix/default-command-memory-cap

Conversation

@ion-alpha-dev

@ion-alpha-dev ion-alpha-dev commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

What

With --max-memory unset, every command the agent runs is now capped at half the machine's physical memory. This covers flynn goal, the interactive session, flynn serve and the MCP server. An explicit --max-memory still wins, and where the RAM cannot be read the command runs uncapped as before.

Why

On Windows a confined command had no memory cap by default. The job object caps processes at 4096, but that does not bound memory. While testing a release candidate, a goal ran go run on a machine where go on PATH is a build-lease shim. Inside the sandbox the shim resolved back to itself and kept starting copies. A few hundred heavy processes committed 94.9 of 95.4 GB, Windows ran low on virtual memory and the WSL service crashed. The process cap was never reached.

How to verify

  • go test ./cmd/flynn/ -run 'TestCommandLimits|TestEveryShellPolicySetsLimits|TestShellFlagsBuildThePolicy'
  • TestCommandLimitsDefaultsToHalfOfRAM pins the arithmetic, TestCommandLimitsReadsThisMachine checks the real RAM probe feeds it on each CI OS, and TestEveryShellPolicySetsLimits fails if a governed.ShellPolicy built in cmd/flynn leaves Limits unset.
  • That a memory cap reaches the Windows job object is already covered by TestApplyJobLimitsResourceCaps in sandbox.

Notes for reviewers

  • The default sits on the agent's shell policy, not inside sandbox.Local. The sandbox also runs local model servers, which can legitimately need more than half the machine, and embedders calling the sandbox directly keep its documented zero-means-uncapped behaviour. No exported signature changes beyond the new hardware.RAMBytes in an internal package.
  • The cap applies per command. Concurrent fan-out children each get their own job, so several runaway commands at once could still together exceed half.
  • The Linux and macOS floors still don't enforce ResourceLimits (documented; a per-run cgroup needs delegation an unprivileged agent may not have), so today the default takes effect on Windows.
  • The shim's self-recursion is being fixed separately, in the project that ships the shim.

On Windows a command the agent ran had no memory cap unless
--max-memory was passed. The job object's process cap (4096) does not
bound memory: a go shim on PATH that resolved back to itself started a
few hundred heavy processes under a goal and committed all 95 GB of
the machine, crashing WSL, long before reaching the process limit.

With --max-memory unset, the agent's shell policy now caps each
command at half the machine's physical memory, for flynn goal, the
interactive session, flynn serve and the MCP server. An explicit
--max-memory still wins, and where the RAM cannot be read the command
runs uncapped as before.

The default is set on the shell policy and not inside sandbox.Local,
because the sandbox also runs local model servers, which can
legitimately need more than half the machine. internal/hardware
exports RAMBytes so the policy reads RAM without the GPU probes.

A source test requires every governed.ShellPolicy built in cmd/flynn
to set Limits, so a new entry point cannot start an uncapped shell.

Signed-off-by: Ion Alpha <contact@ionalpha.io>
@codecov

codecov Bot commented Nov 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@ion-alpha-dev
ion-alpha-dev merged commit 7cf2955 into main Nov 3, 2026
35 checks passed
@ion-alpha-dev
ion-alpha-dev deleted the fix/default-command-memory-cap branch November 3, 2026 08:56
@github-actions github-actions Bot locked and limited conversation to collaborators Nov 3, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant