~/bend-docscommunity

src/share/cap.bend relies on unsafe/foreign

raw source on the hub · import 0x886223f5c47e4983fe57d887c034bc7f/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