From dee31d66b705734be68c1bb21ff5dfc7bdaae23b Mon Sep 17 00:00:00 2001 From: Calvin Morrison Date: Wed, 19 Aug 2026 10:00:34 -0400 Subject: fw: make the /srv name worth watching, and say how to supervise it todo.md said fw daemonizing meant svc could not supervise it, and that it needed a foreground mode. Both wrong. svc has had the shape from the start. ready=srv: watches the /srv name rather than the pid, and its own manual says why: "Use this for a service that posts to /srv and lets the process you started exit, which many Plan 9 file servers do on purpose. For these the /srv file is watched and the process is not, so the process exiting is normal and never causes a restart." init.c agrees -- reap() returns early for Ksrv with that comment on it. Nor is detaching unusual. 42 commands under /sys/src/cmd use postmountsrv or threadpostmountsrv; five call srv() directly, and every one of those is a stdio server (ramfs -i, ext4srv -s, skelfs, hjfs, wacom) speaking 9P on file descriptors it was handed. That is not a foreground service, it is a pipe server: no /srv, no mount, nothing to supervise. A foreground mode for fw would buy a pid to watch, and the /srv name is the better signal -- it survives the process that made it. What was true underneath the wrong diagnosis: the name was not honest. Taking the control filesystem away ends the server proc, and the relays carried on filtering: procs: 3 ... take the ctl filesystem away ... procs after: 2 still filtering? pkt interface: pkt0 A firewall nobody can reach, stop, or notice, and the /srv name gone while it runs. Srv.end now takes the whole thing down, which is the answer the relays already gave when their wire failed. Same test after: three procs become none and the interface goes with them. So: no flag, an example service file in lib/svc, and a SUPERVISION section in fw(8) that says what init should watch and what restarting will and will not fix. Restart=always brings fw back; it does not undo taking the card, so the new fw has no address to read. Supervision works, recovery does not, and that stays open as item 1. Two checks. Against the previous fw.c they fail with two orphaned procs and a pkt interface still bound -- and so do the leak checks at the end of the run, which is what they were built for. 77 pass. Co-Authored-By: Claude Opus 5 --- fw/lib/svc/fw.ether0 | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 fw/lib/svc/fw.ether0 (limited to 'fw/lib') diff --git a/fw/lib/svc/fw.ether0 b/fw/lib/svc/fw.ether0 new file mode 100644 index 0000000..93de412 --- /dev/null +++ b/fw/lib/svc/fw.ether0 @@ -0,0 +1,27 @@ +# +# One firewall, one card. Copy this per card that should be filtered: +# the name, the srv name and the -e argument change together. +# +# fw daemonizes, as Plan 9 file servers do, so what init watches is the +# /srv name and not the pid. The name is there exactly while the +# firewall is filtering: it appears when the server posts it and goes +# when the last of fw exits, whether that is the wire failing, the +# control filesystem going away, or a note. +# +# It has to start after the card has an address, because that is where +# fw reads the address, mask and gateway from - and before anything +# dials, because a connection made before fw is up was never filtered. +# +svc=fw.ether0 + exec=/bin/fw + args=-s + args=fw.ether0 + args=-m + args=/mnt/fw/ether0 + args=-e + args=/net/ether0 + args=/lib/fw/host.ndb + needs=ipconfig + ready=srv:fw.ether0 + restart=always + enable=no -- cgit v1.2.3