From 147b0ca1e4e00f66abb47fff3c543b853033f609 Mon Sep 17 00:00:00 2001 From: Calvin Date: Sun, 16 Aug 2026 20:52:12 -0400 Subject: Initial commit: svc supervisor, design docs, session transcript Existing work moved from /storage/vms/9front/svc, previously unversioned. Object files and linked binaries excluded via .gitignore. --- svc/doc/inventory.md | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 svc/doc/inventory.md (limited to 'svc/doc/inventory.md') diff --git a/svc/doc/inventory.md b/svc/doc/inventory.md new file mode 100644 index 0000000..a63907d --- /dev/null +++ b/svc/doc/inventory.md @@ -0,0 +1,113 @@ +# What termrc and cpurc actually contain + +Taken from reading both scripts and from `ps` on a booted machine, which is +the more reliable of the two — the scripts are full of conditionals that never +fire. + +Kernel processes (0K, `Wakeme`/`Idle`: `pager`, `alarm`, `etherread4`, +`iasata`, …) are not in scope. They are not started by anything in userspace. + +## Adopted — init can stop these but never starts them + +Started by `bootrc`, before init exists. No `exec=`, `adopt=yes`, stop only. + +| what | evidence | how to stop it | +|---|---|---| +| `hjfs` | pids 320–328, `/srv/hjfs.cmd` | `stop=write:/srv/hjfs.cmd:halt` | +| `factotum` | pid 260, `/srv/factotum` | note | +| `paqfs` | pid 8, serves the boot archive | note | + +`hjfs` is the one that must be stopped last, after everything using it. + +## Base namespace — init does these directly, they are not services + +None of this survives as a service, because a service runs in its own namespace +group and so cannot change anyone else's. + +- `for(i in P S f æ t L A J '$') bind -qa '#'^$i /dev` +- `mount -qb /srv/cons /dev` +- binding the `mntgen` channels onto `/n`, `/mnt`, `/mnt/exportfs` +- `mount /srv/factotum /mnt/factotum` and the `bind -q` after it + +## Services + +| service | evidence | ready | needs | notes | +|---|---|---|---|---| +| `slashn` | pid 11 | `srv:slashn` | | `mntgen` for `/n` | +| `slashmnt` | pid 14 | `srv:slashmnt` | | `mntgen` for `/mnt` | +| `mntexport` | pid 17 | `srv:mntexport` | | `mntgen` for `/mnt/exportfs` | +| `kbdfs` | pids 70–74 | `exec` | | posts nothing in `/srv` | +| `usbd` | pids 82–83 | `exec` | | from `nusbrc` | +| `kb` | pids 91–92 | `exec` | `usbd` | from `nusbrc` | +| `cs` | pid 372 | `srv:cs` | | | +| `dns` | pid 446 | `srv:dns` | `cs` | | +| `timesync` | pid 450 | `exec` | `dns` | needs a name to resolve | +| `realemu` | pids 456–457 | `exec` | | vga real-mode calls | +| `webfs` | pid 500 | `exec` | `dns` | | +| `webcookies` | pid 497 | `exec` | | | +| `plumber` | pids 503–504 | see below | | | +| `ipconfig-ra6` | pid 439/440 | `exec` | | the lingering RA listener | + +Only on a machine that is meant to accept logins: + +| service | from | ready | needs | +|---|---|---|---| +| `listen` | `cpurc` | `exec` | `cs` | +| `keyfs` | `cpurc`, auth branch | `srv:keyfs` | | +| `authsrv` | `cpurc`, auth branch | `dial:tcp!*!567` | `keyfs` | + +## Oneshots — `ready=exit` + +- `diskparts` +- `swap` (only when `/dev/sd*/swap` exists) +- `ip/ipconfig -h $sysname ether $ether` — the DHCP one, as opposed to the RA + listener above, which stays +- setting `/dev/sysname` +- `screenrc` + +## What simply disappears + +- **The `service=` branch itself.** `termrc` and `cpurc` are 80% identical: the + same device binds, the same `mntgen` lines, the same `factotum` mount, the + same `cs`/`dns`/`diskparts`/`swap`. The difference is which of two nearly + identical scripts runs. +- **The role detection block.** `cpurc` decides whether this machine is an + authentication server by comparing `$sysname` against the `auth` attribute in + ndb, and starts `keyfs` plus a different `listen` if it matches. That is the + archetype logic, in one `if`. It becomes: is `keyfs` enabled or not. +- **`serviced=` selection** — `/cfg/$sysname/service`, `/cfg/default/service`, + `/rc/bin/service`, in that order. Replaced by `/lib/svc`. +- **The `.local` and `/cfg/$sysname` hooks** — `cpurc.local`, `termrc.local`, + `/cfg/$sysname/cpurc`, `/cfg/$sysname/cpustart`. Four hook points that exist + because a shell script has no other way to be extended. A directory of + service files does not need them. +- **`rm -f /env/i`, `rm -f /env/disk`, `rm -f /env/ether /env/addrs /env/addr`** + — these clean up after `for` loops and backquote assignments. They exist + only because this is a shell script, and vanish with it. +- **`NPROC`, `prompt`, `fn term%`** — shell configuration that has no business + in system startup. Belongs in `profile`. +- **`dontkill`** — a list of process names protected from `kill`. Worth + revisiting rather than porting: with a supervisor that knows what it started, + protecting things by name is the wrong shape. + +## Two problems this turned up + +**`plumber`'s `/srv` name is dynamic.** It posts `/srv/plumb.glenda.502` — +user and pid baked into the name. `ready=srv:name` cannot express that, and +neither can `stop=write:...`. Options: allow a glob in `ready=srv:`, accept +`ready=exec` and lose the liveness check, or treat it as a general escape and +add `ready=file:pattern`. Unresolved, and it will not be the only such server. + +**`ipconfig` appears twice with different lifetimes.** One does DHCP and exits +(a oneshot); the other listens for router advertisements and stays (a service). +They are the same binary with different arguments, so they must be two service +files with different names. Fine, but it means service name and program name +cannot be assumed to match — which the current implementation already allows, +since `svc=` and `exec=` are separate. + +## Also worth noting + +There is no `aux/listen` running on this machine, because it booted as +`service=terminal`. Every service above marked "only on a machine meant to +accept logins" is absent purely because of one word in `plan9.ini` — which is +the whole argument, visible in `ps`. -- cgit v1.2.3