Repository navigation
9P over devssl survives its readers being killed mid-read - #1153
Merged
Merged
Conversation
tests/ninep_disconnect_test.b kills readers of an encrypted 9P mount
(export(2) over loopback TCP with devssl, as listen ... {export dir}
serves a feed) at random moments, round after round, and checks the
same mount still walks, stats and reads byte for byte. It failed at
its first round; four causes:
- devssl hung up the connection on any write error, interrupted
included: a 9P client killed while sending its request took the
mount down for every other client ("inappropriate use of fd"). In
the emulator a record went to the socket from the writer's own
thread, and an interrupt could cut it part way. Records now go
through a queue to a writer kproc, queueing being whole or nothing,
and an interrupt after every record is queued is no reason to hang
up. Native's TCP and pipes are qio, which queues before it waits,
so native needs only the second half.
- emu's osleave raised an interrupt that arrived during a host call
even when the call had done its work: bytes read off a socket were
thrown away and the next devssl record failed its digest ("bad
digest"). osleavekeep drops the interrupt after a socket read or
write that moved bytes; a killed Prog is still found killed at its
next sleep and on its way back to the VM.
- An orphaned call answered before its flush was freed at once and
its tag reused while the flush naming it was still out: the server
flushed the new call and the client took the old flush's answer for
it, so replies reached the wrong calls (an Rclunk to a Twalk, an
Rwalk to a Tclunk: "too many QIDs returned by walk", "unexpected
reply tag"). Such a call is now held, with its tag, on m->held until
its flush is answered. Emu and native.
- A clunk or a walk's new fid given up on unanswered was used again
while the server might still hold it ("fid in use"):
chanfidretire gives the Chan a fid never used before. Emu and
native.
macOS emu: the test passes 60 rounds on every seed tried, under -c1
and -c0; the whole suite 273 passed, 0 failed.
Member
Author
|
Native comparison on the same Orin (QEMU 6.2), virt suite: master 036dd48 gets 200 passed, 5 failed, and this branch gets 200 passed, 5 failed. The five failures are the same in both: USB Ethernet DHCP, its default route, and pings over the usb, xhci and msi adapters. They come from that machine's QEMU, not from this change; master's CI virt job passes them. |
Member
Author
|
On the Raspberry Pi 5, native, |
pdfinn
added a commit
that referenced
this pull request
Nov 10, 2026
…1152 #1133 (merged) and this branch fix the same failures of an encrypted mount whose readers are killed, differently. Where they meet, this branch's design is kept: - osleavekeep: this branch's, which drops an interrupt that came while a host call moved bytes. #1133's left it pending for the next Sleep, which interrupted an exportfs worker's next request ("clone failed: interrupted"). The two definitions had both merged into proc.c. - sslbwrite: this branch's, records queued whole to a writer of their own. #1133's begun-record tracking and the interrupt it raised before each record are left out: merged with them, ninep_disconnect_test crashed in mntfree. - devmnt: #1133's mntkilledsend, which cleared a pending interrupt before a killed call's flush, clunk or remove, is left out: with it ninep_disconnect_test failed 1 run in 8 ("fid in use"). - ipif (FreeBSD, Nt too): this branch's comment, the interrupt dropped. Without them, under -c0: ninep_disconnect_test 10 of 10 (it had failed 3 of 6 merged as git merged it, and #1153 alone passed 5 of 5), and #1133's own ssl_killedcall_test 5 of 5. kill_deadserver_test, kill_uncalled_test, 9p_export_test and tcp_test pass. The native kernel's devssl merged without conflict: #1133 did not change its write path.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Readers killed in the middle of their reads could break an encrypted 9P mount for everyone else on it. This is the robustness half of the 9P/video work: a board's feed went out of step after many viewers left (
too many QIDs returned by walk,fid already in use), unexplained until now.The test
tests/ninep_disconnect_test.bsets up an encrypted mount the way a feed is served: export(2) over loopback TCP with devssl, aslisten ... {export dir}does. The exported tree has a 1 MB file and a file2chan file whose reads answer late, much later, or never. Each round it:Every few rounds it also drops the connection and makes another. At the end no Prog may be left over. It runs 60 rounds (
-n,-sseed) in about 5 seconds and exits on its own, so the runner picks it up.On the unfixed emulator it failed in round 0, every time.
Four causes, each fixed
inappropriate use of fd).osleavethrew away a host call's work when an interrupt arrived during it. Bytes read off a socket were lost, and devssl's next record failed its digest (bad digest).osleavekeepdrops the interrupt after a socket read or write that moved bytes.mismatch ... T110 R121, an Rclunk to a Twalk; then an Rwalk to a Tclunk), as on the Pi.m->helduntil its flush is answered. Emu and native.fid in use).chanfidretiregives the Chan a fid never used before. Emu and native.Verification
-c1and-c0. Before the fixes it failed in round 0. The full suite: 273 passed, 0 failed, 33 skipped.another DHCP client has port 68; waiting, and pings over the adapter failed.