std/sys/net/xous: read NetError code from byte 4 in recv/accept paths#156414
Open
tunnell wants to merge 1 commit into
Open
std/sys/net/xous: read NetError code from byte 4 in recv/accept paths#156414tunnell wants to merge 1 commit into
tunnell wants to merge 1 commit into
Conversation
`respond_with_error` in xous-core's `services/net/src/std_glue.rs` writes the `NetError` code at byte 4 of the 8-byte response buffer. The send path in `tcpstream.rs::write` correctly reads `send_request.raw[4]`. The recv-side decoders, however, read `result[1]` / `raw[1]`, which under the historical `[1, 1, 1, 1, code, 0, 0, 0]` layout is always `1` — so `ErrorKind::TimedOut` and `ErrorKind::WouldBlock` were unreachable from the recv side. Three files affected, identical pattern: - `tcpstream.rs::read_or_peek` (recv decode) - `udp.rs` (UDP recv decode) - `tcplistener.rs` (accept decode) Each `result[1]` / `raw[1]` becomes `result[4]` / `raw[4]`, matching the send path. Behavior is unchanged for any kernel that respects the existing 8-byte error layout. A complementary kernel-side change in `betrusted-io/xous-core` (rust-lang#877) mirrors the code at byte 1 too, so existing toolchain versions also see the right value immediately. The two changes are non-conflicting.
Collaborator
|
r? @nia-e rustbot has assigned @nia-e. Use Why was this reviewer chosen?The reviewer was selected based on:
|
Collaborator
|
Member
|
cc @xobs as target maintainer |
Contributor
|
This fix looks good to me. Thanks for tracking it down, @tunnell . |
nia-e
requested changes
May 12, 2026
| if receive_request.raw[0] != 0 { | ||
| // error case | ||
| if receive_request.raw[1] == NetError::TimedOut as u8 { | ||
| // error case — code lives at byte 4 (where the send path |
Member
There was a problem hiding this comment.
Suggested change
| // error case — code lives at byte 4 (where the send path | |
| // Error case — code lives at byte 4 (where the send path |
| if receive_request.raw[0] != 0 { | ||
| // error case | ||
| if receive_request.raw[1] == NetError::TimedOut as u8 { | ||
| // error case — code lives at byte 4 (where `send_message` |
Member
There was a problem hiding this comment.
Suggested change
| // error case — code lives at byte 4 (where `send_message` | |
| // Error case — code lives at byte 4 (where `send_message` |
Collaborator
|
Reminder, once the PR becomes ready for a review, use |
Member
|
Hi - see the comment from rustbot. Otherwise, I will defer to @xobs's judgement since the code change looks okay with some tiny style nitpicks |
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.
The Xous std backend's TCP send path reads the
NetErrorcode from
send_request.raw[4](correct — that's where thexous-core kernel's
respond_with_errorwrites it). But the TCPrecv, UDP recv, and TcpListener accept paths all read from
raw[1]instead. The kernel's historical layout is[1, 1, 1, 1, code, 0, 0, 0], so byte 1 is always1andErrorKind::TimedOut/ErrorKind::WouldBlockare unreachablefrom the recv side — every error falls through to the catch-all
ErrorKind::Other("recv_slice failure").This patch moves the recv-path checks to
raw[4], matching thesend path and the kernel's existing encoding. Three files,
identical one-byte change in each (+15 / -10 total). No new
behavior; an existing inconsistency between the send and recv
sides of the same backend is removed.
Why this matters in practice: any application using
set_read_timeout()to interleave reads and writes on a XousTcpStream(e.g. a tungstenite-based WebSocket pump) currentlycan't distinguish "no data this poll" from real transport
failure. Concretely, a Signal client using a 5s read timeout saw
every WebSocket torn down within 5s of opening, because the
timeout was indistinguishable from a fatal error.
Coordination with the kernel side: a complementary kernel-
side change has been filed on the xous-core repo —
betrusted-io/xous-core#877
— which mirrors the code at byte 1 in addition to byte 4 so
applications work immediately on stock Rust toolchains while
this PR cycles. After both land, the two sides agree at byte 4
and byte 1 stays mirrored only for backwards-compat with older
Rust. Either change alone fixes the user-visible symptom; both
together remove the wire-format ambiguity.
Tests: Tier-3 target std backends generally don't have CI
coverage in this repo, so I haven't added any. Happy to add an
in-process test that constructs a fake net-server response and
asserts the
ErrorKindmapping if maintainers prefer.Full disclosure: I used an AI agent to debug this problem and eventually track it here.