summaryrefslogtreecommitdiff
path: root/ev_kqueue.c
diff options
context:
space:
mode:
Diffstat (limited to 'ev_kqueue.c')
-rw-r--r--ev_kqueue.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/ev_kqueue.c b/ev_kqueue.c
index bc4ac48..9faf65a 100644
--- a/ev_kqueue.c
+++ b/ev_kqueue.c
@@ -155,7 +155,8 @@ kqueue_poll (EV_P_ ev_tstamp timeout)
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;
@@ -185,8 +186,20 @@ kqueue_destroy (EV_P)
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");