Skip to content

E.NXIO should not be an unexpected error (6) for std.posix.send #23383

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
kj4tmp opened this issue Mar 27, 2025 · 1 comment
Open

E.NXIO should not be an unexpected error (6) for std.posix.send #23383

kj4tmp opened this issue Mar 27, 2025 · 1 comment
Labels
bug Observed behavior contradicts documented or intended behavior contributor friendly This issue is limited in scope and/or knowledge of Zig internals. standard library This issue involves writing Zig code for the standard library.
Milestone

Comments

@kj4tmp
Copy link
Contributor

kj4tmp commented Mar 27, 2025

Zig Version

0.14.0

Steps to Reproduce and Observed Behavior

Be on x86_64-linux (debian 12)

Make file repro.zig: (replace ifname with a name of an ethernet interface, preferably a usb ethernet adapter)

const std = @import("std");

pub fn main() !void {
    const ifname: [:0]const u8 = "enx00e04c68191a"; // <- replace with the name of your ethernet interface

    if (ifname.len > std.posix.IFNAMESIZE - 1) return error.InterfaceNameTooLong;
    const ETH_P_ETHERCAT = 0x88a4;
    const socket: std.posix.socket_t = try std.posix.socket(
        std.posix.AF.PACKET,
        std.posix.SOCK.RAW,
        std.mem.nativeToBig(u32, ETH_P_ETHERCAT),
    );
    var timeout_rcv = std.posix.timeval{
        .sec = 0,
        .usec = 1,
    };
    try std.posix.setsockopt(
        socket,
        std.posix.SOL.SOCKET,
        std.posix.SO.RCVTIMEO,
        std.mem.asBytes(&timeout_rcv),
    );

    var timeout_snd = std.posix.timeval{
        .sec = 0,
        .usec = 1,
    };
    try std.posix.setsockopt(
        socket,
        std.posix.SOL.SOCKET,
        std.posix.SO.SNDTIMEO,
        std.mem.asBytes(&timeout_snd),
    );
    const dontroute_enable: c_int = 1;
    try std.posix.setsockopt(
        socket,
        std.posix.SOL.SOCKET,
        std.posix.SO.DONTROUTE,
        std.mem.asBytes(&dontroute_enable),
    );
    var ifr: std.posix.ifreq = std.mem.zeroInit(std.posix.ifreq, .{});
    @memcpy(ifr.ifrn.name[0..ifname.len], ifname);
    ifr.ifrn.name[ifname.len] = 0;
    try std.posix.ioctl_SIOCGIFINDEX(socket, &ifr);
    const ifindex: i32 = ifr.ifru.ivalue;

    var rval = std.posix.errno(std.os.linux.ioctl(socket, std.os.linux.SIOCGIFFLAGS, @intFromPtr(&ifr)));
    switch (rval) {
        .SUCCESS => {},
        else => {
            return error.NicError;
        },
    }
    ifr.ifru.flags.BROADCAST = true;
    ifr.ifru.flags.PROMISC = true;
    rval = std.posix.errno(std.os.linux.ioctl(socket, std.os.linux.SIOCSIFFLAGS, @intFromPtr(&ifr)));
    switch (rval) {
        .SUCCESS => {},
        else => {
            return error.NicError;
        },
    }
    const sockaddr_ll = std.posix.sockaddr.ll{
        .family = std.posix.AF.PACKET,
        .ifindex = ifindex,
        .protocol = std.mem.nativeToBig(u16, @as(u16, ETH_P_ETHERCAT)),
        .halen = 0, //not used
        .addr = .{ 0, 0, 0, 0, 0, 0, 0, 0 }, //not used
        .pkttype = 0, //not used
        .hatype = 0, //not used
    };
    try std.posix.bind(socket, @ptrCast(&sockaddr_ll), @sizeOf(@TypeOf(sockaddr_ll)));

    for (0..100) |_| {
        std.debug.print("sending...\n", .{});
        _ = try std.posix.send(socket, &.{
            0xff,
            0xff,
            0xff,
            0xff,
            0xff,
            0xff,
            0xff,
            0xff,
            0xff,
            0xff,
            0xff,
            0xff,
            0xff,
            0xff,
            0xff,
            0xff,
            0xff,
            0xff,
            0xff,
            0xff,
            0xff,
            0xff,
        }, 0);
        std.Thread.sleep(std.time.ns_per_s * 1);
    }
}
  1. zig build-exe repro.zig
  2. sudo ./repro.zig (WARNING: this will send bytes over your ethernet interface!)
  3. unplug your USB ethernet adapter while it is running
  4. Observe stack trace:
