FreeBSD and NetBSD have variants of the kqueue(2) system call that allow setting the close-on-exec flag on the returned file descriptor.
In general, I think it is good that the flag can be set atomically for new descriptors. However, it seems to me that it is almost surely a mistake if a kqueue descriptor is passed over an exec. Instead of adding a new system call, maybe close-on-exec should be enabled automatically by kqueue(2). Today it feels backwards that close-on-exec is off by default. Note that kqueue cannot be inherited by accident in fork-then-exec situations because fork(2) closes kqueue descriptors for the child process. Index: sys/kern/kern_event.c =================================================================== RCS file: src/sys/kern/kern_event.c,v retrieving revision 1.197 diff -u -p -r1.197 kern_event.c --- sys/kern/kern_event.c 13 Aug 2023 08:29:28 -0000 1.197 +++ sys/kern/kern_event.c 13 Aug 2023 10:42:45 -0000 @@ -932,7 +932,7 @@ sys_kqueue(struct proc *p, void *v, regi *retval = fd; LIST_INSERT_HEAD(&fdp->fd_kqlist, kq, kq_next); kq = NULL; - fdinsert(fdp, fd, 0, fp); + fdinsert(fdp, fd, UF_EXCLOSE, fp); FRELE(fp, p); out: fdpunlock(fdp); Index: lib/libc/sys/kqueue.2 =================================================================== RCS file: src/lib/libc/sys/kqueue.2,v retrieving revision 1.48 diff -u -p -r1.48 kqueue.2 --- lib/libc/sys/kqueue.2 13 Aug 2023 08:29:28 -0000 1.48 +++ lib/libc/sys/kqueue.2 13 Aug 2023 10:42:45 -0000 @@ -74,6 +74,7 @@ on a file descriptor will remove any kev .Pp .Fn kqueue creates a new kernel event queue and returns a descriptor. +The new descriptor has close-on-exec flag set. The queue is not inherited by a child created with .Xr fork 2 . Similarly, kqueues cannot be passed across UNIX-domain sockets.