mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-03-08 01:24:49 +01:00
std.posix: remove close function
This commit is contained in:
parent
ea30f86113
commit
b600b6e5e0
16 changed files with 165 additions and 234 deletions
|
|
@ -14,6 +14,8 @@ comptime {
|
|||
symbol(&acctLinux, "acct");
|
||||
symbol(&chdirLinux, "chdir");
|
||||
symbol(&chownLinux, "chown");
|
||||
symbol(&close, "close");
|
||||
symbol(&posix_close, "posix_close");
|
||||
symbol(&fchownatLinux, "fchownat");
|
||||
symbol(&lchownLinux, "lchown");
|
||||
symbol(&chrootLinux, "chroot");
|
||||
|
|
@ -49,6 +51,9 @@ comptime {
|
|||
if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
|
||||
symbol(&swab, "swab");
|
||||
}
|
||||
if (builtin.target.isWasiLibC()) {
|
||||
symbol(&closeWasi, "close");
|
||||
}
|
||||
}
|
||||
|
||||
fn _exit(exit_code: c_int) callconv(.c) noreturn {
|
||||
|
|
@ -226,3 +231,28 @@ test swab {
|
|||
swab("abcd", &a, 3);
|
||||
try std.testing.expectEqualSlices(u8, "ba\x00\x00", &a);
|
||||
}
|
||||
|
||||
fn close(fd: std.c.fd_t) callconv(.c) c_int {
|
||||
const signed: isize = @bitCast(linux.close(fd));
|
||||
if (signed < 0) {
|
||||
@branchHint(.unlikely);
|
||||
if (-signed == @intFromEnum(linux.E.INTR)) return 0;
|
||||
std.c._errno().* = @intCast(-signed);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn posix_close(fd: std.c.fd_t, _: c_int) callconv(.c) c_int {
|
||||
return close(fd);
|
||||
}
|
||||
|
||||
fn closeWasi(fd: std.c.fd_t) callconv(.c) c_int {
|
||||
switch (std.os.wasi.fd_close(fd)) {
|
||||
.SUCCESS => return 0,
|
||||
else => |e| {
|
||||
std.c._errno().* = @intFromEnum(e);
|
||||
return -1;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
19
lib/libc/musl/src/unistd/close.c
vendored
19
lib/libc/musl/src/unistd/close.c
vendored
|
|
@ -1,19 +0,0 @@
|
|||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include "aio_impl.h"
|
||||
#include "syscall.h"
|
||||
|
||||
static int dummy(int fd)
|
||||
{
|
||||
return fd;
|
||||
}
|
||||
|
||||
weak_alias(dummy, __aio_close);
|
||||
|
||||
int close(int fd)
|
||||
{
|
||||
fd = __aio_close(fd);
|
||||
int r = __syscall_cp(SYS_close, fd);
|
||||
if (r == -EINTR) r = 0;
|
||||
return __syscall_ret(r);
|
||||
}
|
||||
6
lib/libc/musl/src/unistd/posix_close.c
vendored
6
lib/libc/musl/src/unistd/posix_close.c
vendored
|
|
@ -1,6 +0,0 @@
|
|||
#include <unistd.h>
|
||||
|
||||
int posix_close(int fd, int flags)
|
||||
{
|
||||
return close(fd);
|
||||
}
|
||||
|
|
@ -70,41 +70,3 @@ void drop_udp_socket(udp_socket_t socket) {
|
|||
udp_udp_socket_drop_own(socket.socket);
|
||||
}
|
||||
#endif // __wasilibc_use_wasip2
|
||||
|
||||
int close(int fd) {
|
||||
// Scan the preopen fds before making any changes.
|
||||
__wasilibc_populate_preopens();
|
||||
|
||||
#ifdef __wasilibc_use_wasip2
|
||||
descriptor_table_entry_t entry;
|
||||
if (descriptor_table_remove(fd, &entry)) {
|
||||
|
||||
switch (entry.tag)
|
||||
{
|
||||
case DESCRIPTOR_TABLE_ENTRY_TCP_SOCKET:
|
||||
drop_tcp_socket(entry.tcp_socket);
|
||||
break;
|
||||
case DESCRIPTOR_TABLE_ENTRY_UDP_SOCKET:
|
||||
drop_udp_socket(entry.udp_socket);
|
||||
break;
|
||||
default: /* unreachable */ abort();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif // __wasilibc_use_wasip2
|
||||
|
||||
__wasi_errno_t error = __wasi_fd_close(fd);
|
||||
if (error != 0) {
|
||||
errno = error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
weak void __wasilibc_populate_preopens(void) {
|
||||
// This version does nothing. It may be overridden by a version which does
|
||||
// something if `__wasilibc_find_abspath` or `__wasilibc_find_relpath` are
|
||||
// used.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -693,7 +693,7 @@ const Os = switch (builtin.os.tag) {
|
|||
fatal("failed to open directory {f}: {t}", .{ path, err });
|
||||
};
|
||||
// Empirically the dir has to stay open or else no events are triggered.
|
||||
errdefer if (!skip_open_dir) posix.close(dir_fd);
|
||||
errdefer if (!skip_open_dir) std.Io.Threaded.closeFd(dir_fd);
|
||||
const changes = [1]posix.Kevent{.{
|
||||
.ident = @bitCast(@as(isize, dir_fd)),
|
||||
.filter = std.c.EVFILT.VNODE,
|
||||
|
|
@ -793,7 +793,7 @@ const Os = switch (builtin.os.tag) {
|
|||
};
|
||||
const filtered_changes = if (i == handles.len - 1) changes[0..1] else &changes;
|
||||
_ = try Io.Kqueue.kevent(w.os.kq_fd, filtered_changes, &.{}, null);
|
||||
if (path.sub_path.len != 0) posix.close(dir_fd);
|
||||
if (path.sub_path.len != 0) std.Io.Threaded.closeFd(dir_fd);
|
||||
|
||||
w.dir_table.swapRemoveAt(i);
|
||||
handles.swapRemove(i);
|
||||
|
|
|
|||
|
|
@ -549,7 +549,7 @@ const CachedFd = struct {
|
|||
.initializing => unreachable,
|
||||
_ => |fd| {
|
||||
assert(@intFromEnum(fd) >= 0);
|
||||
std.posix.close(@intFromEnum(fd));
|
||||
_ = std.os.linux.close(@intFromEnum(fd));
|
||||
cached_fd.* = .init;
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ const Allocator = std.mem.Allocator;
|
|||
const Alignment = std.mem.Alignment;
|
||||
const IpAddress = std.Io.net.IpAddress;
|
||||
const errnoBug = std.Io.Threaded.errnoBug;
|
||||
const closeFd = std.Io.Threaded.closeFd;
|
||||
const posix = std.posix;
|
||||
|
||||
/// Must be a thread-safe allocator.
|
||||
|
|
@ -64,7 +65,7 @@ const Thread = struct {
|
|||
};
|
||||
|
||||
fn deinit(thread: *Thread, gpa: Allocator) void {
|
||||
posix.close(thread.kq_fd);
|
||||
closeFd(thread.kq_fd);
|
||||
assert(thread.wait_queues.count() == 0);
|
||||
thread.wait_queues.deinit(gpa);
|
||||
thread.* = undefined;
|
||||
|
|
@ -212,7 +213,7 @@ pub fn init(k: *Kqueue, gpa: Allocator, options: InitOptions) !void {
|
|||
.steal_ready_search_index = 1,
|
||||
.wait_queues = .empty,
|
||||
};
|
||||
errdefer std.posix.close(main_thread.kq_fd);
|
||||
errdefer closeFd(main_thread.kq_fd);
|
||||
std.log.debug("created main idle {*}", .{&main_thread.idle_context});
|
||||
std.log.debug("created main {*}", .{main_fiber});
|
||||
}
|
||||
|
|
@ -371,7 +372,7 @@ fn schedule(k: *Kqueue, thread: *Thread, ready_queue: Fiber.Queue) void {
|
|||
.stack_size = idle_stack_size,
|
||||
.allocator = k.gpa,
|
||||
}, threadEntry, .{ k, new_thread_index }) catch |err| {
|
||||
posix.close(new_thread.kq_fd);
|
||||
closeFd(new_thread.kq_fd);
|
||||
@atomicStore(u32, &k.threads.reserved, new_thread_index, .release);
|
||||
// no more access to `thread` after giving up reservation
|
||||
std.log.warn("unable to create worker thread due spawn failure: {s}", .{@errorName(err)});
|
||||
|
|
@ -1234,7 +1235,7 @@ fn netBindIp(
|
|||
const k: *Kqueue = @ptrCast(@alignCast(userdata));
|
||||
const family = Io.Threaded.posixAddressFamily(address);
|
||||
const socket_fd = try openSocketPosix(k, family, options);
|
||||
errdefer std.posix.close(socket_fd);
|
||||
errdefer closeFd(socket_fd);
|
||||
var storage: Io.Threaded.PosixAddress = undefined;
|
||||
var addr_len = Io.Threaded.addressToPosix(address, &storage);
|
||||
try posixBind(k, socket_fd, &storage.any, addr_len);
|
||||
|
|
@ -1252,7 +1253,7 @@ fn netConnectIp(userdata: ?*anyopaque, address: *const net.IpAddress, options: n
|
|||
.mode = options.mode,
|
||||
.protocol = options.protocol,
|
||||
});
|
||||
errdefer posix.close(socket_fd);
|
||||
errdefer closeFd(socket_fd);
|
||||
var storage: Io.Threaded.PosixAddress = undefined;
|
||||
var addr_len = Io.Threaded.addressToPosix(address, &storage);
|
||||
try posixConnect(k, socket_fd, &storage.any, addr_len);
|
||||
|
|
@ -1565,7 +1566,7 @@ fn openSocketPosix(
|
|||
switch (posix.errno(socket_rc)) {
|
||||
.SUCCESS => {
|
||||
const fd: posix.fd_t = @intCast(socket_rc);
|
||||
errdefer posix.close(fd);
|
||||
errdefer closeFd(fd);
|
||||
if (Io.Threaded.socket_flags_unsupported) {
|
||||
while (true) {
|
||||
try k.checkCancel();
|
||||
|
|
@ -1614,7 +1615,7 @@ fn openSocketPosix(
|
|||
else => |err| return posix.unexpectedErrno(err),
|
||||
}
|
||||
};
|
||||
errdefer posix.close(socket_fd);
|
||||
errdefer closeFd(socket_fd);
|
||||
|
||||
if (options.ip6_only) {
|
||||
if (posix.IPV6 == void) return error.OptionUnsupported;
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ pub const NullFile = switch (native_os) {
|
|||
|
||||
fn deinit(this: *@This()) void {
|
||||
if (this.fd >= 0) {
|
||||
posix.close(this.fd);
|
||||
closeFd(this.fd);
|
||||
this.fd = -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -4337,7 +4337,7 @@ fn dirCreateFilePosix(
|
|||
}
|
||||
}
|
||||
};
|
||||
errdefer posix.close(fd);
|
||||
errdefer closeFd(fd);
|
||||
|
||||
if (have_flock and !have_flock_open_flags and flags.lock != .none) {
|
||||
const lock_nonblocking: i32 = if (flags.lock_nonblocking) posix.LOCK.NB else 0;
|
||||
|
|
@ -4917,7 +4917,7 @@ fn dirOpenFilePosix(
|
|||
}
|
||||
}
|
||||
};
|
||||
errdefer posix.close(fd);
|
||||
errdefer closeFd(fd);
|
||||
|
||||
if (!flags.allow_directory) {
|
||||
const is_dir = is_dir: {
|
||||
|
|
@ -5241,7 +5241,7 @@ fn dirOpenFileWasi(
|
|||
},
|
||||
}
|
||||
}
|
||||
errdefer posix.close(fd);
|
||||
errdefer closeFd(fd);
|
||||
|
||||
if (!flags.allow_directory) {
|
||||
const is_dir = is_dir: {
|
||||
|
|
@ -5457,7 +5457,13 @@ pub fn dirOpenDirWindows(
|
|||
fn dirClose(userdata: ?*anyopaque, dirs: []const Dir) void {
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
_ = t;
|
||||
for (dirs) |dir| posix.close(dir.handle);
|
||||
for (dirs) |dir| {
|
||||
if (is_windows) {
|
||||
windows.CloseHandle(dir.handle);
|
||||
} else {
|
||||
closeFd(dir.handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const dirRead = switch (native_os) {
|
||||
|
|
@ -6777,7 +6783,7 @@ fn dirRealPathFilePosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, o
|
|||
},
|
||||
}
|
||||
};
|
||||
defer posix.close(fd);
|
||||
defer closeFd(fd);
|
||||
return realPathPosix(fd, out_buffer);
|
||||
}
|
||||
|
||||
|
|
@ -8367,7 +8373,7 @@ fn fchmodatFallback(
|
|||
}
|
||||
}
|
||||
};
|
||||
defer posix.close(path_fd);
|
||||
defer closeFd(path_fd);
|
||||
|
||||
const path_mode = mode: {
|
||||
const sys = if (statx_use_c) std.c else std.os.linux;
|
||||
|
|
@ -9592,7 +9598,13 @@ fn dirHardLink(
|
|||
fn fileClose(userdata: ?*anyopaque, files: []const File) void {
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
_ = t;
|
||||
for (files) |file| posix.close(file.handle);
|
||||
for (files) |file| {
|
||||
if (is_windows) {
|
||||
windows.CloseHandle(file.handle);
|
||||
} else {
|
||||
closeFd(file.handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fileReadStreaming(userdata: ?*anyopaque, file: File, data: []const []u8) File.ReadStreamingError!usize {
|
||||
|
|
@ -11783,7 +11795,7 @@ fn netListenIpPosix(
|
|||
.mode = options.mode,
|
||||
.protocol = options.protocol,
|
||||
});
|
||||
errdefer posix.close(socket_fd);
|
||||
errdefer closeFd(socket_fd);
|
||||
|
||||
if (options.reuse_address) {
|
||||
try setSocketOption(socket_fd, posix.SOL.SOCKET, posix.SO.REUSEADDR, 1);
|
||||
|
|
@ -11946,7 +11958,7 @@ fn netListenUnixPosix(
|
|||
error.OptionUnsupported => return error.Unexpected,
|
||||
else => |e| return e,
|
||||
};
|
||||
errdefer posix.close(socket_fd);
|
||||
errdefer closeFd(socket_fd);
|
||||
|
||||
var storage: UnixAddress = undefined;
|
||||
const addr_len = addressUnixToPosix(address, &storage);
|
||||
|
|
@ -12362,7 +12374,7 @@ fn netConnectIpPosix(
|
|||
.mode = options.mode,
|
||||
.protocol = options.protocol,
|
||||
});
|
||||
errdefer posix.close(socket_fd);
|
||||
errdefer closeFd(socket_fd);
|
||||
var storage: PosixAddress = undefined;
|
||||
var addr_len = addressToPosix(address, &storage);
|
||||
try posixConnect(socket_fd, &storage.any, addr_len);
|
||||
|
|
@ -12462,7 +12474,7 @@ fn netConnectUnixPosix(
|
|||
error.OptionUnsupported => return error.Unexpected,
|
||||
else => |e| return e,
|
||||
};
|
||||
errdefer posix.close(socket_fd);
|
||||
errdefer closeFd(socket_fd);
|
||||
var storage: UnixAddress = undefined;
|
||||
const addr_len = addressUnixToPosix(address, &storage);
|
||||
try posixConnectUnix(socket_fd, &storage.any, addr_len);
|
||||
|
|
@ -12536,7 +12548,7 @@ fn netBindIpPosix(
|
|||
_ = t;
|
||||
const family = posixAddressFamily(address);
|
||||
const socket_fd = try openSocketPosix(family, options);
|
||||
errdefer posix.close(socket_fd);
|
||||
errdefer closeFd(socket_fd);
|
||||
var storage: PosixAddress = undefined;
|
||||
var addr_len = addressToPosix(address, &storage);
|
||||
try posixBind(socket_fd, &storage.any, addr_len);
|
||||
|
|
@ -12642,7 +12654,7 @@ fn openSocketPosix(
|
|||
.SUCCESS => {
|
||||
syscall.finish();
|
||||
const fd: posix.fd_t = @intCast(rc);
|
||||
errdefer posix.close(fd);
|
||||
errdefer closeFd(fd);
|
||||
if (socket_flags_unsupported) try setCloexec(fd);
|
||||
break fd;
|
||||
},
|
||||
|
|
@ -12661,7 +12673,7 @@ fn openSocketPosix(
|
|||
else => |err| return syscall.unexpectedErrno(err),
|
||||
}
|
||||
};
|
||||
errdefer posix.close(socket_fd);
|
||||
errdefer closeFd(socket_fd);
|
||||
|
||||
if (options.ip6_only) {
|
||||
if (posix.IPV6 == void) return error.OptionUnsupported;
|
||||
|
|
@ -12707,8 +12719,8 @@ fn netSocketCreatePair(
|
|||
.SUCCESS => {
|
||||
syscall.finish();
|
||||
errdefer {
|
||||
posix.close(sockets[0]);
|
||||
posix.close(sockets[1]);
|
||||
closeFd(sockets[0]);
|
||||
closeFd(sockets[1]);
|
||||
}
|
||||
if (socket_flags_unsupported) {
|
||||
try setCloexec(sockets[0]);
|
||||
|
|
@ -12809,7 +12821,7 @@ fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: net.Socket.Handle) net.Serve
|
|||
.SUCCESS => {
|
||||
syscall.finish();
|
||||
const fd: posix.fd_t = @intCast(rc);
|
||||
errdefer posix.close(fd);
|
||||
errdefer closeFd(fd);
|
||||
if (!have_accept4) try setCloexec(fd);
|
||||
break fd;
|
||||
},
|
||||
|
|
@ -13679,7 +13691,7 @@ fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void {
|
|||
_ = t;
|
||||
switch (native_os) {
|
||||
.windows => for (handles) |handle| closeSocketWindows(handle),
|
||||
else => for (handles) |handle| posix.close(handle),
|
||||
else => for (handles) |handle| closeFd(handle),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -13787,7 +13799,7 @@ fn netInterfaceNameResolve(
|
|||
error.OptionUnsupported => return error.Unexpected,
|
||||
else => |e| return e,
|
||||
};
|
||||
defer posix.close(sock_fd);
|
||||
defer closeFd(sock_fd);
|
||||
|
||||
var ifr: posix.ifreq = .{
|
||||
.ifrn = .{ .name = @bitCast(name.bytes) },
|
||||
|
|
@ -15329,13 +15341,13 @@ fn spawnPosix(t: *Threaded, options: process.SpawnOptions) process.SpawnError!Sp
|
|||
const pid: posix.pid_t = @intCast(pid_result); // We are the parent.
|
||||
errdefer comptime unreachable; // The child is forked; we must not error from now on
|
||||
|
||||
posix.close(err_pipe[1]); // make sure only the child holds the write end open
|
||||
closeFd(err_pipe[1]); // make sure only the child holds the write end open
|
||||
|
||||
if (options.stdin == .pipe) posix.close(stdin_pipe[0]);
|
||||
if (options.stdout == .pipe) posix.close(stdout_pipe[1]);
|
||||
if (options.stderr == .pipe) posix.close(stderr_pipe[1]);
|
||||
if (options.stdin == .pipe) closeFd(stdin_pipe[0]);
|
||||
if (options.stdout == .pipe) closeFd(stdout_pipe[1]);
|
||||
if (options.stderr == .pipe) closeFd(stderr_pipe[1]);
|
||||
|
||||
if (prog_pipe[1] != -1) posix.close(prog_pipe[1]);
|
||||
if (prog_pipe[1] != -1) closeFd(prog_pipe[1]);
|
||||
options.progress_node.setIpcFile(t, .{ .handle = prog_pipe[0], .flags = .{ .nonblocking = true } });
|
||||
|
||||
return .{
|
||||
|
|
@ -15373,7 +15385,7 @@ fn getDevNullFd(t: *Threaded) !posix.fd_t {
|
|||
mutexLock(&t.mutex); // Another thread might have won the race.
|
||||
defer mutexUnlock(&t.mutex);
|
||||
if (t.null_file.fd != -1) {
|
||||
posix.close(fresh_fd);
|
||||
closeFd(fresh_fd);
|
||||
return t.null_file.fd;
|
||||
} else {
|
||||
t.null_file.fd = fresh_fd;
|
||||
|
|
@ -15399,7 +15411,7 @@ fn getDevNullFd(t: *Threaded) !posix.fd_t {
|
|||
fn processSpawnPosix(userdata: ?*anyopaque, options: process.SpawnOptions) process.SpawnError!process.Child {
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
const spawned = try spawnPosix(t, options);
|
||||
defer posix.close(spawned.err_fd);
|
||||
defer closeFd(spawned.err_fd);
|
||||
|
||||
// Wait for the child to report any errors in or before `execvpe`.
|
||||
if (readIntFd(spawned.err_fd)) |child_err_int| {
|
||||
|
|
@ -15666,15 +15678,15 @@ fn childKillPosix(child: *process.Child) !void {
|
|||
|
||||
fn childCleanupPosix(child: *process.Child) void {
|
||||
if (child.stdin) |*stdin| {
|
||||
posix.close(stdin.handle);
|
||||
closeFd(stdin.handle);
|
||||
child.stdin = null;
|
||||
}
|
||||
if (child.stdout) |*stdout| {
|
||||
posix.close(stdout.handle);
|
||||
closeFd(stdout.handle);
|
||||
child.stdout = null;
|
||||
}
|
||||
if (child.stderr) |*stderr| {
|
||||
posix.close(stderr.handle);
|
||||
closeFd(stderr.handle);
|
||||
child.stderr = null;
|
||||
}
|
||||
child.id = null;
|
||||
|
|
@ -15743,14 +15755,14 @@ fn readIntFd(fd: posix.fd_t) !ErrInt {
|
|||
const ErrInt = std.meta.Int(.unsigned, @sizeOf(anyerror) * 8);
|
||||
|
||||
fn destroyPipe(pipe: [2]posix.fd_t) void {
|
||||
if (pipe[0] != -1) posix.close(pipe[0]);
|
||||
if (pipe[0] != pipe[1]) posix.close(pipe[1]);
|
||||
if (pipe[0] != -1) closeFd(pipe[0]);
|
||||
if (pipe[0] != pipe[1]) closeFd(pipe[1]);
|
||||
}
|
||||
|
||||
fn setUpChildIo(stdio: process.SpawnOptions.StdIo, pipe_fd: i32, std_fileno: i32, dev_null_fd: i32) !void {
|
||||
switch (stdio) {
|
||||
.pipe => try dup2(pipe_fd, std_fileno),
|
||||
.close => posix.close(std_fileno),
|
||||
.close => closeFd(std_fileno),
|
||||
.inherit => {},
|
||||
.ignore => try dup2(dev_null_fd, std_fileno),
|
||||
.file => @panic("TODO implement setUpChildIo when file is used"),
|
||||
|
|
@ -17439,7 +17451,7 @@ fn getRandomFd(t: *Threaded) Io.RandomSecureError!posix.fd_t {
|
|||
}
|
||||
}
|
||||
};
|
||||
errdefer posix.close(fd);
|
||||
errdefer closeFd(fd);
|
||||
|
||||
switch (native_os) {
|
||||
.linux => {
|
||||
|
|
@ -17454,7 +17466,7 @@ fn getRandomFd(t: *Threaded) Io.RandomSecureError!posix.fd_t {
|
|||
mutexLock(&t.mutex); // Another thread might have won the race.
|
||||
defer mutexUnlock(&t.mutex);
|
||||
if (t.random_file.fd >= 0) {
|
||||
posix.close(fd);
|
||||
closeFd(fd);
|
||||
return t.random_file.fd;
|
||||
} else if (!posix.S.ISCHR(statx.mode)) {
|
||||
t.random_file.fd = -2;
|
||||
|
|
@ -17482,7 +17494,7 @@ fn getRandomFd(t: *Threaded) Io.RandomSecureError!posix.fd_t {
|
|||
mutexLock(&t.mutex); // Another thread might have won the race.
|
||||
defer mutexUnlock(&t.mutex);
|
||||
if (t.random_file.fd >= 0) {
|
||||
posix.close(fd);
|
||||
closeFd(fd);
|
||||
return t.random_file.fd;
|
||||
} else if (!posix.S.ISCHR(stat.mode)) {
|
||||
t.random_file.fd = -2;
|
||||
|
|
@ -18170,8 +18182,8 @@ pub fn pipe2(flags: posix.O) PipeError![2]posix.fd_t {
|
|||
else => |err| return posix.unexpectedErrno(err),
|
||||
}
|
||||
errdefer {
|
||||
posix.close(fds[0]);
|
||||
posix.close(fds[1]);
|
||||
closeFd(fds[0]);
|
||||
closeFd(fds[1]);
|
||||
}
|
||||
|
||||
// https://github.com/ziglang/zig/issues/18882
|
||||
|
|
@ -19164,3 +19176,17 @@ fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!windows
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn closeFd(fd: posix.fd_t) void {
|
||||
if (native_os == .wasi and !builtin.link_libc) {
|
||||
switch (std.os.wasi.fd_close(fd)) {
|
||||
.SUCCESS, .INTR => {},
|
||||
.BADF => recoverableOsBugDetected(), // use after free
|
||||
else => recoverableOsBugDetected(), // unexpected failure
|
||||
}
|
||||
} else switch (posix.errno(posix.system.close(fd))) {
|
||||
.SUCCESS, .INTR => {}, // INTR still a success, see https://github.com/ziglang/zig/issues/2425
|
||||
.BADF => recoverableOsBugDetected(), // use after free
|
||||
else => recoverableOsBugDetected(), // unexpected failure
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1571,7 +1571,7 @@ pub fn clone2(flags: u32, child_stack_ptr: usize) usize {
|
|||
return syscall2(.clone, flags, child_stack_ptr);
|
||||
}
|
||||
|
||||
pub fn close(fd: i32) usize {
|
||||
pub fn close(fd: fd_t) usize {
|
||||
return syscall1(.close, @as(usize, @bitCast(@as(isize, fd))));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ pub fn init_params(entries: u16, p: *linux.io_uring_params) !IoUring {
|
|||
}
|
||||
const fd = @as(linux.fd_t, @intCast(res));
|
||||
assert(fd >= 0);
|
||||
errdefer posix.close(fd);
|
||||
errdefer _ = linux.close(fd);
|
||||
|
||||
// Kernel versions 5.4 and up use only one mmap() for the submission and completion queues.
|
||||
// This is not an optional feature for us... if the kernel does it, we have to do it.
|
||||
|
|
@ -125,7 +125,7 @@ pub fn deinit(self: *IoUring) void {
|
|||
// The mmaps depend on the fd, so the order of these calls is important:
|
||||
self.cq.deinit();
|
||||
self.sq.deinit();
|
||||
posix.close(self.fd);
|
||||
_ = linux.close(self.fd);
|
||||
self.fd = -1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -440,7 +440,7 @@ test "openat" {
|
|||
try testing.expect(cqe_openat.res > 0);
|
||||
try testing.expectEqual(@as(u32, 0), cqe_openat.flags);
|
||||
|
||||
posix.close(cqe_openat.res);
|
||||
_ = linux.close(cqe_openat.res);
|
||||
}
|
||||
|
||||
test "close" {
|
||||
|
|
@ -530,7 +530,7 @@ test "sendmsg/recvmsg" {
|
|||
};
|
||||
|
||||
const server = try socket(address_server.family, posix.SOCK.DGRAM, 0);
|
||||
defer posix.close(server);
|
||||
defer _ = linux.close(server);
|
||||
try posix.setsockopt(server, posix.SOL.SOCKET, posix.SO.REUSEPORT, &mem.toBytes(@as(c_int, 1)));
|
||||
try posix.setsockopt(server, posix.SOL.SOCKET, posix.SO.REUSEADDR, &mem.toBytes(@as(c_int, 1)));
|
||||
try bind(server, addrAny(&address_server), @sizeOf(linux.sockaddr.in));
|
||||
|
|
@ -540,7 +540,7 @@ test "sendmsg/recvmsg" {
|
|||
try getsockname(server, addrAny(&address_server), &slen);
|
||||
|
||||
const client = try socket(address_server.family, posix.SOCK.DGRAM, 0);
|
||||
defer posix.close(client);
|
||||
defer _ = linux.close(client);
|
||||
|
||||
const buffer_send = [_]u8{42} ** 128;
|
||||
const iovecs_send = [_]iovec_const{
|
||||
|
|
@ -1034,7 +1034,7 @@ test "shutdown" {
|
|||
// Socket bound, expect shutdown to work
|
||||
{
|
||||
const server = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
|
||||
defer posix.close(server);
|
||||
defer _ = linux.close(server);
|
||||
try posix.setsockopt(server, posix.SOL.SOCKET, posix.SO.REUSEADDR, &mem.toBytes(@as(c_int, 1)));
|
||||
try bind(server, addrAny(&address), @sizeOf(linux.sockaddr.in));
|
||||
try listen(server, 1);
|
||||
|
|
@ -1067,7 +1067,7 @@ test "shutdown" {
|
|||
// Socket not bound, expect to fail with ENOTCONN
|
||||
{
|
||||
const server = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
|
||||
defer posix.close(server);
|
||||
defer _ = linux.close(server);
|
||||
|
||||
const shutdown_sqe = ring.shutdown(0x445445445, server, linux.SHUT.RD) catch |err| switch (err) {
|
||||
else => |errno| std.debug.panic("unhandled errno: {}", .{errno}),
|
||||
|
|
@ -1741,7 +1741,7 @@ test "accept multishot" {
|
|||
.addr = @bitCast([4]u8{ 127, 0, 0, 1 }),
|
||||
};
|
||||
const listener_socket = try createListenerSocket(&address);
|
||||
defer posix.close(listener_socket);
|
||||
defer _ = linux.close(listener_socket);
|
||||
|
||||
// submit multishot accept operation
|
||||
var addr: posix.sockaddr = undefined;
|
||||
|
|
@ -1754,7 +1754,7 @@ test "accept multishot" {
|
|||
while (nr > 0) : (nr -= 1) {
|
||||
// connect client
|
||||
const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
|
||||
errdefer posix.close(client);
|
||||
errdefer _ = linux.close(client);
|
||||
try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));
|
||||
|
||||
// test accept completion
|
||||
|
|
@ -1764,7 +1764,7 @@ test "accept multishot" {
|
|||
try testing.expect(cqe.user_data == userdata);
|
||||
try testing.expect(cqe.flags & linux.IORING_CQE_F_MORE > 0); // more flag is set
|
||||
|
||||
posix.close(client);
|
||||
_ = linux.close(client);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1848,7 +1848,7 @@ test "accept_direct" {
|
|||
try ring.register_files(registered_fds[0..]);
|
||||
|
||||
const listener_socket = try createListenerSocket(&address);
|
||||
defer posix.close(listener_socket);
|
||||
defer _ = linux.close(listener_socket);
|
||||
|
||||
const accept_userdata: u64 = 0xaaaaaaaa;
|
||||
const read_userdata: u64 = 0xbbbbbbbb;
|
||||
|
|
@ -1866,7 +1866,7 @@ test "accept_direct" {
|
|||
// connect
|
||||
const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
|
||||
try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));
|
||||
defer posix.close(client);
|
||||
defer _ = linux.close(client);
|
||||
|
||||
// accept completion
|
||||
const cqe_accept = try ring.copy_cqe();
|
||||
|
|
@ -1900,7 +1900,7 @@ test "accept_direct" {
|
|||
// connect
|
||||
const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
|
||||
try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));
|
||||
defer posix.close(client);
|
||||
defer _ = linux.close(client);
|
||||
// completion with error
|
||||
const cqe_accept = try ring.copy_cqe();
|
||||
try testing.expect(cqe_accept.user_data == accept_userdata);
|
||||
|
|
@ -1936,7 +1936,7 @@ test "accept_multishot_direct" {
|
|||
try ring.register_files(registered_fds[0..]);
|
||||
|
||||
const listener_socket = try createListenerSocket(&address);
|
||||
defer posix.close(listener_socket);
|
||||
defer _ = linux.close(listener_socket);
|
||||
|
||||
const accept_userdata: u64 = 0xaaaaaaaa;
|
||||
|
||||
|
|
@ -1950,7 +1950,7 @@ test "accept_multishot_direct" {
|
|||
// connect
|
||||
const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
|
||||
try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));
|
||||
defer posix.close(client);
|
||||
defer _ = linux.close(client);
|
||||
|
||||
// accept completion
|
||||
const cqe_accept = try ring.copy_cqe();
|
||||
|
|
@ -1965,7 +1965,7 @@ test "accept_multishot_direct" {
|
|||
// connect
|
||||
const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
|
||||
try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));
|
||||
defer posix.close(client);
|
||||
defer _ = linux.close(client);
|
||||
// completion with error
|
||||
const cqe_accept = try ring.copy_cqe();
|
||||
try testing.expect(cqe_accept.user_data == accept_userdata);
|
||||
|
|
@ -1998,7 +1998,7 @@ test "socket" {
|
|||
const fd: linux.fd_t = @intCast(cqe.res);
|
||||
try testing.expect(fd > 2);
|
||||
|
||||
posix.close(fd);
|
||||
_ = linux.close(fd);
|
||||
}
|
||||
|
||||
test "socket_direct/socket_direct_alloc/close_direct" {
|
||||
|
|
@ -2042,7 +2042,7 @@ test "socket_direct/socket_direct_alloc/close_direct" {
|
|||
.addr = @bitCast([4]u8{ 127, 0, 0, 1 }),
|
||||
};
|
||||
const listener_socket = try createListenerSocket(&address);
|
||||
defer posix.close(listener_socket);
|
||||
defer _ = linux.close(listener_socket);
|
||||
const accept_userdata: u64 = 0xaaaaaaaa;
|
||||
const connect_userdata: u64 = 0xbbbbbbbb;
|
||||
const close_userdata: u64 = 0xcccccccc;
|
||||
|
|
@ -2599,8 +2599,8 @@ pub const SocketTestHarness = struct {
|
|||
client: posix.socket_t,
|
||||
|
||||
pub fn close(self: SocketTestHarness) void {
|
||||
posix.close(self.client);
|
||||
posix.close(self.listener);
|
||||
_ = linux.close(self.client);
|
||||
_ = linux.close(self.listener);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -2611,7 +2611,7 @@ pub fn createSocketTestHarness(ring: *IoUring) !SocketTestHarness {
|
|||
.addr = @bitCast([4]u8{ 127, 0, 0, 1 }),
|
||||
};
|
||||
const listener_socket = try createListenerSocket(&address);
|
||||
errdefer posix.close(listener_socket);
|
||||
errdefer _ = linux.close(listener_socket);
|
||||
|
||||
// Submit 1 accept
|
||||
var accept_addr: posix.sockaddr = undefined;
|
||||
|
|
@ -2620,7 +2620,7 @@ pub fn createSocketTestHarness(ring: *IoUring) !SocketTestHarness {
|
|||
|
||||
// Create a TCP client socket
|
||||
const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
|
||||
errdefer posix.close(client);
|
||||
errdefer _ = linux.close(client);
|
||||
_ = try ring.connect(0xcccccccc, client, addrAny(&address), @sizeOf(linux.sockaddr.in));
|
||||
|
||||
try testing.expectEqual(@as(u32, 2), try ring.submit());
|
||||
|
|
@ -2660,7 +2660,7 @@ pub fn createSocketTestHarness(ring: *IoUring) !SocketTestHarness {
|
|||
fn createListenerSocket(address: *linux.sockaddr.in) !posix.socket_t {
|
||||
const kernel_backlog = 1;
|
||||
const listener_socket = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
|
||||
errdefer posix.close(listener_socket);
|
||||
errdefer _ = linux.close(listener_socket);
|
||||
|
||||
try posix.setsockopt(listener_socket, posix.SOL.SOCKET, posix.SO.REUSEADDR, &mem.toBytes(@as(c_int, 1)));
|
||||
try bind(listener_socket, addrAny(address), @sizeOf(linux.sockaddr.in));
|
||||
|
|
|
|||
|
|
@ -407,6 +407,42 @@ test "futex2_requeue" {
|
|||
try expectEqual(0, rc);
|
||||
}
|
||||
|
||||
test "timerfd" {
|
||||
const tfd: linux.fd_t = rc: {
|
||||
const rc = linux.timerfd_create(.MONOTONIC, .{ .CLOEXEC = true });
|
||||
switch (linux.errno(rc)) {
|
||||
.SUCCESS => break :rc @intCast(rc),
|
||||
else => @panic("test failed"),
|
||||
}
|
||||
};
|
||||
defer _ = linux.close(tfd);
|
||||
|
||||
// Fire event 10_000_000ns = 10ms after the posix.timerfd_settime call.
|
||||
var sit: linux.itimerspec = .{ .it_interval = .{ .sec = 0, .nsec = 0 }, .it_value = .{ .sec = 0, .nsec = 10 * (1000 * 1000) } };
|
||||
const flags: linux.TFD.TIMER = .{};
|
||||
switch (linux.errno(linux.timerfd_settime(tfd, @bitCast(flags), &sit, null))) {
|
||||
.SUCCESS => {},
|
||||
else => @panic("test failed"),
|
||||
}
|
||||
|
||||
var fds: [1]std.posix.pollfd = .{.{ .fd = tfd, .events = linux.POLL.IN, .revents = 0 }};
|
||||
try expectEqual(@as(usize, 1), try std.posix.poll(&fds, -1)); // -1 => infinite waiting
|
||||
|
||||
const git = rc: {
|
||||
var curr_value: linux.itimerspec = undefined;
|
||||
const rc = linux.timerfd_gettime(tfd, &curr_value);
|
||||
switch (linux.errno(rc)) {
|
||||
.SUCCESS => break :rc curr_value,
|
||||
else => @panic("test failed"),
|
||||
}
|
||||
};
|
||||
const expect_disarmed_timer: linux.itimerspec = .{
|
||||
.it_interval = .{ .sec = 0, .nsec = 0 },
|
||||
.it_value = .{ .sec = 0, .nsec = 0 },
|
||||
};
|
||||
try expectEqual(expect_disarmed_timer, git);
|
||||
}
|
||||
|
||||
test {
|
||||
_ = linux.IoUring;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -278,30 +278,6 @@ pub const socket_t = if (native_os == .windows) windows.ws2_32.SOCKET else fd_t;
|
|||
/// the system function call whose errno value is intended to be observed.
|
||||
pub const errno = system.errno;
|
||||
|
||||
/// Closes the file descriptor.
|
||||
///
|
||||
/// Asserts the file descriptor is open.
|
||||
///
|
||||
/// This function is not capable of returning any indication of failure. An
|
||||
/// application which wants to ensure writes have succeeded before closing must
|
||||
/// call `fsync` before `close`.
|
||||
///
|
||||
/// The Zig standard library does not support POSIX thread cancellation.
|
||||
pub fn close(fd: fd_t) void {
|
||||
if (native_os == .windows) {
|
||||
return windows.CloseHandle(fd);
|
||||
}
|
||||
if (native_os == .wasi and !builtin.link_libc) {
|
||||
_ = std.os.wasi.fd_close(fd);
|
||||
return;
|
||||
}
|
||||
switch (errno(system.close(fd))) {
|
||||
.BADF => unreachable, // Always a race condition.
|
||||
.INTR => return, // This is still a success. See https://github.com/ziglang/zig/issues/2425
|
||||
else => return,
|
||||
}
|
||||
}
|
||||
|
||||
pub const RebootError = error{
|
||||
PermissionDenied,
|
||||
} || UnexpectedError;
|
||||
|
|
@ -1541,60 +1517,6 @@ pub fn perf_event_open(
|
|||
}
|
||||
}
|
||||
|
||||
pub const TimerFdCreateError = error{
|
||||
PermissionDenied,
|
||||
ProcessFdQuotaExceeded,
|
||||
SystemFdQuotaExceeded,
|
||||
NoDevice,
|
||||
SystemResources,
|
||||
} || UnexpectedError;
|
||||
|
||||
pub const TimerFdGetError = error{InvalidHandle} || UnexpectedError;
|
||||
pub const TimerFdSetError = TimerFdGetError || error{Canceled};
|
||||
|
||||
pub fn timerfd_create(clock_id: system.timerfd_clockid_t, flags: system.TFD) TimerFdCreateError!fd_t {
|
||||
const rc = system.timerfd_create(clock_id, @bitCast(flags));
|
||||
return switch (errno(rc)) {
|
||||
.SUCCESS => @intCast(rc),
|
||||
.INVAL => unreachable,
|
||||
.MFILE => return error.ProcessFdQuotaExceeded,
|
||||
.NFILE => return error.SystemFdQuotaExceeded,
|
||||
.NODEV => return error.NoDevice,
|
||||
.NOMEM => return error.SystemResources,
|
||||
.PERM => return error.PermissionDenied,
|
||||
else => |err| return unexpectedErrno(err),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn timerfd_settime(
|
||||
fd: i32,
|
||||
flags: system.TFD.TIMER,
|
||||
new_value: *const system.itimerspec,
|
||||
old_value: ?*system.itimerspec,
|
||||
) TimerFdSetError!void {
|
||||
const rc = system.timerfd_settime(fd, @bitCast(flags), new_value, old_value);
|
||||
return switch (errno(rc)) {
|
||||
.SUCCESS => {},
|
||||
.BADF => error.InvalidHandle,
|
||||
.FAULT => unreachable,
|
||||
.INVAL => unreachable,
|
||||
.CANCELED => error.Canceled,
|
||||
else => |err| return unexpectedErrno(err),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn timerfd_gettime(fd: i32) TimerFdGetError!system.itimerspec {
|
||||
var curr_value: system.itimerspec = undefined;
|
||||
const rc = system.timerfd_gettime(fd, &curr_value);
|
||||
return switch (errno(rc)) {
|
||||
.SUCCESS => return curr_value,
|
||||
.BADF => error.InvalidHandle,
|
||||
.FAULT => unreachable,
|
||||
.INVAL => unreachable,
|
||||
else => |err| return unexpectedErrno(err),
|
||||
};
|
||||
}
|
||||
|
||||
pub const PtraceError = error{
|
||||
DeadLock,
|
||||
DeviceBusy,
|
||||
|
|
|
|||
|
|
@ -522,21 +522,3 @@ test "rename smoke test" {
|
|||
try expectError(error.FileNotFound, Io.Dir.cwd().openDir(io, file_path, .{}));
|
||||
}
|
||||
}
|
||||
|
||||
test "timerfd" {
|
||||
if (native_os != .linux) return error.SkipZigTest;
|
||||
|
||||
const tfd = try posix.timerfd_create(.MONOTONIC, .{ .CLOEXEC = true });
|
||||
defer posix.close(tfd);
|
||||
|
||||
// Fire event 10_000_000ns = 10ms after the posix.timerfd_settime call.
|
||||
var sit: linux.itimerspec = .{ .it_interval = .{ .sec = 0, .nsec = 0 }, .it_value = .{ .sec = 0, .nsec = 10 * (1000 * 1000) } };
|
||||
try posix.timerfd_settime(tfd, .{}, &sit, null);
|
||||
|
||||
var fds: [1]posix.pollfd = .{.{ .fd = tfd, .events = linux.POLL.IN, .revents = 0 }};
|
||||
try expectEqual(@as(usize, 1), try posix.poll(&fds, -1)); // -1 => infinite waiting
|
||||
|
||||
const git = try posix.timerfd_gettime(tfd);
|
||||
const expect_disarmed_timer: linux.itimerspec = .{ .it_interval = .{ .sec = 0, .nsec = 0 }, .it_value = .{ .sec = 0, .nsec = 0 } };
|
||||
try expectEqual(expect_disarmed_timer, git);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1830,7 +1830,6 @@ const src_files = [_][]const u8{
|
|||
"musl/src/time/wcsftime.c",
|
||||
"musl/src/time/__year_to_secs.c",
|
||||
"musl/src/unistd/alarm.c",
|
||||
"musl/src/unistd/close.c",
|
||||
"musl/src/unistd/dup2.c",
|
||||
"musl/src/unistd/dup3.c",
|
||||
"musl/src/unistd/faccessat.c",
|
||||
|
|
@ -1849,7 +1848,6 @@ const src_files = [_][]const u8{
|
|||
"musl/src/unistd/nice.c",
|
||||
"musl/src/unistd/pause.c",
|
||||
"musl/src/unistd/pipe2.c",
|
||||
"musl/src/unistd/posix_close.c",
|
||||
"musl/src/unistd/pread.c",
|
||||
"musl/src/unistd/preadv.c",
|
||||
"musl/src/unistd/pwrite.c",
|
||||
|
|
|
|||
|
|
@ -999,7 +999,6 @@ const libc_top_half_src_files = [_][]const u8{
|
|||
"musl/src/time/strptime.c",
|
||||
"musl/src/time/timespec_get.c",
|
||||
"musl/src/time/__year_to_secs.c",
|
||||
"musl/src/unistd/posix_close.c",
|
||||
|
||||
"wasi/libc-top-half/musl/src/conf/fpathconf.c",
|
||||
"wasi/libc-top-half/musl/src/conf/sysconf.c",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue