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 *
kq_init(struct event_base * base)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
kq_setup_kevent(struct kevent * out,evutil_socket_t fd,int filter,short change)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
kq_build_changes_list(const struct event_changelist * changelist,struct kqop * kqop)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
kq_grow_events(struct kqop * kqop,size_t new_size)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
kq_dispatch(struct event_base * base,struct timeval * tv)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
kqop_free(struct kqop * kqop)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
kq_dealloc(struct event_base * base)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
kq_sig_add(struct event_base * base,int nsignal,short old,short events,void * p)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
kq_sig_del(struct event_base * base,int nsignal,short old,short events,void * p)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
event_kq_add_notify_event_(struct event_base * base)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
event_kq_notify_base_(struct event_base * base)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