Skip to content

rework the POSIX API layer in the standard library #2380

Closed
@andrewrk

Description

@andrewrk

Currently, we have these OS-specific APIs:

  • std.os.linux
  • std.os.windows
  • std.os.darwin
  • std.os.freebsd
  • std.os.netbsd
  • std.os.wasi

std.os.posix is defined like this:

pub const posix = switch (builtin.os) {
    Os.linux => linux,
    Os.macosx, Os.ios => darwin,
    Os.freebsd => freebsd,
    Os.netbsd => netbsd,
    Os.wasi => wasi,
    else => @compileError("Unsupported OS"),
};

So what we have is an identifier posix that is mapped directly to the OS-specific API for all platforms except Windows. This is problematic for several reasons:

  • Each OS-specific API has a different set of functions available.
  • Some functions have different number of or incompatible parameters.
  • It's quite possible to implement a POSIX API layer on top of windows, at least for some things.
  • We have this std.os.posixFoo pattern, which is a code smell, because all the functions are all prefixed with posix but cannot be in the posix namespace.
  • There is a need for "glue code" to work around kernel API footguns. For example when the number of iov_len is greater than some kernel-defined limit, it has to be broken into multiple syscalls. Or when the number of bytes to the write syscall is greater than some number, it has to be broken into multiple syscalls.

This led to 4a8c992 in which, for example, std.os.linux.fork surprisingly does not cause a fork syscall. Further, with the WASI ABI, it's clear that there is a separate "core" API layer as well as a "POSIX" API layer.

I propose to make the following changes:

  • Make the OS-specific files do exactly what they say. E.g. if you call std.os.linux.fork, that is going to do the fork syscall when you observe the program with strace, guaranteed.
  • Instead of std.os.posix mapping directly to OS-specific files, it will provide a "zig flavored POSIX" API on top of the native OS API. This is where kernel limitations will be worked around; fork might call clone on Linux, etc.
  • Functions matching the pattern std.os.posixFoo will be moved to std.os.posix.foo. In Zig-flavored POSIX, errno is not exposed; instead actual zig error unions and error sets are used. When not linking libc on Linux there will never be an errno variable, because the syscall return code contains the error code in it. However for OS-specific APIs, where that OS requires the use of libc, errno may be exposed, for example as std.os.darwin.errno().
  • There will even be a zig flavored POSIX API for Windows. Some functions may cause a compile error if the abstraction does not hold up, but for some things, it will work fine.

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedThis proposal is planned.breakingImplementing this issue could cause existing code to no longer compile or have different behavior.proposalThis issue suggests modifications. If it also has the "accepted" label then it is planned.standard libraryThis issue involves writing Zig code for the standard library.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions