Skip to content

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

@jeffective

Description

@jeffective

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugObserved behavior contradicts documented or intended behaviorcontributor friendlyThis issue is limited in scope and/or knowledge of Zig internals.standard libraryThis issue involves writing Zig code for the standard library.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions