Repository navigation
A TCP stream is one region and one connection to netstack (netstack data-path track, stage 3) - #905
Conversation
|
Rulings on R1-R3, and acceptance.
The track's text moves with these in the build's diff. Accepted: build stage 3. |
… the netstack data-path track) A received byte was copied three times between the card's buffer and the application: into [tcp]'s heap ring, into a kernel pipe under the global pipe lock, and out of it; a sent byte four times. How a stream ended was the order its two pipes closed in, and a stream's client leaving was learned only through those pipes. Stage 3 of issues/netstack-moves-every-byte-through-two-kernel-pipes.md replaces both pipes with a region the client makes and lends, which is [tcp]'s two buffers, and the connection it was opened on, which carries the request and its answer and then only doorbells and the hang-up. Under the orchestrator's rulings on #905: an accepted stream is a region too (R1), what a passive child held copied into it at its offsets, so std's make_socket_fd and SYS_CONNECTION_JOIN go; mio and socket2 reach a stream through std (R2), which keeps the one table of the process's ends; toyos-transport and toyos-untrusted join std's graph as published SDK crates (R3). - toyos-transport: stream.rs gains the ring back, and session.rs is the duplex session, the client's read, write, poll and registration sequences written once over a lock and doorbells the adapter supplies, and the server's publish, release, finish, fail and ring back. Three loom models drive them, each red under the controls the track names. - [tcp]: a ring's storage is its own or lent; a connection is lent the region's rings, what it held moving there, and the user's read and queue are `consume` and `queue`, with no copy into [tcp]. - The node: a stream is a connection, its lent rings and the server end; a hostile word is a Violation that resets that stream alone; the client's hang-up is the close, and the ownerless clock goes. - netstack: a region is judged by `SharedMemory::lent` before it is mapped; a stream is one watch, its connection. - toyos::net::stream: the region's declaration, the process's ends in a fixed table behind futex locks (the lock libc had moves to toyos::sync), connect, accept, read, write, shutdown, nodelay, register and poll. - std: TcpStream is a handle entered there; FromRawFd, IntoRawFd and the OwnedFd conversions take only the process's own ends; File::from_raw_fd and every spawn path refuse a stream's handle; the rust/ fork routes OwnedFd's drop and try_clone_to_owned through toyos::net. std::os::toyos::net gives mio the bell and the registration. - libc: sockets over toyos::net::stream, and poll asks the rings first. - mio and socket2 forks: through std, and neither names toyos any more. - kernel: SYS_CONNECTION_JOIN and ConnectionEnd::joined go. issues/netstack-spends-two-poller-slots-per-piped-connection.md closes: a stream is one watch and WATCHES_PER_PLACE is gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
9a2af1f to
432df72
Compare
…el takes The T14's internet_download boot refused every stream at its first pass: "the kernel refused the watch of its connection: NotSupported". netstack watched a stream's connection `READABLE | OTHER_END_GONE`, and the kernel refuses `OTHER_END_GONE` on a Connection (`ops::pipe_end_watch` answers a pipe end alone, `inbox::arm`). A pipe read end with no writer is readable (`kernel/pure/pipe.rs`), so `READABLE` answers both the client's rings and its hang-up, which the drain reads as 0. QEMU never caught it: no QEMU test runs a stream through netstack, and `stream_handles`' fake netstack watched nothing. The watch is now one declaration, `toyos::net::stream::SERVER_WATCH`, which netstack registers and `stream_handles` holds to the kernel: the watch is taken and answered by the client's hang-up. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Review of #905 at
|
…re cleared; records the change made false updated - toyos::net::stream: an end freed by its last handle or call keeps its slot reserved until `free` has cleared its halves and closed its bell and region, so a concurrent connect cannot take the slot and have its halves cleared under it (the review's blocker 2). - [tcp]'s `Outgoing` says the payload is copied out of a lent buffer, and the track records the send path's second copy (blocker 3). - issues: toyos-has-its-own-network-stack.md loses the ownerless clock and the reset-stream option bullets and names lend/consume/queue for recv_with; a-streams-failure-reaches-its-client-as-a-reset-whatever-it-was.md is narrowed to what is owed, the timeout and unreachable words' tests; a-stream-its-peer-reset-refuses-the-option-requests-a-host-answers.md closes, since no option request is left to refuse (`set_nodelay` writes the region's word, which stays writable after a reset); and nothing-reads-whether-a-streams-tcp-nodelay-reached-netstack.md closes, since the word is what netstack reads and the node's `nodelay_reaches_the_stack` and `nodelay_set_before_the_connect_holds_from_the_first_segment` read its effect on the wire (blocker 4). - issues/a-stream-commits-eight-mebibytes-and-a-process-holds-128.md files the region's commitment and the end table's bound, with exits (blocker 5). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
tests/guest/rust-tests/Cargo.lock: both sides' packages kept, toyos-transport from this branch and toyos-virtio from main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
…de8ab6e2: host suite, images, the netstack QEMU stream run and its control, the server-watch and slot controls
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
…suite, image, guest suite, T14 retake staging
…ME's suite claim corrected
Review round 2 of #905 at
|
…own; two records made true - [tcp]'s net tests: an application can read its connection's lent receive ring itself and give the text back with `consume` (`Net::lend`), and `a_lent_receive_ring_grows_the_window_as_a_read_does` runs the T14-shaped download (gigabit, 15 ms, 32 MiB) that way: the window passes 65,535 and reaches the 4 MiB buffer. Red, at 65,535, when `consume` grows nothing. The T14's 23.7 Mb/s is therefore not [tcp]'s window on a lent ring; the baseline boot of main with the scout's instrument attributes it. - issues/toyos-has-its-own-network-stack.md: the §3.10.7.4 bullet says text published into a client's receive ring, not written to its pipe. - toyos::net::stream: `Slot::Making` is also an end `free` lets go of. - serve.rs: `watch`'s comment rewrapped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
…the lent-window test and its control, host suite, image, round-2 T14 staging
Round 3's T14 boots of PR #905 read run 1 at 107 Mb/s on main's pipe path and 470 Mb/s on stage 3, against 722 to 878 Mb/s for runs 2 to 6 on both, with the CPU idle: a first-run stall independent of stage 3, filed with its candidates and exit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
…e per-run analysis; round 2's boot.txt re-masked
Review round 3 of #905 at
|
…eadings; `finished` keeps its doc - issues/netstack-moves-every-byte-through-two-kernel-pipes.md: stage 3 is done, as stages 1 and 2 are: what it built, the regression and the second send copy it leaves, and the T14 exit as read against main's baseline under the same instrument (pipe_copy_bytes 0.000135 per byte against 2.0029; hold, spin, C0 and rate), linked to the evidence commit. - [tcp]'s net harness: `finished`'s doc comment is back on `finished`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
…suite, image, loom models and controls, the accept-copy, write-after-reset and stream_handles controls, the guest suite and the T14 staging
…de8ab6e2: host suite, images, the netstack QEMU stream run and its control, the server-watch and slot controls
…suite, image, guest suite, T14 retake staging
…ME's suite claim corrected
…the lent-window test and its control, host suite, image, round-2 T14 staging
…e per-run analysis; round 2's boot.txt re-masked
…suite, image, loom models and controls, the accept-copy, write-after-reset and stream_handles controls, the guest suite and the T14 staging
…de8ab6e2: host suite, images, the netstack QEMU stream run and its control, the server-watch and slot controls
…suite, image, guest suite, T14 retake staging
…ME's suite claim corrected
…the lent-window test and its control, host suite, image, round-2 T14 staging
…e per-run analysis; round 2's boot.txt re-masked
|
Evidence branch |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What this is
Stage 3 of
issues/netstack-moves-every-byte-through-two-kernel-pipes.md, built as #905's design round set it out and as the orchestrator ruled on R1 to R3 (#905 (comment)). Draft. The track's stage-3 exit is met on the T14 (below): in every run ofinternet_downloadthe kernel copies 0.00013 to 0.00015 bytes of pipe per byte downloaded, against 2.003 on main's pipe path under the same instrument, at the same rate and C0.A TCP stream — a connected one and an accepted one alike (R1) — is one region the client makes and lends, which is [tcp]'s two buffers, and the connection it was opened on, which carries the request and its answer and then only doorbells and the hang-up. A received byte is copied once by netstack into the region and once by the client out of it; a sent byte once by the client into the region and twice by netstack: out of the region into [tcp]'s segment scratch, then into the frame. A frame builder that copies the region's spans straight into the frame would remove the second; the track records it. Neither passes through a kernel pipe or the
PIPESlock.The change, by layer
toyos-transport(lib/blockring/transport):stream.rsgains the ring back; newsession.rsis the duplex session — the client's read, write, poll (watch/unwatch) andregistersequences written once over aLockandBellsthe adapter supplies, and the server'spublish,release,finish,failandrung. Amendments A (a bell per direction), B (no end held across a wait; a take passed on), D (a registration arms and rings) and rulings 2 and 3 (a fatalendreadies the send direction;writereads it before it copies) live here.Ring's storage is its ownVecor aLentone (copied into and out of, never borrowed).Tcp::lendmoves a synchronized connection onto the region's rings, everything it held at its offsets (amendment C);consumeandqueueare the client's read and publish, with no copy into [tcp]; the send buffer is the whole send ring.recv_withand itstake.rstests go;lent.rsholds the lend, the window update a read owes (RFC 9293 §3.8.6.2.2) and the send ring as segment text.Session] keeps the mapping in netstack). A pass reads the head, publishes, releases, queues, turns the client's shutdown into the FIN and stores a failure as theend. A hostile word is aViolationthat resets that stream alone. The client leaving isNode::left;OWNERLESS_LIFE,OWNERLESS_PER_PEERand the cut go, [tcp]'sORPHAN_IDLEowning the orphan. An accept lends the region (AcceptRefused::NoRegion).lent.rsjudges a region throughSharedMemory::lentbefore mapping it; a stream is one watch, its connection, fortoyos::net::stream::SERVER_WATCH(READABLEalone: the kernel refusesOTHER_END_GONEon a connection, and a connection whose client is gone reads as ended, whichdrainedtakes as the client leaving);WATCHES_PER_PLACEgoes, soissues/netstack-spends-two-poller-slots-per-piped-connection.mdis closed.PLACE_BYTESis the region and three pipe pages.toyos::net::stream: the region's one declaration, the process's ends in a fixed table (MAX_STREAMS= 128) behind futex locks, and connect, accept, read, write, shutdown, nodelay, register, watch/unwatch,adopt,duplicate,let_go,is_stream. libc's three-state futex lock moves totoyos::syncand libc uses it.TcpConnectPiped,TcpAcceptPiped,TcpShutdown,TcpSetOption,read_end,write_refusedandStreamRefusalgo.TcpStreamis a handle entered intoyos::net;FromRawFd,IntoRawFd,From<OwnedFd>andFrom<TcpStream> for OwnedFdtake only the process's own ends;File::from_raw_fdof a stream's handle and every spawn path (stdio slots,inherit_handle,endow,provide) refuse it by name before anything moves;take_erroranswers theend; netstack gone isConnectionAborted.std::os::toyos::net::TcpStreamExtgives mio the bell andregister(R2).OwnedHandle::from_raw's# Safetyexcludes a stream's handle.rust/(73f63e2441bon the fork'smain):OwnedFd's drop andBorrowedFd::try_clone_to_ownedcalltoyos::net::stream::let_goandduplicate;library/Cargo.lockgainstoyos-transportandtoyos-untrusted.build/sdkversion.rs'sPUBLISHEDbeforetoyosandbuild/sysroot.rs's sources, manifests and std patch, with arustc-dep-of-stdfeature.toyos::net::stream;recv/sendanswerECONNRESET,ETIMEDOUT,EHOSTUNREACH,ECONNABORTED;pollasks the rings first and watches the connection forPOLLINand the bell forPOLLOUT.836d14fontoyos) and socket2 (12abd8fontoyos): their ToyOS arms hold std'sTcpStream/TcpListener; neither depends ontoyosany more; mio registers the bell as writable and callsregister.SYS_CONNECTION_JOIN,ConnectionEnd::joined,HandleQueue::deadand the pipe ends'referencego;abuse_pipe_ownerloses itsjoinarm.toyos, host clippy reachestoyos; fourteen lints there are fixed (mechanical:as_chunks,is_multiple_of, aDefault, anis_empty, a range, and a reasonedallowonOwnedHandle::into_raw'sforget).Net lines against main f0a987b (
git diff --numstat): production +3,128 −1,338, tests +1,605 −1,051, issues +162 −224. Production grows by the session (session.rs~850 lines with its tests), the SDK's stream end (~700) and netstack's adapter; the pipe paths it replaces were smaller because the kernel carried their state.Round 4 (after the round-3 review)
finished's doc comment back onfinished; stage 3 marked done inissues/netstack-moves-every-byte-through-two-kernel-pipes.md(the track whose stages 1 and 2 are marked done;toyos-has-its-own-network-stack.md's stages are another track's), with its exit readings and the evidence commit; main9842eeda5merged and the host suite rerun at the merge. No bench rerun: the comment and records change nothing the T14 boots read, and the merge brings only main's #923 (microcode as a file per CPU), outside the stream path; the T14 readings stand onc5c69f12eand mainf0a987bc6, as recorded.The T14 reading (round 3)
One T14 boot per image,
internet_download, six whole runs of the 170,439,044-byte file in each, every sha256 right, judge EXIT=0 for both. The two trees differ by this change alone: baselinef11ebeaf0is mainf0a987bc6plus the instrument, stage 381afbe6c6is this headc5c69f12eplus the same instrument (27 files,git diff 0dcdbe24c 4313cb0b0), andgit diff f11ebeaf0 81afbe6c6equalsgit diff f0a987bc6 c5c69f12e. The baseline is the control. The scout's rows (C0 5.310 ms, H 0.2728, P 0.0397 ms per MB, 785.95 Mb/s) were read on an older base, before #917 and the rest of main since, so they are context and not the comparison.Medians of runs 2 to 6, per MB downloaded (MB = 10⁶ bytes), lock times in ms of TSC; computed from the judge logs by
round3/analysis/per-run.py:pipe_copy_bytesper byte downloadedpipe_copy_bytesis under 0.01 per byte downloaded in every run, all six included. What remains on pipes is the doorbells, DNS and the listener.issues/the-t14s-first-download-after-boot-runs-slower-than-the-rest.md(owner netstack; candidates toyos-i219: drive the PCH's MAC in MSI mode, and prove its message before driving it #917's MSI mode, the client's wake to read, a connection's warm-up) and not chased here.Review round 1
The build review (#905 (comment)) sent back five blockers; the first T14
internet_downloadwas red for the first.READABLE | OTHER_END_GONE; the kernel refusesOTHER_END_GONEon anything not a pipe end (kernel/src/inbox/mod.rs,ops::pipe_end_watch) withNotSupported, andserve.rsread the refusal as the client leaving. The T14 saidnetstack: closing a stream — the kernel refused the watch of its connection: NotSupported, thenhttps_downloadfailed. Fix: the flags are one constant,toyos::net::stream::SERVER_WATCH=READABLE, whichserve.rswatches with throughout. Guard:stream_handles' netstack stand-in watches its connection withSERVER_WATCHand asserts the kernel takes the watch and answers it with the client's hang-up, which then readsOk(0); red under the old flags (Err(NotSupported)). A QEMU virtio-net run through the real netstack (evidence only, not landing) carries a stdTcpStreamconnect, 4 MiB both ways, shutdown and end, and an accepted stream the guest answers and drops, whose host peer reads the end; under the old flags it reproduces the T14's line and fails. That the dropped accepted stream reaches its peer as an end shows aREADABLE-only watch reports the hang-up, so the poller-slot issue's closure stands.free_unusednow leaves the slot reserved (Making);freeclears the halves, closes the bell and region, then unreserves. The table test asserts the freed slot is not taken before; red with the slot freed early.Outgoingcomment and in the track.toyos-has-its-own-network-stack.mdloses the ownerless-clock and reset-option bullets and nameslend/consume/queue;a-streams-failure-reaches-its-client-as-a-reset-whatever-it-was.mdis narrowed to what is owed (node tests forTIMED_OUTandUNREACHABLEand a guest unreachable case);a-stream-its-peer-reset-refuses-the-option-requests-a-host-answers.mdandnothing-reads-whether-a-streams-tcp-nodelay-reached-netstack.mdclose (no option request is left; the node's nodelay tests read the word's effect on the wire).issues/a-stream-commits-eight-mebibytes-and-a-process-holds-128.md, exits demand-allocated regions and a growable or measured table.The six suggestions are not taken in this round: none is a defect, and each would reopen evidence (the loom models, the session) for a change the T14 reading does not need. Suggestions 3 and 4 (the deadline read against the clock; a live-end count before
TABLE) are worth their own change.Review round 2
The round-2 review (#905 (comment)) closed round 1's five blockers and sent back on the T14 reading (R1), with two records to correct (R2, R3).
internet_downloadfrom the instrument tree4313cb0b0(stage 3 at0dcdbe24c):cut bytes=101985020 secs=34.371 mbps=23.7 rtt_ms=[17.5 15.8 16.0 16.0 16.1] busy=0.007 cpu_s=1.799 cpu_ms_per_mb=17.64; idle LAN 0.34–0.42 ms. The row reads PASS becausecutexits 0, but no run was whole, so noperf run=line exists: nopipe_copy_bytesper byte downloaded, no C0, hold or spin per MB. The exit is not met and not read. It is the same measurement as the scout's rows: the samehttps_downloadbinary and file (170,439,044 bytes) from the same host on the same T14, the scout's handshakes 14.8–16.5 ms against these 15.8–17.5 ms, the rate by the same formula; the scout's six whole runs took about 1.7 s each (614.6–845.4 Mb/s). So the exit compares like with like, and the gap, about 33x with the CPU idle, is a stall, not a cost.RECEIVE_BUFFER_INITIAL= 65,535, so a window that never grows on a lent ring would explain it.a_lent_receive_ring_grows_the_window_as_a_read_does([tcp]'snet.rs, with the harness's newNet::lend) runs the T14-shaped download (gigabit, 15 ms, timestamps, 32 MiB) with the reader taking text out of its lent ring and giving it back throughconsume: the window passes 65,535 and reaches the 4 MiB buffer. Under aconsumethat grows nothing it is red at 65,535. [tcp]'s window on a lent ring is therefore not the cause; the node consumes on every receive batch (Node::receiveends in a pass), so the window sees the client's reads as they happen. Unverified alternatives remain: the client's wakes, or toyos-i219: drive the PCH's MAC in MSI mode, and prove its message before driving it #917's switch of the I219 to MSI, which entered with main6caaadf8fafter the first T14 boot.internet_downloadimages were booted once each, both mainf0a987bc6(which carries toyos-i219: drive the PCH's MAC in MSI mode, and prove its message before driving it #917) under one instrument (git diff 0dcdbe24c 4313cb0b0, 27 files): the baselinewt/toyos-netring-s3-baselinef11ebeaf0(main's pipe path) and the retakewt/toyos-netring-s3-instrument81afbe6c6(this head).git diff f11ebeaf0 81afbe6c6is exactlygit diff f0a987bc6 c5c69f12e, so the pair differs by this change alone: the whole change reverted. Both were whole and equal in runs 2 to 6, and both slow in run 1: the slowdown is main's, filed, and stage 3's exit is read.Slot::Making's doc names both reservations: a connect or accept not yet answered, and an endfreeis letting go of.serve.rs'swatchcomment is rewrapped.Checks
Evidence: https://github.com/ToyOSOrg/evidence/tree/4f33146cba323f79708ae51780f395d93619b81e/ (branch
pr-905), every log masked (<tree>,~,<tmp>,<mac>,<email>). Round 1's logs are underround1/andround1b/, round 2's (with the T14 readbacks, masked further:<ip>,<guid>,<serial>,<machine>) underround2/, round 3's T14 readbacks and analysis underround3/; the rest are the first round's.cargo run -- --ci hostround4/host.logcargo run -- --ci hostround3/gates/host.logcargo run -- --ci hostround2/gates/host.logcargo run -- --build-onlyround2/gates/build-only.loground2/controls/lent-window.sh(cargo test -p toyos-net-tcp --test net a_lent_receive_ring)round2/controls/lent-window-1920ac48d.logstream_handles(orchestrator)testcasesbootround2/metal/stage3-*internet_download(orchestrator)round2/metal/instrument-*internet_download, baseline control (orchestrator)round3/metal/baseline-*internet_download, retake (orchestrator)round3/metal/stage3-*,round3/analysis/round1b/cargo test --test toyos-buildround1b/guest-suite.logstream_handlesin QEMUcontrols/guest.sh … greenSome(0)round1b/stream_handles-qemu-0dcdbe24c.loground1/gates/cargo run -- --build-onlyround1/gates/instrument-build-only.loground1/netcheck/netcheck.shround1/netcheck/green-and-control-14142f258.logstream_handlesand the server-watch control, QEMUcontrols/guest.sh … green server-watch-other-end-goneSome(0);Some(101)round1/controls/stream_handles-green-and-server-watch-14142f258.logcargo test -p toyos --lib net::streamround1/controls/slot-freed-early-c0e87be2e.loggates/cargo test --test toyos-buildguest/suite.logstream_handlesin QEMU--debugboot,run test_rs_stream_handles(controls/guest.sh green)guest/stream_handles-qemu.logcontrols/controls.sh(cargo test -p toyos-transport [--features <c>] --test loom -- …)loom/session-models-and-controls.logloom/unbounded.sh(LOOM_MAX_PREEMPTIONS=255, 600 s cap)a_poll_beside_*gave no verdict in 600 sloom/unbounded.logcontrols/accept.shcontrols/accept-copy.logcontrols/write.shcontrols/write-after-reset.logstream_handles' six std controls, QEMUcontrols/guest.sh <control>…exit_code: Some(101)controls/stream_handles-std-controls.logWhat each control reds:
one-doorbell→ bothtwo_sleepers_*.no-pass-on→ all threea_poll_beside_*.register-no-arm,register-no-ring,register-neither→ all eighta_source_registered_*.want-relaxed→ bothtwo_sleepers_*, the threea_poll_beside_*and the four racing registration cases.head-only→ exactly the two reset cases. Each control is inbuild/ci.rs'sCONTROLS, andbuild/clippy.rs's$CONTROLSshape lints it.accept-drops-in-order→a_listener_answers_a_syn_…andwhat_a_child_held_in_order_past_a_hole_and_its_fin_reaches_its_stream;accept-drops-out-of-orderandaccept-drops-fin→ the second alone.write-copies-before-end→a_write_with_room_after_a_reset_answers_it_and_copies_nothing(copiedis 3, not 0).into-raw-lets-go→ the client never saysshared;file-takes-a-stream→ the as-file child is taken; each spawn control → its own path's line (stdio slot took the stream's handle,slot past stdio took …,endow took …).spawn-takes-providereds on the launcher's refusal (provide answered only a launch carries a provided connector, and this process holds no launcher):testcasesgives the test no launcher, soprovide's "handle moves and entry stays" arm is shown red but not by a moved handle.The six std controls ran at a39ff1b7d, before the squash and two merges of
main; the std, SDK and test sources they mutate are unchanged since but for module headers and the clippy fixes above, which change no behaviour they read. The green run ofstream_handleswas repeated at e7daded. e7daded to 432df72 is two merges ofmain(ABI/SDK changes for HDA and ps2server, none in this branch's files). Round 1 changesserve.rs's watch,toyos::net::stream's table andstream_handles, and merges main 6caaadf, whose kernel change (#910: a process's end published after its releases) touches the hang-up path; so the host suite, the image,stream_handlesand the netstack run were rerun at 14142f2. main 5b48a3d (#922's audio rows, #918's claim vectors) was then merged at 0dcdbe2, touching nothing on the stream path; the host suite, the image, the guest suite andstream_handleswere rerun there, and the netstack run and its controls stand on 14142f2. Round 2 adds a [tcp] test, two comment fixes and main f0a987b (#919's citation sweep, #917 already in); host suite and image were rerun at c5c69f1, and nothing else could have changed. The loom models, the [tcp] and node controls and the std controls read none of what round 1 changed and stand on their earlier heads.Independent oracles: RFC 9293 (§3.8.6.2.2, §3.10.4, §3.6.1, §3.10.7.4, §3.10.2, §3.10.8), POSIX.1-2024 (
send,recv,select), virtio 1.2 §2.9 and, unchanged, the host kernel's TCP in the node's differential tests. The whole change reverted cannot be the control for the unit and guest tests, which name APIs that do not exist onmain; each decision's own control above stands for them. On metal it is the control: the T14 baseline is main under the same instrument, and the two trees differ by this change alone.Why
stream_handlesis a guest test, and where it runsstd's ToyOS arms build only for
toyosand stand on the kernel's handle table, and a refused spawn needs a real spawn. It plays netstack itself (a port of its own served asnetstack, the region judged and published into withtoyos-transport's server end), so no NIC or peer is needed. It is a shared-boot member: on the T14 it rides thetestcasesboot; under QEMU it ran through the harness's debug boot. Supported: x86-64 (T14, QEMU); AArch64 untested.T14
First boot (432df72 / instrument 0de249252):
stream_handlespassed;internet_downloadwas red, exit 1, every stream closed at its first watch (round 1's blocker 1). Second boot (0dcdbe2 / instrument 4313cb0b0):stream_handlespassed;internet_downloadcrawled and was cut (Review round 2 above). Third (c5c69f1 / instrument 81afbe6c6, beside the baseline f11ebeaf0): both green, every run whole; the exit is met (the T14 reading above). The instrument is the scout's (git diff 777c96b2b 2f9e090b8) less every netstack stamp and the cadenceKword, which stage 3's tree no longer has, and the baseline carries exactly the same files.stream_handlespassed on the second boot'stestcases, at 0dcdbe2; since then only a [tcp] test, two comments, an issue and main f0a987b changed, none of whichstream_handlesreads.Removed tests, and what holds their behaviour
node/tests/streams.rsis rewritten over the real session client end on a heap region (35 cases). Cut, with pipe meaning only: the pipe-end ordering cases (a_reset_after_the_clients_shutdown_lets_the_send_pipe_go_first,a_finished_send_pipe_goes_with_its_reader,the_peers_fin_after_the_clients_shutdown_leaves_the_send_pipe_to_its_writer,a_writer_that_leaves_after_the_shutdown_leaves_the_stream_to_its_reader,a_shutdown_after_the_peers_fin_keeps_the_send_pipe_past_the_connections_end), the ownerless clock (a_departed_clients_unsent_bytes_have_100_seconds,…tail_arrives_whole…,…100_seconds_without_progress, the three sixteen-per-peer cases), the pipe refusals (a_pipe_that_is_no_pipe_resets_its_connection,a_refused_watch_resets_only_a_stream_that_holds_the_end) and the pipe-room cases (a_full_pipe_keeps_the_rest_in_the_stack…,nothing_leaves_the_pipe_that_the_stack_will_not_take,a_send_pipe_found_empty…). Their region meanings are held by the reset-is-the-end cases,a_head_past_what_was_published_resets_that_stream_alone,a_tail_past_the_send_rings_room_resets_that_stream,text_published_after_the_shutdown_resets_that_stream,a_write_larger_than_the_window_is_queued_whole_and_arrives_wholeanda_read_opens_a_shut_window_at_the_next_opportunity.listeners.rs:an_accept_answers_the_option_of_a_stream_its_own_pass_let_goandan_accepted_stream_is_one_of_its_peers_addresss_sixteengo with the pipe and the clock (ruling 1 named the first's replacement, nowwhat_a_child_held_…); the departed-client place cases are rewritten over [tcp]'sORPHAN_IDLE.shard/tcp/tests/take.rsgoes withrecv_with;lent.rsholds the window update it held.toyos::net'sread_endandwrite_refusedtests go with the functions.Risks and what I am unsure of
stream_handlesserver-watch arm is the landing guard for the boundary that broke. Run 1's stall is main's too (filed).MAX_STREAMS= 128 a process is an estimate, and 8 MiB of contiguous memory is committed at every connect and accept: both filed inissues/a-stream-commits-eight-mebibytes-and-a-process-holds-128.md.OwnedFddrop,try_clone_to_owned,File::from_raw_fdand spawn takes the table's lock for a lookup; not measured.toyos::net::stream's read and write wait with a fresh one-handlePollerwhen a deadline is set; a blocking call with no deadline waits inSYS_READon the doorbell.issues/a-stream-cannot-move-between-processes.md);provide's refusal is shown only by its launcher-less red under QEMU.ConnectionAbortedfor netstack gone remains the closest word, as the design said.🤖 Generated with Claude Code
https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy