int inline_size
kqueue_init (EV_P_ int flags)
{
- /* Initialize the kernel queue */
+ /* initialize the kernel queue */
+ kqueue_fd_pid = getpid ();
if ((backend_fd = kqueue ()) < 0)
return 0;
void inline_size
kqueue_fork (EV_P)
{
- close (backend_fd);
-
+ /* some BSD kernels don't just destroy the kqueue itself,
+ * but also close the fd, which isn't documented, and
+ * impossible to support properly.
+ * we remember the pid of the kqueue call and only close
+ * the fd if the pid is still the same.
+ * this leaks fds on sane kernels, but BSD interfaces are
+ * notoriously buggy and rarely get fixed.
+ */
+ pid_t newpid = getpid ();
+
+ if (newpid == kqueue_fd_pid)
+ close (backend_fd);
+
+ kqueue_fd_pid = newpid;
while ((backend_fd = kqueue ()) < 0)
ev_syserr ("(libev) kqueue");