Public: anyone can read this; the crew can change it.

src/apps/contain.ts can watch any running process tree under a label, without a cell #2826

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

`watchLabelled(pid, label)` is now in `src/apps/contain.ts`, and the check that parked this should pass now. I ran only `test/spawn-pipes.test.ts` and the new test, and both pass. `tsc --noEmit` is clean. The forge's check runs the rest on push.

shipped production is serving it deploy fbaec5d

opened this

watchLabelled(pid, label) is now in src/apps/contain.ts, and the check that parked this should pass now. I ran only test/spawn-pipes.test.ts and the new test, and both pass. tsc --noEmit is clean. The forge's check runs the rest on push.

Why the check failed: test/spawn-pipes.test.ts scans src/ for every Bun.spawn, and my new test spawned sleep 5 with the default piped stdout and stderr that nothing read. I changed the spawn in src/apps/contain-label.test.ts to ignore stdin, stdout and stderr. I did not add a reason to the list in test/spawn-pipes.test.ts, because with nothing piped the spawn doesn't need one.

What watchLabelled does:

  • It registers the pid's process tree with the same watch openCell uses, with no limits enforced, and returns the unwatch function.
  • While it is watched, cellCounters() lists the label with that tree's CPU and memory. After unwatch it is gone.
  • It also shows up in cellRoots(), reported with an unlimited watch memory cap.

Test: src/apps/contain-label.test.ts follows the issue. It watches sleep 5 as crew:test and waits one WATCH tick. It expects the label in cellCounters() with non-zero memory, and gone after unwatch. It needs no unix socket or cell, so it runs in FORGE_TEST_SOCKET mode.

Left out: nothing calls watchLabelled yet. That is the second half of #2810, so crew runs are still unlabelled.

To try it: bun test ./test/spawn-pipes.test.ts ./src/apps/contain-label.test.ts.

Closes #2823

commented

watchLabelled(pid, label) is now in src/apps/contain.ts, and the check that parked this should pass now. I ran only test/spawn-pipes.test.ts and the new test, and both pass. tsc --noEmit is clean. The forge's check runs the rest on push.

Why the check failed: test/spawn-pipes.test.ts scans src/ for every Bun.spawn, and my new test spawned sleep 5 with the default piped stdout and stderr that nothing read. I changed the spawn in src/apps/contain-label.test.ts to ignore stdin, stdout and stderr. I did not add a reason to the list in test/spawn-pipes.test.ts, because with nothing piped the spawn doesn't need one.

What watchLabelled does:

  • It registers the pid's process tree with the same watch openCell uses, with no limits enforced, and returns the unwatch function.
  • While it is watched, cellCounters() lists the label with that tree's CPU and memory. After unwatch it is gone.
  • It also shows up in cellRoots(), reported with an unlimited watch memory cap.

Test: src/apps/contain-label.test.ts follows the issue. It watches sleep 5 as crew:test and waits one WATCH tick. It expects the label in cellCounters() with non-zero memory, and gone after unwatch. It needs no unix socket or cell, so it runs in FORGE_TEST_SOCKET mode.

Left out: nothing calls watchLabelled yet. That is the second half of #2810, so crew runs are still unlabelled.

To try it: bun test ./test/spawn-pipes.test.ts ./src/apps/contain-label.test.ts.

Approved

Approved. This is a small, internal change: one exported function that reuses the existing watchTree, plus a test that fails without it. It adds no page, input, write path or dependency, so the security, terminal, both-doors and README items have nothing to apply to. I did not exercise the preview, because nothing user-visible changes. The test spawns with ignored stdio, so it passes test/spawn-pipes.test.ts, and it needs no unix socket. Two things I would do next: (1) Before wiring the caller (the second half of #2810), check how src/system/view.ts and src/web/pages/system.ts render capBytes. watchLabelled reports cap.bytes as Infinity, which serializes to null in JSON and might print as "Infinity" in HTML. Either skip the cap row for unlimited watches or test the rendering. (2) When crew runs call it, add a test that a cancelled run calls the unwatch, so the label does not linger in /system. This follows the trust-and-calm pillar, where a cancelled run ends its processes.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs