| author | |
| committer | |
| log | b600b6e5e08bc443ef9742b36d51c95715c8150a |
| tree | ff9dc624970254de1b3500858df3064095cafb87 |
| parent | ea30f86113cb1ef2ea53f8d35598061ebb153c8e |
16 files changed, 165 insertions(+), 234 deletions(-)
lib/c/unistd.zig+30| ... | ... | @@ -14,6 +14,8 @@ comptime { |
| 14 | 14 | symbol(&acctLinux, "acct"); |
| 15 | 15 | symbol(&chdirLinux, "chdir"); |
| 16 | 16 | symbol(&chownLinux, "chown"); |
| 17 | symbol(&close, "close"); | |
| 18 | symbol(&posix_close, "posix_close"); | |
| 17 | 19 | symbol(&fchownatLinux, "fchownat"); |
| 18 | 20 | symbol(&lchownLinux, "lchown"); |
| 19 | 21 | symbol(&chrootLinux, "chroot"); |
| ... | ... | @@ -49,6 +51,9 @@ comptime { |
| 49 | 51 | if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) { |
| 50 | 52 | symbol(&swab, "swab"); |
| 51 | 53 | } |
| 54 | if (builtin.target.isWasiLibC()) { | |
| 55 | symbol(&closeWasi, "close"); | |
| 56 | } | |
| 52 | 57 | } |
| 53 | 58 | |
| 54 | 59 | fn _exit(exit_code: c_int) callconv(.c) noreturn { |
| ... | ... | @@ -226,3 +231,28 @@ test swab { |
| 226 | 231 | swab("abcd", &a, 3); |
| 227 | 232 | try std.testing.expectEqualSlices(u8, "ba\x00\x00", &a); |
| 228 | 233 | } |
| 234 | ||
| 235 | fn close(fd: std.c.fd_t) callconv(.c) c_int { | |
| 236 | const signed: isize = @bitCast(linux.close(fd)); | |
| 237 | if (signed < 0) { | |
| 238 | @branchHint(.unlikely); | |
| 239 | if (-signed == @intFromEnum(linux.E.INTR)) return 0; | |
| 240 | std.c._errno().* = @intCast(-signed); | |
| 241 | return -1; | |
| 242 | } | |
| 243 | return 0; | |
| 244 | } | |
| 245 | ||
| 246 | fn posix_close(fd: std.c.fd_t, _: c_int) callconv(.c) c_int { | |
| 247 | return close(fd); | |
| 248 | } | |
| 249 | ||
| 250 | fn closeWasi(fd: std.c.fd_t) callconv(.c) c_int { | |
| 251 | switch (std.os.wasi.fd_close(fd)) { | |
| 252 | .SUCCESS => return 0, | |
| 253 | else => |e| { | |
| 254 | std.c._errno().* = @intFromEnum(e); | |
| 255 | return -1; | |
| 256 | }, | |
| 257 | } | |
| 258 | } |
lib/libc/musl/src/unistd/close.c deleted-19| ... | ... | @@ -1,19 +0,0 @@ |
| 1 | #include <unistd.h> | |
| 2 | #include <errno.h> | |
| 3 | #include "aio_impl.h" | |
| 4 | #include "syscall.h" | |
| 5 | ||
| 6 | static int dummy(int fd) | |
| 7 | { | |
| 8 | 	return fd; | |
| 9 | } | |
| 10 | ||
| 11 | weak_alias(dummy, __aio_close); | |
| 12 | ||
| 13 | int close(int fd) | |
| 14 | { | |
| 15 | 	fd = __aio_close(fd); | |
| 16 | 	int r = __syscall_cp(SYS_close, fd); | |
| 17 | 	if (r == -EINTR) r = 0; | |
| 18 | 	return __syscall_ret(r); | |
| 19 | } |
lib/libc/musl/src/unistd/posix_close.c deleted-6| ... | ... | @@ -1,6 +0,0 @@ |
| 1 | #include <unistd.h> | |
| 2 | ||
| 3 | int posix_close(int fd, int flags) | |
| 4 | { | |
| 5 | 	return close(fd); | |
| 6 | } |
lib/libc/wasi/libc-bottom-half/sources/__wasilibc_fd_renumber.c-38| ... | ... | @@ -70,41 +70,3 @@ void drop_udp_socket(udp_socket_t socket) { |
| 70 | 70 | udp_udp_socket_drop_own(socket.socket); |
| 71 | 71 | } |
| 72 | 72 | #endif // __wasilibc_use_wasip2 |
| 73 | ||
| 74 | int close(int fd) { | |
| 75 | // Scan the preopen fds before making any changes. | |
| 76 | __wasilibc_populate_preopens(); | |
| 77 | ||
| 78 | #ifdef __wasilibc_use_wasip2 | |
| 79 | descriptor_table_entry_t entry; | |
| 80 | if (descriptor_table_remove(fd, &entry)) { | |
| 81 | ||
| 82 | switch (entry.tag) | |
| 83 | { | |
| 84 | case DESCRIPTOR_TABLE_ENTRY_TCP_SOCKET: | |
| 85 | drop_tcp_socket(entry.tcp_socket); | |
| 86 | break; | |
| 87 | case DESCRIPTOR_TABLE_ENTRY_UDP_SOCKET: | |
| 88 | drop_udp_socket(entry.udp_socket); | |
| 89 | break; | |
| 90 | default: /* unreachable */ abort(); | |
| 91 | } | |
| 92 | ||
| 93 | return 0; | |
| 94 | } | |
| 95 | #endif // __wasilibc_use_wasip2 | |
| 96 | ||
| 97 | __wasi_errno_t error = __wasi_fd_close(fd); | |
| 98 | if (error != 0) { | |
| 99 | errno = error; | |
| 100 | return -1; | |
| 101 | } | |
| 102 | ||
| 103 | return 0; | |
| 104 | } | |
| 105 | ||
| 106 | weak void __wasilibc_populate_preopens(void) { | |
| 107 | // This version does nothing. It may be overridden by a version which does | |
| 108 | // something if `__wasilibc_find_abspath` or `__wasilibc_find_relpath` are | |
| 109 | // used. | |
| 110 | } |
lib/std/Build/Watch.zig+2-2| ... | ... | @@ -693,7 +693,7 @@ const Os = switch (builtin.os.tag) { |
| 693 | 693 | fatal("failed to open directory {f}: {t}", .{ path, err }); |
| 694 | 694 | }; |
| 695 | 695 | // Empirically the dir has to stay open or else no events are triggered. |
| 696 | errdefer if (!skip_open_dir) posix.close(dir_fd); | |
| 696 | errdefer if (!skip_open_dir) std.Io.Threaded.closeFd(dir_fd); | |
| 697 | 697 | const changes = [1]posix.Kevent{.{ |
| 698 | 698 | .ident = @bitCast(@as(isize, dir_fd)), |
| 699 | 699 | .filter = std.c.EVFILT.VNODE, |
| ... | ... | @@ -793,7 +793,7 @@ const Os = switch (builtin.os.tag) { |
| 793 | 793 | }; |
| 794 | 794 | const filtered_changes = if (i == handles.len - 1) changes[0..1] else &changes; |
| 795 | 795 | _ = try Io.Kqueue.kevent(w.os.kq_fd, filtered_changes, &.{}, null); |
| 796 | if (path.sub_path.len != 0) posix.close(dir_fd); | |
| 796 | if (path.sub_path.len != 0) std.Io.Threaded.closeFd(dir_fd); | |
| 797 | 797 | |
| 798 | 798 | w.dir_table.swapRemoveAt(i); |
| 799 | 799 | handles.swapRemove(i); |
lib/std/Io/IoUring.zig+1-1| ... | ... | @@ -549,7 +549,7 @@ const CachedFd = struct { |
| 549 | 549 | .initializing => unreachable, |
| 550 | 550 | _ => |fd| { |
| 551 | 551 | assert(@intFromEnum(fd) >= 0); |
| 552 | std.posix.close(@intFromEnum(fd)); | |
| 552 | _ = std.os.linux.close(@intFromEnum(fd)); | |
| 553 | 553 | cached_fd.* = .init; |
| 554 | 554 | }, |
| 555 | 555 | } |
lib/std/Io/Kqueue.zig+8-7| ... | ... | @@ -11,6 +11,7 @@ const Allocator = std.mem.Allocator; |
| 11 | 11 | const Alignment = std.mem.Alignment; |
| 12 | 12 | const IpAddress = std.Io.net.IpAddress; |
| 13 | 13 | const errnoBug = std.Io.Threaded.errnoBug; |
| 14 | const closeFd = std.Io.Threaded.closeFd; | |
| 14 | 15 | const posix = std.posix; |
| 15 | 16 | |
| 16 | 17 | /// Must be a thread-safe allocator. |
| ... | ... | @@ -64,7 +65,7 @@ const Thread = struct { |
| 64 | 65 | }; |
| 65 | 66 | |
| 66 | 67 | fn deinit(thread: *Thread, gpa: Allocator) void { |
| 67 | posix.close(thread.kq_fd); | |
| 68 | closeFd(thread.kq_fd); | |
| 68 | 69 | assert(thread.wait_queues.count() == 0); |
| 69 | 70 | thread.wait_queues.deinit(gpa); |
| 70 | 71 | thread.* = undefined; |
| ... | ... | @@ -212,7 +213,7 @@ pub fn init(k: *Kqueue, gpa: Allocator, options: InitOptions) !void { |
| 212 | 213 | .steal_ready_search_index = 1, |
| 213 | 214 | .wait_queues = .empty, |
| 214 | 215 | }; |
| 215 | errdefer std.posix.close(main_thread.kq_fd); | |
| 216 | errdefer closeFd(main_thread.kq_fd); | |
| 216 | 217 | std.log.debug("created main idle {*}", .{&main_thread.idle_context}); |
| 217 | 218 | std.log.debug("created main {*}", .{main_fiber}); |
| 218 | 219 | } |
| ... | ... | @@ -371,7 +372,7 @@ fn schedule(k: *Kqueue, thread: *Thread, ready_queue: Fiber.Queue) void { |
| 371 | 372 | .stack_size = idle_stack_size, |
| 372 | 373 | .allocator = k.gpa, |
| 373 | 374 | }, threadEntry, .{ k, new_thread_index }) catch |err| { |
| 374 | posix.close(new_thread.kq_fd); | |
| 375 | closeFd(new_thread.kq_fd); | |
| 375 | 376 | @atomicStore(u32, &k.threads.reserved, new_thread_index, .release); |
| 376 | 377 | // no more access to `thread` after giving up reservation |
| 377 | 378 | std.log.warn("unable to create worker thread due spawn failure: {s}", .{@errorName(err)}); |
| ... | ... | @@ -1234,7 +1235,7 @@ fn netBindIp( |
| 1234 | 1235 | const k: *Kqueue = @ptrCast(@alignCast(userdata)); |
| 1235 | 1236 | const family = Io.Threaded.posixAddressFamily(address); |
| 1236 | 1237 | const socket_fd = try openSocketPosix(k, family, options); |
| 1237 | errdefer std.posix.close(socket_fd); | |
| 1238 | errdefer closeFd(socket_fd); | |
| 1238 | 1239 | var storage: Io.Threaded.PosixAddress = undefined; |
| 1239 | 1240 | var addr_len = Io.Threaded.addressToPosix(address, &storage); |
| 1240 | 1241 | try posixBind(k, socket_fd, &storage.any, addr_len); |
| ... | ... | @@ -1252,7 +1253,7 @@ fn netConnectIp(userdata: ?*anyopaque, address: *const net.IpAddress, options: n |
| 1252 | 1253 | .mode = options.mode, |
| 1253 | 1254 | .protocol = options.protocol, |
| 1254 | 1255 | }); |
| 1255 | errdefer posix.close(socket_fd); | |
| 1256 | errdefer closeFd(socket_fd); | |
| 1256 | 1257 | var storage: Io.Threaded.PosixAddress = undefined; |
| 1257 | 1258 | var addr_len = Io.Threaded.addressToPosix(address, &storage); |
| 1258 | 1259 | try posixConnect(k, socket_fd, &storage.any, addr_len); |
| ... | ... | @@ -1565,7 +1566,7 @@ fn openSocketPosix( |
| 1565 | 1566 | switch (posix.errno(socket_rc)) { |
| 1566 | 1567 | .SUCCESS => { |
| 1567 | 1568 | const fd: posix.fd_t = @intCast(socket_rc); |
| 1568 | errdefer posix.close(fd); | |
| 1569 | errdefer closeFd(fd); | |
| 1569 | 1570 | if (Io.Threaded.socket_flags_unsupported) { |
| 1570 | 1571 | while (true) { |
| 1571 | 1572 | try k.checkCancel(); |
| ... | ... | @@ -1614,7 +1615,7 @@ fn openSocketPosix( |
| 1614 | 1615 | else => |err| return posix.unexpectedErrno(err), |
| 1615 | 1616 | } |
| 1616 | 1617 | }; |
| 1617 | errdefer posix.close(socket_fd); | |
| 1618 | errdefer closeFd(socket_fd); | |
| 1618 | 1619 | |
| 1619 | 1620 | if (options.ip6_only) { |
| 1620 | 1621 | if (posix.IPV6 == void) return error.OptionUnsupported; |
lib/std/Io/Threaded.zig+64-38| ... | ... | @@ -303,7 +303,7 @@ pub const NullFile = switch (native_os) { |
| 303 | 303 | |
| 304 | 304 | fn deinit(this: *@This()) void { |
| 305 | 305 | if (this.fd >= 0) { |
| 306 | posix.close(this.fd); | |
| 306 | closeFd(this.fd); | |
| 307 | 307 | this.fd = -1; |
| 308 | 308 | } |
| 309 | 309 | } |
| ... | ... | @@ -4337,7 +4337,7 @@ fn dirCreateFilePosix( |
| 4337 | 4337 | } |
| 4338 | 4338 | } |
| 4339 | 4339 | }; |
| 4340 | errdefer posix.close(fd); | |
| 4340 | errdefer closeFd(fd); | |
| 4341 | 4341 | |
| 4342 | 4342 | if (have_flock and !have_flock_open_flags and flags.lock != .none) { |
| 4343 | 4343 | const lock_nonblocking: i32 = if (flags.lock_nonblocking) posix.LOCK.NB else 0; |
| ... | ... | @@ -4917,7 +4917,7 @@ fn dirOpenFilePosix( |
| 4917 | 4917 | } |
| 4918 | 4918 | } |
| 4919 | 4919 | }; |
| 4920 | errdefer posix.close(fd); | |
| 4920 | errdefer closeFd(fd); | |
| 4921 | 4921 | |
| 4922 | 4922 | if (!flags.allow_directory) { |
| 4923 | 4923 | const is_dir = is_dir: { |
| ... | ... | @@ -5241,7 +5241,7 @@ fn dirOpenFileWasi( |
| 5241 | 5241 | }, |
| 5242 | 5242 | } |
| 5243 | 5243 | } |
| 5244 | errdefer posix.close(fd); | |
| 5244 | errdefer closeFd(fd); | |
| 5245 | 5245 | |
| 5246 | 5246 | if (!flags.allow_directory) { |
| 5247 | 5247 | const is_dir = is_dir: { |
| ... | ... | @@ -5457,7 +5457,13 @@ pub fn dirOpenDirWindows( |
| 5457 | 5457 | fn dirClose(userdata: ?*anyopaque, dirs: []const Dir) void { |
| 5458 | 5458 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 5459 | 5459 | _ = t; |
| 5460 | for (dirs) |dir| posix.close(dir.handle); | |
| 5460 | for (dirs) |dir| { | |
| 5461 | if (is_windows) { | |
| 5462 | windows.CloseHandle(dir.handle); | |
| 5463 | } else { | |
| 5464 | closeFd(dir.handle); | |
| 5465 | } | |
| 5466 | } | |
| 5461 | 5467 | } |
| 5462 | 5468 | |
| 5463 | 5469 | const dirRead = switch (native_os) { |
| ... | ... | @@ -6777,7 +6783,7 @@ fn dirRealPathFilePosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, o |
| 6777 | 6783 | }, |
| 6778 | 6784 | } |
| 6779 | 6785 | }; |
| 6780 | defer posix.close(fd); | |
| 6786 | defer closeFd(fd); | |
| 6781 | 6787 | return realPathPosix(fd, out_buffer); |
| 6782 | 6788 | } |
| 6783 | 6789 | |
| ... | ... | @@ -8367,7 +8373,7 @@ fn fchmodatFallback( |
| 8367 | 8373 | } |
| 8368 | 8374 | } |
| 8369 | 8375 | }; |
| 8370 | defer posix.close(path_fd); | |
| 8376 | defer closeFd(path_fd); | |
| 8371 | 8377 | |
| 8372 | 8378 | const path_mode = mode: { |
| 8373 | 8379 | const sys = if (statx_use_c) std.c else std.os.linux; |
| ... | ... | @@ -9592,7 +9598,13 @@ fn dirHardLink( |
| 9592 | 9598 | fn fileClose(userdata: ?*anyopaque, files: []const File) void { |
| 9593 | 9599 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 9594 | 9600 | _ = t; |
| 9595 | for (files) |file| posix.close(file.handle); | |
| 9601 | for (files) |file| { | |
| 9602 | if (is_windows) { | |
| 9603 | windows.CloseHandle(file.handle); | |
| 9604 | } else { | |
| 9605 | closeFd(file.handle); | |
| 9606 | } | |
| 9607 | } | |
| 9596 | 9608 | } |
| 9597 | 9609 | |
| 9598 | 9610 | fn fileReadStreaming(userdata: ?*anyopaque, file: File, data: []const []u8) File.ReadStreamingError!usize { |
| ... | ... | @@ -11783,7 +11795,7 @@ fn netListenIpPosix( |
| 11783 | 11795 | .mode = options.mode, |
| 11784 | 11796 | .protocol = options.protocol, |
| 11785 | 11797 | }); |
| 11786 | errdefer posix.close(socket_fd); | |
| 11798 | errdefer closeFd(socket_fd); | |
| 11787 | 11799 | |
| 11788 | 11800 | if (options.reuse_address) { |
| 11789 | 11801 | try setSocketOption(socket_fd, posix.SOL.SOCKET, posix.SO.REUSEADDR, 1); |
| ... | ... | @@ -11946,7 +11958,7 @@ fn netListenUnixPosix( |
| 11946 | 11958 | error.OptionUnsupported => return error.Unexpected, |
| 11947 | 11959 | else => |e| return e, |
| 11948 | 11960 | }; |
| 11949 | errdefer posix.close(socket_fd); | |
| 11961 | errdefer closeFd(socket_fd); | |
| 11950 | 11962 | |
| 11951 | 11963 | var storage: UnixAddress = undefined; |
| 11952 | 11964 | const addr_len = addressUnixToPosix(address, &storage); |
| ... | ... | @@ -12362,7 +12374,7 @@ fn netConnectIpPosix( |
| 12362 | 12374 | .mode = options.mode, |
| 12363 | 12375 | .protocol = options.protocol, |
| 12364 | 12376 | }); |
| 12365 | errdefer posix.close(socket_fd); | |
| 12377 | errdefer closeFd(socket_fd); | |
| 12366 | 12378 | var storage: PosixAddress = undefined; |
| 12367 | 12379 | var addr_len = addressToPosix(address, &storage); |
| 12368 | 12380 | try posixConnect(socket_fd, &storage.any, addr_len); |
| ... | ... | @@ -12462,7 +12474,7 @@ fn netConnectUnixPosix( |
| 12462 | 12474 | error.OptionUnsupported => return error.Unexpected, |
| 12463 | 12475 | else => |e| return e, |
| 12464 | 12476 | }; |
| 12465 | errdefer posix.close(socket_fd); | |
| 12477 | errdefer closeFd(socket_fd); | |
| 12466 | 12478 | var storage: UnixAddress = undefined; |
| 12467 | 12479 | const addr_len = addressUnixToPosix(address, &storage); |
| 12468 | 12480 | try posixConnectUnix(socket_fd, &storage.any, addr_len); |
| ... | ... | @@ -12536,7 +12548,7 @@ fn netBindIpPosix( |
| 12536 | 12548 | _ = t; |
| 12537 | 12549 | const family = posixAddressFamily(address); |
| 12538 | 12550 | const socket_fd = try openSocketPosix(family, options); |
| 12539 | errdefer posix.close(socket_fd); | |
| 12551 | errdefer closeFd(socket_fd); | |
| 12540 | 12552 | var storage: PosixAddress = undefined; |
| 12541 | 12553 | var addr_len = addressToPosix(address, &storage); |
| 12542 | 12554 | try posixBind(socket_fd, &storage.any, addr_len); |
| ... | ... | @@ -12642,7 +12654,7 @@ fn openSocketPosix( |
| 12642 | 12654 | .SUCCESS => { |
| 12643 | 12655 | syscall.finish(); |
| 12644 | 12656 | const fd: posix.fd_t = @intCast(rc); |
| 12645 | errdefer posix.close(fd); | |
| 12657 | errdefer closeFd(fd); | |
| 12646 | 12658 | if (socket_flags_unsupported) try setCloexec(fd); |
| 12647 | 12659 | break fd; |
| 12648 | 12660 | }, |
| ... | ... | @@ -12661,7 +12673,7 @@ fn openSocketPosix( |
| 12661 | 12673 | else => |err| return syscall.unexpectedErrno(err), |
| 12662 | 12674 | } |
| 12663 | 12675 | }; |
| 12664 | errdefer posix.close(socket_fd); | |
| 12676 | errdefer closeFd(socket_fd); | |
| 12665 | 12677 | |
| 12666 | 12678 | if (options.ip6_only) { |
| 12667 | 12679 | if (posix.IPV6 == void) return error.OptionUnsupported; |
| ... | ... | @@ -12707,8 +12719,8 @@ fn netSocketCreatePair( |
| 12707 | 12719 | .SUCCESS => { |
| 12708 | 12720 | syscall.finish(); |
| 12709 | 12721 | errdefer { |
| 12710 | posix.close(sockets[0]); | |
| 12711 | posix.close(sockets[1]); | |
| 12722 | closeFd(sockets[0]); | |
| 12723 | closeFd(sockets[1]); | |
| 12712 | 12724 | } |
| 12713 | 12725 | if (socket_flags_unsupported) { |
| 12714 | 12726 | try setCloexec(sockets[0]); |
| ... | ... | @@ -12809,7 +12821,7 @@ fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: net.Socket.Handle) net.Serve |
| 12809 | 12821 | .SUCCESS => { |
| 12810 | 12822 | syscall.finish(); |
| 12811 | 12823 | const fd: posix.fd_t = @intCast(rc); |
| 12812 | errdefer posix.close(fd); | |
| 12824 | errdefer closeFd(fd); | |
| 12813 | 12825 | if (!have_accept4) try setCloexec(fd); |
| 12814 | 12826 | break fd; |
| 12815 | 12827 | }, |
| ... | ... | @@ -13679,7 +13691,7 @@ fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void { |
| 13679 | 13691 | _ = t; |
| 13680 | 13692 | switch (native_os) { |
| 13681 | 13693 | .windows => for (handles) |handle| closeSocketWindows(handle), |
| 13682 | else => for (handles) |handle| posix.close(handle), | |
| 13694 | else => for (handles) |handle| closeFd(handle), | |
| 13683 | 13695 | } |
| 13684 | 13696 | } |
| 13685 | 13697 | |
| ... | ... | @@ -13787,7 +13799,7 @@ fn netInterfaceNameResolve( |
| 13787 | 13799 | error.OptionUnsupported => return error.Unexpected, |
| 13788 | 13800 | else => |e| return e, |
| 13789 | 13801 | }; |
| 13790 | defer posix.close(sock_fd); | |
| 13802 | defer closeFd(sock_fd); | |
| 13791 | 13803 | |
| 13792 | 13804 | var ifr: posix.ifreq = .{ |
| 13793 | 13805 | .ifrn = .{ .name = @bitCast(name.bytes) }, |
| ... | ... | @@ -15329,13 +15341,13 @@ fn spawnPosix(t: *Threaded, options: process.SpawnOptions) process.SpawnError!Sp |
| 15329 | 15341 | const pid: posix.pid_t = @intCast(pid_result); // We are the parent. |
| 15330 | 15342 | errdefer comptime unreachable; // The child is forked; we must not error from now on |
| 15331 | 15343 | |
| 15332 | posix.close(err_pipe[1]); // make sure only the child holds the write end open | |
| 15344 | closeFd(err_pipe[1]); // make sure only the child holds the write end open | |
| 15333 | 15345 | |
| 15334 | if (options.stdin == .pipe) posix.close(stdin_pipe[0]); | |
| 15335 | if (options.stdout == .pipe) posix.close(stdout_pipe[1]); | |
| 15336 | if (options.stderr == .pipe) posix.close(stderr_pipe[1]); | |
| 15346 | if (options.stdin == .pipe) closeFd(stdin_pipe[0]); | |
| 15347 | if (options.stdout == .pipe) closeFd(stdout_pipe[1]); | |
| 15348 | if (options.stderr == .pipe) closeFd(stderr_pipe[1]); | |
| 15337 | 15349 | |
| 15338 | if (prog_pipe[1] != -1) posix.close(prog_pipe[1]); | |
| 15350 | if (prog_pipe[1] != -1) closeFd(prog_pipe[1]); | |
| 15339 | 15351 | options.progress_node.setIpcFile(t, .{ .handle = prog_pipe[0], .flags = .{ .nonblocking = true } }); |
| 15340 | 15352 | |
| 15341 | 15353 | return .{ |
| ... | ... | @@ -15373,7 +15385,7 @@ fn getDevNullFd(t: *Threaded) !posix.fd_t { |
| 15373 | 15385 | mutexLock(&t.mutex); // Another thread might have won the race. |
| 15374 | 15386 | defer mutexUnlock(&t.mutex); |
| 15375 | 15387 | if (t.null_file.fd != -1) { |
| 15376 | posix.close(fresh_fd); | |
| 15388 | closeFd(fresh_fd); | |
| 15377 | 15389 | return t.null_file.fd; |
| 15378 | 15390 | } else { |
| 15379 | 15391 | t.null_file.fd = fresh_fd; |
| ... | ... | @@ -15399,7 +15411,7 @@ fn getDevNullFd(t: *Threaded) !posix.fd_t { |
| 15399 | 15411 | fn processSpawnPosix(userdata: ?*anyopaque, options: process.SpawnOptions) process.SpawnError!process.Child { |
| 15400 | 15412 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 15401 | 15413 | const spawned = try spawnPosix(t, options); |
| 15402 | defer posix.close(spawned.err_fd); | |
| 15414 | defer closeFd(spawned.err_fd); | |
| 15403 | 15415 | |
| 15404 | 15416 | // Wait for the child to report any errors in or before `execvpe`. |
| 15405 | 15417 | if (readIntFd(spawned.err_fd)) |child_err_int| { |
| ... | ... | @@ -15666,15 +15678,15 @@ fn childKillPosix(child: *process.Child) !void { |
| 15666 | 15678 | |
| 15667 | 15679 | fn childCleanupPosix(child: *process.Child) void { |
| 15668 | 15680 | if (child.stdin) |*stdin| { |
| 15669 | posix.close(stdin.handle); | |
| 15681 | closeFd(stdin.handle); | |
| 15670 | 15682 | child.stdin = null; |
| 15671 | 15683 | } |
| 15672 | 15684 | if (child.stdout) |*stdout| { |
| 15673 | posix.close(stdout.handle); | |
| 15685 | closeFd(stdout.handle); | |
| 15674 | 15686 | child.stdout = null; |
| 15675 | 15687 | } |
| 15676 | 15688 | if (child.stderr) |*stderr| { |
| 15677 | posix.close(stderr.handle); | |
| 15689 | closeFd(stderr.handle); | |
| 15678 | 15690 | child.stderr = null; |
| 15679 | 15691 | } |
| 15680 | 15692 | child.id = null; |
| ... | ... | @@ -15743,14 +15755,14 @@ fn readIntFd(fd: posix.fd_t) !ErrInt { |
| 15743 | 15755 | const ErrInt = std.meta.Int(.unsigned, @sizeOf(anyerror) * 8); |
| 15744 | 15756 | |
| 15745 | 15757 | fn destroyPipe(pipe: [2]posix.fd_t) void { |
| 15746 | if (pipe[0] != -1) posix.close(pipe[0]); | |
| 15747 | if (pipe[0] != pipe[1]) posix.close(pipe[1]); | |
| 15758 | if (pipe[0] != -1) closeFd(pipe[0]); | |
| 15759 | if (pipe[0] != pipe[1]) closeFd(pipe[1]); | |
| 15748 | 15760 | } |
| 15749 | 15761 | |
| 15750 | 15762 | fn setUpChildIo(stdio: process.SpawnOptions.StdIo, pipe_fd: i32, std_fileno: i32, dev_null_fd: i32) !void { |
| 15751 | 15763 | switch (stdio) { |
| 15752 | 15764 | .pipe => try dup2(pipe_fd, std_fileno), |
| 15753 | .close => posix.close(std_fileno), | |
| 15765 | .close => closeFd(std_fileno), | |
| 15754 | 15766 | .inherit => {}, |
| 15755 | 15767 | .ignore => try dup2(dev_null_fd, std_fileno), |
| 15756 | 15768 | .file => @panic("TODO implement setUpChildIo when file is used"), |
| ... | ... | @@ -17439,7 +17451,7 @@ fn getRandomFd(t: *Threaded) Io.RandomSecureError!posix.fd_t { |
| 17439 | 17451 | } |
| 17440 | 17452 | } |
| 17441 | 17453 | }; |
| 17442 | errdefer posix.close(fd); | |
| 17454 | errdefer closeFd(fd); | |
| 17443 | 17455 | |
| 17444 | 17456 | switch (native_os) { |
| 17445 | 17457 | .linux => { |
| ... | ... | @@ -17454,7 +17466,7 @@ fn getRandomFd(t: *Threaded) Io.RandomSecureError!posix.fd_t { |
| 17454 | 17466 | mutexLock(&t.mutex); // Another thread might have won the race. |
| 17455 | 17467 | defer mutexUnlock(&t.mutex); |
| 17456 | 17468 | if (t.random_file.fd >= 0) { |
| 17457 | posix.close(fd); | |
| 17469 | closeFd(fd); | |
| 17458 | 17470 | return t.random_file.fd; |
| 17459 | 17471 | } else if (!posix.S.ISCHR(statx.mode)) { |
| 17460 | 17472 | t.random_file.fd = -2; |
| ... | ... | @@ -17482,7 +17494,7 @@ fn getRandomFd(t: *Threaded) Io.RandomSecureError!posix.fd_t { |
| 17482 | 17494 | mutexLock(&t.mutex); // Another thread might have won the race. |
| 17483 | 17495 | defer mutexUnlock(&t.mutex); |
| 17484 | 17496 | if (t.random_file.fd >= 0) { |
| 17485 | posix.close(fd); | |
| 17497 | closeFd(fd); | |
| 17486 | 17498 | return t.random_file.fd; |
| 17487 | 17499 | } else if (!posix.S.ISCHR(stat.mode)) { |
| 17488 | 17500 | t.random_file.fd = -2; |
| ... | ... | @@ -18170,8 +18182,8 @@ pub fn pipe2(flags: posix.O) PipeError![2]posix.fd_t { |
| 18170 | 18182 | else => |err| return posix.unexpectedErrno(err), |
| 18171 | 18183 | } |
| 18172 | 18184 | errdefer { |
| 18173 | posix.close(fds[0]); | |
| 18174 | posix.close(fds[1]); | |
| 18185 | closeFd(fds[0]); | |
| 18186 | closeFd(fds[1]); | |
| 18175 | 18187 | } |
| 18176 | 18188 | |
| 18177 | 18189 | // https://github.com/ziglang/zig/issues/18882 |
| ... | ... | @@ -19164,3 +19176,17 @@ fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!windows |
| 19164 | 19176 | } |
| 19165 | 19177 | } |
| 19166 | 19178 | } |
| 19179 | ||
| 19180 | pub fn closeFd(fd: posix.fd_t) void { | |
| 19181 | if (native_os == .wasi and !builtin.link_libc) { | |
| 19182 | switch (std.os.wasi.fd_close(fd)) { | |
| 19183 | .SUCCESS, .INTR => {}, | |
| 19184 | .BADF => recoverableOsBugDetected(), // use after free | |
| 19185 | else => recoverableOsBugDetected(), // unexpected failure | |
| 19186 | } | |
| 19187 | } else switch (posix.errno(posix.system.close(fd))) { | |
| 19188 | .SUCCESS, .INTR => {}, // INTR still a success, see https://github.com/ziglang/zig/issues/2425 | |
| 19189 | .BADF => recoverableOsBugDetected(), // use after free | |
| 19190 | else => recoverableOsBugDetected(), // unexpected failure | |
| 19191 | } | |
| 19192 | } |
lib/std/os/linux.zig+1-1| ... | ... | @@ -1571,7 +1571,7 @@ pub fn clone2(flags: u32, child_stack_ptr: usize) usize { |
| 1571 | 1571 | return syscall2(.clone, flags, child_stack_ptr); |
| 1572 | 1572 | } |
| 1573 | 1573 | |
| 1574 | pub fn close(fd: i32) usize { | |
| 1574 | pub fn close(fd: fd_t) usize { | |
| 1575 | 1575 | return syscall1(.close, @as(usize, @bitCast(@as(isize, fd)))); |
| 1576 | 1576 | } |
| 1577 | 1577 |
lib/std/os/linux/IoUring.zig+2-2| ... | ... | @@ -67,7 +67,7 @@ pub fn init_params(entries: u16, p: *linux.io_uring_params) !IoUring { |
| 67 | 67 | } |
| 68 | 68 | const fd = @as(linux.fd_t, @intCast(res)); |
| 69 | 69 | assert(fd >= 0); |
| 70 | errdefer posix.close(fd); | |
| 70 | errdefer _ = linux.close(fd); | |
| 71 | 71 | |
| 72 | 72 | // Kernel versions 5.4 and up use only one mmap() for the submission and completion queues. |
| 73 | 73 | // 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 { |
| 125 | 125 | // The mmaps depend on the fd, so the order of these calls is important: |
| 126 | 126 | self.cq.deinit(); |
| 127 | 127 | self.sq.deinit(); |
| 128 | posix.close(self.fd); | |
| 128 | _ = linux.close(self.fd); | |
| 129 | 129 | self.fd = -1; |
| 130 | 130 | } |
| 131 | 131 |
lib/std/os/linux/IoUring/test.zig+21-21| ... | ... | @@ -440,7 +440,7 @@ test "openat" { |
| 440 | 440 | try testing.expect(cqe_openat.res > 0); |
| 441 | 441 | try testing.expectEqual(@as(u32, 0), cqe_openat.flags); |
| 442 | 442 | |
| 443 | posix.close(cqe_openat.res); | |
| 443 | _ = linux.close(cqe_openat.res); | |
| 444 | 444 | } |
| 445 | 445 | |
| 446 | 446 | test "close" { |
| ... | ... | @@ -530,7 +530,7 @@ test "sendmsg/recvmsg" { |
| 530 | 530 | }; |
| 531 | 531 | |
| 532 | 532 | const server = try socket(address_server.family, posix.SOCK.DGRAM, 0); |
| 533 | defer posix.close(server); | |
| 533 | defer _ = linux.close(server); | |
| 534 | 534 | try posix.setsockopt(server, posix.SOL.SOCKET, posix.SO.REUSEPORT, &mem.toBytes(@as(c_int, 1))); |
| 535 | 535 | try posix.setsockopt(server, posix.SOL.SOCKET, posix.SO.REUSEADDR, &mem.toBytes(@as(c_int, 1))); |
| 536 | 536 | try bind(server, addrAny(&address_server), @sizeOf(linux.sockaddr.in)); |
| ... | ... | @@ -540,7 +540,7 @@ test "sendmsg/recvmsg" { |
| 540 | 540 | try getsockname(server, addrAny(&address_server), &slen); |
| 541 | 541 | |
| 542 | 542 | const client = try socket(address_server.family, posix.SOCK.DGRAM, 0); |
| 543 | defer posix.close(client); | |
| 543 | defer _ = linux.close(client); | |
| 544 | 544 | |
| 545 | 545 | const buffer_send = [_]u8{42} ** 128; |
| 546 | 546 | const iovecs_send = [_]iovec_const{ |
| ... | ... | @@ -1034,7 +1034,7 @@ test "shutdown" { |
| 1034 | 1034 | // Socket bound, expect shutdown to work |
| 1035 | 1035 | { |
| 1036 | 1036 | const server = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); |
| 1037 | defer posix.close(server); | |
| 1037 | defer _ = linux.close(server); | |
| 1038 | 1038 | try posix.setsockopt(server, posix.SOL.SOCKET, posix.SO.REUSEADDR, &mem.toBytes(@as(c_int, 1))); |
| 1039 | 1039 | try bind(server, addrAny(&address), @sizeOf(linux.sockaddr.in)); |
| 1040 | 1040 | try listen(server, 1); |
| ... | ... | @@ -1067,7 +1067,7 @@ test "shutdown" { |
| 1067 | 1067 | // Socket not bound, expect to fail with ENOTCONN |
| 1068 | 1068 | { |
| 1069 | 1069 | const server = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); |
| 1070 | defer posix.close(server); | |
| 1070 | defer _ = linux.close(server); | |
| 1071 | 1071 | |
| 1072 | 1072 | const shutdown_sqe = ring.shutdown(0x445445445, server, linux.SHUT.RD) catch |err| switch (err) { |
| 1073 | 1073 | else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), |
| ... | ... | @@ -1741,7 +1741,7 @@ test "accept multishot" { |
| 1741 | 1741 | .addr = @bitCast([4]u8{ 127, 0, 0, 1 }), |
| 1742 | 1742 | }; |
| 1743 | 1743 | const listener_socket = try createListenerSocket(&address); |
| 1744 | defer posix.close(listener_socket); | |
| 1744 | defer _ = linux.close(listener_socket); | |
| 1745 | 1745 | |
| 1746 | 1746 | // submit multishot accept operation |
| 1747 | 1747 | var addr: posix.sockaddr = undefined; |
| ... | ... | @@ -1754,7 +1754,7 @@ test "accept multishot" { |
| 1754 | 1754 | while (nr > 0) : (nr -= 1) { |
| 1755 | 1755 | // connect client |
| 1756 | 1756 | const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); |
| 1757 | errdefer posix.close(client); | |
| 1757 | errdefer _ = linux.close(client); | |
| 1758 | 1758 | try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in)); |
| 1759 | 1759 | |
| 1760 | 1760 | // test accept completion |
| ... | ... | @@ -1764,7 +1764,7 @@ test "accept multishot" { |
| 1764 | 1764 | try testing.expect(cqe.user_data == userdata); |
| 1765 | 1765 | try testing.expect(cqe.flags & linux.IORING_CQE_F_MORE > 0); // more flag is set |
| 1766 | 1766 | |
| 1767 | posix.close(client); | |
| 1767 | _ = linux.close(client); | |
| 1768 | 1768 | } |
| 1769 | 1769 | } |
| 1770 | 1770 | |
| ... | ... | @@ -1848,7 +1848,7 @@ test "accept_direct" { |
| 1848 | 1848 | try ring.register_files(registered_fds[0..]); |
| 1849 | 1849 | |
| 1850 | 1850 | const listener_socket = try createListenerSocket(&address); |
| 1851 | defer posix.close(listener_socket); | |
| 1851 | defer _ = linux.close(listener_socket); | |
| 1852 | 1852 | |
| 1853 | 1853 | const accept_userdata: u64 = 0xaaaaaaaa; |
| 1854 | 1854 | const read_userdata: u64 = 0xbbbbbbbb; |
| ... | ... | @@ -1866,7 +1866,7 @@ test "accept_direct" { |
| 1866 | 1866 | // connect |
| 1867 | 1867 | const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); |
| 1868 | 1868 | try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in)); |
| 1869 | defer posix.close(client); | |
| 1869 | defer _ = linux.close(client); | |
| 1870 | 1870 | |
| 1871 | 1871 | // accept completion |
| 1872 | 1872 | const cqe_accept = try ring.copy_cqe(); |
| ... | ... | @@ -1900,7 +1900,7 @@ test "accept_direct" { |
| 1900 | 1900 | // connect |
| 1901 | 1901 | const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); |
| 1902 | 1902 | try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in)); |
| 1903 | defer posix.close(client); | |
| 1903 | defer _ = linux.close(client); | |
| 1904 | 1904 | // completion with error |
| 1905 | 1905 | const cqe_accept = try ring.copy_cqe(); |
| 1906 | 1906 | try testing.expect(cqe_accept.user_data == accept_userdata); |
| ... | ... | @@ -1936,7 +1936,7 @@ test "accept_multishot_direct" { |
| 1936 | 1936 | try ring.register_files(registered_fds[0..]); |
| 1937 | 1937 | |
| 1938 | 1938 | const listener_socket = try createListenerSocket(&address); |
| 1939 | defer posix.close(listener_socket); | |
| 1939 | defer _ = linux.close(listener_socket); | |
| 1940 | 1940 | |
| 1941 | 1941 | const accept_userdata: u64 = 0xaaaaaaaa; |
| 1942 | 1942 | |
| ... | ... | @@ -1950,7 +1950,7 @@ test "accept_multishot_direct" { |
| 1950 | 1950 | // connect |
| 1951 | 1951 | const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); |
| 1952 | 1952 | try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in)); |
| 1953 | defer posix.close(client); | |
| 1953 | defer _ = linux.close(client); | |
| 1954 | 1954 | |
| 1955 | 1955 | // accept completion |
| 1956 | 1956 | const cqe_accept = try ring.copy_cqe(); |
| ... | ... | @@ -1965,7 +1965,7 @@ test "accept_multishot_direct" { |
| 1965 | 1965 | // connect |
| 1966 | 1966 | const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); |
| 1967 | 1967 | try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in)); |
| 1968 | defer posix.close(client); | |
| 1968 | defer _ = linux.close(client); | |
| 1969 | 1969 | // completion with error |
| 1970 | 1970 | const cqe_accept = try ring.copy_cqe(); |
| 1971 | 1971 | try testing.expect(cqe_accept.user_data == accept_userdata); |
| ... | ... | @@ -1998,7 +1998,7 @@ test "socket" { |
| 1998 | 1998 | const fd: linux.fd_t = @intCast(cqe.res); |
| 1999 | 1999 | try testing.expect(fd > 2); |
| 2000 | 2000 | |
| 2001 | posix.close(fd); | |
| 2001 | _ = linux.close(fd); | |
| 2002 | 2002 | } |
| 2003 | 2003 | |
| 2004 | 2004 | test "socket_direct/socket_direct_alloc/close_direct" { |
| ... | ... | @@ -2042,7 +2042,7 @@ test "socket_direct/socket_direct_alloc/close_direct" { |
| 2042 | 2042 | .addr = @bitCast([4]u8{ 127, 0, 0, 1 }), |
| 2043 | 2043 | }; |
| 2044 | 2044 | const listener_socket = try createListenerSocket(&address); |
| 2045 | defer posix.close(listener_socket); | |
| 2045 | defer _ = linux.close(listener_socket); | |
| 2046 | 2046 | const accept_userdata: u64 = 0xaaaaaaaa; |
| 2047 | 2047 | const connect_userdata: u64 = 0xbbbbbbbb; |
| 2048 | 2048 | const close_userdata: u64 = 0xcccccccc; |
| ... | ... | @@ -2599,8 +2599,8 @@ pub const SocketTestHarness = struct { |
| 2599 | 2599 | client: posix.socket_t, |
| 2600 | 2600 | |
| 2601 | 2601 | pub fn close(self: SocketTestHarness) void { |
| 2602 | posix.close(self.client); | |
| 2603 | posix.close(self.listener); | |
| 2602 | _ = linux.close(self.client); | |
| 2603 | _ = linux.close(self.listener); | |
| 2604 | 2604 | } |
| 2605 | 2605 | }; |
| 2606 | 2606 | |
| ... | ... | @@ -2611,7 +2611,7 @@ pub fn createSocketTestHarness(ring: *IoUring) !SocketTestHarness { |
| 2611 | 2611 | .addr = @bitCast([4]u8{ 127, 0, 0, 1 }), |
| 2612 | 2612 | }; |
| 2613 | 2613 | const listener_socket = try createListenerSocket(&address); |
| 2614 | errdefer posix.close(listener_socket); | |
| 2614 | errdefer _ = linux.close(listener_socket); | |
| 2615 | 2615 | |
| 2616 | 2616 | // Submit 1 accept |
| 2617 | 2617 | var accept_addr: posix.sockaddr = undefined; |
| ... | ... | @@ -2620,7 +2620,7 @@ pub fn createSocketTestHarness(ring: *IoUring) !SocketTestHarness { |
| 2620 | 2620 | |
| 2621 | 2621 | // Create a TCP client socket |
| 2622 | 2622 | const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); |
| 2623 | errdefer posix.close(client); | |
| 2623 | errdefer _ = linux.close(client); | |
| 2624 | 2624 | _ = try ring.connect(0xcccccccc, client, addrAny(&address), @sizeOf(linux.sockaddr.in)); |
| 2625 | 2625 | |
| 2626 | 2626 | try testing.expectEqual(@as(u32, 2), try ring.submit()); |
| ... | ... | @@ -2660,7 +2660,7 @@ pub fn createSocketTestHarness(ring: *IoUring) !SocketTestHarness { |
| 2660 | 2660 | fn createListenerSocket(address: *linux.sockaddr.in) !posix.socket_t { |
| 2661 | 2661 | const kernel_backlog = 1; |
| 2662 | 2662 | const listener_socket = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); |
| 2663 | errdefer posix.close(listener_socket); | |
| 2663 | errdefer _ = linux.close(listener_socket); | |
| 2664 | 2664 | |
| 2665 | 2665 | try posix.setsockopt(listener_socket, posix.SOL.SOCKET, posix.SO.REUSEADDR, &mem.toBytes(@as(c_int, 1))); |
| 2666 | 2666 | try bind(listener_socket, addrAny(address), @sizeOf(linux.sockaddr.in)); |
lib/std/os/linux/test.zig+36| ... | ... | @@ -407,6 +407,42 @@ test "futex2_requeue" { |
| 407 | 407 | try expectEqual(0, rc); |
| 408 | 408 | } |
| 409 | 409 | |
| 410 | test "timerfd" { | |
| 411 | const tfd: linux.fd_t = rc: { | |
| 412 | const rc = linux.timerfd_create(.MONOTONIC, .{ .CLOEXEC = true }); | |
| 413 | switch (linux.errno(rc)) { | |
| 414 | .SUCCESS => break :rc @intCast(rc), | |
| 415 | else => @panic("test failed"), | |
| 416 | } | |
| 417 | }; | |
| 418 | defer _ = linux.close(tfd); | |
| 419 | ||
| 420 | // Fire event 10_000_000ns = 10ms after the posix.timerfd_settime call. | |
| 421 | var sit: linux.itimerspec = .{ .it_interval = .{ .sec = 0, .nsec = 0 }, .it_value = .{ .sec = 0, .nsec = 10 * (1000 * 1000) } }; | |
| 422 | const flags: linux.TFD.TIMER = .{}; | |
| 423 | switch (linux.errno(linux.timerfd_settime(tfd, @bitCast(flags), &sit, null))) { | |
| 424 | .SUCCESS => {}, | |
| 425 | else => @panic("test failed"), | |
| 426 | } | |
| 427 | ||
| 428 | var fds: [1]std.posix.pollfd = .{.{ .fd = tfd, .events = linux.POLL.IN, .revents = 0 }}; | |
| 429 | try expectEqual(@as(usize, 1), try std.posix.poll(&fds, -1)); // -1 => infinite waiting | |
| 430 | ||
| 431 | const git = rc: { | |
| 432 | var curr_value: linux.itimerspec = undefined; | |
| 433 | const rc = linux.timerfd_gettime(tfd, &curr_value); | |
| 434 | switch (linux.errno(rc)) { | |
| 435 | .SUCCESS => break :rc curr_value, | |
| 436 | else => @panic("test failed"), | |
| 437 | } | |
| 438 | }; | |
| 439 | const expect_disarmed_timer: linux.itimerspec = .{ | |
| 440 | .it_interval = .{ .sec = 0, .nsec = 0 }, | |
| 441 | .it_value = .{ .sec = 0, .nsec = 0 }, | |
| 442 | }; | |
| 443 | try expectEqual(expect_disarmed_timer, git); | |
| 444 | } | |
| 445 | ||
| 410 | 446 | test { |
| 411 | 447 | _ = linux.IoUring; |
| 412 | 448 | } |
lib/std/posix.zig-78| ... | ... | @@ -278,30 +278,6 @@ pub const socket_t = if (native_os == .windows) windows.ws2_32.SOCKET else fd_t; |
| 278 | 278 | /// the system function call whose errno value is intended to be observed. |
| 279 | 279 | pub const errno = system.errno; |
| 280 | 280 | |
| 281 | /// Closes the file descriptor. | |
| 282 | /// | |
| 283 | /// Asserts the file descriptor is open. | |
| 284 | /// | |
| 285 | /// This function is not capable of returning any indication of failure. An | |
| 286 | /// application which wants to ensure writes have succeeded before closing must | |
| 287 | /// call `fsync` before `close`. | |
| 288 | /// | |
| 289 | /// The Zig standard library does not support POSIX thread cancellation. | |
| 290 | pub fn close(fd: fd_t) void { | |
| 291 | if (native_os == .windows) { | |
| 292 | return windows.CloseHandle(fd); | |
| 293 | } | |
| 294 | if (native_os == .wasi and !builtin.link_libc) { | |
| 295 | _ = std.os.wasi.fd_close(fd); | |
| 296 | return; | |
| 297 | } | |
| 298 | switch (errno(system.close(fd))) { | |
| 299 | .BADF => unreachable, // Always a race condition. | |
| 300 | .INTR => return, // This is still a success. See https://github.com/ziglang/zig/issues/2425 | |
| 301 | else => return, | |
| 302 | } | |
| 303 | } | |
| 304 | ||
| 305 | 281 | pub const RebootError = error{ |
| 306 | 282 | PermissionDenied, |
| 307 | 283 | } || UnexpectedError; |
| ... | ... | @@ -1541,60 +1517,6 @@ pub fn perf_event_open( |
| 1541 | 1517 | } |
| 1542 | 1518 | } |
| 1543 | 1519 | |
| 1544 | pub const TimerFdCreateError = error{ | |
| 1545 | PermissionDenied, | |
| 1546 | ProcessFdQuotaExceeded, | |
| 1547 | SystemFdQuotaExceeded, | |
| 1548 | NoDevice, | |
| 1549 | SystemResources, | |
| 1550 | } || UnexpectedError; | |
| 1551 | ||
| 1552 | pub const TimerFdGetError = error{InvalidHandle} || UnexpectedError; | |
| 1553 | pub const TimerFdSetError = TimerFdGetError || error{Canceled}; | |
| 1554 | ||
| 1555 | pub fn timerfd_create(clock_id: system.timerfd_clockid_t, flags: system.TFD) TimerFdCreateError!fd_t { | |
| 1556 | const rc = system.timerfd_create(clock_id, @bitCast(flags)); | |
| 1557 | return switch (errno(rc)) { | |
| 1558 | .SUCCESS => @intCast(rc), | |
| 1559 | .INVAL => unreachable, | |
| 1560 | .MFILE => return error.ProcessFdQuotaExceeded, | |
| 1561 | .NFILE => return error.SystemFdQuotaExceeded, | |
| 1562 | .NODEV => return error.NoDevice, | |
| 1563 | .NOMEM => return error.SystemResources, | |
| 1564 | .PERM => return error.PermissionDenied, | |
| 1565 | else => |err| return unexpectedErrno(err), | |
| 1566 | }; | |
| 1567 | } | |
| 1568 | ||
| 1569 | pub fn timerfd_settime( | |
| 1570 | fd: i32, | |
| 1571 | flags: system.TFD.TIMER, | |
| 1572 | new_value: *const system.itimerspec, | |
| 1573 | old_value: ?*system.itimerspec, | |
| 1574 | ) TimerFdSetError!void { | |
| 1575 | const rc = system.timerfd_settime(fd, @bitCast(flags), new_value, old_value); | |
| 1576 | return switch (errno(rc)) { | |
| 1577 | .SUCCESS => {}, | |
| 1578 | .BADF => error.InvalidHandle, | |
| 1579 | .FAULT => unreachable, | |
| 1580 | .INVAL => unreachable, | |
| 1581 | .CANCELED => error.Canceled, | |
| 1582 | else => |err| return unexpectedErrno(err), | |
| 1583 | }; | |
| 1584 | } | |
| 1585 | ||
| 1586 | pub fn timerfd_gettime(fd: i32) TimerFdGetError!system.itimerspec { | |
| 1587 | var curr_value: system.itimerspec = undefined; | |
| 1588 | const rc = system.timerfd_gettime(fd, &curr_value); | |
| 1589 | return switch (errno(rc)) { | |
| 1590 | .SUCCESS => return curr_value, | |
| 1591 | .BADF => error.InvalidHandle, | |
| 1592 | .FAULT => unreachable, | |
| 1593 | .INVAL => unreachable, | |
| 1594 | else => |err| return unexpectedErrno(err), | |
| 1595 | }; | |
| 1596 | } | |
| 1597 | ||
| 1598 | 1520 | pub const PtraceError = error{ |
| 1599 | 1521 | DeadLock, |
| 1600 | 1522 | DeviceBusy, |
lib/std/posix/test.zig-18| ... | ... | @@ -522,21 +522,3 @@ test "rename smoke test" { |
| 522 | 522 | try expectError(error.FileNotFound, Io.Dir.cwd().openDir(io, file_path, .{})); |
| 523 | 523 | } |
| 524 | 524 | } |
| 525 | ||
| 526 | test "timerfd" { | |
| 527 | if (native_os != .linux) return error.SkipZigTest; | |
| 528 | ||
| 529 | const tfd = try posix.timerfd_create(.MONOTONIC, .{ .CLOEXEC = true }); | |
| 530 | defer posix.close(tfd); | |
| 531 | ||
| 532 | // Fire event 10_000_000ns = 10ms after the posix.timerfd_settime call. | |
| 533 | var sit: linux.itimerspec = .{ .it_interval = .{ .sec = 0, .nsec = 0 }, .it_value = .{ .sec = 0, .nsec = 10 * (1000 * 1000) } }; | |
| 534 | try posix.timerfd_settime(tfd, .{}, &sit, null); | |
| 535 | ||
| 536 | var fds: [1]posix.pollfd = .{.{ .fd = tfd, .events = linux.POLL.IN, .revents = 0 }}; | |
| 537 | try expectEqual(@as(usize, 1), try posix.poll(&fds, -1)); // -1 => infinite waiting | |
| 538 | ||
| 539 | const git = try posix.timerfd_gettime(tfd); | |
| 540 | const expect_disarmed_timer: linux.itimerspec = .{ .it_interval = .{ .sec = 0, .nsec = 0 }, .it_value = .{ .sec = 0, .nsec = 0 } }; | |
| 541 | try expectEqual(expect_disarmed_timer, git); | |
| 542 | } |
src/libs/musl.zig-2| ... | ... | @@ -1830,7 +1830,6 @@ const src_files = [_][]const u8{ |
| 1830 | 1830 | "musl/src/time/wcsftime.c", |
| 1831 | 1831 | "musl/src/time/__year_to_secs.c", |
| 1832 | 1832 | "musl/src/unistd/alarm.c", |
| 1833 | "musl/src/unistd/close.c", | |
| 1834 | 1833 | "musl/src/unistd/dup2.c", |
| 1835 | 1834 | "musl/src/unistd/dup3.c", |
| 1836 | 1835 | "musl/src/unistd/faccessat.c", |
| ... | ... | @@ -1849,7 +1848,6 @@ const src_files = [_][]const u8{ |
| 1849 | 1848 | "musl/src/unistd/nice.c", |
| 1850 | 1849 | "musl/src/unistd/pause.c", |
| 1851 | 1850 | "musl/src/unistd/pipe2.c", |
| 1852 | "musl/src/unistd/posix_close.c", | |
| 1853 | 1851 | "musl/src/unistd/pread.c", |
| 1854 | 1852 | "musl/src/unistd/preadv.c", |
| 1855 | 1853 | "musl/src/unistd/pwrite.c", |
src/libs/wasi_libc.zig-1| ... | ... | @@ -999,7 +999,6 @@ const libc_top_half_src_files = [_][]const u8{ |
| 999 | 999 | "musl/src/time/strptime.c", |
| 1000 | 1000 | "musl/src/time/timespec_get.c", |
| 1001 | 1001 | "musl/src/time/__year_to_secs.c", |
| 1002 | "musl/src/unistd/posix_close.c", | |
| 1003 | 1002 | |
| 1004 | 1003 | "wasi/libc-top-half/musl/src/conf/fpathconf.c", |
| 1005 | 1004 | "wasi/libc-top-half/musl/src/conf/sysconf.c", |