Zig 0.16 : os.linux.epoll_create1() return value should be i32, not usize, shouldn't it?

In zig-0.16/lib/std/os/linux.zig we see

pub fn epoll_create1(flags: usize) usize {
    return syscall1(.epoll_create1, flags);
}

According to man epoll_create1

       int epoll_create(int size);
       int epoll_create1(int flags);

Why usize then?
epoll_create() returns “file descriptor”, which was always signed 32-bit integer.

Moreover, in zig 0.14/0.15 there were two variants of this function:

  • one in lib/std/posix.zig, with correct retval type, but in wrong place, epoll is Linux specific, it’s not POSIX stuff.
  • and another in lib/std/os/linux.zig, in right place, but it’s signature is the same as in 0.16 (and without error handling)

In 0.16 there is the only one, in lib/std/os/linux.zig

Of course, I can write

var fd: i32 = @intCast(epollCreate(0))
// const epollCreate = os.linux.epoll_create1;

but I do not think it’s right thing to do.
So, is it (usize) intended or should I post an issue?

I believe usize is intended simply because what this function is doing is performing a linux syscall without linking libc. this is possible because linux syscalls have a stable ABI, one part of which is returning usize.

1 Like

I always do something like:

const epoll_create_rc = std.os.linux.epoll_create1(...); // This is the return code of the syscall

// Then check for errors on the return code.
const epoll_errno = std.os.linux.errno(epoll_create_rc);
switch (epoll_errno) {
  .SUCCESS => {
    // No errors, so epoll_create_rc is an actual file descriptor.
   return epoll_create_rc; // Just an example.  
},
  else => {
    // Handle errors properly.
  }
}

If I recall correctly, this should be insipred by the musl libc

2 Likes

If I remember right drivers’ methods (for ex.) in case of error return -ESOMEERROR and then syscall (or libc wrapper, do not know exactly) return -1 (usually) and set errno to ESOMEERROR.

I suspect there should be a wrapper similar to

pub fn epoll_create1(flags: u32) EpollCreateError!i32

in zig-0.15/lib/std/posix.zig (or to what filo wrote)

Or just @intCast()? I want to have fd to be i32, because it’s int

You could do @as(i32, @intCast(rc)) where rc is the return code.
If you’re using zig 0.16 you have to use std.os.linux, it returns a usize because it is doing actual syscalls, bypassing libc, have a look here and here.

The posix namespace will be removed because it will be redundant with the new std.Io stuff iirc.

fd = @intCast(os.linux.epoll_create1(0)) is enough, @as() is not needed here
Ok, thanx. Maybe, I’ll try to write some wrapper.

1 Like