Re: Kqueues and fork
- Reply: Konstantin Belousov : "Re: Kqueues and fork"
- In reply to: Konstantin Belousov : "Kqueues and fork"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 29 Aug 2025 10:57:52 UTC
On Wed, Aug 20, 2025 at 2:12 PM Konstantin Belousov <kostikbel@gmail.com> 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()