From 654a5b20d7a8eb2d4267b859aff615e4806733c2 Mon Sep 17 00:00:00 2001 From: David Rubin Date: Thu, 6 Nov 2025 10:29:42 -0800 Subject: [PATCH 1/2] Io: fix compile error in `receive` and `receiveTimeout` Correctly uses the `netReceive` API. If an error was returned, we propagate that error, otherwise assert we only received one message. --- lib/std/Io/net.zig | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/std/Io/net.zig b/lib/std/Io/net.zig index b691b1501ef4..c051d004e2de 100644 --- a/lib/std/Io/net.zig +++ b/lib/std/Io/net.zig @@ -1119,7 +1119,13 @@ pub const Socket = struct { /// * `receiveTimeout` pub fn receive(s: *const Socket, io: Io, buffer: []u8) ReceiveError!IncomingMessage { var message: IncomingMessage = undefined; - assert(1 == try io.vtable.netReceive(io.userdata, s.handle, (&message)[0..1], buffer, .{}, .none)); + const maybe_err, const count = io.vtable.netReceive(io.userdata, s.handle, (&message)[0..1], buffer, .{}, .none); + if (maybe_err) |err| switch (err) { + // No timeout is passed to `netReceieve`, so it must not return timeout related errors. + error.Timeout, error.UnsupportedClock => unreachable, + else => |e| return e, + }; + assert(1 == count); return message; } @@ -1139,7 +1145,9 @@ pub const Socket = struct { timeout: Io.Timeout, ) ReceiveTimeoutError!IncomingMessage { var message: IncomingMessage = undefined; - assert(1 == try io.vtable.netReceive(io.userdata, s.handle, (&message)[0..1], buffer, .{}, timeout)); + const maybe_err, const count = io.vtable.netReceive(io.userdata, s.handle, (&message)[0..1], buffer, .{}, timeout); + if (maybe_err) |err| return err; + assert(1 == count); return message; } From 71988d6719db20e1be24586bab201af72b021b3c Mon Sep 17 00:00:00 2001 From: David Rubin Date: Thu, 6 Nov 2025 17:44:28 -0800 Subject: [PATCH 2/2] Io.net: set `receive{,Timeout}` message to `init` If we use `undefined`, then `netReceive` can `@intCast` the control slice len to msghdr controllen, which is sometimes `u32`, even on 64-bit platforms. `init` just avoids this entirely by setting `control` to an empty slice rather than undefined. --- lib/std/Io/net.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/std/Io/net.zig b/lib/std/Io/net.zig index c051d004e2de..ee1e93ced21d 100644 --- a/lib/std/Io/net.zig +++ b/lib/std/Io/net.zig @@ -1118,7 +1118,7 @@ pub const Socket = struct { /// See also: /// * `receiveTimeout` pub fn receive(s: *const Socket, io: Io, buffer: []u8) ReceiveError!IncomingMessage { - var message: IncomingMessage = undefined; + var message: IncomingMessage = .init; const maybe_err, const count = io.vtable.netReceive(io.userdata, s.handle, (&message)[0..1], buffer, .{}, .none); if (maybe_err) |err| switch (err) { // No timeout is passed to `netReceieve`, so it must not return timeout related errors. @@ -1144,7 +1144,7 @@ pub const Socket = struct { buffer: []u8, timeout: Io.Timeout, ) ReceiveTimeoutError!IncomingMessage { - var message: IncomingMessage = undefined; + var message: IncomingMessage = .init; const maybe_err, const count = io.vtable.netReceive(io.userdata, s.handle, (&message)[0..1], buffer, .{}, timeout); if (maybe_err) |err| return err; assert(1 == count);