diff options
-rw-r--r-- | Changes | 2 | ||||
-rw-r--r-- | ev.pod | 6 | ||||
-rw-r--r-- | ev_kqueue.c | 19 | ||||
-rw-r--r-- | ev_vars.h | 3 | ||||
-rw-r--r-- | ev_wrap.h | 2 |
5 files changed, 25 insertions, 7 deletions
@@ -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 @@ -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<EVBACKEND_EPOLL>, it still adds up to -two event changes per incident. Support for C<fork ()> 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<fork ()> 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"); @@ -1,7 +1,7 @@ /* * loop member variable declarations * - * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de> + * Copyright (c) 2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann <libev@schmorp.de> * 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) @@ -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 |