authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-29 20:11:18-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-30 01:58:49-08:00
loge7e168727e3c024869de9d114a7dd49d2a80de4d
tree7715229cfa895837f2c03ff46eb78261a8a20f73
parentb9819fce69e0f208e9e20071071a40863fbdb8a9

std.posix: goodbye connect, eventfd


2 files changed, 19 insertions(+), 76 deletions(-)

lib/std/os/linux/IoUring/test.zig+12-5
...@@ -1755,7 +1755,7 @@ test "accept multishot" {...@@ -1755,7 +1755,7 @@ test "accept multishot" {
1755 // connect client1755 // connect client
1756 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);1756 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
1757 errdefer posix.close(client);1757 errdefer posix.close(client);
1758 try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));1758 try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));
17591759
1760 // test accept completion1760 // test accept completion
1761 var cqe = try ring.copy_cqe();1761 var cqe = try ring.copy_cqe();
...@@ -1865,7 +1865,7 @@ test "accept_direct" {...@@ -1865,7 +1865,7 @@ test "accept_direct" {
18651865
1866 // connect1866 // connect
1867 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);1867 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
1868 try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));1868 try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));
1869 defer posix.close(client);1869 defer posix.close(client);
18701870
1871 // accept completion1871 // accept completion
...@@ -1899,7 +1899,7 @@ test "accept_direct" {...@@ -1899,7 +1899,7 @@ test "accept_direct" {
1899 try testing.expectEqual(@as(u32, 1), try ring.submit());1899 try testing.expectEqual(@as(u32, 1), try ring.submit());
1900 // connect1900 // connect
1901 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);1901 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
1902 try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));1902 try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));
1903 defer posix.close(client);1903 defer posix.close(client);
1904 // completion with error1904 // completion with error
1905 const cqe_accept = try ring.copy_cqe();1905 const cqe_accept = try ring.copy_cqe();
...@@ -1949,7 +1949,7 @@ test "accept_multishot_direct" {...@@ -1949,7 +1949,7 @@ test "accept_multishot_direct" {
1949 for (registered_fds) |_| {1949 for (registered_fds) |_| {
1950 // connect1950 // connect
1951 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);1951 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
1952 try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));1952 try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));
1953 defer posix.close(client);1953 defer posix.close(client);
19541954
1955 // accept completion1955 // accept completion
...@@ -1964,7 +1964,7 @@ test "accept_multishot_direct" {...@@ -1964,7 +1964,7 @@ test "accept_multishot_direct" {
1964 {1964 {
1965 // connect1965 // connect
1966 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);1966 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
1967 try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));1967 try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));
1968 defer posix.close(client);1968 defer posix.close(client);
1969 // completion with error1969 // completion with error
1970 const cqe_accept = try ring.copy_cqe();1970 const cqe_accept = try ring.copy_cqe();
...@@ -2734,3 +2734,10 @@ fn send(sockfd: posix.socket_t, buf: []const u8, flags: u32) !usize {...@@ -2734,3 +2734,10 @@ fn send(sockfd: posix.socket_t, buf: []const u8, flags: u32) !usize {
2734 else => return error.SendFailed,2734 else => return error.SendFailed,
2735 }2735 }
2736}2736}
2737
2738fn connect(sock: posix.socket_t, sock_addr: *const posix.sockaddr, len: posix.socklen_t) !void {
2739 switch (posix.errno(posix.system.connect(sock, sock_addr, len))) {
2740 .SUCCESS => return,
2741 else => return error.ConnectFailed,
2742 }
2743}
lib/std/posix.zig+7-71
...@@ -1,27 +1,18 @@...@@ -1,27 +1,18 @@
1//! POSIX API layer.1//! POSIX API layer.
2//!2//!
3//! This is more cross platform than using OS-specific APIs, however, it is3//! This is more cross platform than using OS-specific APIs, however, it is
4//! lower-level and less portable than other namespaces such as `std.fs` and4//! lower-level and less portable than other namespaces such as `std.Io` and
5//! `std.process`.5//! `std.process`.
6//!6//!
7//! These APIs are generally lowered to libc function calls if and only if libc7//! These APIs are generally lowered to libc function calls if and only if libc
8//! is linked. Most operating systems other than Windows, Linux, and WASI8//! is linked. Most operating systems other than Windows, Linux, and WASI
9//! require always linking libc because they use it as the stable syscall ABI.9//! require always linking libc because they use it as the stable syscall ABI.
10//!
11//! Operating systems that are not POSIX-compliant are sometimes supported by
12//! this API layer; sometimes not. Generally, an implementation will be
13//! provided only if such implementation is straightforward on that operating
14//! system. Otherwise, programmers are expected to use OS-specific logic to
15//! deal with the exception.
16
17const builtin = @import("builtin");10const builtin = @import("builtin");
18const native_os = builtin.os.tag;11const native_os = builtin.os.tag;
1912
20const std = @import("std.zig");13const std = @import("std.zig");
21const Io = std.Io;14const Io = std.Io;
22const mem = std.mem;15const mem = std.mem;
23const fs = std.fs;
24const max_path_bytes = std.fs.max_path_bytes;
25const maxInt = std.math.maxInt;16const maxInt = std.math.maxInt;
26const cast = std.math.cast;17const cast = std.math.cast;
27const assert = std.debug.assert;18const assert = std.debug.assert;
...@@ -122,15 +113,14 @@ pub const STDIN_FILENO = system.STDIN_FILENO;...@@ -122,15 +113,14 @@ pub const STDIN_FILENO = system.STDIN_FILENO;
122pub const STDOUT_FILENO = system.STDOUT_FILENO;113pub const STDOUT_FILENO = system.STDOUT_FILENO;
123pub const SYS = system.SYS;114pub const SYS = system.SYS;
124pub const Sigaction = system.Sigaction;115pub const Sigaction = system.Sigaction;
116/// Windows has no concept of `stat`.
117///
118/// On Linux, the `stat` bits/wrappers are removed due to having to maintain
119/// the different varying stat structs per target and libc, leading to runtime
120/// errors. Users targeting Linux should add a comptime check and use statx,
121/// similar to how `Io.File.stat` does.
125pub const Stat = switch (native_os) {122pub const Stat = switch (native_os) {
126 // Has no concept of `stat`.
127 .windows => void,123 .windows => void,
128 // The `stat` bits/wrappers are removed due to having to maintain the
129 // different varying `struct stat`s per target and libc, leading to runtime
130 // errors.
131 //
132 // Users targeting linux should add a comptime check and use `statx`,
133 // similar to how `std.fs.File.stat` does.
134 .linux => void,124 .linux => void,
135 else => system.Stat,125 else => system.Stat,
136};126};
...@@ -645,26 +635,6 @@ fn setSockFlags(sock: socket_t, flags: u32) !void {...@@ -645,26 +635,6 @@ fn setSockFlags(sock: socket_t, flags: u32) !void {
645 }635 }
646}636}
647637
648pub const EventFdError = error{
649 SystemResources,
650 ProcessFdQuotaExceeded,
651 SystemFdQuotaExceeded,
652} || UnexpectedError;
653
654pub fn eventfd(initval: u32, flags: u32) EventFdError!i32 {
655 const rc = system.eventfd(initval, flags);
656 switch (errno(rc)) {
657 .SUCCESS => return @intCast(rc),
658 else => |err| return unexpectedErrno(err),
659
660 .INVAL => unreachable, // invalid parameters
661 .MFILE => return error.ProcessFdQuotaExceeded,
662 .NFILE => return error.SystemFdQuotaExceeded,
663 .NODEV => return error.SystemResources,
664 .NOMEM => return error.SystemResources,
665 }
666}
667
668pub const GetSockNameError = error{638pub const GetSockNameError = error{
669 /// Insufficient resources were available in the system to perform the operation.639 /// Insufficient resources were available in the system to perform the operation.
670 SystemResources,640 SystemResources,
...@@ -707,40 +677,6 @@ pub fn getpeername(sock: socket_t, addr: *sockaddr, addrlen: *socklen_t) GetSock...@@ -707,40 +677,6 @@ pub fn getpeername(sock: socket_t, addr: *sockaddr, addrlen: *socklen_t) GetSock
707 }677 }
708}678}
709679
710pub const ConnectError = std.Io.net.IpAddress.ConnectError || std.Io.net.UnixAddress.ConnectError;
711
712pub fn connect(sock: socket_t, sock_addr: *const sockaddr, len: socklen_t) ConnectError!void {
713 if (native_os == .windows) {
714 @compileError("use std.Io instead");
715 }
716
717 while (true) {
718 switch (errno(system.connect(sock, sock_addr, len))) {
719 .SUCCESS => return,
720 .ACCES => return error.AccessDenied,
721 .PERM => return error.PermissionDenied,
722 .ADDRNOTAVAIL => return error.AddressUnavailable,
723 .AFNOSUPPORT => return error.AddressFamilyUnsupported,
724 .AGAIN, .INPROGRESS => return error.WouldBlock,
725 .ALREADY => return error.ConnectionPending,
726 .BADF => unreachable, // sockfd is not a valid open file descriptor.
727 .CONNREFUSED => return error.ConnectionRefused,
728 .CONNRESET => return error.ConnectionResetByPeer,
729 .FAULT => unreachable, // The socket structure address is outside the user's address space.
730 .INTR => continue,
731 .ISCONN => @panic("AlreadyConnected"), // The socket is already connected.
732 .HOSTUNREACH => return error.NetworkUnreachable,
733 .NETUNREACH => return error.NetworkUnreachable,
734 .NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket.
735 .PROTOTYPE => unreachable, // The socket type does not support the requested communications protocol.
736 .TIMEDOUT => return error.Timeout,
737 .NOENT => return error.FileNotFound, // Returned when socket is AF.UNIX and the given path does not exist.
738 .CONNABORTED => unreachable, // Tried to reuse socket that previously received error.ConnectionRefused.
739 else => |err| return unexpectedErrno(err),
740 }
741 }
742}
743
744pub const FStatError = std.Io.File.StatError;680pub const FStatError = std.Io.File.StatError;
745681
746/// Return information about a file descriptor.682/// Return information about a file descriptor.