diff options
| author | Calvin Morrison <calvin@pobox.com> | 2026-08-19 10:00:34 -0400 |
|---|---|---|
| committer | Calvin Morrison <calvin@pobox.com> | 2026-08-19 10:00:34 -0400 |
| commit | dee31d66b705734be68c1bb21ff5dfc7bdaae23b (patch) | |
| tree | a878c2b64b4106c02d4039f2c91c6b43ef548a01 /fw/test | |
| parent | 1575b83f102060eab99248c8e7660e9f61df1389 (diff) | |
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 <noreply@anthropic.com>
Diffstat (limited to 'fw/test')
| -rwxr-xr-x | fw/test/fwtest.rc | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/fw/test/fwtest.rc b/fw/test/fwtest.rc index 0325bfd..3f80242 100755 --- a/fw/test/fwtest.rc +++ b/fw/test/fwtest.rc @@ -46,7 +46,7 @@ mkdir -p $mtpt # The stacks the packet checks build for themselves. Fixed numbers are # fine because they are unbound again at the end of each block, and the # last check proves it. -stacks=(20 21 22 23 24 25 26) +stacks=(20 21 22 23 24 25 26 27 28) # A port of our own. Conversations outlive the run that made them - a # devip Conv is never freed - so a fixed port makes one run's leftovers @@ -551,6 +551,38 @@ echo '== a card' } } +echo '== supervision' +# fw daemonizes, like every other Plan 9 file server: the process you +# exec posts to /srv, forks the server and exits. A supervisor watches +# the /srv name instead of the pid, so the name has to mean what it +# says - present exactly while the firewall is filtering. +@{ + rfork n + mkdir -p $tmp/nD $tmp/nE $tmp/sctl + bind -a '#I27' $tmp/nD + bind -a '#I28' $tmp/nE + $fw -s fw.test.$pid -m $tmp/sctl $tmp/empty.ndb \ + $tmp/nD^'!'^10.9.9.1^'!'^/24 $tmp/nE^'!'^10.9.9.2^'!'^/24 >[2]/dev/null + check 'the process that starts it exits, as a file server does' '' $"status + sleep 2 + + r=`{if(test -e /srv/fw.test.^$pid) echo yes; if not echo no} + check 'and leaves its name in /srv' yes $"r + r=`{ls $tmp/sctl | wc -l} + check 'with the control files mounted' 4 $"r + + # what a supervisor would restart on. Taking the control + # filesystem away used to end the server proc and leave the relays + # filtering: a firewall nobody could reach, stop, or notice. + unmount $tmp/sctl + rm /srv/fw.test.$pid + sleep 3 + r=`{ps | awk '$NF == "fw"' | wc -l} + check 'losing the control filesystem stops the whole firewall' 0 $"r + r=`{sed 1q $tmp/nD/ipifc/0/status | awk '{print $2}'} + check 'and the interface it made goes with it' maxtu $"r +} + echo '== fwstart' if(test -f $lib/fwstart) @{ |