$ sudo ./repro
sending...
sending...
sending...
sending...
sending...
unexpected errno: 6
/home/jeff/zig/0.14.0/files/lib/std/debug.zig:315:31: 0x104c6b6 in dumpCurrentStackTrace (repro)
        writeCurrentStackTrace(stderr, debug_info, io.tty.detectConfig(io.getStdErr()), start_addr) catch |err| {
                              ^
/home/jeff/zig/0.14.0/files/lib/std/posix.zig:7503:40: 0x106c002 in unexpectedErrno (repro)
        std.debug.dumpCurrentStackTrace(null);
                                       ^
/home/jeff/zig/0.14.0/files/lib/std/posix.zig:6191:49: 0x10e1d12 in sendto (repro)
            else => |err| return unexpectedErrno(err),
                                                ^
/home/jeff/zig/0.14.0/files/lib/std/posix.zig:6221:18: 0x10e0326 in send (repro)
    return sendto(sockfd, buf, flags, null, 0) catch |err| switch (err) {
                 ^
/home/jeff/repos/untracked/repro.zig:76:31: 0x10df8d9 in main (repro)
        _ = try std.posix.send(socket, &.{
                              ^
/home/jeff/zig/0.14.0/files/lib/std/start.zig:656:37: 0x10df33a in posixCallMainAndExit (repro)
            const result = root.main() catch |err| {
                                    ^
/home/jeff/zig/0.14.0/files/lib/std/start.zig:271:5: 0x10deeed in _start (repro)
    asm volatile (switch (native_arch) {
    ^
???:?:?: 0x0 in ??? (???)
error: Unexpected
/home/jeff/zig/0.14.0/files/lib/std/posix.zig:7505:5: 0x106c00b in unexpectedErrno (repro)
    return error.Unexpected;
    ^
/home/jeff/zig/0.14.0/files/lib/std/posix.zig:6191:27: 0x10e1d22 in sendto (repro)
            else => |err| return unexpectedErrno(err),
                          ^
/home/jeff/zig/0.14.0/files/lib/std/posix.zig:6232:21: 0x10e0510 in send (repro)
        else => |e| return e,
                    ^
/home/jeff/repos/untracked/repro.zig:76:13: 0x10df8fb in main (repro)
        _ = try std.posix.send(socket, &.{
            ^

Expected Behavior

errno(6) "NXIO" should be expected for std.posix.send

@kj4tmp kj4tmp added the bug Observed behavior contradicts documented or intended behavior label Mar 27, 2025
@alexrp alexrp added standard library This issue involves writing Zig code for the standard library. contributor friendly This issue is limited in scope and/or knowledge of Zig internals. labels Mar 27, 2025
@alexrp alexrp added this to the 0.14.1 milestone Mar 27, 2025
@alexrp
Copy link
Member

alexrp commented Apr 1, 2025

Presumably this affects other socket-related functions/syscalls? It would be nice to figure out a complete list.

@alexrp alexrp modified the milestones: 0.14.1, 0.15.0 Apr 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior contributor friendly This issue is limited in scope and/or knowledge of Zig internals. standard library This issue involves writing Zig code for the standard library.
Projects
None yet
Development

No branches or pull requests

2 participants