Re: Kqueues and fork
Gleb Popov <[email protected]> Fri, 29 Aug 2025 13:57:52 +0300
| Newsgroups | gmane.os.freebsd.architechture |
|---|---|
| Message-ID | <CALH631=RwquUfzvyxRuaQcdr96RMgea_ZcyxQC=afjJtx_x=aA@mail.gmail.com> |
On Wed, Aug 20, 2025 at 2:12 PM Konstantin Belousov <[email protected]> wrote: > > Is this what the app writers want? I was one of those who asked Konstantin about this feature. My context is the dbus-daemon program, which is essentially an RPC server working over unix sockets. It has an abstraction called "pollable set" that is implemented via epoll(7) on Linux and poll(2) as a fallback. I developed the kqueue(2) based implementation which was straightforward, but then I bumped into the mentioned difference on fork. The daemon does basically this: parent: kqueuex(0x1) = 3 (0x3) parent: fork() parent: bind(4,{ AF_UNIX "/var/run/dbus/system_bus_socket" },33) parent: listen(4,128) parent: kevent(3, { 4,EVFILT_READ}, ... ) child: connect(...) = 5 child: kevent(3,{ 5,EVFILT_READ}, ... ) This obviously doesn't work for kqueue without KQUEUE_CPONFORK, but works for Linux, because epoll fds are inherited by children by default. At the same time dbus-daemon doesn't really need any intricate events sharing. My theory is that the code is written this way simply because the software is primarily developed on Linux and dbus-daemon authors didn't notice that they are leaking the epoll fd into the child. I imagine that there might be other software in the wild that accidentally shares the epoll fd. With Konstantin's patch (and after some bugfixing on my side of things) the kqueue-based implementation worked flawlessly. All the extensive dbus tests pass with no overhead. The proposed KQUEUE_CPONFORK flag would also be really useful for the devel/libepoll-shim library, which tries its best to emulate epoll(7) via kqueue(2), but can't do anything about consumers that expect the fd to live after calling fork()