diff options
| author | Calvin Morrison <calvin@pobox.com> | 2026-08-18 22:10:28 -0400 |
|---|---|---|
| committer | Calvin Morrison <calvin@pobox.com> | 2026-08-18 22:10:28 -0400 |
| commit | 95cd286e5018e6d12bae869406e38397a3d069c1 (patch) | |
| tree | 37d530382ff988f9a628e8926fbd077b4e073194 /fw | |
| parent | ed972197544a12d2527cfe6d9ac0c0d9beb399b0 (diff) | |
fwstart: make the directory before mounting on it, and let go of the console
if(! test -d /mnt/fw)
mntgen /mnt/fw
mount(2) needs its mount point to exist, so mntgen cannot create
/mnt/fw -- and this ran it only when /mnt/fw was missing, which is
exactly the case where it fails:
mntgen: mount /tmp/mg/fw: file does not exist: '/tmp/mg'
So on a machine that had never had a /mnt/fw, the control directories
never appeared, and fw's own "not touching the card until the mountpoint
exists" check then refused every card in the file. The script has never
worked on a fresh machine. It has also never been run by the suite,
which is the other half of why nobody noticed.
Now the directory first, then mntgen only if it is not already there --
under mntgen every name exists, which is the test.
Both mntgen and fw leave a server behind, and a server started from a
shell keeps that shell's descriptors, so at boot they sit on the
console's input and it reads as a wedged terminal. This is the trap
CLAUDE.md documents; the script was walking into it. They get
/dev/null.
Three checks, and fwstart now gets run at all: a control directory
appears, a card that is not there is reported and skipped, and nothing
left running holds the descriptors we started it with. The first fails
against the old script. The third does not, because the old script
never started anything for want of the directory -- it guards the fix
from here, not the bug that was there.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'fw')
| -rwxr-xr-x | fw/lib/fwstart | 20 | ||||
| -rwxr-xr-x | fw/test/fwtest.rc | 36 |
2 files changed, 53 insertions, 3 deletions
diff --git a/fw/lib/fwstart b/fw/lib/fwstart index 00b4d3a..ce89691 100755 --- a/fw/lib/fwstart +++ b/fw/lib/fwstart @@ -38,9 +38,23 @@ fn rulesfor { ' $cfg } -# each card gets its own control directory; mntgen makes them appear +# Each card gets its own control directory; mntgen makes them appear. +# +# mount(2) needs the mount point to exist, so mntgen cannot make /mnt/fw +# and this used to run it only when /mnt/fw was missing - which is the +# one case where it fails. So the directory first, and then mntgen only +# if it is not already there: under mntgen every name exists, which is +# the test. +# +# mntgen and fw both leave a server behind, and a server started from a +# shell keeps that shell's file descriptors. Started from the console - +# or from a serial shell, which is where this gets tried first - that +# means a daemon sitting on the console's input, which looks exactly +# like a wedged terminal. Give them nothing to hold. if(! test -d /mnt/fw) - mntgen /mnt/fw + mkdir -p /mnt/fw +if(! test -d /mnt/fw/is-mntgen-here) + mntgen /mnt/fw </dev/null >/dev/null >[2]/dev/null for(name in `{cards}){ dev=/net/$name @@ -52,7 +66,7 @@ for(name in `{cards}){ if not if(! test -f $rules) echo fwstart: $rules missing, $name skipped >[1=2] if not { - fw -m /mnt/fw/$name -e $dev $rules + fw -m /mnt/fw/$name -e $dev $rules </dev/null >/dev/null if(~ $status '') echo fwstart: $name filtered by $rules if not diff --git a/fw/test/fwtest.rc b/fw/test/fwtest.rc index 15ea531..d4222a8 100755 --- a/fw/test/fwtest.rc +++ b/fw/test/fwtest.rc @@ -30,6 +30,11 @@ src=$2 if(~ $#src 0) src=/sys/src/cmd/fw +# where the scripts are, likewise +lib=$3 +if(~ $#lib 0) + lib=/lib/fw + tmp=/tmp/fwtest.$pid mkdir -p $tmp nA=$tmp/nA @@ -391,6 +396,37 @@ echo '== packets, between two stacks' stopfw $nA $nB } +echo '== fwstart' +if(test -f $lib/fwstart) +@{ + rfork n + # /mnt as it is at boot: a real directory, with no fw in it yet. + # -c because without it the bound directory forbids creation and + # fwstart's mkdir fails for a reason the real /mnt would not give. + mkdir -p $tmp/mnt + bind -c $tmp/mnt /mnt + >$tmp/marker + echo 'fw=nosuchether rules='^$tmp/empty.ndb > $tmp/fwcfg + @{ rc $lib/fwstart $tmp/fwcfg } <$tmp/marker >$tmp/fwout >[2=1] + sleep 1 + + # mount(2) needs the mount point to exist, so the old + # "mntgen /mnt/fw only if /mnt/fw is missing" ran it exactly when + # it could not work, and every card's control directory failed + r=`{if(test -d /mnt/fw/whatever) echo yes; if not echo no} + check 'a control directory appears for each card' yes $"r + + r=`{grep -c nosuchether $tmp/fwout} + check 'a card that is not there is reported and skipped' 1 $"r + + # anything it leaves running holds the descriptors it was started + # with, and on a console that is the console + r=`{cat /proc/*/fd >[2]/dev/null | grep -c $tmp/marker} + check 'and nothing it started kept our descriptors' 0 $"r +} +if not + echo ' skip no '^$lib^'/fwstart' + echo '== the test cleans up after itself' r=`{nfw} check 'no fw processes are left running' $"fwbefore $"r |
