From eddee1b8cb2723b38d735c58a5e4fc8f4e027596 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Sat, 7 Jun 2025 00:30:58 -0700 Subject: [PATCH] `*anyopaque` -> `mach_port_t` (#20243) --- src/async/posix_event_loop.zig | 19 +++++++++---- src/bun.js/api/bun/dns_resolver.zig | 31 ++++++++++----------- src/bun.zig | 2 ++ src/darwin.zig | 2 ++ src/io/io_darwin.cpp | 11 ++++++-- src/sys.zig | 43 +++++++++++++++++++++++++++++ 6 files changed, 84 insertions(+), 24 deletions(-) diff --git a/src/async/posix_event_loop.zig b/src/async/posix_event_loop.zig index 7e8a8c989c..1d19019439 100644 --- a/src/async/posix_event_loop.zig +++ b/src/async/posix_event_loop.zig @@ -1132,7 +1132,7 @@ pub const LinuxWaker = struct { pub const KEventWaker = struct { kq: std.posix.fd_t, - machport: *anyopaque = undefined, + machport: bun.mach_port = undefined, machport_buf: []u8 = &.{}, has_pending_wake: bool = false, @@ -1155,6 +1155,10 @@ pub const KEventWaker = struct { } pub fn wait(this: Waker) void { + if (!bun.FD.fromNative(this.kq).isValid()) { + return; + } + bun.JSC.markBinding(@src()); var events = zeroed; @@ -1169,14 +1173,15 @@ pub const KEventWaker = struct { ); } + extern fn io_darwin_close_machport(bun.mach_port) void; + extern fn io_darwin_create_machport( - *anyopaque, std.posix.fd_t, *anyopaque, usize, - ) ?*anyopaque; + ) bun.mach_port; - extern fn io_darwin_schedule_wakeup(*anyopaque) bool; + extern fn io_darwin_schedule_wakeup(bun.mach_port) bool; pub fn init() !Waker { return initWithFileDescriptor(bun.default_allocator, try std.posix.kqueue()); @@ -1187,11 +1192,13 @@ pub const KEventWaker = struct { bun.assert(kq > -1); const machport_buf = try allocator.alloc(u8, 1024); const machport = io_darwin_create_machport( - machport_buf.ptr, kq, machport_buf.ptr, 1024, - ) orelse return error.MachportCreationFailed; + ); + if (machport == 0) { + return error.MachportCreationFailed; + } return Waker{ .kq = kq, diff --git a/src/bun.js/api/bun/dns_resolver.zig b/src/bun.js/api/bun/dns_resolver.zig index 23cc22214d..ec937a5259 100644 --- a/src/bun.js/api/bun/dns_resolver.zig +++ b/src/bun.js/api/bun/dns_resolver.zig @@ -29,9 +29,9 @@ const LibInfo = struct { // static int32_t (*getaddrinfo_async_handle_reply)(void*); // static void (*getaddrinfo_async_cancel)(mach_port_t); // typedef void getaddrinfo_async_callback(int32_t, struct addrinfo*, void*) - const GetaddrinfoAsyncStart = fn (*?*anyopaque, noalias node: ?[*:0]const u8, noalias service: ?[*:0]const u8, noalias hints: ?*const std.c.addrinfo, callback: *const GetAddrInfoAsyncCallback, noalias context: ?*anyopaque) callconv(.C) i32; - const GetaddrinfoAsyncHandleReply = fn (?**anyopaque) callconv(.C) i32; - const GetaddrinfoAsyncCancel = fn (?**anyopaque) callconv(.C) void; + const GetaddrinfoAsyncStart = fn (*bun.mach_port, noalias node: ?[*:0]const u8, noalias service: ?[*:0]const u8, noalias hints: ?*const std.c.addrinfo, callback: *const GetAddrInfoAsyncCallback, noalias context: ?*anyopaque) callconv(.C) i32; + const GetaddrinfoAsyncHandleReply = fn (?*bun.mach_port) callconv(.C) i32; + const GetaddrinfoAsyncCancel = fn (?*bun.mach_port) callconv(.C) void; var handle: ?*anyopaque = null; var loaded = false; @@ -117,7 +117,7 @@ const LibInfo = struct { return promise_value; } - bun.assert(request.backend.libinfo.machport != null); + bun.assert(request.backend.libinfo.machport != 0); var poll = bun.Async.FilePoll.init( this.vm, // TODO: WHAT????????? @@ -131,7 +131,7 @@ const LibInfo = struct { this.vm.event_loop_handle.?, .machport, .one_shot, - .fromNative(@intCast(@intFromPtr(request.backend.libinfo.machport))), + .fromNative(@bitCast(request.backend.libinfo.machport)), ); bun.assert(rc == .result); @@ -805,15 +805,15 @@ pub const GetAddrInfoRequest = struct { pub const LibInfo = struct { file_poll: ?*bun.Async.FilePoll = null, - machport: ?*anyopaque = null, + machport: bun.mach_port = 0, - extern fn getaddrinfo_send_reply(*anyopaque, *const bun.api.DNS.LibInfo.GetaddrinfoAsyncHandleReply) bool; + extern fn getaddrinfo_send_reply(bun.mach_port, *const bun.api.DNS.LibInfo.GetaddrinfoAsyncHandleReply) bool; pub fn onMachportChange(this: *GetAddrInfoRequest) void { if (comptime !Environment.isMac) unreachable; bun.JSC.markBinding(@src()); - if (!getaddrinfo_send_reply(this.backend.libinfo.machport.?, bun.api.DNS.LibInfo.getaddrinfo_async_handle_reply().?)) { + if (!getaddrinfo_send_reply(this.backend.libinfo.machport, bun.api.DNS.LibInfo.getaddrinfo_async_handle_reply().?)) { log("onMachportChange: getaddrinfo_send_reply failed", .{}); getAddrInfoAsyncCallback(-1, null, this); } @@ -1232,11 +1232,11 @@ pub const InternalDNS = struct { pub const MacAsyncDNS = struct { file_poll: ?*bun.Async.FilePoll = null, - machport: ?*anyopaque = null, + machport: bun.mach_port = 0, - extern fn getaddrinfo_send_reply(*anyopaque, *const bun.api.DNS.LibInfo.GetaddrinfoAsyncHandleReply) bool; + extern fn getaddrinfo_send_reply(bun.mach_port, *const bun.api.DNS.LibInfo.GetaddrinfoAsyncHandleReply) bool; pub fn onMachportChange(this: *Request) void { - if (!getaddrinfo_send_reply(this.libinfo.machport.?, LibInfo.getaddrinfo_async_handle_reply().?)) { + if (!getaddrinfo_send_reply(this.libinfo.machport, LibInfo.getaddrinfo_async_handle_reply().?)) { libinfoCallback(@intFromEnum(std.c.E.NOSYS), null, this); } } @@ -1603,7 +1603,7 @@ pub const InternalDNS = struct { pub fn lookupLibinfo(req: *Request, loop: JSC.EventLoopHandle) bool { const getaddrinfo_async_start_ = LibInfo.getaddrinfo_async_start() orelse return false; - var machport: ?*anyopaque = null; + var machport: bun.mach_port = 0; var service_buf: [bun.fmt.fastDigitCount(std.math.maxInt(u16)) + 2]u8 = undefined; const service: ?[*:0]const u8 = if (req.key.port > 0) (std.fmt.bufPrintZ(&service_buf, "{d}", .{req.key.port}) catch unreachable).ptr @@ -1621,12 +1621,11 @@ pub const InternalDNS = struct { req, ); - if (errno != 0 or machport == null) { + if (errno != 0 or machport == 0) { return false; } - const fake_fd: i32 = @intCast(@intFromPtr(machport)); - var poll = bun.Async.FilePoll.init(loop, .fromNative(fake_fd), .{}, InternalDNSRequest, req); + var poll = bun.Async.FilePoll.init(loop, .fromNative(@bitCast(machport)), .{}, InternalDNSRequest, req); const rc = poll.register(loop.loop(), .machport, true); if (rc == .err) { @@ -1657,7 +1656,7 @@ pub const InternalDNS = struct { else null; const getaddrinfo_async_start_ = LibInfo.getaddrinfo_async_start() orelse return; - var machport: ?*anyopaque = null; + var machport: bun.mach_port = 0; var hints = getHints(); hints.flags.ADDRCONFIG = false; diff --git a/src/bun.zig b/src/bun.zig index 8e070de409..0fb24bf626 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -3770,3 +3770,5 @@ pub fn move(dest: []u8, src: []const u8) void { } _ = bun.c.memmove(dest.ptr, src.ptr, src.len); } + +pub const mach_port = if (Environment.isMac) std.c.mach_port_t else u32; diff --git a/src/darwin.zig b/src/darwin.zig index ba214732ed..80c9c51995 100644 --- a/src/darwin.zig +++ b/src/darwin.zig @@ -25,6 +25,8 @@ pub const nocancel = struct { pub extern "c" fn @"write$NOCANCEL"(fd: c.fd_t, buf: [*]const u8, nbyte: usize) isize; pub extern "c" fn @"writev$NOCANCEL"(fd: c.fd_t, buf: [*]const std.posix.iovec_const, count: i32) isize; pub extern "c" fn @"pwritev$NOCANCEL"(fd: c.fd_t, buf: [*]const std.posix.iovec_const, count: i32, offset: c.off_t) isize; + pub extern "c" fn @"poll$NOCANCEL"(fds: [*]std.posix.pollfd, nfds: c_int, timeout: c_int) isize; + pub extern "c" fn @"ppoll$NOCANCEL"(fds: [*]std.posix.pollfd, nfds: c_int, timeout: ?*const std.posix.timespec, sigmask: ?*const std.posix.sigset_t) isize; }; pub const OSLog = opaque { diff --git a/src/io/io_darwin.cpp b/src/io/io_darwin.cpp index 04d14c6424..a1fb1ed03a 100644 --- a/src/io/io_darwin.cpp +++ b/src/io/io_darwin.cpp @@ -9,7 +9,7 @@ #include "wtf/Assertions.h" -extern "C" mach_port_t io_darwin_create_machport(uint64_t wakeup, int32_t fd, +extern "C" mach_port_t io_darwin_create_machport(int32_t fd, void* wakeup_buffer_, size_t nbytes) { @@ -117,10 +117,15 @@ extern "C" bool io_darwin_schedule_wakeup(mach_port_t waker) } } +extern "C" void io_darwin_close_machport(mach_port_t port) +{ + mach_port_deallocate(mach_task_self(), port); +} + #else // stub out these symbols -extern "C" int io_darwin_create_machport(unsigned long long wakeup, int fd, +extern "C" int io_darwin_create_machport(int fd, void* wakeup_buffer_, unsigned long long nbytes) { @@ -130,4 +135,6 @@ extern "C" int io_darwin_create_machport(unsigned long long wakeup, int fd, // stub out these symbols extern "C" bool io_darwin_schedule_wakeup(void* waker) { return false; } +extern "C" void io_darwin_close_machport(unsigned port) {} + #endif diff --git a/src/sys.zig b/src/sys.zig index c581733f3b..cd8b2db818 100644 --- a/src/sys.zig +++ b/src/sys.zig @@ -271,6 +271,7 @@ pub const Tag = enum(u8) { futime, pidfd_open, poll, + ppoll, watch, scandir, @@ -2202,6 +2203,36 @@ pub fn recvNonBlock(fd: bun.FileDescriptor, buf: []u8) Maybe(usize) { return recv(fd, buf, socket_flags_nonblock); } +pub fn poll(fds: []std.posix.pollfd, timeout: i32) Maybe(usize) { + while (true) { + const rc = switch (Environment.os) { + .mac => darwin_nocancel.@"poll$NOCANCEL"(fds.ptr, fds.len, timeout), + .linux => linux.poll(fds.ptr, fds.len, timeout), + else => @compileError("poll is not implemented on this platform"), + }; + if (Maybe(usize).errnoSys(rc, .poll)) |err| { + if (err.getErrno() == .INTR) continue; + return err; + } + return .{ .result = @as(usize, @intCast(rc)) }; + } +} + +pub fn ppoll(fds: []std.posix.pollfd, timeout: ?*std.posix.timespec, sigmask: ?*const std.posix.sigset_t) Maybe(usize) { + while (true) { + const rc = switch (Environment.os) { + .mac => darwin_nocancel.@"ppoll$NOCANCEL"(fds.ptr, fds.len, timeout, sigmask), + .linux => linux.ppoll(fds.ptr, fds.len, timeout, sigmask), + else => @compileError("ppoll is not implemented on this platform"), + }; + if (Maybe(usize).errnoSys(rc, .ppoll)) |err| { + if (err.getErrno() == .INTR) continue; + return err; + } + return .{ .result = @as(usize, @intCast(rc)) }; + } +} + pub fn recv(fd: bun.FileDescriptor, buf: []u8, flag: u32) Maybe(usize) { const adjusted_len = @min(buf.len, max_count); const debug_timer = bun.Output.DebugTimer.start(); @@ -2237,6 +2268,18 @@ pub fn recv(fd: bun.FileDescriptor, buf: []u8, flag: u32) Maybe(usize) { } } +pub fn kevent(fd: bun.FileDescriptor, changelist: []const std.c.Kevent, eventlist: []std.c.Kevent, timeout: ?*std.posix.timespec) Maybe(usize) { + while (true) { + const rc = std.c.kevent(fd.cast(), changelist.ptr, @intCast(changelist.len), eventlist.ptr, @intCast(eventlist.len), timeout); + if (Maybe(usize).errnoSysFd(rc, .kevent, fd)) |err| { + if (err.getErrno() == .INTR) continue; + return err; + } + return .{ .result = @as(usize, @intCast(rc)) }; + } + unreachable; +} + pub fn sendNonBlock(fd: bun.FileDescriptor, buf: []const u8) Maybe(usize) { return send(fd, buf, socket_flags_nonblock); }