12b15cb3dSCy Schubert /* $OpenBSD: kqueue.c,v 1.5 2002/07/10 14:41:31 art Exp $ */ 22b15cb3dSCy Schubert 32b15cb3dSCy Schubert /* 42b15cb3dSCy Schubert * Copyright 2000-2007 Niels Provos <provos@citi.umich.edu> 52b15cb3dSCy Schubert * Copyright 2007-2012 Niels Provos and Nick Mathewson 62b15cb3dSCy Schubert * 72b15cb3dSCy Schubert * Redistribution and use in source and binary forms, with or without 82b15cb3dSCy Schubert * modification, are permitted provided that the following conditions 92b15cb3dSCy Schubert * are met: 102b15cb3dSCy Schubert * 1. Redistributions of source code must retain the above copyright 112b15cb3dSCy Schubert * notice, this list of conditions and the following disclaimer. 122b15cb3dSCy Schubert * 2. Redistributions in binary form must reproduce the above copyright 132b15cb3dSCy Schubert * notice, this list of conditions and the following disclaimer in the 142b15cb3dSCy Schubert * documentation and/or other materials provided with the distribution. 152b15cb3dSCy Schubert * 3. The name of the author may not be used to endorse or promote products 162b15cb3dSCy Schubert * derived from this software without specific prior written permission. 172b15cb3dSCy Schubert * 182b15cb3dSCy Schubert * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 192b15cb3dSCy Schubert * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 202b15cb3dSCy Schubert * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 212b15cb3dSCy Schubert * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 222b15cb3dSCy Schubert * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 232b15cb3dSCy Schubert * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 242b15cb3dSCy Schubert * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 252b15cb3dSCy Schubert * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 262b15cb3dSCy Schubert * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 272b15cb3dSCy Schubert * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 282b15cb3dSCy Schubert */ 292b15cb3dSCy Schubert #include "event2/event-config.h" 302b15cb3dSCy Schubert #include "evconfig-private.h" 312b15cb3dSCy Schubert 322b15cb3dSCy Schubert #ifdef EVENT__HAVE_KQUEUE 332b15cb3dSCy Schubert 342b15cb3dSCy Schubert #include <sys/types.h> 352b15cb3dSCy Schubert #ifdef EVENT__HAVE_SYS_TIME_H 362b15cb3dSCy Schubert #include <sys/time.h> 372b15cb3dSCy Schubert #endif 382b15cb3dSCy Schubert #include <sys/queue.h> 392b15cb3dSCy Schubert #include <sys/event.h> 40a466cc55SCy Schubert #include <limits.h> 412b15cb3dSCy Schubert #include <signal.h> 422b15cb3dSCy Schubert #include <stdio.h> 432b15cb3dSCy Schubert #include <stdlib.h> 442b15cb3dSCy Schubert #include <string.h> 452b15cb3dSCy Schubert #include <unistd.h> 462b15cb3dSCy Schubert #include <errno.h> 472b15cb3dSCy Schubert #ifdef EVENT__HAVE_INTTYPES_H 482b15cb3dSCy Schubert #include <inttypes.h> 492b15cb3dSCy Schubert #endif 502b15cb3dSCy Schubert 512b15cb3dSCy Schubert /* Some platforms apparently define the udata field of struct kevent as 522b15cb3dSCy Schubert * intptr_t, whereas others define it as void*. There doesn't seem to be an 532b15cb3dSCy Schubert * easy way to tell them apart via autoconf, so we need to use OS macros. */ 54a466cc55SCy Schubert #if defined(__NetBSD__) 55a466cc55SCy Schubert #define PTR_TO_UDATA(x) ((typeof(((struct kevent *)0)->udata))(x)) 56a466cc55SCy Schubert #define INT_TO_UDATA(x) ((typeof(((struct kevent *)0)->udata))(intptr_t)(x)) 57a466cc55SCy Schubert #elif defined(EVENT__HAVE_INTTYPES_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__darwin__) && !defined(__APPLE__) && !defined(__CloudABI__) 582b15cb3dSCy Schubert #define PTR_TO_UDATA(x) ((intptr_t)(x)) 592b15cb3dSCy Schubert #define INT_TO_UDATA(x) ((intptr_t)(x)) 602b15cb3dSCy Schubert #else 612b15cb3dSCy Schubert #define PTR_TO_UDATA(x) (x) 622b15cb3dSCy Schubert #define INT_TO_UDATA(x) ((void*)(x)) 632b15cb3dSCy Schubert #endif 642b15cb3dSCy Schubert 652b15cb3dSCy Schubert #include "event-internal.h" 662b15cb3dSCy Schubert #include "log-internal.h" 672b15cb3dSCy Schubert #include "evmap-internal.h" 682b15cb3dSCy Schubert #include "event2/thread.h" 69a466cc55SCy Schubert #include "event2/util.h" 702b15cb3dSCy Schubert #include "evthread-internal.h" 712b15cb3dSCy Schubert #include "changelist-internal.h" 722b15cb3dSCy Schubert 732b15cb3dSCy Schubert #include "kqueue-internal.h" 742b15cb3dSCy Schubert 752b15cb3dSCy Schubert #define NEVENT 64 762b15cb3dSCy Schubert 772b15cb3dSCy Schubert struct kqop { 782b15cb3dSCy Schubert struct kevent *changes; 792b15cb3dSCy Schubert int changes_size; 802b15cb3dSCy Schubert 812b15cb3dSCy Schubert struct kevent *events; 822b15cb3dSCy Schubert int events_size; 832b15cb3dSCy Schubert int kq; 842b15cb3dSCy Schubert int notify_event_added; 852b15cb3dSCy Schubert pid_t pid; 862b15cb3dSCy Schubert }; 872b15cb3dSCy Schubert 882b15cb3dSCy Schubert static void kqop_free(struct kqop *kqop); 892b15cb3dSCy Schubert 902b15cb3dSCy Schubert static void *kq_init(struct event_base *); 912b15cb3dSCy Schubert static int kq_sig_add(struct event_base *, int, short, short, void *); 922b15cb3dSCy Schubert static int kq_sig_del(struct event_base *, int, short, short, void *); 932b15cb3dSCy Schubert static int kq_dispatch(struct event_base *, struct timeval *); 942b15cb3dSCy Schubert static void kq_dealloc(struct event_base *); 952b15cb3dSCy Schubert 962b15cb3dSCy Schubert const struct eventop kqops = { 972b15cb3dSCy Schubert "kqueue", 982b15cb3dSCy Schubert kq_init, 992b15cb3dSCy Schubert event_changelist_add_, 1002b15cb3dSCy Schubert event_changelist_del_, 1012b15cb3dSCy Schubert kq_dispatch, 1022b15cb3dSCy Schubert kq_dealloc, 1032b15cb3dSCy Schubert 1 /* need reinit */, 1042b15cb3dSCy Schubert EV_FEATURE_ET|EV_FEATURE_O1|EV_FEATURE_FDS, 1052b15cb3dSCy Schubert EVENT_CHANGELIST_FDINFO_SIZE 1062b15cb3dSCy Schubert }; 1072b15cb3dSCy Schubert 1082b15cb3dSCy Schubert static const struct eventop kqsigops = { 1092b15cb3dSCy Schubert "kqueue_signal", 1102b15cb3dSCy Schubert NULL, 1112b15cb3dSCy Schubert kq_sig_add, 1122b15cb3dSCy Schubert kq_sig_del, 1132b15cb3dSCy Schubert NULL, 1142b15cb3dSCy Schubert NULL, 1152b15cb3dSCy Schubert 1 /* need reinit */, 1162b15cb3dSCy Schubert 0, 1172b15cb3dSCy Schubert 0 1182b15cb3dSCy Schubert }; 1192b15cb3dSCy Schubert 1202b15cb3dSCy Schubert static void * 1212b15cb3dSCy Schubert kq_init(struct event_base *base) 1222b15cb3dSCy Schubert { 1232b15cb3dSCy Schubert int kq = -1; 1242b15cb3dSCy Schubert struct kqop *kqueueop = NULL; 1252b15cb3dSCy Schubert 1262b15cb3dSCy Schubert if (!(kqueueop = mm_calloc(1, sizeof(struct kqop)))) 1272b15cb3dSCy Schubert return (NULL); 1282b15cb3dSCy Schubert 1292b15cb3dSCy Schubert /* Initialize the kernel queue */ 1302b15cb3dSCy Schubert 1312b15cb3dSCy Schubert if ((kq = kqueue()) == -1) { 1322b15cb3dSCy Schubert event_warn("kqueue"); 1332b15cb3dSCy Schubert goto err; 1342b15cb3dSCy Schubert } 1352b15cb3dSCy Schubert 1362b15cb3dSCy Schubert kqueueop->kq = kq; 1372b15cb3dSCy Schubert 1382b15cb3dSCy Schubert kqueueop->pid = getpid(); 1392b15cb3dSCy Schubert 1402b15cb3dSCy Schubert /* Initialize fields */ 1412b15cb3dSCy Schubert kqueueop->changes = mm_calloc(NEVENT, sizeof(struct kevent)); 1422b15cb3dSCy Schubert if (kqueueop->changes == NULL) 1432b15cb3dSCy Schubert goto err; 1442b15cb3dSCy Schubert kqueueop->events = mm_calloc(NEVENT, sizeof(struct kevent)); 1452b15cb3dSCy Schubert if (kqueueop->events == NULL) 1462b15cb3dSCy Schubert goto err; 1472b15cb3dSCy Schubert kqueueop->events_size = kqueueop->changes_size = NEVENT; 1482b15cb3dSCy Schubert 1492b15cb3dSCy Schubert /* Check for Mac OS X kqueue bug. */ 1502b15cb3dSCy Schubert memset(&kqueueop->changes[0], 0, sizeof kqueueop->changes[0]); 1512b15cb3dSCy Schubert kqueueop->changes[0].ident = -1; 1522b15cb3dSCy Schubert kqueueop->changes[0].filter = EVFILT_READ; 1532b15cb3dSCy Schubert kqueueop->changes[0].flags = EV_ADD; 1542b15cb3dSCy Schubert /* 1552b15cb3dSCy Schubert * If kqueue works, then kevent will succeed, and it will 1562b15cb3dSCy Schubert * stick an error in events[0]. If kqueue is broken, then 1572b15cb3dSCy Schubert * kevent will fail. 1582b15cb3dSCy Schubert */ 1592b15cb3dSCy Schubert if (kevent(kq, 1602b15cb3dSCy Schubert kqueueop->changes, 1, kqueueop->events, NEVENT, NULL) != 1 || 1612b15cb3dSCy Schubert (int)kqueueop->events[0].ident != -1 || 162a466cc55SCy Schubert !(kqueueop->events[0].flags & EV_ERROR)) { 1632b15cb3dSCy Schubert event_warn("%s: detected broken kqueue; not using.", __func__); 1642b15cb3dSCy Schubert goto err; 1652b15cb3dSCy Schubert } 1662b15cb3dSCy Schubert 1672b15cb3dSCy Schubert base->evsigsel = &kqsigops; 1682b15cb3dSCy Schubert 1692b15cb3dSCy Schubert return (kqueueop); 1702b15cb3dSCy Schubert err: 1712b15cb3dSCy Schubert if (kqueueop) 1722b15cb3dSCy Schubert kqop_free(kqueueop); 1732b15cb3dSCy Schubert 1742b15cb3dSCy Schubert return (NULL); 1752b15cb3dSCy Schubert } 1762b15cb3dSCy Schubert 1772b15cb3dSCy Schubert #define ADD_UDATA 0x30303 1782b15cb3dSCy Schubert 1792b15cb3dSCy Schubert static void 1802b15cb3dSCy Schubert kq_setup_kevent(struct kevent *out, evutil_socket_t fd, int filter, short change) 1812b15cb3dSCy Schubert { 1822b15cb3dSCy Schubert memset(out, 0, sizeof(struct kevent)); 1832b15cb3dSCy Schubert out->ident = fd; 1842b15cb3dSCy Schubert out->filter = filter; 1852b15cb3dSCy Schubert 1862b15cb3dSCy Schubert if (change & EV_CHANGE_ADD) { 1872b15cb3dSCy Schubert out->flags = EV_ADD; 1882b15cb3dSCy Schubert /* We set a magic number here so that we can tell 'add' 1892b15cb3dSCy Schubert * errors from 'del' errors. */ 1902b15cb3dSCy Schubert out->udata = INT_TO_UDATA(ADD_UDATA); 1912b15cb3dSCy Schubert if (change & EV_ET) 1922b15cb3dSCy Schubert out->flags |= EV_CLEAR; 1932b15cb3dSCy Schubert #ifdef NOTE_EOF 1942b15cb3dSCy Schubert /* Make it behave like select() and poll() */ 1952b15cb3dSCy Schubert if (filter == EVFILT_READ) 1962b15cb3dSCy Schubert out->fflags = NOTE_EOF; 1972b15cb3dSCy Schubert #endif 1982b15cb3dSCy Schubert } else { 1992b15cb3dSCy Schubert EVUTIL_ASSERT(change & EV_CHANGE_DEL); 2002b15cb3dSCy Schubert out->flags = EV_DELETE; 2012b15cb3dSCy Schubert } 2022b15cb3dSCy Schubert } 2032b15cb3dSCy Schubert 2042b15cb3dSCy Schubert static int 2052b15cb3dSCy Schubert kq_build_changes_list(const struct event_changelist *changelist, 2062b15cb3dSCy Schubert struct kqop *kqop) 2072b15cb3dSCy Schubert { 2082b15cb3dSCy Schubert int i; 2092b15cb3dSCy Schubert int n_changes = 0; 2102b15cb3dSCy Schubert 2112b15cb3dSCy Schubert for (i = 0; i < changelist->n_changes; ++i) { 2122b15cb3dSCy Schubert struct event_change *in_ch = &changelist->changes[i]; 2132b15cb3dSCy Schubert struct kevent *out_ch; 2142b15cb3dSCy Schubert if (n_changes >= kqop->changes_size - 1) { 215a466cc55SCy Schubert int newsize; 2162b15cb3dSCy Schubert struct kevent *newchanges; 2172b15cb3dSCy Schubert 218a466cc55SCy Schubert if (kqop->changes_size > INT_MAX / 2 || 219a466cc55SCy Schubert (size_t)kqop->changes_size * 2 > EV_SIZE_MAX / 220a466cc55SCy Schubert sizeof(struct kevent)) { 221a466cc55SCy Schubert event_warnx("%s: int overflow", __func__); 222a466cc55SCy Schubert return (-1); 223a466cc55SCy Schubert } 224a466cc55SCy Schubert 225a466cc55SCy Schubert newsize = kqop->changes_size * 2; 2262b15cb3dSCy Schubert newchanges = mm_realloc(kqop->changes, 2272b15cb3dSCy Schubert newsize * sizeof(struct kevent)); 2282b15cb3dSCy Schubert if (newchanges == NULL) { 2292b15cb3dSCy Schubert event_warn("%s: realloc", __func__); 2302b15cb3dSCy Schubert return (-1); 2312b15cb3dSCy Schubert } 2322b15cb3dSCy Schubert kqop->changes = newchanges; 2332b15cb3dSCy Schubert kqop->changes_size = newsize; 2342b15cb3dSCy Schubert } 2352b15cb3dSCy Schubert if (in_ch->read_change) { 2362b15cb3dSCy Schubert out_ch = &kqop->changes[n_changes++]; 2372b15cb3dSCy Schubert kq_setup_kevent(out_ch, in_ch->fd, EVFILT_READ, 2382b15cb3dSCy Schubert in_ch->read_change); 2392b15cb3dSCy Schubert } 2402b15cb3dSCy Schubert if (in_ch->write_change) { 2412b15cb3dSCy Schubert out_ch = &kqop->changes[n_changes++]; 2422b15cb3dSCy Schubert kq_setup_kevent(out_ch, in_ch->fd, EVFILT_WRITE, 2432b15cb3dSCy Schubert in_ch->write_change); 2442b15cb3dSCy Schubert } 2452b15cb3dSCy Schubert } 2462b15cb3dSCy Schubert return n_changes; 2472b15cb3dSCy Schubert } 2482b15cb3dSCy Schubert 2492b15cb3dSCy Schubert static int 2502b15cb3dSCy Schubert kq_grow_events(struct kqop *kqop, size_t new_size) 2512b15cb3dSCy Schubert { 2522b15cb3dSCy Schubert struct kevent *newresult; 2532b15cb3dSCy Schubert 2542b15cb3dSCy Schubert newresult = mm_realloc(kqop->events, 2552b15cb3dSCy Schubert new_size * sizeof(struct kevent)); 2562b15cb3dSCy Schubert 2572b15cb3dSCy Schubert if (newresult) { 2582b15cb3dSCy Schubert kqop->events = newresult; 2592b15cb3dSCy Schubert kqop->events_size = new_size; 2602b15cb3dSCy Schubert return 0; 2612b15cb3dSCy Schubert } else { 2622b15cb3dSCy Schubert return -1; 2632b15cb3dSCy Schubert } 2642b15cb3dSCy Schubert } 2652b15cb3dSCy Schubert 2662b15cb3dSCy Schubert static int 2672b15cb3dSCy Schubert kq_dispatch(struct event_base *base, struct timeval *tv) 2682b15cb3dSCy Schubert { 2692b15cb3dSCy Schubert struct kqop *kqop = base->evbase; 2702b15cb3dSCy Schubert struct kevent *events = kqop->events; 2712b15cb3dSCy Schubert struct kevent *changes; 2722b15cb3dSCy Schubert struct timespec ts, *ts_p = NULL; 2732b15cb3dSCy Schubert int i, n_changes, res; 2742b15cb3dSCy Schubert 2752b15cb3dSCy Schubert if (tv != NULL) { 276a466cc55SCy Schubert ts.tv_sec = tv->tv_sec; 277a466cc55SCy Schubert ts.tv_nsec = tv->tv_usec * 1000; 2782b15cb3dSCy Schubert ts_p = &ts; 2792b15cb3dSCy Schubert } 2802b15cb3dSCy Schubert 2812b15cb3dSCy Schubert /* Build "changes" from "base->changes" */ 2822b15cb3dSCy Schubert EVUTIL_ASSERT(kqop->changes); 2832b15cb3dSCy Schubert n_changes = kq_build_changes_list(&base->changelist, kqop); 2842b15cb3dSCy Schubert if (n_changes < 0) 2852b15cb3dSCy Schubert return -1; 2862b15cb3dSCy Schubert 2872b15cb3dSCy Schubert event_changelist_remove_all_(&base->changelist, base); 2882b15cb3dSCy Schubert 2892b15cb3dSCy Schubert /* steal the changes array in case some broken code tries to call 2902b15cb3dSCy Schubert * dispatch twice at once. */ 2912b15cb3dSCy Schubert changes = kqop->changes; 2922b15cb3dSCy Schubert kqop->changes = NULL; 2932b15cb3dSCy Schubert 2942b15cb3dSCy Schubert /* Make sure that 'events' is at least as long as the list of changes: 2952b15cb3dSCy Schubert * otherwise errors in the changes can get reported as a -1 return 2962b15cb3dSCy Schubert * value from kevent() rather than as EV_ERROR events in the events 2972b15cb3dSCy Schubert * array. 2982b15cb3dSCy Schubert * 2992b15cb3dSCy Schubert * (We could instead handle -1 return values from kevent() by 3002b15cb3dSCy Schubert * retrying with a smaller changes array or a larger events array, 3012b15cb3dSCy Schubert * but this approach seems less risky for now.) 3022b15cb3dSCy Schubert */ 3032b15cb3dSCy Schubert if (kqop->events_size < n_changes) { 3042b15cb3dSCy Schubert int new_size = kqop->events_size; 3052b15cb3dSCy Schubert do { 3062b15cb3dSCy Schubert new_size *= 2; 3072b15cb3dSCy Schubert } while (new_size < n_changes); 3082b15cb3dSCy Schubert 3092b15cb3dSCy Schubert kq_grow_events(kqop, new_size); 3102b15cb3dSCy Schubert events = kqop->events; 3112b15cb3dSCy Schubert } 3122b15cb3dSCy Schubert 3132b15cb3dSCy Schubert EVBASE_RELEASE_LOCK(base, th_base_lock); 3142b15cb3dSCy Schubert 3152b15cb3dSCy Schubert res = kevent(kqop->kq, changes, n_changes, 3162b15cb3dSCy Schubert events, kqop->events_size, ts_p); 3172b15cb3dSCy Schubert 3182b15cb3dSCy Schubert EVBASE_ACQUIRE_LOCK(base, th_base_lock); 3192b15cb3dSCy Schubert 3202b15cb3dSCy Schubert EVUTIL_ASSERT(kqop->changes == NULL); 3212b15cb3dSCy Schubert kqop->changes = changes; 3222b15cb3dSCy Schubert 3232b15cb3dSCy Schubert if (res == -1) { 3242b15cb3dSCy Schubert if (errno != EINTR) { 3252b15cb3dSCy Schubert event_warn("kevent"); 3262b15cb3dSCy Schubert return (-1); 3272b15cb3dSCy Schubert } 3282b15cb3dSCy Schubert 3292b15cb3dSCy Schubert return (0); 3302b15cb3dSCy Schubert } 3312b15cb3dSCy Schubert 3322b15cb3dSCy Schubert event_debug(("%s: kevent reports %d", __func__, res)); 3332b15cb3dSCy Schubert 3342b15cb3dSCy Schubert for (i = 0; i < res; i++) { 3352b15cb3dSCy Schubert int which = 0; 3362b15cb3dSCy Schubert 3372b15cb3dSCy Schubert if (events[i].flags & EV_ERROR) { 3382b15cb3dSCy Schubert switch (events[i].data) { 3392b15cb3dSCy Schubert 3402b15cb3dSCy Schubert /* Can occur on delete if we are not currently 3412b15cb3dSCy Schubert * watching any events on this fd. That can 3422b15cb3dSCy Schubert * happen when the fd was closed and another 3432b15cb3dSCy Schubert * file was opened with that fd. */ 3442b15cb3dSCy Schubert case ENOENT: 3452b15cb3dSCy Schubert /* Can occur for reasons not fully understood 3462b15cb3dSCy Schubert * on FreeBSD. */ 3472b15cb3dSCy Schubert case EINVAL: 3482b15cb3dSCy Schubert continue; 349*f5f40dd6SCy Schubert #if defined(__FreeBSD__) && defined(ENOTCAPABLE) 350a25439b6SCy Schubert /* 351a25439b6SCy Schubert * This currently occurs if an FD is closed 352a25439b6SCy Schubert * before the EV_DELETE makes it out via kevent(). 353a25439b6SCy Schubert * The FreeBSD capabilities code sees the blank 354a25439b6SCy Schubert * capability set and rejects the request to 355a25439b6SCy Schubert * modify an event. 356a25439b6SCy Schubert * 357a25439b6SCy Schubert * To be strictly correct - when an FD is closed, 358a25439b6SCy Schubert * all the registered events are also removed. 359a25439b6SCy Schubert * Queuing EV_DELETE to a closed FD is wrong. 360a25439b6SCy Schubert * The event(s) should just be deleted from 361a25439b6SCy Schubert * the pending changelist. 362a25439b6SCy Schubert */ 363a25439b6SCy Schubert case ENOTCAPABLE: 364a25439b6SCy Schubert continue; 365a25439b6SCy Schubert #endif 3662b15cb3dSCy Schubert 3672b15cb3dSCy Schubert /* Can occur on a delete if the fd is closed. */ 3682b15cb3dSCy Schubert case EBADF: 3692b15cb3dSCy Schubert /* XXXX On NetBSD, we can also get EBADF if we 3702b15cb3dSCy Schubert * try to add the write side of a pipe, but 3712b15cb3dSCy Schubert * the read side has already been closed. 3722b15cb3dSCy Schubert * Other BSDs call this situation 'EPIPE'. It 3732b15cb3dSCy Schubert * would be good if we had a way to report 3742b15cb3dSCy Schubert * this situation. */ 3752b15cb3dSCy Schubert continue; 3762b15cb3dSCy Schubert /* These two can occur on an add if the fd was one side 3772b15cb3dSCy Schubert * of a pipe, and the other side was closed. */ 3782b15cb3dSCy Schubert case EPERM: 3792b15cb3dSCy Schubert case EPIPE: 3802b15cb3dSCy Schubert /* Report read events, if we're listening for 3812b15cb3dSCy Schubert * them, so that the user can learn about any 3822b15cb3dSCy Schubert * add errors. (If the operation was a 3832b15cb3dSCy Schubert * delete, then udata should be cleared.) */ 3842b15cb3dSCy Schubert if (events[i].udata) { 3852b15cb3dSCy Schubert /* The operation was an add: 3862b15cb3dSCy Schubert * report the error as a read. */ 3872b15cb3dSCy Schubert which |= EV_READ; 3882b15cb3dSCy Schubert break; 3892b15cb3dSCy Schubert } else { 3902b15cb3dSCy Schubert /* The operation was a del: 3912b15cb3dSCy Schubert * report nothing. */ 3922b15cb3dSCy Schubert continue; 3932b15cb3dSCy Schubert } 3942b15cb3dSCy Schubert 3952b15cb3dSCy Schubert /* Other errors shouldn't occur. */ 3962b15cb3dSCy Schubert default: 3972b15cb3dSCy Schubert errno = events[i].data; 3982b15cb3dSCy Schubert return (-1); 3992b15cb3dSCy Schubert } 4002b15cb3dSCy Schubert } else if (events[i].filter == EVFILT_READ) { 4012b15cb3dSCy Schubert which |= EV_READ; 4022b15cb3dSCy Schubert } else if (events[i].filter == EVFILT_WRITE) { 4032b15cb3dSCy Schubert which |= EV_WRITE; 4042b15cb3dSCy Schubert } else if (events[i].filter == EVFILT_SIGNAL) { 4052b15cb3dSCy Schubert which |= EV_SIGNAL; 4062b15cb3dSCy Schubert #ifdef EVFILT_USER 4072b15cb3dSCy Schubert } else if (events[i].filter == EVFILT_USER) { 4082b15cb3dSCy Schubert base->is_notify_pending = 0; 4092b15cb3dSCy Schubert #endif 4102b15cb3dSCy Schubert } 4112b15cb3dSCy Schubert 4122b15cb3dSCy Schubert if (!which) 4132b15cb3dSCy Schubert continue; 4142b15cb3dSCy Schubert 4152b15cb3dSCy Schubert if (events[i].filter == EVFILT_SIGNAL) { 4162b15cb3dSCy Schubert evmap_signal_active_(base, events[i].ident, 1); 4172b15cb3dSCy Schubert } else { 4182b15cb3dSCy Schubert evmap_io_active_(base, events[i].ident, which | EV_ET); 4192b15cb3dSCy Schubert } 4202b15cb3dSCy Schubert } 4212b15cb3dSCy Schubert 4222b15cb3dSCy Schubert if (res == kqop->events_size) { 4232b15cb3dSCy Schubert /* We used all the events space that we have. Maybe we should 4242b15cb3dSCy Schubert make it bigger. */ 4252b15cb3dSCy Schubert kq_grow_events(kqop, kqop->events_size * 2); 4262b15cb3dSCy Schubert } 4272b15cb3dSCy Schubert 4282b15cb3dSCy Schubert return (0); 4292b15cb3dSCy Schubert } 4302b15cb3dSCy Schubert 4312b15cb3dSCy Schubert static void 4322b15cb3dSCy Schubert kqop_free(struct kqop *kqop) 4332b15cb3dSCy Schubert { 4342b15cb3dSCy Schubert if (kqop->changes) 4352b15cb3dSCy Schubert mm_free(kqop->changes); 4362b15cb3dSCy Schubert if (kqop->events) 4372b15cb3dSCy Schubert mm_free(kqop->events); 4382b15cb3dSCy Schubert if (kqop->kq >= 0 && kqop->pid == getpid()) 4392b15cb3dSCy Schubert close(kqop->kq); 4402b15cb3dSCy Schubert memset(kqop, 0, sizeof(struct kqop)); 4412b15cb3dSCy Schubert mm_free(kqop); 4422b15cb3dSCy Schubert } 4432b15cb3dSCy Schubert 4442b15cb3dSCy Schubert static void 4452b15cb3dSCy Schubert kq_dealloc(struct event_base *base) 4462b15cb3dSCy Schubert { 4472b15cb3dSCy Schubert struct kqop *kqop = base->evbase; 4482b15cb3dSCy Schubert evsig_dealloc_(base); 4492b15cb3dSCy Schubert kqop_free(kqop); 4502b15cb3dSCy Schubert } 4512b15cb3dSCy Schubert 4522b15cb3dSCy Schubert /* signal handling */ 4532b15cb3dSCy Schubert static int 4542b15cb3dSCy Schubert kq_sig_add(struct event_base *base, int nsignal, short old, short events, void *p) 4552b15cb3dSCy Schubert { 4562b15cb3dSCy Schubert struct kqop *kqop = base->evbase; 4572b15cb3dSCy Schubert struct kevent kev; 4582b15cb3dSCy Schubert struct timespec timeout = { 0, 0 }; 4592b15cb3dSCy Schubert (void)p; 4602b15cb3dSCy Schubert 4612b15cb3dSCy Schubert EVUTIL_ASSERT(nsignal >= 0 && nsignal < NSIG); 4622b15cb3dSCy Schubert 4632b15cb3dSCy Schubert memset(&kev, 0, sizeof(kev)); 4642b15cb3dSCy Schubert kev.ident = nsignal; 4652b15cb3dSCy Schubert kev.filter = EVFILT_SIGNAL; 4662b15cb3dSCy Schubert kev.flags = EV_ADD; 4672b15cb3dSCy Schubert 4682b15cb3dSCy Schubert /* Be ready for the signal if it is sent any 4692b15cb3dSCy Schubert * time between now and the next call to 4702b15cb3dSCy Schubert * kq_dispatch. */ 4712b15cb3dSCy Schubert if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1) 4722b15cb3dSCy Schubert return (-1); 4732b15cb3dSCy Schubert 4742b15cb3dSCy Schubert /* We can set the handler for most signals to SIG_IGN and 4752b15cb3dSCy Schubert * still have them reported to us in the queue. However, 4762b15cb3dSCy Schubert * if the handler for SIGCHLD is SIG_IGN, the system reaps 4772b15cb3dSCy Schubert * zombie processes for us, and we don't get any notification. 4782b15cb3dSCy Schubert * This appears to be the only signal with this quirk. */ 4792b15cb3dSCy Schubert if (evsig_set_handler_(base, nsignal, 4802b15cb3dSCy Schubert nsignal == SIGCHLD ? SIG_DFL : SIG_IGN) == -1) 4812b15cb3dSCy Schubert return (-1); 4822b15cb3dSCy Schubert 4832b15cb3dSCy Schubert return (0); 4842b15cb3dSCy Schubert } 4852b15cb3dSCy Schubert 4862b15cb3dSCy Schubert static int 4872b15cb3dSCy Schubert kq_sig_del(struct event_base *base, int nsignal, short old, short events, void *p) 4882b15cb3dSCy Schubert { 4892b15cb3dSCy Schubert struct kqop *kqop = base->evbase; 4902b15cb3dSCy Schubert struct kevent kev; 4912b15cb3dSCy Schubert 4922b15cb3dSCy Schubert struct timespec timeout = { 0, 0 }; 4932b15cb3dSCy Schubert (void)p; 4942b15cb3dSCy Schubert 4952b15cb3dSCy Schubert EVUTIL_ASSERT(nsignal >= 0 && nsignal < NSIG); 4962b15cb3dSCy Schubert 4972b15cb3dSCy Schubert memset(&kev, 0, sizeof(kev)); 4982b15cb3dSCy Schubert kev.ident = nsignal; 4992b15cb3dSCy Schubert kev.filter = EVFILT_SIGNAL; 5002b15cb3dSCy Schubert kev.flags = EV_DELETE; 5012b15cb3dSCy Schubert 5022b15cb3dSCy Schubert /* Because we insert signal events 5032b15cb3dSCy Schubert * immediately, we need to delete them 5042b15cb3dSCy Schubert * immediately, too */ 5052b15cb3dSCy Schubert if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1) 5062b15cb3dSCy Schubert return (-1); 5072b15cb3dSCy Schubert 5082b15cb3dSCy Schubert if (evsig_restore_handler_(base, nsignal) == -1) 5092b15cb3dSCy Schubert return (-1); 5102b15cb3dSCy Schubert 5112b15cb3dSCy Schubert return (0); 5122b15cb3dSCy Schubert } 5132b15cb3dSCy Schubert 5142b15cb3dSCy Schubert 5152b15cb3dSCy Schubert /* OSX 10.6 and FreeBSD 8.1 add support for EVFILT_USER, which we can use 5162b15cb3dSCy Schubert * to wake up the event loop from another thread. */ 5172b15cb3dSCy Schubert 5182b15cb3dSCy Schubert /* Magic number we use for our filter ID. */ 5192b15cb3dSCy Schubert #define NOTIFY_IDENT 42 5202b15cb3dSCy Schubert 5212b15cb3dSCy Schubert int 5222b15cb3dSCy Schubert event_kq_add_notify_event_(struct event_base *base) 5232b15cb3dSCy Schubert { 5242b15cb3dSCy Schubert struct kqop *kqop = base->evbase; 5252b15cb3dSCy Schubert #if defined(EVFILT_USER) && defined(NOTE_TRIGGER) 5262b15cb3dSCy Schubert struct kevent kev; 5272b15cb3dSCy Schubert struct timespec timeout = { 0, 0 }; 5282b15cb3dSCy Schubert #endif 5292b15cb3dSCy Schubert 5302b15cb3dSCy Schubert if (kqop->notify_event_added) 5312b15cb3dSCy Schubert return 0; 5322b15cb3dSCy Schubert 5332b15cb3dSCy Schubert #if defined(EVFILT_USER) && defined(NOTE_TRIGGER) 5342b15cb3dSCy Schubert memset(&kev, 0, sizeof(kev)); 5352b15cb3dSCy Schubert kev.ident = NOTIFY_IDENT; 5362b15cb3dSCy Schubert kev.filter = EVFILT_USER; 5372b15cb3dSCy Schubert kev.flags = EV_ADD | EV_CLEAR; 5382b15cb3dSCy Schubert 5392b15cb3dSCy Schubert if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1) { 5402b15cb3dSCy Schubert event_warn("kevent: adding EVFILT_USER event"); 5412b15cb3dSCy Schubert return -1; 5422b15cb3dSCy Schubert } 5432b15cb3dSCy Schubert 5442b15cb3dSCy Schubert kqop->notify_event_added = 1; 5452b15cb3dSCy Schubert 5462b15cb3dSCy Schubert return 0; 5472b15cb3dSCy Schubert #else 5482b15cb3dSCy Schubert return -1; 5492b15cb3dSCy Schubert #endif 5502b15cb3dSCy Schubert } 5512b15cb3dSCy Schubert 5522b15cb3dSCy Schubert int 5532b15cb3dSCy Schubert event_kq_notify_base_(struct event_base *base) 5542b15cb3dSCy Schubert { 5552b15cb3dSCy Schubert struct kqop *kqop = base->evbase; 5562b15cb3dSCy Schubert #if defined(EVFILT_USER) && defined(NOTE_TRIGGER) 5572b15cb3dSCy Schubert struct kevent kev; 5582b15cb3dSCy Schubert struct timespec timeout = { 0, 0 }; 5592b15cb3dSCy Schubert #endif 5602b15cb3dSCy Schubert if (! kqop->notify_event_added) 5612b15cb3dSCy Schubert return -1; 5622b15cb3dSCy Schubert 5632b15cb3dSCy Schubert #if defined(EVFILT_USER) && defined(NOTE_TRIGGER) 5642b15cb3dSCy Schubert memset(&kev, 0, sizeof(kev)); 5652b15cb3dSCy Schubert kev.ident = NOTIFY_IDENT; 5662b15cb3dSCy Schubert kev.filter = EVFILT_USER; 5672b15cb3dSCy Schubert kev.fflags = NOTE_TRIGGER; 5682b15cb3dSCy Schubert 5692b15cb3dSCy Schubert if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1) { 5702b15cb3dSCy Schubert event_warn("kevent: triggering EVFILT_USER event"); 5712b15cb3dSCy Schubert return -1; 5722b15cb3dSCy Schubert } 5732b15cb3dSCy Schubert 5742b15cb3dSCy Schubert return 0; 5752b15cb3dSCy Schubert #else 5762b15cb3dSCy Schubert return -1; 5772b15cb3dSCy Schubert #endif 5782b15cb3dSCy Schubert } 5792b15cb3dSCy Schubert 5802b15cb3dSCy Schubert #endif /* EVENT__HAVE_KQUEUE */ 581