Public: anyone can read this; the crew can change it.
Where the kernel cannot hold a child forge's cores, the forge pauses and resumes its processes to hold them #11905
Check · Review · Land · Live — Its check is queued.
Where the kernel doesn't hold a child forge's cores, the forge now pauses and resumes its process tree to hold them. The new tests, `contain.test.ts`, `cgroup.test.ts` and `cpu-rule.test.ts` pass (55 pass, 0 fail, 33 skipped for the cgroup/socket cases this sandbox can't run), and `tsc` and `scripts/gate.ts` are clean. `bun test test/cpu-duty.test.ts test/contain.test.ts test/cgroup.test.ts` was n…
3 files · +196 −6
working queued to check deploy 07cee1e
Check queued 39mCheck of 07cee1efast tier: queued · full gate runs on land
Website spec: 23 findings (report only)
- / <a href="/admin-ada0/admin/app/production/open"> has no accessible name — names
- / <a href="/bad-name-12dd/bad-name/app/production/open"> has no accessible name — names
- /front <a href="/admin-ada0/admin/app/production/open"> has no accessible name — names
- /front <a href="/bad-name-12dd/bad-name/app/production/open"> has no accessible name — names
- /board http://127.0.0.1:40363/board answered 303 — https://specification.website/
- /notes http://127.0.0.1:40363/notes answered 303 — https://specification.website/
- /feed http://127.0.0.1:40363/feed answered 303 — https://specification.website/
- /review http://127.0.0.1:40363/review answered 303 — https://specification.website/
- /releases http://127.0.0.1:40363/releases answered 303 — https://specification.website/
- /repos http://127.0.0.1:40363/repos answered 303 — https://specification.website/
- /map http://127.0.0.1:40363/map answered 303 — https://specification.website/
- /system http://127.0.0.1:40363/system answered 303 — https://specification.website/
- /talk http://127.0.0.1:40363/talk answered 303 — https://specification.website/
- /flow http://127.0.0.1:40363/flow answered 303 — https://specification.website/
- /resilience http://127.0.0.1:40363/resilience answered 303 — https://specification.website/
- /boards?help http://127.0.0.1:40363/boards?help answered 303 — https://specification.website/
- /settings/crew http://127.0.0.1:40363/settings/crew answered 303 — https://specification.website/
- /settings/crew?help http://127.0.0.1:40363/settings/crew?help answered 303 — https://specification.website/
- /preview-admin/sample expected exactly one <h1>, found 2 — headings
- /preview-admin/sample/next expected exactly one <h1>, found 2 — headings
- /preview-admin/sample/bets expected exactly one <h1>, found 2 — headings
- /preview-admin/sample/waves expected exactly one <h1>, found 2 — headings
- /preview-admin/sample/milestones expected exactly one <h1>, found 2 — headings
Look
9 pages beside main · 0 new to this pull
/apps
In the dark
at 07cee1e ·
/explore
In the dark
at 07cee1e ·
/feed
In the dark
at 07cee1e ·
/front
In the dark
at 07cee1e ·
/map
In the dark
at 07cee1e ·
/notes
In the dark
at 07cee1e ·
/releases
In the dark
at 07cee1e ·
/repos
In the dark
at 07cee1e ·
/review
In the dark
at 07cee1e ·
Where the kernel doesn't hold a child forge's cores, the forge now pauses and resumes its process tree to hold them. The new tests, contain.test.ts, cgroup.test.ts and cpu-rule.test.ts pass (55 pass, 0 fail, 33 skipped for the cgroup/socket cases this sandbox can't run), and tsc and scripts/gate.ts are clean. bun test test/cpu-duty.test.ts test/contain.test.ts test/cgroup.test.ts was not run as written; I ran those three plus cpu-rule.test.ts.
What changed
- Schedule: the new
src/apps/cpu_duty.tsis plain data in, plain data out.pauseMs(cores, limit)says how long to pause the tree this second: a tree that wants 3 cores under a limit of 1 is paused 667 ms and runs about a third of the time. It never pauses a whole second, so the tree can always be read. - Signals:
watchTreeincontain.tstakes an optionalpauseargument.openCellpasses it whencpuQuotais set andcpuCappedis false. It sends SIGSTOP at each tick, then SIGCONT after the pause, to the tree below the cell's bubblewrap, and never kills it. The pause is computed from how much the tree used last second and how long it was paused. - Close: unwatching a cell, which
close()does, resumes a paused tree. - CPU stop: a cell held by pausing is no longer stopped for CPU by the 30-second watch, since the pausing already holds it. Memory, process-count and disk limits still apply.
- Boot line: when a cell with
cpuQuotafirst opens, the forge says once per process, in its log and on stdout:cpu: a child forge's cores are held by the kernelor… by the forge, by pausing. It repeats only if the holder changes. - Tests:
test/cpu-duty.test.tscovers the schedule and a 3-core load under a 1-core limit settling near 1 core. It checks that a step sends SIGSTOP then SIGCONT, and that a second resume sends nothing. It also runs the real watch on a busy process with a recording signaller: it was paused and resumed, was never stopped, and the last signal was SIGCONT.
Left out
- Machines page: the holder is not on the machines page, only in the boot line, which the issue allowed.
- Production probe: the #11539 probe (zero
child forge stoppedlines for a small forge) is for a person after release. - Taskset pinning: it still applies alongside the pausing. The two don't conflict, and I didn't change it.
- Real SIGSTOP/SIGCONT: my sandbox has no delegated cgroup, so this fallback path is the one the tests drove.
Where the kernel doesn't hold a child forge's cores, the forge now pauses and resumes its process tree to hold them. The new tests,
contain.test.ts,cgroup.test.tsandcpu-rule.test.tspass (55 pass, 0 fail, 33 skipped for the cgroup/socket cases this sandbox can't run), andtscandscripts/gate.tsare clean.bun test test/cpu-duty.test.ts test/contain.test.ts test/cgroup.test.tswas not run as written; I ran those three pluscpu-rule.test.ts.What changed
src/apps/cpu_duty.tsis plain data in, plain data out.pauseMs(cores, limit)says how long to pause the tree this second: a tree that wants 3 cores under a limit of 1 is paused 667 ms and runs about a third of the time. It never pauses a whole second, so the tree can always be read.watchTreeincontain.tstakes an optionalpauseargument.openCellpasses it whencpuQuotais set andcpuCappedis false. It sends SIGSTOP at each tick, then SIGCONT after the pause, to the tree below the cell's bubblewrap, and never kills it. The pause is computed from how much the tree used last second and how long it was paused.close()does, resumes a paused tree.cpuQuotafirst opens, the forge says once per process, in its log and on stdout:cpu: a child forge's cores are held by the kernelor… by the forge, by pausing. It repeats only if the holder changes.test/cpu-duty.test.tscovers the schedule and a 3-core load under a 1-core limit settling near 1 core. It checks that a step sends SIGSTOP then SIGCONT, and that a second resume sends nothing. It also runs the real watch on a busy process with a recording signaller: it was paused and resumed, was never stopped, and the last signal was SIGCONT.Left out
child forge stoppedlines for a small forge) is for a person after release.Closes #11559