From 1a78f29c569e692a7e7fb56b47f0cc7f7398a9b6 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 2 Apr 2012 18:39:54 +0000 Subject: *** empty log message *** --- Changes | 2 ++ ev.pod | 6 +++--- ev_kqueue.c | 19 ++++++++++++++++--- ev_vars.h | 3 ++- ev_wrap.h | 2 ++ 5 files changed, 25 insertions(+), 7 deletions(-) diff --git a/Changes b/Changes index ae491e1..b32b1b4 100644 --- a/Changes +++ b/Changes @@ -12,6 +12,8 @@ TODO: use __OPTIMIZE__ or __OPTIMIZE_SIZE__? TODO: Jeff Davey libev patch - (ecb) add memory fence support for xlC (Darin McBride). - (ecb) add memory fence support for gcc-mips (Anton Kirilov). + - work around some kernels losing file descriptors by leaking + the kqueue descriptor in the child. 4.11 Sat Feb 4 19:52:39 CET 2012 - INCOMPATIBLE CHANGE: ev_timer_again now clears the pending status, as diff --git a/ev.pod b/ev.pod index bb1f95a..9ea2cd6 100644 --- a/ev.pod +++ b/ev.pod @@ -569,9 +569,9 @@ It scales in the same way as the epoll backend, but the interface to the kernel is more efficient (which says nothing about its actual speed, of course). While stopping, setting and starting an I/O watcher does never cause an extra system call as with C, it still adds up to -two event changes per incident. Support for C is very bad (but -sane, unlike epoll) and it drops fds silently in similarly hard-to-detect -cases +two event changes per incident. Support for C is very bad (you +might have to leak fd's on fork, but it's more sane than epoll) and it +drops fds silently in similarly hard-to-detect cases This backend usually performs well under most conditions. 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"); diff --git a/ev_vars.h b/ev_vars.h index 9f7acb6..667a986 100644 --- a/ev_vars.h +++ b/ev_vars.h @@ -1,7 +1,7 @@ /* * loop member variable declarations * - * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann + * Copyright (c) 2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann * All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- @@ -110,6 +110,7 @@ VARx(int, epoll_epermmax) #endif #if EV_USE_KQUEUE || EV_GENWRAP +VARx(pid_t, kqueue_fd_pid) VARx(struct kevent *, kqueue_changes) VARx(int, kqueue_changemax) VARx(int, kqueue_changecnt) diff --git a/ev_wrap.h b/ev_wrap.h index 36edbd2..3c47c6e 100644 --- a/ev_wrap.h +++ b/ev_wrap.h @@ -45,6 +45,7 @@ #define epoll_eperms ((loop)->epoll_eperms) #define epoll_epermcnt ((loop)->epoll_epermcnt) #define epoll_epermmax ((loop)->epoll_epermmax) +#define kqueue_fd_pid ((loop)->kqueue_fd_pid) #define kqueue_changes ((loop)->kqueue_changes) #define kqueue_changemax ((loop)->kqueue_changemax) #define kqueue_changecnt ((loop)->kqueue_changecnt) @@ -143,6 +144,7 @@ #undef epoll_eperms #undef epoll_epermcnt #undef epoll_epermmax +#undef kqueue_fd_pid #undef kqueue_changes #undef kqueue_changemax #undef kqueue_changecnt -- cgit v1.2.3