Skip to content

Commit d1ef71c

Browse files
Rollup merge of rust-lang#156414 - tunnell:pr-xous-net-recv-byte-offset, r=nia-e
std/sys/net/xous: read NetError code from byte 4 in recv/accept paths The Xous std backend's TCP **send** path reads the `NetError` code from `send_request.raw[4]` (correct — that's where the xous-core kernel's `respond_with_error` writes it). But the TCP recv, 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 always `1` and `ErrorKind::TimedOut` / `ErrorKind::WouldBlock` are unreachable from 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 the send 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 Xous `TcpStream` (e.g. a tungstenite-based WebSocket pump) currently can'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](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 `ErrorKind` mapping if maintainers prefer. Full disclosure: I used an AI agent to debug this problem and eventually track it here.
2 parents b3f7e32 + 4ec7394 commit d1ef71c

3 files changed

Lines changed: 15 additions & 10 deletions

File tree

library/std/src/sys/net/connection/xous/tcplistener.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,13 @@ impl TcpListener {
129129
0,
130130
) {
131131
if receive_request.raw[0] != 0 {
132-
// error case
133-
if receive_request.raw[1] == NetError::TimedOut as u8 {
132+
// Error case — code lives at byte 4 (where the send path
133+
// also reads it). Byte 1 is part of the marker header.
134+
if receive_request.raw[4] == NetError::TimedOut as u8 {
134135
return Err(io::const_error!(io::ErrorKind::TimedOut, "accept timed out"));
135-
} else if receive_request.raw[1] == NetError::WouldBlock as u8 {
136+
} else if receive_request.raw[4] == NetError::WouldBlock as u8 {
136137
return Err(io::const_error!(io::ErrorKind::WouldBlock, "accept would block"));
137-
} else if receive_request.raw[1] == NetError::LibraryError as u8 {
138+
} else if receive_request.raw[4] == NetError::LibraryError as u8 {
138139
return Err(io::const_error!(io::ErrorKind::Other, "library error"));
139140
} else {
140141
return Err(io::const_error!(io::ErrorKind::Other, "library error"));

library/std/src/sys/net/connection/xous/tcpstream.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,11 +213,14 @@ impl TcpStream {
213213
} else {
214214
let result = receive_request.raw;
215215
if result[0] != 0 {
216-
if result[1] == 8 {
216+
// The error code lives at byte 4 of the kernel's response buffer
217+
// (matches the byte the send path reads in `write` below). Byte 1
218+
// is part of the marker header, not the code.
219+
if result[4] == 8 {
217220
// timed out
218221
return Err(io::const_error!(io::ErrorKind::TimedOut, "timeout"));
219222
}
220-
if result[1] == 9 {
223+
if result[4] == 9 {
221224
// would block
222225
return Err(io::const_error!(io::ErrorKind::WouldBlock, "would block"));
223226
}

library/std/src/sys/net/connection/xous/udp.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,13 @@ impl UdpSocket {
145145
0,
146146
) {
147147
if receive_request.raw[0] != 0 {
148-
// error case
149-
if receive_request.raw[1] == NetError::TimedOut as u8 {
148+
// Error case — code lives at byte 4 (where `send_message`
149+
// also reads it). Byte 1 is part of the marker header.
150+
if receive_request.raw[4] == NetError::TimedOut as u8 {
150151
return Err(io::const_error!(io::ErrorKind::TimedOut, "recv timed out"));
151-
} else if receive_request.raw[1] == NetError::WouldBlock as u8 {
152+
} else if receive_request.raw[4] == NetError::WouldBlock as u8 {
152153
return Err(io::const_error!(io::ErrorKind::WouldBlock, "recv would block"));
153-
} else if receive_request.raw[1] == NetError::LibraryError as u8 {
154+
} else if receive_request.raw[4] == NetError::LibraryError as u8 {
154155
return Err(io::const_error!(io::ErrorKind::Other, "library error"));
155156
} else {
156157
return Err(io::const_error!(io::ErrorKind::Other, "library error"));

0 commit comments

Comments
 (0)