src/share/cap.bend relies on unsafe/foreign
raw source on the hub · import 0x74799d3f846634a3d7461d4336d7c9d4/src/share/cap.bend as Cap
share/cap: every bend the runner starts, inside a memory cap.
bend's C backend, not clang, is what costs the memory: emitting the C for a large program peaked at 18.8 GB here while clang on that same C peaked at 242 MB. An uncapped run reached 35 GB and took the host down. Worse, bend prints that all terms check *before* it emits any C, so a build the kernel kills for memory looks exactly like one that succeeded and happened to write no binary. The cap is what turns that into a legible exit 137.
4 imports
import Base import 0xabe575924687afad4cee1a2c1194d639/main.bend as R import ./env.bend as Env import ./args.bend as Args
Definitions
def gb source · line 23 · raw
IO(String)
how many gigabytes one bend may have. 8 is what fits beside the rest of
this machine; a project whose closure costs more says so in EZ_CAP.
The cap is also the divisor the gate picks its width from, since a run has to assume every job it starts at once could want the whole of it. So a cap set higher than a tree needs does not only reserve memory, it narrows the gate: the dearest aggregate here peaks at 3.3G, and at the 8G cap that is a width of 4 where 11 would fit. Lower EZ_CAP, or set EZ_JOBS outright, for a tree you have measured.
def ok source · line 30 · raw
IO(Bool)
whether a bend can be capped. The cap is systemd-run --user. That
fails when the program is absent, and it fails when the program is present
and the user bus is not. Either failure is no cap. A probe that would
wait on a password fails closed instead.
def scope source · line 38 · raw
@+gigs:String -> List<&2, String>
the cgroup a capped run gets. MemorySwapMax=0 matters: without it the
cgroup spills into swap and the cap stops meaning anything.
def pre source · line 43 · raw
@on:Bool -> @+gigs:String -> List<&2, String>
the words a capped run is prefixed with, or none when nothing can cap it
def argv source · line 53 · raw
@on:Bool -> @+gigs:String -> @+at:String -> @args:List<&2, String> -> List<&2, String>
a program's arguments dressed the way the cap wants them, for a caller that
is not going to run it here. The cap goes outside env, so the variable is
set inside the cgroup.
def run source · line 57 · raw
@on:Bool -> @args:List<&2, String> -> IO(String)
a program run under the cap, with this project's BEND_LIB set for it
def killed source · line 64 · raw
@+out:String -> Bool
the status the kernel leaves on a process it killed for memory
def why source · line 68 · raw
@+out:String -> @+gigs:String -> String
what to say when a run died for memory rather than for being wrong
def warning source · line 73 · raw
String
what is said when nothing is capping the jobs
def warn source · line 77 · raw
@on:Bool -> IO(Unit)
a warning printed once when nothing is capping the jobs
def warn.err source · line 85 · raw
@on:Bool -> IO(Unit)
the same warning on stderr, for a command whose stdout is the program's