--- libev/ev_kqueue.c 2012/02/12 08:39:38 1.53 +++ libev/ev_kqueue.c 2019/06/22 22:18:39 1.58 @@ -1,7 +1,7 @@ /* * libev kqueue backend * - * Copyright (c) 2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann + * Copyright (c) 2007,2008,2009,2010,2011,2012,2013,2016,2019 Marc Alexander Lehmann * All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- @@ -43,11 +43,12 @@ #include #include -void inline_speed +inline_speed +void kqueue_change (EV_P_ int fd, int filter, int flags, int fflags) { ++kqueue_changecnt; - array_needsize (struct kevent, kqueue_changes, kqueue_changemax, kqueue_changecnt, EMPTY2); + array_needsize (struct kevent, kqueue_changes, kqueue_changemax, kqueue_changecnt, array_needsize_noinit); EV_SET (&kqueue_changes [kqueue_changecnt - 1], fd, filter, flags, fflags, 0, 0); } @@ -105,7 +106,7 @@ if (expect_false (res < 0)) { if (errno != EINTR) - ev_syserr ("(libev) kevent"); + ev_syserr ("(libev) kqueue kevent"); return; } @@ -152,10 +153,12 @@ } } -int inline_size +inline_size +int 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; @@ -175,18 +178,32 @@ return EVBACKEND_KQUEUE; } -void inline_size +inline_size +void kqueue_destroy (EV_P) { ev_free (kqueue_events); ev_free (kqueue_changes); } -void inline_size +inline_size +void 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");