From 1db04b8702f1bccd918d9222b7c722a8d769e1d0 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 20 Oct 2009 00:31:17 +0000 Subject: [PATCH 0001/1120] initial import git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@1 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 57 +++ vendor/libkqueue/README | 51 +++ vendor/libkqueue/config.h | 5 + vendor/libkqueue/configure | 34 ++ vendor/libkqueue/filter.c | 172 ++++++++ vendor/libkqueue/kevent.c | 230 +++++++++++ vendor/libkqueue/knote.c | 67 ++++ vendor/libkqueue/kqueue.2 | 608 +++++++++++++++++++++++++++++ vendor/libkqueue/kqueue.c | 155 ++++++++ vendor/libkqueue/os/linux/signal.c | 135 +++++++ vendor/libkqueue/os/linux/socket.c | 149 +++++++ vendor/libkqueue/os/linux/timer.c | 175 +++++++++ vendor/libkqueue/os/linux/vnode.c | 238 +++++++++++ vendor/libkqueue/os/posix/signal.c | 133 +++++++ vendor/libkqueue/os/posix/timer.c | 168 ++++++++ vendor/libkqueue/os/posix/user.c | 67 ++++ vendor/libkqueue/private.h | 103 +++++ vendor/libkqueue/sys/event.h | 156 ++++++++ vendor/libkqueue/test.c | 467 ++++++++++++++++++++++ 19 files changed, 3170 insertions(+) create mode 100644 vendor/libkqueue/Makefile create mode 100644 vendor/libkqueue/README create mode 100644 vendor/libkqueue/config.h create mode 100755 vendor/libkqueue/configure create mode 100644 vendor/libkqueue/filter.c create mode 100644 vendor/libkqueue/kevent.c create mode 100644 vendor/libkqueue/knote.c create mode 100644 vendor/libkqueue/kqueue.2 create mode 100644 vendor/libkqueue/kqueue.c create mode 100644 vendor/libkqueue/os/linux/signal.c create mode 100644 vendor/libkqueue/os/linux/socket.c create mode 100644 vendor/libkqueue/os/linux/timer.c create mode 100644 vendor/libkqueue/os/linux/vnode.c create mode 100644 vendor/libkqueue/os/posix/signal.c create mode 100644 vendor/libkqueue/os/posix/timer.c create mode 100644 vendor/libkqueue/os/posix/user.c create mode 100644 vendor/libkqueue/private.h create mode 100644 vendor/libkqueue/sys/event.h create mode 100644 vendor/libkqueue/test.c diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile new file mode 100644 index 000000000..31c6378fb --- /dev/null +++ b/vendor/libkqueue/Makefile @@ -0,0 +1,57 @@ +# +# Copyright (c) 2009 Mark Heily +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +PROGRAM=libkqueue +INSTALL=/usr/bin/install +PREFIX=/usr +DISTFILES=*.c *.h kqueue.2 README Makefile configure os sys +SOURCES=src/$(UNAME)/*.c +CFLAGS=-fPIC -I. -Wall -Werror -fvisibility=hidden +FILTERS=vnode.c timer.c signal.c socket.c user.c + +include config.mk + +build: + gcc $(CFLAGS) -c *.c + ar rcs libkqueue.a *.o + gcc -shared -Wl,-soname,libkqueue.so -o libkqueue.so *.o + +install: + mkdir -p $(PREFIX)/include/kqueue/sys + cp event.h $(PREFIX)/include/kqueue/sys + cp libkqueue.so $(PREFIX)/lib + cp kqueue.2 $(PREFIX)/share/man/man2/kqueue.2 + ln -s kqueue.2 $(PREFIX)/share/man/man2/kevent.2 + +check: + make build CFLAGS="$(CFLAGS) -g -O0 -DKQUEUE_DEBUG -DUNIT_TEST" + gcc -g -O0 $(CFLAGS) test.c libkqueue.a -lpthread -lrt + ./a.out + +check-installed: + gcc -g -O0 -Wall -Werror -I$(PREFIX)/kqueue test.c -lkqueue -lpthread -lrt + ./a.out + +dist: + mkdir $(PROGRAM) + cp -R $(DISTFILES) $(PROGRAM) + tar zcvf $(PROGRAM)-`date +%y%m%d_%H%M`.tar.gz $(PROGRAM) + rm -rf $(PROGRAM) + +clean: + rm -f a.out *.a *.o *.so $(FILTERS) + +distclean: clean + rm -f *.tar.gz config.mk diff --git a/vendor/libkqueue/README b/vendor/libkqueue/README new file mode 100644 index 000000000..407f94c78 --- /dev/null +++ b/vendor/libkqueue/README @@ -0,0 +1,51 @@ +libkqueue emulates the kqueue(2) kernel event notification mechanism +on platforms which do not provide it natively. Currently, the only +supported platform is Linux and the only tested platform is +Ubuntu x64 with kernel 2.6.28. + + + kevent.flags Implementation Status + + ADD DELETE ENABLE DISABLE DISPATCH ONESHOT CLEAR EOF + +READ/WRITE Y Y Y Y N Y N N +AIO N N N N N N N N +VNODE Y N N N N N N N +PROC NO -- Cannot fully implement on Linux +SIGNAL Y N N N N N N N +NETDEV NO -- Don't know how to implement on Linux +TIMER Y N N N N N N N +USER Totally broken + + kevent.fflags Implementation Status + + Status +READ + NOTE_LOWAT No + EV_EOF No +WRITE + NOTE_LOWAT No + EV_EOF No +VNODE + NOTE_DELETE No + NOTE_WRITE No + NOTE_EXTEND No + NOTE_ATTRIB No + NOTE_LINK No + NOTE_RENAME No + NOTE_REVOKE N/A +USER + NOTE_FFNOP Ignore the input fflags. + NOTE_FFAND Bitwise AND fflags. + NOTE_FFOR Bitwise OR fflags. + NOTE_COPY Copy fflags. + NOTE_FFCTRLMASK Control mask for fflags. + NOTE_FFLAGSMASK User defined flag mask for fflags. + NOTE_TRIGGER Cause the event to be triggered. + + Filter sets kevent.data structure when returning +EV_RECEIPT Yes +kevent.data No + +-- +Mark Heily diff --git a/vendor/libkqueue/config.h b/vendor/libkqueue/config.h new file mode 100644 index 000000000..ad68a925a --- /dev/null +++ b/vendor/libkqueue/config.h @@ -0,0 +1,5 @@ +# AUTOMATICALLY GENERATED -- DO NOT EDIT +#define HAVE_SYS_EPOLL_H +#define HAVE_SYS_INOTIFY_H +#undef HAVE_SYS_SIGNALFD_H +#undef HAVE_SYS_TIMERFD_H diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure new file mode 100755 index 000000000..7cb92d583 --- /dev/null +++ b/vendor/libkqueue/configure @@ -0,0 +1,34 @@ +#!/bin/sh + +check_header() { + sym=`echo "HAVE_$1" | tr a-z A-Z | sed 's,[./],_,g'` + if [ -f /usr/include/$1 ] ; then + echo "#define $sym" >> config.h + return 0 + else + echo "#undef $sym" >> config.h + return 1 + fi +} + +echo "Checking operating system type... `uname`" +kernel=`uname -s | tr A-Z a-z` +target=$kernel + +echo "Creating config.h" +echo "# AUTOMATICALLY GENERATED -- DO NOT EDIT" > config.h +if [ $kernel = "linux" ] ; then + check_header sys/epoll.h && ln -s os/linux/socket.c \ + || ln -s os/posix/socket.c + check_header sys/inotify.h && ln -s os/linux/vnode.c \ + || ln -s os/posix/vnode.c + check_header sys/signalfd.h && ln -s os/linux/signal.c \ + || ln -s os/posix/signal.c + check_header sys/timerfd.h && ln -s os/linux/timer.c \ + || ln -s os/posix/timer.c + ln -s os/posix/user.c +fi + +echo "Creating config.mk" +echo "# AUTOMATICALLY GENERATED -- DO NOT EDIT" > config.mk +echo "UNAME=$target" >> config.mk diff --git a/vendor/libkqueue/filter.c b/vendor/libkqueue/filter.c new file mode 100644 index 000000000..a87942f50 --- /dev/null +++ b/vendor/libkqueue/filter.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "private.h" + +extern const struct filter evfilt_read; +extern const struct filter evfilt_write; +extern const struct filter evfilt_signal; +extern const struct filter evfilt_vnode; +extern const struct filter evfilt_timer; +extern const struct filter evfilt_user; + +static int +filter_register(struct kqueue *kq, short filter, const struct filter *src) +{ + struct filter *dst; + u_int filt; + int rv = 0; + + filt = (-1 * filter) - 1; + if (filt >= EVFILT_SYSCOUNT) + return (-1); + + dst = &kq->kq_filt[filt]; + memcpy(dst, src, sizeof(*src)); + dst->kf_kqueue = kq; + KNOTELIST_INIT(&dst->knl); + if (src->kf_init == NULL) { + dbg_puts("filter has no initializer"); + return (-1); + } + + rv = src->kf_init(dst); + if (rv < 0) { + dbg_puts("filter failed to initialize"); + dst->kf_id = 0; /* FIXME: lame magic constant */ + return (-1); + } + + /* Add the filter's event descriptor to the main fdset */ + if (dst->kf_pfd <= 0) { + dbg_printf("FIXME - filter %s did not return a fd to poll!", + filter_name(filter)); + return (-1); + } + FD_SET(dst->kf_pfd, &kq->kq_fds); + if (dst->kf_pfd > kq->kq_nfds) + kq->kq_nfds = dst->kf_pfd; + dbg_printf("fds: added %d (nfds=%d)", dst->kf_pfd, kq->kq_nfds); + dbg_printf("%s registered", filter_name(filter)); + + return (0); +} + +int +filter_register_all(struct kqueue *kq) +{ + int rv; + + FD_ZERO(&kq->kq_fds); + rv = 0; + rv += filter_register(kq, EVFILT_READ, &evfilt_read); + rv += filter_register(kq, EVFILT_WRITE, &evfilt_write); + rv += filter_register(kq, EVFILT_SIGNAL, &evfilt_signal); + rv += filter_register(kq, EVFILT_VNODE, &evfilt_vnode); + rv += filter_register(kq, EVFILT_TIMER, &evfilt_timer); + rv += filter_register(kq, EVFILT_USER, &evfilt_user); + kq->kq_nfds++; + if (rv != 0) { + filter_unregister_all(kq); + return (-1); + } else { + return (0); + } +} + +void +filter_unregister_all(struct kqueue *kq) +{ + struct knote *n1, *n2; + int i; + + for (i = 0; i < EVFILT_SYSCOUNT; i++) { + if (kq->kq_filt[i].kf_id == 0) + continue; + + if (kq->kq_filt[i].kf_destroy != NULL) + kq->kq_filt[i].kf_destroy(&kq->kq_filt[i]); + + /* Destroy all knotes associated with this filter */ + for (n1 = LIST_FIRST(&kq->kq_filt[i].knl); n1 != NULL; n1 = n2) { + n2 = LIST_NEXT(n1, entries); + free(n1); + } + } + memset(&kq->kq_filt[0], 0, sizeof(kq->kq_filt)); +} + +int +filter_socketpair(struct filter *filt) +{ + int sockfd[2]; + + if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd) < 0) + return (-1); + + fcntl(sockfd[0], F_SETFL, O_NONBLOCK); + filt->kf_wfd = sockfd[0]; + filt->kf_pfd = sockfd[1]; + return (0); +} + +struct filter * +filter_lookup(struct kqueue *kq, short id) +{ + id = (-1 * id) - 1; + if (id < 0 || id >= EVFILT_SYSCOUNT) { + errno = EINVAL; + return (NULL); + } + if (kq->kq_filt[id].kf_copyin == NULL) { + errno = ENOTSUP; + return (NULL); + } + + return (&kq->kq_filt[id]); +} + +const char * +filter_name(short filt) +{ + const char *fname[EVFILT_SYSCOUNT] = { + "EVFILT_READ", + "EVFILT_WRITE", + "EVFILT_AIO", + "EVFILT_VNODE", + "EVFILT_PROC", + "EVFILT_SIGNAL", + "EVFILT_TIMER", + "EVFILT_NETDEV", + "EVFILT_FS", + "EVFILT_LIO", + "EVFILT_USER" + }; + + if (~filt >= EVFILT_SYSCOUNT) + return "EVFILT_BAD_RANGE"; + else + return fname[~filt]; +} diff --git a/vendor/libkqueue/kevent.c b/vendor/libkqueue/kevent.c new file mode 100644 index 000000000..eda0dc5e9 --- /dev/null +++ b/vendor/libkqueue/kevent.c @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* To get asprintf(3) */ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sys/event.h" +#include "private.h" + +const char * +kevent_dump(struct kevent *kev) +{ + char buf[512]; + snprintf(&buf[0], sizeof(buf), "[filter=%d,flags=%d,ident=%u,udata=%p]", + kev->filter, + kev->flags, + (u_int) kev->ident, + kev->udata); + return (strdup(buf)); +} + +static void +kevent_error(struct kevent *dst, const struct kevent *src, int data) +{ + memcpy(dst, src, sizeof(*src)); + dst->data = data; +} + +static int +kevent_copyin(struct kqueue *kq, const struct kevent *src, int nchanges, + struct kevent *eventlist, int nevents) +{ + struct knote *dst; + struct filter *filt; + int kn_alloc,status; + + for (; nchanges > 0; src++, nchanges--) { + + if ((filt = filter_lookup(kq, src->filter)) == NULL) { + status = -EINVAL; + goto err_out; + } + + /* + * Retrieve an existing knote object, or create a new one. + */ + kn_alloc = 0; + dst = knote_lookup(filt, src->ident); + if (dst == NULL) { + if (src->flags & EV_ADD) { + if ((dst = knote_new(filt)) == NULL) { + status = -ENOMEM; + goto err_out; + } + dbg_puts(kevent_dump(&dst->kev)); + kn_alloc = 1; + } else if (src->flags & EV_ENABLE + || src->flags & EV_DISABLE + || src->flags & EV_DELETE) { + status = -ENOENT; + goto err_out; + } else { + /* flags == 0 or no action */ + status = -EINVAL; + goto err_out; + } + } + + if (filt->kf_copyin(filt, dst, src) < 0) { + if (kn_alloc) + knote_free(dst); + status = -EBADMSG; + goto err_out; + } + + /* + * Update the knote flags based on src->flags. + */ + if (src->flags & EV_ENABLE) { + dst->kev.flags |= EV_ENABLE; + dst->kev.flags &= ~EV_DISABLE; + } + if (src->flags & EV_DISABLE) { + dst->kev.flags &= ~EV_ENABLE; + dst->kev.flags |= EV_DISABLE; + } + if (src->flags & EV_DELETE) { + knote_free(dst); + } + if (src->flags & EV_RECEIPT) { + status = 0; + goto err_out; + } + + continue; + +err_out: + if (status != 0 && kn_alloc) + knote_free(dst); + if (nevents > 0) { + kevent_error(eventlist++, src, status); + nevents--; + } else { + return (-1); + } + } + + return (0); +} + +int +kevent(int kqfd, const struct kevent *changelist, int nchanges, + struct kevent *eventlist, int nevents, + const struct timespec *timeout) +{ + struct kqueue *kq; + struct filter *filt; + fd_set fds; + int i, rv, n, nret; + + errno = 0; + + kq = kqueue_lookup(kqfd); + if (kq == NULL) { + dbg_printf("fd lookup failed; fd=%d", kqfd); + errno = EINVAL; + return (-1); + } + + /* + * Process each kevent on the changelist. + */ + if (nchanges) { + kqueue_lock(kq); + rv = kevent_copyin(kq, changelist, nchanges, eventlist, nevents); + kqueue_unlock(kq); + if (rv < 0) + return (-1); + } + + /* Determine if we need to wait for events. */ + if (nevents == 0) + return (0); + if (nevents > MAX_KEVENT) + nevents = MAX_KEVENT; + + /* + * Wait for one or more filters to have events. + */ + fds = kq->kq_fds; +#if BROKEN + n = pselect(kq->kq_nfds, &fds, NULL , NULL, timeout, NULL); +#else + /* BROKEn, but testing vnode crap */ + struct timeval tv; + struct timeval *tvp = &tv; + if (timeout) { + tv.tv_sec = timeout->tv_sec; + tv.tv_usec = timeout->tv_nsec / 1000; + } else { + dbg_puts("null timeout.."); + tvp = NULL; + } + n = select(kq->kq_nfds, &fds, NULL, NULL, tvp); +#endif + if (n < 0) { + if (errno == EINTR) { + dbg_puts("signal caught"); + return (-1); + } + dbg_perror("pselect(2)"); + return (-1); + } + dbg_printf("pselect(2): %d bits set", n); + if (n == 0) + return (0); + + /* + * Process each event and place it on the eventlist + */ + nret = 0; + kqueue_lock(kq); + for (i = 0; (i < EVFILT_SYSCOUNT && n > 0 && nevents > 0); i++) { + dbg_printf("eventlist: n = %d nevents = %d", n, nevents); + filt = &kq->kq_filt[i]; + dbg_printf("pfd[%d] = %d", i, filt->kf_pfd); + if (FD_ISSET(filt->kf_pfd, &fds)) { + dbg_printf("event(s) for filter #%d", i); + rv = filt->kf_copyout(filt, eventlist, nevents); + if (rv < 0) { + kqueue_unlock(kq); + dbg_puts("kevent_copyout failed"); + return (-1); + } + nret += rv; + eventlist += rv; + nevents -= rv; + n--; + } + } + kqueue_unlock(kq); + + return (nret); +} diff --git a/vendor/libkqueue/knote.c b/vendor/libkqueue/knote.c new file mode 100644 index 000000000..e904d9a1b --- /dev/null +++ b/vendor/libkqueue/knote.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include "private.h" + +/* TODO: These must be called with the kqueue lock held */ + +struct knote * +knote_new(struct filter *filt) +{ + struct knote *dst; + + if ((dst = calloc(1, sizeof(*dst))) == NULL) + return (NULL); + KNOTE_INSERT(&filt->knl, dst); + return (dst); +} + +void +knote_free(struct knote *kn) +{ + dbg_printf("knote_free(): filt=%d, ident=%u", + kn->kev.filter, (u_int) kn->kev.ident); + LIST_REMOVE(kn, entries); + free(kn); +} + +/* TODO: rename to knote_lookup_ident */ +struct knote * +knote_lookup(struct filter *filt, short ident) +{ + struct knote *kn; + LIST_FOREACH(kn, &filt->knl, entries) { + if (ident == kn->kev.ident) + break; + } + return (kn); +} + +struct knote * +knote_lookup_data(struct filter *filt, intptr_t data) +{ + struct knote *kn; + LIST_FOREACH(kn, &filt->knl, entries) { + if (data == kn->kev.data) + break; + } + return (kn); +} diff --git a/vendor/libkqueue/kqueue.2 b/vendor/libkqueue/kqueue.2 new file mode 100644 index 000000000..6a80875bd --- /dev/null +++ b/vendor/libkqueue/kqueue.2 @@ -0,0 +1,608 @@ +.\" $FreeBSD: Revision: 197243$ +.\" Copyright (c) 2000 Jonathan Lemon +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd September 15, 2009 +.Dt KQUEUE 2 +.Os +.Sh NAME +.Nm kqueue , +.Nm kevent +.Nd kernel event notification mechanism +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In sys/types.h +.In sys/event.h +.In sys/time.h +.Ft int +.Fn kqueue "void" +.Ft int +.Fn kevent "int kq" "const struct kevent *changelist" "int nchanges" "struct kevent *eventlist" "int nevents" "const struct timespec *timeout" +.Fn EV_SET "&kev" ident filter flags fflags data udata +.Sh DESCRIPTION +The +.Fn kqueue +system call +provides a generic method of notifying the user when an event +happens or a condition holds, based on the results of small +pieces of kernel code termed filters. +A kevent is identified by the (ident, filter) pair; there may only +be one unique kevent per kqueue. +.Pp +The filter is executed upon the initial registration of a kevent +in order to detect whether a preexisting condition is present, and is also +executed whenever an event is passed to the filter for evaluation. +If the filter determines that the condition should be reported, +then the kevent is placed on the kqueue for the user to retrieve. +.Pp +The filter is also run when the user attempts to retrieve the kevent +from the kqueue. +If the filter indicates that the condition that triggered +the event no longer holds, the kevent is removed from the kqueue and +is not returned. +.Pp +Multiple events which trigger the filter do not result in multiple +kevents being placed on the kqueue; instead, the filter will aggregate +the events into a single struct kevent. +Calling +.Fn close +on a file descriptor will remove any kevents that reference the descriptor. +.Pp +The +.Fn kqueue +system call +creates a new kernel event queue and returns a descriptor. +The queue is not inherited by a child created with +.Xr fork 2 . +However, if +.Xr rfork 2 +is called without the +.Dv RFFDG +flag, then the descriptor table is shared, +which will allow sharing of the kqueue between two processes. +.Pp +The +.Fn kevent +system call +is used to register events with the queue, and return any pending +events to the user. +The +.Fa changelist +argument +is a pointer to an array of +.Va kevent +structures, as defined in +.In sys/event.h . +All changes contained in the +.Fa changelist +are applied before any pending events are read from the queue. +The +.Fa nchanges +argument +gives the size of +.Fa changelist . +The +.Fa eventlist +argument +is a pointer to an array of kevent structures. +The +.Fa nevents +argument +determines the size of +.Fa eventlist . +When +.Fa nevents +is zero, +.Fn kevent +will return immediately even if there is a +.Fa timeout +specified unlike +.Xr select 2 . +If +.Fa timeout +is a non-NULL pointer, it specifies a maximum interval to wait +for an event, which will be interpreted as a struct timespec. +If +.Fa timeout +is a NULL pointer, +.Fn kevent +waits indefinitely. +To effect a poll, the +.Fa timeout +argument should be non-NULL, pointing to a zero-valued +.Va timespec +structure. +The same array may be used for the +.Fa changelist +and +.Fa eventlist . +.Pp +The +.Fn EV_SET +macro is provided for ease of initializing a +kevent structure. +.Pp +The +.Va kevent +structure is defined as: +.Bd -literal +struct kevent { + uintptr_t ident; /* identifier for this event */ + short filter; /* filter for event */ + u_short flags; /* action flags for kqueue */ + u_int fflags; /* filter flag value */ + intptr_t data; /* filter data value */ + void *udata; /* opaque user data identifier */ +}; +.Ed +.Pp +The fields of +.Fa struct kevent +are: +.Bl -tag -width XXXfilter +.It ident +Value used to identify this event. +The exact interpretation is determined by the attached filter, +but often is a file descriptor. +.It filter +Identifies the kernel filter used to process this event. +The pre-defined +system filters are described below. +.It flags +Actions to perform on the event. +.It fflags +Filter-specific flags. +.It data +Filter-specific data value. +.It udata +Opaque user-defined value passed through the kernel unchanged. +.El +.Pp +The +.Va flags +field can contain the following values: +.Bl -tag -width XXXEV_ONESHOT +.It EV_ADD +Adds the event to the kqueue. +Re-adding an existing event +will modify the parameters of the original event, and not result +in a duplicate entry. +Adding an event automatically enables it, +unless overridden by the EV_DISABLE flag. +.It EV_ENABLE +Permit +.Fn kevent +to return the event if it is triggered. +.It EV_DISABLE +Disable the event so +.Fn kevent +will not return it. +The filter itself is not disabled. +.It EV_DISPATCH +Disable the event source immediately after delivery of an event. +See +.Dv EV_DISABLE +above. +.It EV_DELETE +Removes the event from the kqueue. +Events which are attached to +file descriptors are automatically deleted on the last close of +the descriptor. +.It EV_RECEIPT +This flag is useful for making bulk changes to a kqueue without draining +any pending events. +When passed as input, it forces +.Dv EV_ERROR +to always be returned. +When a filter is successfully added the +.Va data +field will be zero. +.It EV_ONESHOT +Causes the event to return only the first occurrence of the filter +being triggered. +After the user retrieves the event from the kqueue, +it is deleted. +.It EV_CLEAR +After the event is retrieved by the user, its state is reset. +This is useful for filters which report state transitions +instead of the current state. +Note that some filters may automatically +set this flag internally. +.It EV_EOF +Filters may set this flag to indicate filter-specific EOF condition. +.It EV_ERROR +See +.Sx RETURN VALUES +below. +.El +.Pp +The predefined system filters are listed below. +Arguments may be passed to and from the filter via the +.Va fflags +and +.Va data +fields in the kevent structure. +.Bl -tag -width EVFILT_SIGNAL +.It EVFILT_READ +Takes a descriptor as the identifier, and returns whenever +there is data available to read. +The behavior of the filter is slightly different depending +on the descriptor type. +.Pp +.Bl -tag -width 2n +.It Sockets +Sockets which have previously been passed to +.Fn listen +return when there is an incoming connection pending. +.Va data +contains the size of the listen backlog. +.Pp +Other socket descriptors return when there is data to be read, +subject to the +.Dv SO_RCVLOWAT +value of the socket buffer. +This may be overridden with a per-filter low water mark at the +time the filter is added by setting the +NOTE_LOWAT +flag in +.Va fflags , +and specifying the new low water mark in +.Va data . +On return, +.Va data +contains the number of bytes of protocol data available to read. +.Pp +If the read direction of the socket has shutdown, then the filter +also sets EV_EOF in +.Va flags , +and returns the socket error (if any) in +.Va fflags . +It is possible for EOF to be returned (indicating the connection is gone) +while there is still data pending in the socket buffer. +.It Vnodes +Returns when the file pointer is not at the end of file. +.Va data +contains the offset from current position to end of file, +and may be negative. +.It "Fifos, Pipes" +Returns when the there is data to read; +.Va data +contains the number of bytes available. +.Pp +When the last writer disconnects, the filter will set EV_EOF in +.Va flags . +This may be cleared by passing in EV_CLEAR, at which point the +filter will resume waiting for data to become available before +returning. +.It "BPF devices" +Returns when the BPF buffer is full, the BPF timeout has expired, or +when the BPF has +.Dq immediate mode +enabled and there is any data to read; +.Va data +contains the number of bytes available. +.El +.It EVFILT_WRITE +Takes a descriptor as the identifier, and returns whenever +it is possible to write to the descriptor. +For sockets, pipes +and fifos, +.Va data +will contain the amount of space remaining in the write buffer. +The filter will set EV_EOF when the reader disconnects, and for +the fifo case, this may be cleared by use of EV_CLEAR. +Note that this filter is not supported for vnodes or BPF devices. +.Pp +For sockets, the low water mark and socket error handling is +identical to the EVFILT_READ case. +.It EVFILT_AIO +The sigevent portion of the AIO request is filled in, with +.Va sigev_notify_kqueue +containing the descriptor of the kqueue that the event should +be attached to, +.Va sigev_value +containing the udata value, and +.Va sigev_notify +set to SIGEV_KEVENT. +When the +.Fn aio_* +system call is made, the event will be registered +with the specified kqueue, and the +.Va ident +argument set to the +.Fa struct aiocb +returned by the +.Fn aio_* +system call. +The filter returns under the same conditions as aio_error. +.It EVFILT_VNODE +Takes a file descriptor as the identifier and the events to watch for in +.Va fflags , +and returns when one or more of the requested events occurs on the descriptor. +The events to monitor are: +.Bl -tag -width XXNOTE_RENAME +.It NOTE_DELETE +The +.Fn unlink +system call +was called on the file referenced by the descriptor. +.It NOTE_WRITE +A write occurred on the file referenced by the descriptor. +.It NOTE_EXTEND +The file referenced by the descriptor was extended. +.It NOTE_ATTRIB +The file referenced by the descriptor had its attributes changed. +.It NOTE_LINK +The link count on the file changed. +.It NOTE_RENAME +The file referenced by the descriptor was renamed. +.It NOTE_REVOKE +Access to the file was revoked via +.Xr revoke 2 +or the underlying file system was unmounted. +.El +.Pp +On return, +.Va fflags +contains the events which triggered the filter. +.It EVFILT_PROC +Takes the process ID to monitor as the identifier and the events to watch for +in +.Va fflags , +and returns when the process performs one or more of the requested events. +If a process can normally see another process, it can attach an event to it. +The events to monitor are: +.Bl -tag -width XXNOTE_TRACKERR +.It NOTE_EXIT +The process has exited. +The exit status will be stored in +.Va data . +.It NOTE_FORK +The process has called +.Fn fork . +.It NOTE_EXEC +The process has executed a new process via +.Xr execve 2 +or similar call. +.It NOTE_TRACK +Follow a process across +.Fn fork +calls. +The parent process will return with NOTE_TRACK set in the +.Va fflags +field, while the child process will return with NOTE_CHILD set in +.Va fflags +and the parent PID in +.Va data . +.It NOTE_TRACKERR +This flag is returned if the system was unable to attach an event to +the child process, usually due to resource limitations. +.El +.Pp +On return, +.Va fflags +contains the events which triggered the filter. +.It EVFILT_SIGNAL +Takes the signal number to monitor as the identifier and returns +when the given signal is delivered to the process. +This coexists with the +.Fn signal +and +.Fn sigaction +facilities, and has a lower precedence. +The filter will record +all attempts to deliver a signal to a process, even if the signal has +been marked as SIG_IGN. +Event notification happens after normal +signal delivery processing. +.Va data +returns the number of times the signal has occurred since the last call to +.Fn kevent . +This filter automatically sets the EV_CLEAR flag internally. +.It EVFILT_TIMER +Establishes an arbitrary timer identified by +.Va ident . +When adding a timer, +.Va data +specifies the timeout period in milliseconds. +The timer will be periodic unless EV_ONESHOT is specified. +On return, +.Va data +contains the number of times the timeout has expired since the last call to +.Fn kevent . +This filter automatically sets the EV_CLEAR flag internally. +There is a system wide limit on the number of timers +which is controlled by the +.Va kern.kq_calloutmax +sysctl. +.It Dv EVFILT_NETDEV +Takes a descriptor to a network interface as the identifier, and the events to watch for in +.Va fflags . +It returns, when one or more of the requested events occur on the descriptor. +The events to monitor are: +.Bl -tag -width XXNOTE_LINKDOWN +.It Dv NOTE_LINKUP +The link is up. +.It Dv NOTE_LINKDOWN +The link is down. +.It Dv NOTE_LINKINV +The link state is invalid. +.El +.Pp +On return, +.Va fflags +contains the events which triggered the filter. +.It Dv EVFILT_USER +Establishes a user event identified by +.Va ident +which is not assosicated with any kernel mechanism but is triggered by +user level code. +The lower 24 bits of the +.Va fflags +may be used for user defined flags and manipulated using the following: +.Bl -tag -width XXNOTE_FFLAGSMASK +.It Dv NOTE_FFNOP +Ignore the input +.Va fflags . +.It Dv NOTE_FFAND +Bitwise AND +.Va fflags . +.It Dv NOTE_FFOR +Bitwise OR +.Va fflags . +.It Dv NOTE_COPY +Copy +.Va fflags . +.It Dv NOTE_FFCTRLMASK +Control mask for +.Va fflags . +.It Dv NOTE_FFLAGSMASK +User defined flag mask for +.Va fflags . +.El +.Pp +A user event is triggered for output with the following: +.Bl -tag -width XXNOTE_FFLAGSMASK +.It Dv NOTE_TRIGGER +Cause the event to be triggered. +.El +.Pp +On return, +.Va fflags +contains the users defined flags in the lower 24 bits. +.El +.Sh RETURN VALUES +The +.Fn kqueue +system call +creates a new kernel event queue and returns a file descriptor. +If there was an error creating the kernel event queue, a value of -1 is +returned and errno set. +.Pp +The +.Fn kevent +system call +returns the number of events placed in the +.Fa eventlist , +up to the value given by +.Fa nevents . +If an error occurs while processing an element of the +.Fa changelist +and there is enough room in the +.Fa eventlist , +then the event will be placed in the +.Fa eventlist +with +.Dv EV_ERROR +set in +.Va flags +and the system error in +.Va data . +Otherwise, +.Dv -1 +will be returned, and +.Dv errno +will be set to indicate the error condition. +If the time limit expires, then +.Fn kevent +returns 0. +.Sh ERRORS +The +.Fn kqueue +system call fails if: +.Bl -tag -width Er +.It Bq Er ENOMEM +The kernel failed to allocate enough memory for the kernel queue. +.It Bq Er EMFILE +The per-process descriptor table is full. +.It Bq Er ENFILE +The system file table is full. +.El +.Pp +The +.Fn kevent +system call fails if: +.Bl -tag -width Er +.It Bq Er EACCES +The process does not have permission to register a filter. +.It Bq Er EFAULT +There was an error reading or writing the +.Va kevent +structure. +.It Bq Er EBADF +The specified descriptor is invalid. +.It Bq Er EINTR +A signal was delivered before the timeout expired and before any +events were placed on the kqueue for return. +.It Bq Er EINVAL +The specified time limit or filter is invalid. +.It Bq Er ENOENT +The event could not be found to be modified or deleted. +.It Bq Er ENOMEM +No memory was available to register the event +or, in the special case of a timer, the maximum number of +timers has been exceeded. +This maximum is configurable via the +.Va kern.kq_calloutmax +sysctl. +.It Bq Er ESRCH +The specified process to attach to does not exist. +.El +.Sh SEE ALSO +.Xr aio_error 2 , +.Xr aio_read 2 , +.Xr aio_return 2 , +.Xr poll 2 , +.Xr read 2 , +.Xr select 2 , +.Xr sigaction 2 , +.Xr write 2 , +.Xr signal 3 +.Sh HISTORY +The +.Fn kqueue +and +.Fn kevent +system calls first appeared in +.Fx 4.1 . +.Sh AUTHORS +The +.Fn kqueue +system and this manual page were written by +.An Jonathan Lemon Aq jlemon@FreeBSD.org . +.Sh BUGS +The +.Dv EVFILT_NETDEV +filter is currently only implemented for devices that use the +.Xr miibus 4 +driver for LINKUP and LINKDOWN operations. +Therefore, it will not work with many non-ethernet devices. +.Pp +The +.Fa timeout +value is limited to 24 hours; longer timeouts will be silently +reinterpreted as 24 hours. diff --git a/vendor/libkqueue/kqueue.c b/vendor/libkqueue/kqueue.c new file mode 100644 index 000000000..242b18b96 --- /dev/null +++ b/vendor/libkqueue/kqueue.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sys/event.h" +#include "private.h" + +static LIST_HEAD(,kqueue) kqlist = LIST_HEAD_INITIALIZER(&kqlist); +static pthread_mutex_t kqlist_mtx = PTHREAD_MUTEX_INITIALIZER; +#define kqlist_lock() pthread_mutex_lock(&kqlist_mtx) +#define kqlist_unlock() pthread_mutex_unlock(&kqlist_mtx) + +struct kqueue * +kqueue_lookup(int kq) +{ + struct kqueue *ent = NULL; + + kqlist_lock(); + LIST_FOREACH(ent, &kqlist, entries) { + if (ent->kq_sockfd[1] == kq) + break; + } + kqlist_unlock(); + + return (ent); +} + +static void +kqueue_shutdown(struct kqueue *kq) +{ + dbg_puts("shutdown invoked\n"); + + kqlist_lock(); + LIST_REMOVE(kq, entries); + kqlist_unlock(); + filter_unregister_all(kq); + free(kq); + pthread_exit(NULL); +} + +static void * +kqueue_close_wait(void *arg) +{ + struct kqueue *kq = (struct kqueue *) arg; + struct pollfd fds[1]; + int n; + + /* Block all signals in this thread */ + sigset_t mask; + sigfillset(&mask); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) { + dbg_printf("sigprocmask: %s", strerror(errno)); + abort(); + } + + /* Watch for the close(2) of the kqueue fd */ + fds[0].fd = kq->kq_sockfd[0]; + fds[0].events = POLLIN; + + /* Almost solves a race condition when close(2) is called immediately + after kqueue(2). Also helps prevent signal races. + */ + kqlist_unlock(); + + for (;;) { + n = poll(&fds[0], 1, -1); + if (n == 0) + continue; /* Should never happen */ + if (n < 0) { + if (errno == EINTR) + continue; + dbg_printf("poll(2): %s", strerror(errno)); + abort(); //FIXME + } + } + dbg_puts("kqueue: fd closed"); + + kqueue_shutdown(kq); + + return (NULL); +} + + +void +kqueue_lock(struct kqueue *kq) +{ + dbg_puts("kqueue_lock()"); + pthread_mutex_lock(&kq->kq_mtx); +} + +void +kqueue_unlock(struct kqueue *kq) +{ + dbg_puts("kqueue_unlock()"); + pthread_mutex_unlock(&kq->kq_mtx); +} + +int +kqueue(void) +{ + struct kqueue *kq; + + kq = calloc(1, sizeof(*kq)); + if (kq == NULL) + return (-1); + pthread_mutex_init(&kq->kq_mtx, NULL); + + if (filter_register_all(kq) < 0) + return (-1); + + if (socketpair(AF_LOCAL, SOCK_STREAM, 0, kq->kq_sockfd) < 0) { + free(kq); + return (-1); + } + + kqlist_lock(); + if (pthread_create(&kq->kq_close_tid, NULL, kqueue_close_wait, kq) != 0) { + close(kq->kq_sockfd[0]); + close(kq->kq_sockfd[1]); + free(kq); + return (-1); + } + + kqlist_lock(); + LIST_INSERT_HEAD(&kqlist, kq, entries); + kqlist_unlock(); + + dbg_printf("created kqueue: fd=%d", kq->kq_sockfd[1]); + return (kq->kq_sockfd[1]); +} diff --git a/vendor/libkqueue/os/linux/signal.c b/vendor/libkqueue/os/linux/signal.c new file mode 100644 index 000000000..bad9052a2 --- /dev/null +++ b/vendor/libkqueue/os/linux/signal.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "sys/event.h" +#include "../../private.h" + +/* Highest signal number supported. POSIX standard signals are < 32 */ +#define SIGNAL_MAX 32 + +int +evfilt_signal_init(struct filter *filt) +{ + sigemptyset(&filt->kf_sigmask); + filt->kf_pfd = signalfd(-1, &filt->kf_sigmask, 0); + dbg_printf("signalfd = %d", filt->kf_pfd); + if (filt->kf_pfd < 0) + return (-1); + + return (0); +} + +void +evfilt_signal_destroy(struct filter *filt) +{ + close (filt->kf_pfd); +} + +int +evfilt_signal_copyin(struct filter *filt, + struct knote *dst, const struct kevent *src) +{ + int rv; + + if (src->ident >= SIGNAL_MAX) { + dbg_printf("unsupported signal number %u", (u_int) src->ident); + return (-1); + } + + if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) { + memcpy(&dst->kev, src, sizeof(*src)); + dst->kev.flags |= EV_CLEAR; + } + if (src->flags & EV_ADD || src->flags & EV_ENABLE) + sigaddset(&filt->kf_sigmask, src->ident); + if (src->flags & EV_DISABLE || src->flags & EV_DELETE) + sigdelset(&filt->kf_sigmask, src->ident); + + rv = signalfd(filt->kf_pfd, &filt->kf_sigmask, 0); + dbg_printf("signalfd = %d", filt->kf_pfd); + if (rv < 0 || rv != filt->kf_pfd) { + dbg_printf("signalfd(2): %s", strerror(errno)); + return (-1); + } + + return (0); +} + +int +evfilt_signal_copyout(struct filter *filt, + struct kevent *dst, + int nevents) +{ + struct knote *kn; + struct signalfd_siginfo sig[MAX_KEVENT]; + int i; + ssize_t n; + + /* NOTE: This will consume the signals so they will not be delivered + * to the process. This differs from kqueue(2) behavior. */ + n = read(filt->kf_pfd, &sig, nevents * sizeof(sig[0])); + if (n < 0 || n < sizeof(sig[0])) { + dbg_puts("invalid read from signalfd"); + return (-1); + } + n /= sizeof(sig[0]); + + for (i = 0, nevents = 0; i < n; i++) { + /* This is not an error because of this race condition: + * 1. Signal arrives and is queued + * 2. The kevent is deleted via kevent(..., EV_DELETE) + * 3. The event is dequeued from the signalfd + */ + kn = knote_lookup(filt, sig[i].ssi_signo); + if (kn == NULL) + continue; + + dbg_printf("got signal %d", sig[i].ssi_signo); + /* TODO: dst->data should be the number of times the signal occurred */ + dst->ident = sig[i].ssi_signo; + dst->filter = EVFILT_SIGNAL; + dst->udata = kn->kev.udata; + dst->flags = 0; + dst->fflags = 0; + dst->data = 1; + dst++; + nevents++; + } + + return (nevents); +} + +const struct filter evfilt_signal = { + EVFILT_SIGNAL, + evfilt_signal_init, + evfilt_signal_destroy, + evfilt_signal_copyin, + evfilt_signal_copyout, +}; diff --git a/vendor/libkqueue/os/linux/socket.c b/vendor/libkqueue/os/linux/socket.c new file mode 100644 index 000000000..a01f94aa0 --- /dev/null +++ b/vendor/libkqueue/os/linux/socket.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "sys/event.h" +#include "private.h" + +int +evfilt_socket_init(struct filter *filt) +{ + filt->kf_pfd = epoll_create(1); + if (filt->kf_pfd < 0) + return (-1); + + dbg_printf("socket epollfd = %d", filt->kf_pfd); + return (0); +} + +void +evfilt_socket_destroy(struct filter *filt) +{ + close(filt->kf_pfd); +} + +int +evfilt_socket_copyin(struct filter *filt, + struct knote *dst, const struct kevent *src) +{ + struct epoll_event ev; + int op, rv; + + /* Determine which operation to perform */ + if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) { + op = EPOLL_CTL_ADD; + memcpy(&dst->kev, src, sizeof(*src)); + } + if (src->flags & EV_DELETE) + op = EPOLL_CTL_DEL; + if (src->flags & EV_ENABLE || src->flags & EV_DISABLE) + op = EPOLL_CTL_MOD; + // FIXME: probably won't work with EV_ADD | EV_DISABLE + + /* Convert the kevent into an epoll_event */ + if (src->filter == EVFILT_READ) + ev.events = EPOLLIN; + else + ev.events = EPOLLOUT; + if (src->flags & EV_ONESHOT) + ev.events |= EPOLLONESHOT; + if (src->flags & EV_CLEAR) + ev.events |= EPOLLET; + ev.data.fd = src->ident; + + if (src->flags & EV_DISABLE) + ev.events = 0; + + dbg_printf("epoll_ctl(2): epfd=%d, op=%d, fd=%d evts=%d", + filt->kf_pfd, op, (int)src->ident, ev.events); + rv = epoll_ctl(filt->kf_pfd, op, src->ident, &ev); + if (rv < 0) { + dbg_printf("epoll_ctl(2): %s", strerror(errno)); + return (-1); + } + + return (0); +} + +int +evfilt_socket_copyout(struct filter *filt, + struct kevent *dst, + int nevents) +{ + struct epoll_event epevt[MAX_KEVENT]; + struct knote *kn; + int i, nret; + + for (;;) { + nret = epoll_wait(filt->kf_pfd, &epevt[0], nevents, 0); + if (nret < 0) { + if (errno == EINTR) + continue; + dbg_perror("epoll_wait"); + return (-1); + } else { + break; + } + } + + for (i = 0, nevents = 0; i < nret; i++) { + kn = knote_lookup(filt, epevt[i].data.fd); + if (kn != NULL) { + dst->ident = kn->kev.ident; + dst->filter = kn->kev.filter; + dst->udata = kn->kev.udata; + + /* FIXME: this is wrong. See the manpage */ + dst->flags = 0; + dst->fflags = 0; + dst->data = 0; + + nevents++; + dst++; + } + } + + return (nevents); +} + +const struct filter evfilt_read = { + EVFILT_READ, + evfilt_socket_init, + evfilt_socket_destroy, + evfilt_socket_copyin, + evfilt_socket_copyout, +}; + +const struct filter evfilt_write = { + EVFILT_WRITE, + evfilt_socket_init, + evfilt_socket_destroy, + evfilt_socket_copyin, + evfilt_socket_copyout, +}; diff --git a/vendor/libkqueue/os/linux/timer.c b/vendor/libkqueue/os/linux/timer.c new file mode 100644 index 000000000..bd28f7100 --- /dev/null +++ b/vendor/libkqueue/os/linux/timer.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Linux equivalents to kqueue(2) */ +#include + +#include "sys/event.h" +#include "../../private.h" + +static void timer_convert(struct itimerspec *dst, int src); + +struct evfilt_data { + int dummy; +}; + +/* + * Determine the smallest interval used by active timers. + */ +static int +update_timeres(struct filter *filt) +{ + struct knote *kn; + struct itimerspec tval; + u_int cur = filt->kf_timeres; + + KNOTELIST_FOREACH(kn, &filt->knl) { + if (kn->kev.data < cur) + cur = kn->kev.data; + } + + if (cur == filt->kf_timeres) + return (0); + + dbg_printf("new timer interval = %d", cur); + filt->kf_timeres = cur; + + /* Convert from miliseconds to seconds+nanoseconds */ + timer_convert(&tval, cur); + if (timerfd_settime(filt->kf_pfd, 0, &tval, NULL) < 0) { + dbg_printf("signalfd(2): %s", strerror(errno)); + return (-1); + } + + return (0); +} + +/* Convert milliseconds into seconds+nanoseconds */ +static void +timer_convert(struct itimerspec *dst, int src) +{ + struct timespec now; + time_t x, y; + + /* Set the interval */ + /* XXX-FIXME: this is probably horribly wrong :) */ + x = src / 1000; + y = (src % 1000) * 1000000; + dst->it_interval.tv_sec = x; + dst->it_interval.tv_nsec = y; + + /* Set the initial expiration */ + clock_gettime(CLOCK_MONOTONIC, &now); + dst->it_value.tv_sec = now.tv_sec + x; + dst->it_value.tv_nsec = now.tv_nsec + 7; +} + +int +evfilt_timer_init(struct filter *filt) +{ + filt->kf_pfd = timerfd_create(CLOCK_MONOTONIC, 0); + if (filt->kf_pfd < 0) + return (-1); + + return (0); +} + +void +evfilt_timer_destroy(struct filter *filt) +{ + close (filt->kf_pfd); +} + +int +evfilt_timer_copyin(struct filter *filt, + struct knote *dst, const struct kevent *src) +{ + if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) { + memcpy(&dst->kev, src, sizeof(*src)); + dst->kev.flags |= EV_CLEAR; + } + if (src->flags & EV_ADD || src->flags & EV_ENABLE) { + if (update_timeres(filt) < 0) + return (-1); + } + if (src->flags & EV_DISABLE || src->flags & EV_DELETE) { + // TODO + } + + return (0); +} + +int +evfilt_timer_copyout(struct filter *filt, + struct kevent *dst, + int nevents) +{ + //struct knote *kn; + uint64_t buf; + int i; + ssize_t n; + + n = read(filt->kf_pfd, &buf, sizeof(buf)); + if (n < 0 || n < sizeof(buf)) { + dbg_puts("invalid read from timerfd"); + return (-1); + } + n = 1; // KLUDGE + + //KNOTELIST_FOREACH(kn, &filt->knl) { + + for (i = 0, nevents = 0; i < n; i++) { +#if FIXME + /* Want to have multiple timers, so maybe multiple timerfds... */ + kn = knote_lookup(filt, sig[i].ssi_signo); + if (kn == NULL) + continue; + + /* TODO: dst->data should be the number of times the signal occurred */ + dst->ident = sig[i].ssi_signo; + dst->filter = EVFILT_SIGNAL; + dst->udata = kn->kev.udata; + dst->flags = 0; + dst->fflags = 0; + dst->data = 1; + dst++; + nevents++; +#endif + } + + return (nevents); +} + +const struct filter evfilt_timer = { + EVFILT_TIMER, + evfilt_timer_init, + evfilt_timer_destroy, + evfilt_timer_copyin, + evfilt_timer_copyout, +}; diff --git a/vendor/libkqueue/os/linux/vnode.c b/vendor/libkqueue/os/linux/vnode.c new file mode 100644 index 000000000..b9fdf6da3 --- /dev/null +++ b/vendor/libkqueue/os/linux/vnode.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "sys/event.h" +#include "private.h" + +#define INEVT_MASK_DUMP(attrib) \ + if (evt->mask & attrib) \ + fputs(#attrib, stdout); + +static void +inotify_event_dump(struct inotify_event *evt) +{ + fputs("[BEGIN: inotify_event dump]\n", stdout); + fprintf(stdout, " wd = %d\n", evt->wd); + fprintf(stdout, " mask = %o (", evt->mask); + INEVT_MASK_DUMP(IN_ACCESS); + INEVT_MASK_DUMP(IN_MODIFY); + INEVT_MASK_DUMP(IN_ATTRIB); + INEVT_MASK_DUMP(IN_CLOSE_WRITE); + INEVT_MASK_DUMP(IN_CLOSE_NOWRITE); + INEVT_MASK_DUMP(IN_OPEN); + INEVT_MASK_DUMP(IN_MOVED_FROM); + INEVT_MASK_DUMP(IN_MOVED_TO); + INEVT_MASK_DUMP(IN_CREATE); + INEVT_MASK_DUMP(IN_DELETE); + INEVT_MASK_DUMP(IN_DELETE_SELF); + INEVT_MASK_DUMP(IN_MOVE_SELF); + fputs(")\n", stdout); + fputs("[END: inotify_event dump]\n", stdout); + fflush(stdout); +} + +static int +fd_to_path(char *buf, size_t bufsz, int fd) +{ + char path[1024]; //TODO: Maxpathlen, etc. + + if (snprintf(&path[0], sizeof(path), "/proc/%d/fd/%d", getpid(), fd) < 0) + return (-1); + + memset(buf, 0, bufsz); + return (readlink(path, buf, bufsz)); +} + + +int +evfilt_vnode_init(struct filter *filt) +{ + filt->kf_pfd = inotify_init(); + dbg_printf("inotify fd = %d", filt->kf_pfd); + if (filt->kf_pfd < 0) + return (-1); + + return (0); +} + +void +evfilt_vnode_destroy(struct filter *filt) +{ + close(filt->kf_pfd); +} + +int +evfilt_vnode_copyin(struct filter *filt, + struct knote *dst, const struct kevent *src) +{ + char path[1024]; //FIXME: maxpathlen + int rv; + uint32_t mask; + + if (src->flags & EV_DELETE) { + dbg_puts("hi"); + if (inotify_rm_watch(filt->kf_pfd, dst->kev.data) < 0) { + dbg_printf("inotify_rm_watch(2): %s", strerror(errno)); + return (-1); + } else { + return (0); + } + } + + if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) { + memcpy(&dst->kev, src, sizeof(*src)); + if (fd_to_path(&path[0], sizeof(path), src->ident) < 0) + return (-1); + + /* Convert the fflags to the inotify mask */ + mask = 0; + + /* FIXME: buggy inotify will not send IN_DELETE events + if the application has the file opened. +See: http://lists.schmorp.de/pipermail/libev/2008q4/000443.html + Need to proccess this case during copyout. + + Actually it seems that IN_DELETE | IN_DELETE_SELF is only + returned when watching directories; when watching + files, IN_ATTRIB seems to be returned only. + */ + if (src->fflags & NOTE_DELETE) + mask |= IN_ATTRIB | IN_DELETE | IN_DELETE_SELF; + + if (src->flags & EV_ONESHOT) + mask |= IN_ONESHOT; +#if FIXME + if (src->flags & EV_CLEAR) + ev.events |= EPOLLET; +#endif + dbg_printf("inotify_add_watch(2); inofd=%d, mask=%d, path=%s", + filt->kf_pfd, mask, path); + rv = inotify_add_watch(filt->kf_pfd, path, mask); + if (rv < 0) { + dbg_printf("inotify_add_watch(2): %s", strerror(errno)); + return (-1); + } else { + dbg_printf("watch descriptor = %d", rv); + dst->kev.data = rv; + return (0); + } + + } + if (src->flags & EV_ENABLE || src->flags & EV_DISABLE) { + abort(); + //FIXME todo + } + + //REFACTOR this + return (0); +} + +int +evfilt_vnode_copyout(struct filter *filt, + struct kevent *dst, + int nevents) +{ + struct inotify_event inevt[MAX_KEVENT]; + struct knote *kn; + struct stat sb; + ssize_t n; + int i; + + dbg_puts("draining inotify events"); + for (;;) { + n = read(filt->kf_pfd, &inevt[0], nevents * sizeof(inevt[0])); + if (n < 0) { + if (errno == EINTR) + continue; + dbg_perror("read"); + return (-1); + } else { + break; + } + } + dbg_printf("read(2) from inotify wd: %zu bytes", n); + + for (i = 0, nevents = 0; i < n; i++) { + if (inevt[i].wd == 0) + break; + inotify_event_dump(&inevt[i]); + /* FIXME: support variable-length structures.. */ + if (inevt[i].len != 0) + abort(); + + kn = knote_lookup_data(filt, inevt[i].wd); + if (kn != NULL) { + kevent_dump(&kn->kev); + dst->ident = kn->kev.ident; + dst->filter = kn->kev.filter; + dst->udata = kn->kev.udata; + + /* FIXME: this is wrong. See the manpage */ + dst->flags = 0; + dst->fflags = 0; + dst->data = 0; + + /* NOTE: unavoidable filesystem race here */ + if (kn->kev.fflags & EV_DELETE) { + if (fstat(kn->kev.ident, &sb) < 0) { + /* TODO: handle signals */ + dbg_puts("woot!"); + dst->fflags = EV_DELETE; + } else { + dbg_printf("link count = %zu", sb.st_nlink); + if (sb.st_nlink == 0) { + dbg_puts("woot! woot!"); + dst->fflags = EV_DELETE; + } else { + /* FIXME: not delete.. maybe ATTRIB event */ + } + } + } + + nevents++; + dst++; + } else { + dbg_printf("no match for wd # %d", inevt[i].wd); + } + } + + return (nevents); +} + +const struct filter evfilt_vnode = { + EVFILT_VNODE, + evfilt_vnode_init, + evfilt_vnode_destroy, + evfilt_vnode_copyin, + evfilt_vnode_copyout, +}; diff --git a/vendor/libkqueue/os/posix/signal.c b/vendor/libkqueue/os/posix/signal.c new file mode 100644 index 000000000..69171298c --- /dev/null +++ b/vendor/libkqueue/os/posix/signal.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sys/event.h" +#include "private.h" + +/* Highest signal number supported. POSIX standard signals are < 32 */ +#define SIGNAL_MAX 32 + +int +evfilt_signal_init(struct filter *filt) +{ + return filter_socketpair(filt); +} + +void +evfilt_signal_destroy(struct filter *filt) +{ + close (filt->kf_pfd); +} + +int +evfilt_signal_copyin(struct filter *filt, + struct knote *dst, const struct kevent *src) +{ + //int rv; + + if (src->ident >= SIGNAL_MAX) { + dbg_printf("unsupported signal number %u", (u_int) src->ident); + return (-1); + } + + if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) { + memcpy(&dst->kev, src, sizeof(*src)); + dst->kev.flags |= EV_CLEAR; + } + if (src->flags & EV_ADD || src->flags & EV_ENABLE) + sigaddset(&filt->kf_sigmask, src->ident); + if (src->flags & EV_DISABLE || src->flags & EV_DELETE) + sigdelset(&filt->kf_sigmask, src->ident); + +#if FIXME + /* TODO */ + rv = signalfd(filt->kf_pfd, &filt->kf_sigmask, 0); + dbg_printf("signalfd = %d", filt->kf_pfd); + if (rv < 0 || rv != filt->kf_pfd) { + dbg_printf("signalfd(2): %s", strerror(errno)); + return (-1); + } +#endif + + return (0); +} + +int +evfilt_signal_copyout(struct filter *filt, + struct kevent *dst, + int nevents) +{ + return (-1); +#if TODO + struct knote *kn; + struct signalfd_siginfo sig[MAX_KEVENT]; + int i; + ssize_t n; + + /* NOTE: This will consume the signals so they will not be delivered + * to the process. This differs from kqueue(2) behavior. */ + n = read(filt->kf_pfd, &sig, nevents * sizeof(sig[0])); + if (n < 0 || n < sizeof(sig[0])) { + dbg_puts("invalid read from signalfd"); + return (-1); + } + n /= sizeof(sig[0]); + + for (i = 0, nevents = 0; i < n; i++) { + /* This is not an error because of this race condition: + * 1. Signal arrives and is queued + * 2. The kevent is deleted via kevent(..., EV_DELETE) + * 3. The event is dequeued from the signalfd + */ + kn = knote_lookup(filt, sig[i].ssi_signo); + if (kn == NULL) + continue; + + dbg_printf("got signal %d", sig[i].ssi_signo); + /* TODO: dst->data should be the number of times the signal occurred */ + dst->ident = sig[i].ssi_signo; + dst->filter = EVFILT_SIGNAL; + dst->udata = kn->kev.udata; + dst->flags = 0; + dst->fflags = 0; + dst->data = 1; + dst++; + nevents++; + } + + return (nevents); +#endif +} + +const struct filter evfilt_signal = { + EVFILT_SIGNAL, + evfilt_signal_init, + evfilt_signal_destroy, + evfilt_signal_copyin, + evfilt_signal_copyout, +}; diff --git a/vendor/libkqueue/os/posix/timer.c b/vendor/libkqueue/os/posix/timer.c new file mode 100644 index 000000000..9385a4742 --- /dev/null +++ b/vendor/libkqueue/os/posix/timer.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sys/event.h" +#include "private.h" + +static void timer_convert(struct itimerspec *dst, int src); + +struct evfilt_data { + int dummy; +}; + +/* + * Determine the smallest interval used by active timers. + */ +static int +update_timeres(struct filter *filt) +{ + struct knote *kn; + struct itimerspec tval; + u_int cur = filt->kf_timeres; + + KNOTELIST_FOREACH(kn, &filt->knl) { + if (kn->kev.data < cur) + cur = kn->kev.data; + } + + if (cur == filt->kf_timeres) + return (0); + + dbg_printf("new timer interval = %d", cur); + filt->kf_timeres = cur; + + /* Convert from miliseconds to seconds+nanoseconds */ + timer_convert(&tval, cur); + //if (timerfd_settime(filt->kf_pfd, 0, &tval, NULL) < 0) { + // dbg_printf("signalfd(2): %s", strerror(errno)); + // return (-1); + // } + + return (0); +} + +/* Convert milliseconds into seconds+nanoseconds */ +static void +timer_convert(struct itimerspec *dst, int src) +{ + struct timespec now; + time_t x, y; + + /* Set the interval */ + /* XXX-FIXME: this is probably horribly wrong :) */ + x = src / 1000; + y = (src % 1000) * 1000000; + dst->it_interval.tv_sec = x; + dst->it_interval.tv_nsec = y; + + /* Set the initial expiration */ + clock_gettime(CLOCK_MONOTONIC, &now); + dst->it_value.tv_sec = now.tv_sec + x; + dst->it_value.tv_nsec = now.tv_nsec + 7; +} + +int +evfilt_timer_init(struct filter *filt) +{ + return filter_socketpair(filt); +} + +void +evfilt_timer_destroy(struct filter *filt) +{ + close (filt->kf_pfd); +} + +int +evfilt_timer_copyin(struct filter *filt, + struct knote *dst, const struct kevent *src) +{ + if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) { + memcpy(&dst->kev, src, sizeof(*src)); + dst->kev.flags |= EV_CLEAR; + } + if (src->flags & EV_ADD || src->flags & EV_ENABLE) { + if (update_timeres(filt) < 0) + return (-1); + } + if (src->flags & EV_DISABLE || src->flags & EV_DELETE) { + // TODO + } + + return (0); +} + +int +evfilt_timer_copyout(struct filter *filt, + struct kevent *dst, + int nevents) +{ + //struct knote *kn; + uint64_t buf; + int i; + ssize_t n; + + n = read(filt->kf_pfd, &buf, sizeof(buf)); + if (n < 0 || n < sizeof(buf)) { + dbg_puts("invalid read from timerfd"); + return (-1); + } + n = 1; // KLUDGE + + //KNOTELIST_FOREACH(kn, &filt->knl) { + + for (i = 0, nevents = 0; i < n; i++) { +#if FIXME + /* Want to have multiple timers, so maybe multiple timerfds... */ + kn = knote_lookup(filt, sig[i].ssi_signo); + if (kn == NULL) + continue; + + /* TODO: dst->data should be the number of times the signal occurred */ + dst->ident = sig[i].ssi_signo; + dst->filter = EVFILT_SIGNAL; + dst->udata = kn->kev.udata; + dst->flags = 0; + dst->fflags = 0; + dst->data = 1; + dst++; + nevents++; +#endif + } + + return (nevents); +} + +const struct filter evfilt_timer = { + EVFILT_TIMER, + evfilt_timer_init, + evfilt_timer_destroy, + evfilt_timer_copyin, + evfilt_timer_copyout, +}; diff --git a/vendor/libkqueue/os/posix/user.c b/vendor/libkqueue/os/posix/user.c new file mode 100644 index 000000000..6a9204381 --- /dev/null +++ b/vendor/libkqueue/os/posix/user.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sys/event.h" +#include "private.h" + +int +evfilt_user_init(struct filter *filt) +{ + return filter_socketpair(filt); +} + +void +evfilt_user_destroy(struct filter *filt) +{ + close(filt->kf_wfd); /* TODO: do this in the parent */ + return; +} + +int +evfilt_user_copyin(struct filter *filt, + struct knote *dst, const struct kevent *src) +{ + /* STUB */ + return (-1); +} + +int +evfilt_user_copyout(struct filter *filt, + struct kevent *dst, + int nevents) +{ + return (0); +} + +const struct filter evfilt_user = { + EVFILT_USER, + evfilt_user_init, + evfilt_user_destroy, + evfilt_user_copyin, + evfilt_user_copyout, +}; diff --git a/vendor/libkqueue/private.h b/vendor/libkqueue/private.h new file mode 100644 index 000000000..e6f9945fc --- /dev/null +++ b/vendor/libkqueue/private.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _KQUEUE_PRIVATE_H +#define _KQUEUE_PRIVATE_H + +#include +#include +#include "sys/event.h" + +/* Maximum events returnable in a single kevent() call */ +#define MAX_KEVENT 512 + +#ifdef KQUEUE_DEBUG +# define dbg_puts(str) fprintf(stderr, "%s\n", str) +# define dbg_printf(fmt,...) fprintf(stderr, fmt"\n", __VA_ARGS__) +# define dbg_perror(str) fprintf(stderr, "%s: %s\n", str, strerror(errno)) +#else +# define dbg_puts(str) ; +# define dbg_printf(fmt,...) ; +# define dbg_perror(str) ; +#endif + +struct kqueue; +struct kevent; +struct evfilt_data; + +struct knote { + struct kevent kev; + LIST_ENTRY(knote) entries; +}; +LIST_HEAD(knotelist, knote); + +/* TODO: This should be a red-black tree or a heap */ +#define KNOTELIST_INIT(knl) LIST_INIT((knl)) +#define KNOTELIST_FOREACH(ent,knl) LIST_FOREACH((ent),(knl), entries) +#define KNOTE_INSERT(knl, ent) LIST_INSERT_HEAD((knl), (ent), entries) +#define KNOTE_EMPTY(ent) ((ent)->kev.filter == 0) + +struct filter { + int kf_id; + int (*kf_init)(struct filter *); + void (*kf_destroy)(struct filter *); + int (*kf_copyin)(struct filter *, + struct knote *, + const struct kevent *); + int (*kf_copyout)(struct filter *, struct kevent *, int); + int kf_pfd; /* fd to poll(2) for readiness */ + int kf_wfd; /* fd to write when an event occurs */ + u_int kf_timeres; /* timer resolution, in miliseconds */ + sigset_t kf_sigmask; + struct evfilt_data *kf_data; /* filter-specific data */ + struct knotelist knl; + struct kqueue *kf_kqueue; +}; + +struct kqueue { + int kq_sockfd[2]; + pthread_t kq_close_tid; + struct filter kq_filt[EVFILT_SYSCOUNT]; + fd_set kq_fds; + int kq_nfds; + pthread_mutex_t kq_mtx; + LIST_ENTRY(kqueue) entries; +}; + +struct knote * knote_lookup(struct filter *, short); +struct knote * knote_lookup_data(struct filter *filt, intptr_t); +struct knote * knote_new(struct filter *); +void knote_free(struct knote *); + +struct filter * filter_lookup(struct kqueue *, short); +int filter_socketpair(struct filter *); +int filter_register_all(struct kqueue *); +void filter_unregister_all(struct kqueue *); +const char *filter_name(short); + +int kevent_init(struct kqueue *); +const char * kevent_dump(struct kevent *); +int kevent_wait(struct kqueue *kq, + struct kevent *kevent, + int nevents, + const struct timespec *timeout); +void kevent_free(struct kqueue *); + +struct kqueue * kqueue_lookup(int kq); +void kqueue_lock(struct kqueue *kq); +void kqueue_unlock(struct kqueue *kq); + +#endif /* ! _KQUEUE_PRIVATE_H */ diff --git a/vendor/libkqueue/sys/event.h b/vendor/libkqueue/sys/event.h new file mode 100644 index 000000000..5de68469e --- /dev/null +++ b/vendor/libkqueue/sys/event.h @@ -0,0 +1,156 @@ +/*- + * Copyright (c) 2009 Mark Heily + * Copyright (c) 1999,2000,2001 Jonathan Lemon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD SVN Revision 197533$ + */ + +#ifndef _SYS_EVENT_H_ +#define _SYS_EVENT_H_ + +#include +#include +#include +#include + +struct timespec; + + +#define EVFILT_READ (-1) +#define EVFILT_WRITE (-2) +#define EVFILT_AIO (-3) /* attached to aio requests */ +#define EVFILT_VNODE (-4) /* attached to vnodes */ +#define EVFILT_PROC (-5) /* attached to struct proc */ +#define EVFILT_SIGNAL (-6) /* attached to struct proc */ +#define EVFILT_TIMER (-7) /* timers */ +#define EVFILT_NETDEV (-8) /* network devices */ +#define EVFILT_FS (-9) /* filesystem events */ +#define EVFILT_LIO (-10) /* attached to lio requests */ +#define EVFILT_USER (-11) /* User events */ +#define EVFILT_SYSCOUNT 11 + +#define EV_SET(kevp_, a, b, c, d, e, f) do { \ + struct kevent *kevp = (kevp_); \ + (kevp)->ident = (a); \ + (kevp)->filter = (b); \ + (kevp)->flags = (c); \ + (kevp)->fflags = (d); \ + (kevp)->data = (e); \ + (kevp)->udata = (f); \ +} while(0) + +struct kevent { + uintptr_t ident; /* identifier for this event */ + short filter; /* filter for event */ + u_short flags; + u_int fflags; + intptr_t data; + void *udata; /* opaque user data identifier */ +}; + +/* actions */ +#define EV_ADD 0x0001 /* add event to kq (implies enable) */ +#define EV_DELETE 0x0002 /* delete event from kq */ +#define EV_ENABLE 0x0004 /* enable event */ +#define EV_DISABLE 0x0008 /* disable event (not reported) */ + +/* flags */ +#define EV_ONESHOT 0x0010 /* only report one occurrence */ +#define EV_CLEAR 0x0020 /* clear event state after reporting */ +#define EV_RECEIPT 0x0040 /* force EV_ERROR on success, data=0 */ +#define EV_DISPATCH 0x0080 /* disable event after reporting */ + +#define EV_SYSFLAGS 0xF000 /* reserved by system */ +#define EV_FLAG1 0x2000 /* filter-specific flag */ + +/* returned values */ +#define EV_EOF 0x8000 /* EOF detected */ +#define EV_ERROR 0x4000 /* error, data contains errno */ + + /* + * data/hint flags/masks for EVFILT_USER + * + * On input, the top two bits of fflags specifies how the lower twenty four + * bits should be applied to the stored value of fflags. + * + * On output, the top two bits will always be set to NOTE_FFNOP and the + * remaining twenty four bits will contain the stored fflags value. + */ +#define NOTE_FFNOP 0x00000000 /* ignore input fflags */ +#define NOTE_FFAND 0x40000000 /* AND fflags */ +#define NOTE_FFOR 0x80000000 /* OR fflags */ +#define NOTE_FFCOPY 0xc0000000 /* copy fflags */ +#define NOTE_FFCTRLMASK 0xc0000000 /* masks for operations */ +#define NOTE_FFLAGSMASK 0x00ffffff + +#define NOTE_TRIGGER 0x01000000 /* Cause the event to be + triggered for output. */ + +/* + * data/hint flags for EVFILT_{READ|WRITE} + */ +#define NOTE_LOWAT 0x0001 /* low water mark */ + +/* + * data/hint flags for EVFILT_VNODE + */ +#define NOTE_DELETE 0x0001 /* vnode was removed */ +#define NOTE_WRITE 0x0002 /* data contents changed */ +#define NOTE_EXTEND 0x0004 /* size increased */ +#define NOTE_ATTRIB 0x0008 /* attributes changed */ +#define NOTE_LINK 0x0010 /* link count changed */ +#define NOTE_RENAME 0x0020 /* vnode was renamed */ +#define NOTE_REVOKE 0x0040 /* vnode access was revoked */ + +/* + * data/hint flags for EVFILT_PROC + */ +#define NOTE_EXIT 0x80000000 /* process exited */ +#define NOTE_FORK 0x40000000 /* process forked */ +#define NOTE_EXEC 0x20000000 /* process exec'd */ +#define NOTE_PCTRLMASK 0xf0000000 /* mask for hint bits */ +#define NOTE_PDATAMASK 0x000fffff /* mask for pid */ + +/* additional flags for EVFILT_PROC */ +#define NOTE_TRACK 0x00000001 /* follow across forks */ +#define NOTE_TRACKERR 0x00000002 /* could not track child */ +#define NOTE_CHILD 0x00000004 /* am a child process */ + +/* + * data/hint flags for EVFILT_NETDEV + */ +#define NOTE_LINKUP 0x0001 /* link is up */ +#define NOTE_LINKDOWN 0x0002 /* link is down */ +#define NOTE_LINKINV 0x0004 /* link state is invalid */ + +__BEGIN_DECLS +int kqueue(void); +int kevent(int kq, const struct kevent *changelist, int nchanges, + struct kevent *eventlist, int nevents, + const struct timespec *timeout); +__END_DECLS + +#endif /* !_SYS_EVENT_H_ */ + diff --git a/vendor/libkqueue/test.c b/vendor/libkqueue/test.c new file mode 100644 index 000000000..88c01751a --- /dev/null +++ b/vendor/libkqueue/test.c @@ -0,0 +1,467 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef UNIT_TEST + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sys/event.h" + +char *cur_test_id = "undef"; +int kqfd; +int sockfd[2]; +int vnode_fd; + +/* In kevent.c */ +const char * kevent_dump(struct kevent *); + +#define KEV_CMP(kev,_ident,_filter,_flags) do { \ + if (kev.ident != (_ident) || \ + kev.filter != (_filter) || \ + kev.flags != (_flags)) \ + err(1, "kevent mismatch: got %s but expecting [%d,%d,%d]", \ + kevent_dump(&kev),\ + (int)kev.ident, kev.filter, kev.flags);\ +} while (0); + +/* Checks if any events are pending, which is an error. */ +void +test_no_kevents(void) +{ + int nfds; + struct timespec timeo; + struct kevent kev; + + puts("confirming that there are no events pending"); + memset(&timeo, 0, sizeof(timeo)); + nfds = kevent(kqfd, NULL, 0, &kev, 1, &timeo); + if (nfds != 0) { + puts(kevent_dump(&kev)); + errx(1, "%d event(s) pending, but none expected:", nfds); + } +} + + +void +test_begin(const char *func) +{ + static int testnum = 1; + cur_test_id = (char *) func; + printf("\n\nTest %d: %s\n", testnum++, func); +} + +void +success(const char *func) +{ + printf("%-70s %s\n", func, "passed"); +} + +void +test_kqueue(void) +{ + test_begin("kqueue()"); + if ((kqfd = kqueue()) < 0) + err(1, "kqueue()"); + test_no_kevents(); + success("kqueue()"); +} + +void +test_kqueue_close(void) +{ + test_begin("close(kq)"); + if (close(kqfd) < 0) + err(1, "close()"); + success("kqueue_close()"); +} + +void +test_kevent_socket_add(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_ADD)"; + struct kevent kev; + + test_begin(test_id); + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_socket_get(void) +{ + const char *test_id = "kevent(EVFILT_READ) wait"; + char buf[1]; + struct kevent kev; + int nfds; + + test_begin(test_id); + + if (write(sockfd[1], ".", 1) < 1) + err(1, "write(2)"); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); + + /* Drain the read buffer, then make sure there are no more events. */ + puts("draining the read buffer"); + if (read(sockfd[0], &buf[0], 1) < 1) + err(1, "read(2)"); + test_no_kevents(); + + success(test_id); +} + +void +test_kevent_socket_disable(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_DISABLE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DISABLE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + puts("filling the read buffer"); + if (write(sockfd[1], ".", 1) < 1) + err(1, "write(2)"); + test_no_kevents(); + + success(test_id); +} + +void +test_kevent_socket_enable(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_ENABLE)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ENABLE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); + + success(test_id); +} + +void +test_kevent_socket_del(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_DELETE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + puts("filling the read buffer"); + if (write(sockfd[1], ".", 1) < 1) + err(1, "write(2)"); + test_no_kevents(); + + success(test_id); +} + +void +test_kevent_signal_add(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, EV_ADD)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_signal_get(void) +{ + const char *test_id = "kevent(get signal)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "test failed: %s, retval %d", test_id, nfds); + if (kev.ident != SIGUSR1 || + kev.filter != EVFILT_SIGNAL || + kev.flags != 0) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + //FIXME: test kev->flags, fflags, data + + success(test_id); +} + +void +test_kevent_signal_disable(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + test_no_kevents(); + + success(test_id); +} + +void +test_kevent_signal_enable(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "test failed: %s, retval %d", test_id, nfds); + if (kev.ident != SIGUSR1 || + kev.filter != EVFILT_SIGNAL || + kev.flags != 0) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + + success(test_id); +} + +void +test_kevent_signal_del(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)"; + struct kevent kev; + + test_begin(test_id); + + /* Delete the kevent */ + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + test_no_kevents(); + success(test_id); +} + +void +test_kevent_vnode_add(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, EV_ADD)"; + const char *testfile = "/tmp/kqueue-test.tmp"; + struct kevent kev; + + test_begin(test_id); + + system("touch /tmp/kqueue-test.tmp"); + vnode_fd = open(testfile, O_RDONLY); + if (vnode_fd < 0) + err(1, "open of %s", testfile); + else + printf("vnode_fd = %d\n", vnode_fd); + + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD, NOTE_DELETE, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + // XXX-causes an event.. + close(vnode_fd); + + success(test_id); +} + +void +test_kevent_vnode_get(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, get)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + if (unlink("/tmp/kqueue-test.tmp") < 0) + err(1, "unlink"); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + if (kev.ident != vnode_fd || + kev.filter != EVFILT_VNODE || + kev.fflags != NOTE_DELETE) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + + success(test_id); +} + +void +test_kevent_vnode_del(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, EV_DELETE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +int +main(int argc, char **argv) +{ + int test_socket = 1; + int test_signal = 0;//XXX-FIXME + int test_vnode = 1; + int test_timer = 1; + + while (argc) { + if (strcmp(argv[0], "--no-socket") == 0) + test_socket = 0; + if (strcmp(argv[0], "--no-timer") == 0) + test_timer = 0; + if (strcmp(argv[0], "--no-signal") == 0) + test_signal = 0; + if (strcmp(argv[0], "--no-vnode") == 0) + test_vnode = 0; + argv++; + argc--; + } + + /* Create a connected pair of full-duplex sockets for testing socket events */ + if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd) < 0) + abort(); + + test_kqueue(); + + if (test_socket) { + test_kevent_socket_add(); + test_kevent_socket_get(); + test_kevent_socket_disable(); + test_kevent_socket_enable(); + test_kevent_socket_del(); + } + + if (test_signal) { + test_kevent_signal_add(); + test_kevent_signal_get(); + test_kevent_signal_disable(); + test_kevent_signal_enable(); + test_kevent_signal_del(); + } + + if (test_vnode) { + test_kevent_vnode_add(); +#if ! FIXME + //broken, hangs on epoll of kq->pfd + test_kevent_vnode_get(); +#endif + test_kevent_vnode_del(); + } + + if (test_timer) { + } + + test_kqueue_close(); + + puts("all tests completed."); + return (0); +} + +#else /* UNIT_TEST */ + +void __kqueue_dummy(void) +{ + /* STUB */ +} + +#endif /* ! UNIT_TEST */ From ca7174550a01caafb5bac4b934c0d3136e63bc25 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 20 Oct 2009 00:41:19 +0000 Subject: [PATCH 0002/1120] basic webpage git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@2 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/www/index.html | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 vendor/libkqueue/www/index.html diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html new file mode 100644 index 000000000..c8cf83262 --- /dev/null +++ b/vendor/libkqueue/www/index.html @@ -0,0 +1,15 @@ + + + + + + + libkqueue + + + +

Download

+svn co svn://mark.heily.com/libkqueue/trunk libkqueue + + From 9397bad27ac112bc8d3cf198907cd1154f07eeed Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 20 Oct 2009 00:46:26 +0000 Subject: [PATCH 0003/1120] remove pselect workaround git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@3 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/kevent.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/vendor/libkqueue/kevent.c b/vendor/libkqueue/kevent.c index eda0dc5e9..bc80e3cbf 100644 --- a/vendor/libkqueue/kevent.c +++ b/vendor/libkqueue/kevent.c @@ -174,21 +174,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, * Wait for one or more filters to have events. */ fds = kq->kq_fds; -#if BROKEN n = pselect(kq->kq_nfds, &fds, NULL , NULL, timeout, NULL); -#else - /* BROKEn, but testing vnode crap */ - struct timeval tv; - struct timeval *tvp = &tv; - if (timeout) { - tv.tv_sec = timeout->tv_sec; - tv.tv_usec = timeout->tv_nsec / 1000; - } else { - dbg_puts("null timeout.."); - tvp = NULL; - } - n = select(kq->kq_nfds, &fds, NULL, NULL, tvp); -#endif if (n < 0) { if (errno == EINTR) { dbg_puts("signal caught"); From 427cd753a46fe589f5ecf7fe976a11475bca7c55 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 20 Oct 2009 02:08:04 +0000 Subject: [PATCH 0004/1120] set kev.data for EVFILT_READ/WRITE git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@4 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 3 +++ vendor/libkqueue/os/linux/socket.c | 14 +++++++++++++- vendor/libkqueue/test.c | 2 ++ vendor/libkqueue/www/index.html | 4 ++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 31c6378fb..c2021992f 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -50,6 +50,9 @@ dist: tar zcvf $(PROGRAM)-`date +%y%m%d_%H%M`.tar.gz $(PROGRAM) rm -rf $(PROGRAM) +publish-www: + rm -rf ~/public_html/libkqueue/ ; cp -R www ~/public_html/libkqueue/ + clean: rm -f a.out *.a *.o *.so $(FILTERS) diff --git a/vendor/libkqueue/os/linux/socket.c b/vendor/libkqueue/os/linux/socket.c index a01f94aa0..3eaaabebd 100644 --- a/vendor/libkqueue/os/linux/socket.c +++ b/vendor/libkqueue/os/linux/socket.c @@ -16,10 +16,12 @@ #include #include +#include #include #include #include #include +#include #include #include #include @@ -122,7 +124,17 @@ evfilt_socket_copyout(struct filter *filt, /* FIXME: this is wrong. See the manpage */ dst->flags = 0; dst->fflags = 0; - dst->data = 0; + + /* On return, data contains the number of bytes of protocol + data available to read. + */ + if (ioctl(dst->ident, + (dst->filter == EVFILT_READ) ? SIOCINQ : SIOCOUTQ, + &dst->data) < 0) { + /* race condition with socket close, so ignore this error */ + dbg_puts("ioctl(2) of socket failed"); + dst->data = 0; + } nevents++; dst++; diff --git a/vendor/libkqueue/test.c b/vendor/libkqueue/test.c index 88c01751a..4e0f03a27 100644 --- a/vendor/libkqueue/test.c +++ b/vendor/libkqueue/test.c @@ -127,6 +127,8 @@ test_kevent_socket_get(void) if (nfds < 1) err(1, "%s", test_id); KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); + if (kev.data != 1) + err(1, "incorrect data value %d", kev.data); // FIXME: make part of KEV_CMP /* Drain the read buffer, then make sure there are no more events. */ puts("draining the read buffer"); diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index c8cf83262..e0c415b50 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -11,5 +11,9 @@

Download

svn co svn://mark.heily.com/libkqueue/trunk libkqueue + +

Status

+The current implementation status is here. + From 5feaf7c2228efd600a1b010956e0d2eb9fd1b023 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 24 Oct 2009 03:01:00 +0000 Subject: [PATCH 0005/1120] port build changes to 2.6 linux git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@5 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/config.h | 4 ++-- vendor/libkqueue/os/linux/signal.c | 2 +- vendor/libkqueue/os/linux/timer.c | 2 +- vendor/libkqueue/test.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/config.h b/vendor/libkqueue/config.h index ad68a925a..8c1008b47 100644 --- a/vendor/libkqueue/config.h +++ b/vendor/libkqueue/config.h @@ -1,5 +1,5 @@ # AUTOMATICALLY GENERATED -- DO NOT EDIT #define HAVE_SYS_EPOLL_H #define HAVE_SYS_INOTIFY_H -#undef HAVE_SYS_SIGNALFD_H -#undef HAVE_SYS_TIMERFD_H +#define HAVE_SYS_SIGNALFD_H +#define HAVE_SYS_TIMERFD_H diff --git a/vendor/libkqueue/os/linux/signal.c b/vendor/libkqueue/os/linux/signal.c index bad9052a2..97a931f81 100644 --- a/vendor/libkqueue/os/linux/signal.c +++ b/vendor/libkqueue/os/linux/signal.c @@ -29,7 +29,7 @@ #include #include "sys/event.h" -#include "../../private.h" +#include "private.h" /* Highest signal number supported. POSIX standard signals are < 32 */ #define SIGNAL_MAX 32 diff --git a/vendor/libkqueue/os/linux/timer.c b/vendor/libkqueue/os/linux/timer.c index bd28f7100..d4cee1839 100644 --- a/vendor/libkqueue/os/linux/timer.c +++ b/vendor/libkqueue/os/linux/timer.c @@ -31,7 +31,7 @@ #include #include "sys/event.h" -#include "../../private.h" +#include "private.h" static void timer_convert(struct itimerspec *dst, int src); diff --git a/vendor/libkqueue/test.c b/vendor/libkqueue/test.c index 4e0f03a27..cc487e820 100644 --- a/vendor/libkqueue/test.c +++ b/vendor/libkqueue/test.c @@ -127,8 +127,8 @@ test_kevent_socket_get(void) if (nfds < 1) err(1, "%s", test_id); KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); - if (kev.data != 1) - err(1, "incorrect data value %d", kev.data); // FIXME: make part of KEV_CMP + if ((int)kev.data != 1) + err(1, "incorrect data value %d", (int) kev.data); // FIXME: make part of KEV_CMP /* Drain the read buffer, then make sure there are no more events. */ puts("draining the read buffer"); From 790796bb2a1a99dda89ccd54becebd98a8a81c84 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 24 Oct 2009 03:01:15 +0000 Subject: [PATCH 0006/1120] remove config.h git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@6 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/config.h | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 vendor/libkqueue/config.h diff --git a/vendor/libkqueue/config.h b/vendor/libkqueue/config.h deleted file mode 100644 index 8c1008b47..000000000 --- a/vendor/libkqueue/config.h +++ /dev/null @@ -1,5 +0,0 @@ -# AUTOMATICALLY GENERATED -- DO NOT EDIT -#define HAVE_SYS_EPOLL_H -#define HAVE_SYS_INOTIFY_H -#define HAVE_SYS_SIGNALFD_H -#define HAVE_SYS_TIMERFD_H From 7b0ed4b8c4a4c5234653a852666815b8252b3902 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 24 Oct 2009 03:01:38 +0000 Subject: [PATCH 0007/1120] new file git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@7 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/www/status.html | 100 +++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 vendor/libkqueue/www/status.html diff --git a/vendor/libkqueue/www/status.html b/vendor/libkqueue/www/status.html new file mode 100644 index 000000000..d8cc114dc --- /dev/null +++ b/vendor/libkqueue/www/status.html @@ -0,0 +1,100 @@ + + + + + + + libkqueue - Implementation status + + + +

Implementation Status

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FilterEV_ADD
+ EV_DELETE
EV_ENABLE
+ EV_DISABLE
EV_DISPATCHEV_ONESHOTEV_CLEAREV_EOF
EVFILT_READ
EVFILT_WRITE
YesYesNoNoNoNo
EVFILT_AIO
No
EVFILT_VNODEYesYesNoNoNoNo
+ +
+                kevent.flags Implementation Status
+
+            ADD DELETE  ENABLE  DISABLE DISPATCH    ONESHOT CLEAR   EOF
+
+VNODE        Y  N       N       N       N           N       N       N
+PROC        NO -- Cannot fully implement on Linux   
+SIGNAL       Y  N       N       N       N           N       N       N
+NETDEV      NO -- Don't know how to implement on Linux
+TIMER        Y  N       N       N       N           N       N       N 
+USER        Totally broken
+
+            kevent.fflags Implementation Status
+
+                        Status
+READ
+    NOTE_LOWAT          No
+    EV_EOF              No
+WRITE
+    NOTE_LOWAT          No
+    EV_EOF              No
+VNODE
+    NOTE_DELETE         No
+    NOTE_WRITE          No
+    NOTE_EXTEND         No
+    NOTE_ATTRIB         No
+    NOTE_LINK           No
+    NOTE_RENAME         No
+    NOTE_REVOKE         N/A 
+USER
+    NOTE_FFNOP         Ignore the input fflags.
+    NOTE_FFAND         Bitwise AND fflags.
+    NOTE_FFOR          Bitwise OR fflags.
+    NOTE_COPY          Copy fflags.
+    NOTE_FFCTRLMASK    Control mask for fflags.
+    NOTE_FFLAGSMASK    User defined flag mask for fflags.
+    NOTE_TRIGGER       Cause the event to be triggered.
+
+            Filter sets kevent.data structure when returning
+EV_RECEIPT  Yes
+kevent.data No
+
+ +-- +Mark Heily + + From 6387ed31f501d55142bcc212b100ce05a999cc5a Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 24 Oct 2009 03:04:01 +0000 Subject: [PATCH 0008/1120] doc up git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@8 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/www/index.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index e0c415b50..acf69c856 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -8,9 +8,11 @@ libkqueue +libkqueue is a portable implementation of the kqueue(2) kernel event notification mechanism. +

Download

-svn co svn://mark.heily.com/libkqueue/trunk libkqueue +svn checkout svn://mark.heily.com/libkqueue

Status

The current implementation status is here. From 89027345f93a13ec91d6772a92610573eb3638d1 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 24 Oct 2009 03:08:45 +0000 Subject: [PATCH 0009/1120] doc up git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@9 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/www/index.html | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index acf69c856..176dbfc8c 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -8,14 +8,19 @@ libkqueue -libkqueue is a portable implementation of the kqueue(2) kernel event notification mechanism. - + +

libkqueue

+ +libkqueue is a portable userspace implementation of the kqueue(2) kernel event notification mechanism. Initial efforts are focused on porting the kqueue API to the Linux 2.6 kernel. +

Download

svn checkout svn://mark.heily.com/libkqueue

Status

The current implementation status is here. +

Contact

+For more information, contact Mark Heily. From 7b0b732853da7fb3814afe736a79a218989a189c Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 24 Oct 2009 03:15:09 +0000 Subject: [PATCH 0010/1120] doc up git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@10 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/www/index.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index 176dbfc8c..d02103124 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -15,6 +15,9 @@

libkqueue

libkqueue is a portable userspace implementation of the kqueue(2) kernel event notification mechanism. Initial efforts are focused on porting the kqueue API to the Linux 2.6 kernel.

Download

+ +To checkout the SVN repository, run the following command: + svn checkout svn://mark.heily.com/libkqueue

Status

From 6828ea4808fb304897b2a294680a8197384798b8 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 24 Oct 2009 03:15:34 +0000 Subject: [PATCH 0011/1120] doc up git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@11 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/www/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index d02103124..fafd3a0bb 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -17,7 +17,7 @@

libkqueue

Download

To checkout the SVN repository, run the following command: - +

svn checkout svn://mark.heily.com/libkqueue

Status

From e35fad4994dd723f7afd0eed633910c1e3adbf76 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 24 Oct 2009 03:27:02 +0000 Subject: [PATCH 0012/1120] doc up git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@12 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/www/status.html | 49 +++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/vendor/libkqueue/www/status.html b/vendor/libkqueue/www/status.html index d8cc114dc..ebbccfccb 100644 --- a/vendor/libkqueue/www/status.html +++ b/vendor/libkqueue/www/status.html @@ -11,6 +11,8 @@

Implementation Status

+

kevent.flags

+ @@ -49,22 +51,47 @@

Implementation Status

-
No No
-
-                kevent.flags Implementation Status
+
+EVFILT_TIMER
+Yes +No +No +No +No +No + + + +EVFILT_PROC
+No - This will be difficult to implement fully + + + +EVFILT_SIGNAL +Yes +Yes +No +No +No +No + - ADD DELETE ENABLE DISABLE DISPATCH ONESHOT CLEAR EOF + +EVFILT_NETDEV
+No - low priority + -VNODE Y N N N N N N N -PROC NO -- Cannot fully implement on Linux -SIGNAL Y N N N N N N N -NETDEV NO -- Don't know how to implement on Linux -TIMER Y N N N N N N N -USER Totally broken + +EVFILT_USER
+No - stub + - kevent.fflags Implementation Status + + +

kevent.fflags

+
                         Status
 READ
     NOTE_LOWAT          No

From 6e5402e9d322746fc887f7740bb0b619d8327d50 Mon Sep 17 00:00:00 2001
From: mheily 
Date: Sat, 24 Oct 2009 04:05:23 +0000
Subject: [PATCH 0013/1120] implement EV_EOF for sockets

git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@13 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7
---
 vendor/libkqueue/os/linux/socket.c | 13 +++++++++----
 vendor/libkqueue/test.c            | 29 +++++++++++++++++++++++++++++
 vendor/libkqueue/www/index.html    |  7 +++++++
 vendor/libkqueue/www/status.html   |  2 +-
 4 files changed, 46 insertions(+), 5 deletions(-)

diff --git a/vendor/libkqueue/os/linux/socket.c b/vendor/libkqueue/os/linux/socket.c
index 3eaaabebd..062663c94 100644
--- a/vendor/libkqueue/os/linux/socket.c
+++ b/vendor/libkqueue/os/linux/socket.c
@@ -67,10 +67,11 @@ evfilt_socket_copyin(struct filter *filt,
     if (src->flags & EV_ENABLE || src->flags & EV_DISABLE) 
         op = EPOLL_CTL_MOD;
     // FIXME: probably won't work with EV_ADD | EV_DISABLE 
+    // XXX-FIXME: need to update dst for delete/modify
 
     /* Convert the kevent into an epoll_event */
     if (src->filter == EVFILT_READ)
-        ev.events = EPOLLIN;
+        ev.events = EPOLLIN | EPOLLRDHUP;
     else
         ev.events = EPOLLOUT;
     if (src->flags & EV_ONESHOT)
@@ -99,6 +100,7 @@ evfilt_socket_copyout(struct filter *filt,
             int nevents)
 {
     struct epoll_event epevt[MAX_KEVENT];
+    struct epoll_event *ev;
     struct knote *kn;
     int i, nret;
 
@@ -115,15 +117,18 @@ evfilt_socket_copyout(struct filter *filt,
     }
 
     for (i = 0, nevents = 0; i < nret; i++) {
-        kn = knote_lookup(filt, epevt[i].data.fd);
+        ev = &epevt[i];
+        kn = knote_lookup(filt, ev->data.fd);
         if (kn != NULL) {
             dst->ident = kn->kev.ident;
             dst->filter = kn->kev.filter;
             dst->udata = kn->kev.udata;
-
-            /* FIXME: this is wrong. See the manpage */
             dst->flags = 0; 
             dst->fflags = 0;
+            if (ev->events & EPOLLRDHUP || ev->events & EPOLLHUP)
+                dst->flags |= EV_EOF;
+            if (ev->events & EPOLLERR)
+                dst->fflags = 1; /* FIXME: Return the actual socket error */
 
             /* On return, data contains the number of bytes of protocol
                data available to read.
diff --git a/vendor/libkqueue/test.c b/vendor/libkqueue/test.c
index cc487e820..569d8d610 100644
--- a/vendor/libkqueue/test.c
+++ b/vendor/libkqueue/test.c
@@ -185,6 +185,7 @@ test_kevent_socket_del(void)
 {
     const char *test_id = "kevent(EVFILT_READ, EV_DELETE)";
     struct kevent kev;
+    char buf[100];
 
     test_begin(test_id);
 
@@ -196,10 +197,37 @@ test_kevent_socket_del(void)
     if (write(sockfd[1], ".", 1) < 1)
         err(1, "write(2)");
     test_no_kevents();
+    if (read(sockfd[0], &buf[0], sizeof(buf)) < 1)
+        err(1, "read(2)");
 
     success(test_id);
 }
 
+void
+test_kevent_socket_eof(void)
+{
+    const char *test_id = "kevent(EVFILT_READ, EV_EOF)";
+    struct kevent kev;
+
+    test_begin(test_id);
+
+    /* Re-add the watch and make sure no events are pending */
+    EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+        err(1, "%s", test_id);
+    test_no_kevents();
+
+    if (close(sockfd[1]) < 0)
+        err(1, "close(2)");
+
+    if (kevent(kqfd, NULL, 0, &kev, 1, NULL) < 1)
+        err(1, "%s", test_id);
+    KEV_CMP(kev, sockfd[0], EVFILT_READ, EV_EOF);
+
+    success(test_id);
+}
+
+
 void
 test_kevent_signal_add(void)
 {
@@ -431,6 +459,7 @@ main(int argc, char **argv)
         test_kevent_socket_disable();
         test_kevent_socket_enable();
         test_kevent_socket_del();
+        test_kevent_socket_eof();
     }
 
     if (test_signal) {
diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html
index fafd3a0bb..9dca408f2 100644
--- a/vendor/libkqueue/www/index.html
+++ b/vendor/libkqueue/www/index.html
@@ -23,7 +23,14 @@ 

Download

Status

The current implementation status is here. +

Links

+ + +

Contact

For more information, contact Mark Heily. + diff --git a/vendor/libkqueue/www/status.html b/vendor/libkqueue/www/status.html index ebbccfccb..8ebd29d4a 100644 --- a/vendor/libkqueue/www/status.html +++ b/vendor/libkqueue/www/status.html @@ -34,7 +34,7 @@

kevent.flags

No No No -No +Yes From 1779ab54939a44b19e0c85dade8375994034296f Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 24 Oct 2009 04:11:52 +0000 Subject: [PATCH 0014/1120] doc up git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@14 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/www/index.html | 5 +++++ vendor/libkqueue/www/status.html | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index 9dca408f2..01fade9d7 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -26,6 +26,11 @@

Status

Links

diff --git a/vendor/libkqueue/www/status.html b/vendor/libkqueue/www/status.html index 8ebd29d4a..da62985a7 100644 --- a/vendor/libkqueue/www/status.html +++ b/vendor/libkqueue/www/status.html @@ -95,10 +95,8 @@

kevent.fflags

Status READ NOTE_LOWAT No - EV_EOF No WRITE NOTE_LOWAT No - EV_EOF No VNODE NOTE_DELETE No NOTE_WRITE No From 53fa2d3947090276c162adc4ec1f6890bf3ef771 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 25 Oct 2009 02:55:29 +0000 Subject: [PATCH 0015/1120] implement EV_ONESHOT and EV_DISPATCH for sockets git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@15 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/os/linux/socket.c | 48 +++++++++++- vendor/libkqueue/test.c | 116 +++++++++++++++++++++++++---- vendor/libkqueue/www/status.html | 4 +- 3 files changed, 147 insertions(+), 21 deletions(-) diff --git a/vendor/libkqueue/os/linux/socket.c b/vendor/libkqueue/os/linux/socket.c index 062663c94..0100a751e 100644 --- a/vendor/libkqueue/os/linux/socket.c +++ b/vendor/libkqueue/os/linux/socket.c @@ -33,6 +33,33 @@ #include "sys/event.h" #include "private.h" + +char * +epoll_event_dump(struct epoll_event *evt) +{ + +#define EPEVT_DUMP(attrib) \ + if (evt->events & attrib) \ + fputs(#attrib" ", stdout); + + fprintf(stdout, " { data = %p, events = ", evt->data.ptr); + EPEVT_DUMP(EPOLLIN); + EPEVT_DUMP(EPOLLOUT); + EPEVT_DUMP(EPOLLRDHUP); + EPEVT_DUMP(EPOLLONESHOT); + EPEVT_DUMP(EPOLLET); + fputs("}\n", stdout); + fflush(stdout); + + return ""; //XXX-BROKEN +} + +static int +socket_knote_delete(int epfd, int fd) +{ + return epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL); +} + int evfilt_socket_init(struct filter *filt) { @@ -74,7 +101,7 @@ evfilt_socket_copyin(struct filter *filt, ev.events = EPOLLIN | EPOLLRDHUP; else ev.events = EPOLLOUT; - if (src->flags & EV_ONESHOT) + if (src->flags & EV_ONESHOT || src->flags & EV_DISPATCH) ev.events |= EPOLLONESHOT; if (src->flags & EV_CLEAR) ev.events |= EPOLLET; @@ -83,8 +110,12 @@ evfilt_socket_copyin(struct filter *filt, if (src->flags & EV_DISABLE) ev.events = 0; - dbg_printf("epoll_ctl(2): epfd=%d, op=%d, fd=%d evts=%d", - filt->kf_pfd, op, (int)src->ident, ev.events); + dbg_printf("epoll_ctl(2): epfd=%d, op=%d, fd=%d event=%s", + filt->kf_pfd, + op, + (int)src->ident, + epoll_event_dump(&ev) + ); rv = epoll_ctl(filt->kf_pfd, op, src->ident, &ev); if (rv < 0) { dbg_printf("epoll_ctl(2): %s", strerror(errno)); @@ -118,6 +149,7 @@ evfilt_socket_copyout(struct filter *filt, for (i = 0, nevents = 0; i < nret; i++) { ev = &epevt[i]; + epoll_event_dump(ev); kn = knote_lookup(filt, ev->data.fd); if (kn != NULL) { dst->ident = kn->kev.ident; @@ -129,7 +161,7 @@ evfilt_socket_copyout(struct filter *filt, dst->flags |= EV_EOF; if (ev->events & EPOLLERR) dst->fflags = 1; /* FIXME: Return the actual socket error */ - + /* On return, data contains the number of bytes of protocol data available to read. */ @@ -141,6 +173,14 @@ evfilt_socket_copyout(struct filter *filt, dst->data = 0; } + if (kn->kev.flags & EV_ONESHOT) { + socket_knote_delete(filt->kf_pfd, kn->kev.ident); + knote_free(kn); + } + if (kn->kev.flags & EV_DISPATCH) { + /* NOOP: EPOLLONESHOT disables, does not delete */ + } + nevents++; dst++; } diff --git a/vendor/libkqueue/test.c b/vendor/libkqueue/test.c index 569d8d610..9e3452324 100644 --- a/vendor/libkqueue/test.c +++ b/vendor/libkqueue/test.c @@ -57,6 +57,7 @@ test_no_kevents(void) memset(&timeo, 0, sizeof(timeo)); nfds = kevent(kqfd, NULL, 0, &kev, 1, &timeo); if (nfds != 0) { + puts("\nUnexpected event:"); puts(kevent_dump(&kev)); errx(1, "%d event(s) pending, but none expected:", nfds); } @@ -96,6 +97,25 @@ test_kqueue_close(void) success("kqueue_close()"); } +static void +kevent_socket_drain(void) +{ + char buf[1]; + + /* Drain the read buffer, then make sure there are no more events. */ + puts("draining the read buffer"); + if (read(sockfd[0], &buf[0], 1) < 1) + err(1, "read(2)"); +} + +static void +kevent_socket_fill(void) +{ + puts("filling the read buffer"); + if (write(sockfd[1], ".", 1) < 1) + err(1, "write(2)"); +} + void test_kevent_socket_add(void) { @@ -114,7 +134,6 @@ void test_kevent_socket_get(void) { const char *test_id = "kevent(EVFILT_READ) wait"; - char buf[1]; struct kevent kev; int nfds; @@ -130,10 +149,7 @@ test_kevent_socket_get(void) if ((int)kev.data != 1) err(1, "incorrect data value %d", (int) kev.data); // FIXME: make part of KEV_CMP - /* Drain the read buffer, then make sure there are no more events. */ - puts("draining the read buffer"); - if (read(sockfd[0], &buf[0], 1) < 1) - err(1, "read(2)"); + kevent_socket_drain(); test_no_kevents(); success(test_id); @@ -151,10 +167,9 @@ test_kevent_socket_disable(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - puts("filling the read buffer"); - if (write(sockfd[1], ".", 1) < 1) - err(1, "write(2)"); + kevent_socket_fill(); test_no_kevents(); + kevent_socket_drain(); success(test_id); } @@ -172,10 +187,12 @@ test_kevent_socket_enable(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); + kevent_socket_fill(); nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); if (nfds < 1) err(1, "%s", test_id); KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); + kevent_socket_drain(); success(test_id); } @@ -185,7 +202,6 @@ test_kevent_socket_del(void) { const char *test_id = "kevent(EVFILT_READ, EV_DELETE)"; struct kevent kev; - char buf[100]; test_begin(test_id); @@ -193,12 +209,76 @@ test_kevent_socket_del(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - puts("filling the read buffer"); - if (write(sockfd[1], ".", 1) < 1) - err(1, "write(2)"); + kevent_socket_fill(); test_no_kevents(); - if (read(sockfd[0], &buf[0], sizeof(buf)) < 1) - err(1, "read(2)"); + kevent_socket_drain(); + + success(test_id); +} + +void +test_kevent_socket_oneshot(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_ONESHOT)"; + struct kevent kev; + + test_begin(test_id); + + /* Re-add the watch and make sure no events are pending */ + puts("-- re-adding knote"); + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + test_no_kevents(); + + puts("-- getting one event"); + kevent_socket_fill(); + if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) + err(1, "%s", test_id); + KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); + + puts("-- checking knote disabled"); + test_no_kevents(); + + /* Try to delete the knote, it should already be deleted */ + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0) + err(1, "%s", test_id); + + kevent_socket_drain(); + + success(test_id); +} + +void +test_kevent_socket_dispatch(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_DISPATCH)"; + struct kevent kev; + + test_begin(test_id); + + /* Re-add the watch and make sure no events are pending */ + puts("-- re-adding knote"); + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + test_no_kevents(); + + /* Since the knote is disabled, there are no events. */ + puts("-- checking if knote is disabled.."); + kevent_socket_fill(); + if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) + err(1, "%s", test_id); + KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); + test_no_kevents(); + + /* Since the knote is disabled, the EV_DELETE operation succeeds. */ + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + kevent_socket_drain(); success(test_id); } @@ -224,10 +304,14 @@ test_kevent_socket_eof(void) err(1, "%s", test_id); KEV_CMP(kev, sockfd[0], EVFILT_READ, EV_EOF); + /* Delete the watch */ + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + success(test_id); } - void test_kevent_signal_add(void) { @@ -459,6 +543,8 @@ main(int argc, char **argv) test_kevent_socket_disable(); test_kevent_socket_enable(); test_kevent_socket_del(); + test_kevent_socket_oneshot(); + test_kevent_socket_dispatch(); test_kevent_socket_eof(); } diff --git a/vendor/libkqueue/www/status.html b/vendor/libkqueue/www/status.html index da62985a7..07efa7c18 100644 --- a/vendor/libkqueue/www/status.html +++ b/vendor/libkqueue/www/status.html @@ -31,8 +31,8 @@

kevent.flags

EVFILT_READ
EVFILT_WRITE
Yes Yes -No -No +Yes +Yes No Yes From c747b5ce5a157b3a262110f7f3ef1f12de4caeae Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 26 Oct 2009 02:10:43 +0000 Subject: [PATCH 0016/1120] attempt to support NOTE_LOWAT ; exposes bug in error handling path git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@16 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/os/linux/socket.c | 26 +++++++++++++++++++++++ vendor/libkqueue/test.c | 33 ++++++++++++++++++++++++++++++ vendor/libkqueue/www/status.html | 6 ++---- 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/os/linux/socket.c b/vendor/libkqueue/os/linux/socket.c index 0100a751e..d8c95b704 100644 --- a/vendor/libkqueue/os/linux/socket.c +++ b/vendor/libkqueue/os/linux/socket.c @@ -110,6 +110,32 @@ evfilt_socket_copyin(struct filter *filt, if (src->flags & EV_DISABLE) ev.events = 0; + /* Set the low water mark */ + /* PORTABILITY - + BSD kqueue(2) NOTE_LOWAT does not modify the underlying + socket. + + It appears that epoll(2) does not respect the SO_RCVLOWAT + setting. + + */ + if (src->fflags & NOTE_LOWAT) { +#if EPOLL_IS_NOT_BROKEN + const socklen_t optlen = sizeof(int); + int sockopt; + + sockopt = src->data; + if (setsockopt(src->ident, SOL_SOCKET, SO_RCVLOWAT, &sockopt, optlen) < 0) { + dbg_printf("setsockopt(2): %s", strerror(errno)); + return (-1); + } + dbg_printf("Low watermark set to %d", sockopt); +#else + errno = ENOTSUP; + return (-1); +#endif + } + dbg_printf("epoll_ctl(2): epfd=%d, op=%d, fd=%d event=%s", filt->kf_pfd, op, diff --git a/vendor/libkqueue/test.c b/vendor/libkqueue/test.c index 9e3452324..90866706a 100644 --- a/vendor/libkqueue/test.c +++ b/vendor/libkqueue/test.c @@ -283,6 +283,38 @@ test_kevent_socket_dispatch(void) success(test_id); } +void +test_kevent_socket_lowat(void) +{ + const char *test_id = "kevent(EVFILT_READ, NOTE_LOWAT)"; + struct kevent kev; + + test_begin(test_id); + + /* Re-add the watch and make sure no events are pending */ + puts("-- re-adding knote, setting low watermark to 2 bytes"); + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + test_no_kevents(); + + puts("-- checking that one byte does not trigger an event.."); + kevent_socket_fill(); + test_no_kevents(); + + puts("-- checking that two bytes triggers an event.."); + kevent_socket_fill(); + if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) + err(1, "%s", test_id); + KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); + test_no_kevents(); + + kevent_socket_drain(); + kevent_socket_drain(); + + success(test_id); +} + void test_kevent_socket_eof(void) { @@ -545,6 +577,7 @@ main(int argc, char **argv) test_kevent_socket_del(); test_kevent_socket_oneshot(); test_kevent_socket_dispatch(); + test_kevent_socket_lowat(); test_kevent_socket_eof(); } diff --git a/vendor/libkqueue/www/status.html b/vendor/libkqueue/www/status.html index 07efa7c18..fce9d0f05 100644 --- a/vendor/libkqueue/www/status.html +++ b/vendor/libkqueue/www/status.html @@ -93,10 +93,8 @@

kevent.fflags

                         Status
-READ
-    NOTE_LOWAT          No
-WRITE
-    NOTE_LOWAT          No
+READ / WRITE
+    NOTE_LOWAT          No -- Not supported by Linux
 VNODE
     NOTE_DELETE         No
     NOTE_WRITE          No

From 67ad3b2f7d2c9d1841932a6a0ecdd3030a7ec309 Mon Sep 17 00:00:00 2001
From: mheily 
Date: Thu, 29 Oct 2009 03:13:40 +0000
Subject: [PATCH 0017/1120] fix double free in copyin. note linux note_lowat
 problem.

git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@17 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7
---
 vendor/libkqueue/kevent.c         |  2 --
 vendor/libkqueue/os/linux/vnode.c |  6 +++++
 vendor/libkqueue/test.c           | 45 +++++++++++++++++++++++++------
 vendor/libkqueue/www/index.html   | 16 +++++++++++
 4 files changed, 59 insertions(+), 10 deletions(-)

diff --git a/vendor/libkqueue/kevent.c b/vendor/libkqueue/kevent.c
index bc80e3cbf..703f47e68 100644
--- a/vendor/libkqueue/kevent.c
+++ b/vendor/libkqueue/kevent.c
@@ -93,8 +93,6 @@ kevent_copyin(struct kqueue *kq, const struct kevent *src, int nchanges,
         }
 
         if (filt->kf_copyin(filt, dst, src) < 0) {
-            if (kn_alloc)
-                knote_free(dst);
             status = -EBADMSG;
             goto err_out;
         }
diff --git a/vendor/libkqueue/os/linux/vnode.c b/vendor/libkqueue/os/linux/vnode.c
index b9fdf6da3..e49dd282b 100644
--- a/vendor/libkqueue/os/linux/vnode.c
+++ b/vendor/libkqueue/os/linux/vnode.c
@@ -128,6 +128,8 @@ See: http://lists.schmorp.de/pipermail/libev/2008q4/000443.html
         */
         if (src->fflags & NOTE_DELETE)
             mask |= IN_ATTRIB | IN_DELETE | IN_DELETE_SELF;
+        if (src->fflags & NOTE_WRITE)
+            mask |= IN_MODIFY;
 
         if (src->flags & EV_ONESHOT)
             mask |= IN_ONESHOT;
@@ -197,6 +199,10 @@ evfilt_vnode_copyout(struct filter *filt,
             dst->filter = kn->kev.filter;
             dst->udata = kn->kev.udata;
 
+            if (inevt[i].events & IN_MODIFY && kn->kev.fflags & EV_WRITE) {
+                dst->flags |= EV_WRITE;
+            }
+
             /* FIXME: this is wrong. See the manpage */
             dst->flags = 0; 
             dst->fflags = 0;
diff --git a/vendor/libkqueue/test.c b/vendor/libkqueue/test.c
index 90866706a..2e2e4ba4d 100644
--- a/vendor/libkqueue/test.c
+++ b/vendor/libkqueue/test.c
@@ -493,7 +493,8 @@ test_kevent_vnode_add(void)
     else
         printf("vnode_fd = %d\n", vnode_fd);
 
-    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD, NOTE_DELETE, 0, &sockfd[0]);
+    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD, 
+            NOTE_WRITE | NOTE_DELETE, 0, &sockfd[0]);
     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
         err(1, "%s", test_id);
 
@@ -504,9 +505,9 @@ test_kevent_vnode_add(void)
 }
 
 void
-test_kevent_vnode_get(void)
+test_kevent_vnode_note_delete(void)
 {
-    const char *test_id = "kevent(EVFILT_VNODE, get)";
+    const char *test_id = "kevent(EVFILT_VNODE, NOTE_DELETE)";
     struct kevent kev;
     int nfds;
 
@@ -527,6 +528,34 @@ test_kevent_vnode_get(void)
     success(test_id);
 }
 
+void
+test_kevent_vnode_note_write(void)
+{
+    const char *test_id = "kevent(EVFILT_VNODE, NOTE_WRITE)";
+    struct kevent kev;
+    int nfds;
+
+    test_begin(test_id);
+
+    //EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD, NOTE_WRITE, 0, &sockfd[0]);
+    //if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
+    //    err(1, "%s", test_id);
+
+    if (system("echo hello >> /tmp/kqueue-test.tmp") < 0)
+        err(1, "system");
+
+    nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
+    if (nfds < 1)
+        err(1, "%s", test_id);
+    if (kev.ident != vnode_fd ||
+            kev.filter != EVFILT_VNODE || 
+            kev.fflags != NOTE_WRITE)
+        err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", 
+                test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
+
+    success(test_id);
+}
+
 void
 test_kevent_vnode_del(void)
 {
@@ -577,7 +606,7 @@ main(int argc, char **argv)
         test_kevent_socket_del();
         test_kevent_socket_oneshot();
         test_kevent_socket_dispatch();
-        test_kevent_socket_lowat();
+        /* TODO: broken on linux: test_kevent_socket_lowat(); */
         test_kevent_socket_eof();
     }
 
@@ -591,10 +620,10 @@ main(int argc, char **argv)
 
     if (test_vnode) {
         test_kevent_vnode_add();
-#if ! FIXME
-        //broken, hangs on epoll of kq->pfd
-        test_kevent_vnode_get();
-#endif
+        /* XXX-FIXME
+           test_kevent_vnode_note_delete();
+         */
+        test_kevent_vnode_note_write();
         test_kevent_vnode_del();
     }
 
diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html
index 01fade9d7..a6548283b 100644
--- a/vendor/libkqueue/www/index.html
+++ b/vendor/libkqueue/www/index.html
@@ -6,6 +6,9 @@
     
 
     libkqueue
+    
 
 
 
@@ -22,6 +25,19 @@ 

Download

Status

The current implementation status is here. +

+There are several compatibility issues to be aware of when using this library under Linux:

+

    + +
  1. The NOTE_LOWAT flag is not supported. According to socket(7),

    +

    +"The select(2) and poll(2) system  calls  currently  do not respect the 
    +SO_RCVLOWAT setting on Linux, and mark a socket readable when even  a  
    +single  byte  of data is available.  A subsequent read from the socket 
    +will block until SO_RCVLOWAT bytes are available."
    +
  2. + +

Links

From fde9c6bc383073af62bccd4abaa286c61ef3526a Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 29 Oct 2009 05:24:53 +0000 Subject: [PATCH 0018/1120] fixed most of evfilt_vnode git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@18 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/kevent.c | 20 +-- vendor/libkqueue/os/linux/vnode.c | 208 +++++++++++++++--------------- vendor/libkqueue/private.h | 10 ++ vendor/libkqueue/test.c | 174 +++++++++++++++++++++++-- vendor/libkqueue/www/index.html | 3 + vendor/libkqueue/www/status.html | 18 +-- 6 files changed, 296 insertions(+), 137 deletions(-) diff --git a/vendor/libkqueue/kevent.c b/vendor/libkqueue/kevent.c index 703f47e68..9bd03baf0 100644 --- a/vendor/libkqueue/kevent.c +++ b/vendor/libkqueue/kevent.c @@ -100,17 +100,12 @@ kevent_copyin(struct kqueue *kq, const struct kevent *src, int nchanges, /* * Update the knote flags based on src->flags. */ - if (src->flags & EV_ENABLE) { - dst->kev.flags |= EV_ENABLE; - dst->kev.flags &= ~EV_DISABLE; - } - if (src->flags & EV_DISABLE) { - dst->kev.flags &= ~EV_ENABLE; - dst->kev.flags |= EV_DISABLE; - } - if (src->flags & EV_DELETE) { + if (src->flags & EV_ENABLE) + KNOTE_ENABLE(dst); + if (src->flags & EV_DISABLE) + KNOTE_DISABLE(dst); + if (src->flags & EV_DELETE) knote_free(dst); - } if (src->flags & EV_RECEIPT) { status = 0; goto err_out; @@ -171,6 +166,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, /* * Wait for one or more filters to have events. */ +wait_for_events: fds = kq->kq_fds; n = pselect(kq->kq_nfds, &fds, NULL , NULL, timeout, NULL); if (n < 0) { @@ -210,5 +206,9 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, } kqueue_unlock(kq); + /* Handle spurious wakeups where no events are generated. */ + if (nret == 0) + goto wait_for_events; + return (nret); } diff --git a/vendor/libkqueue/os/linux/vnode.c b/vendor/libkqueue/os/linux/vnode.c index e49dd282b..bafa16fa6 100644 --- a/vendor/libkqueue/os/linux/vnode.c +++ b/vendor/libkqueue/os/linux/vnode.c @@ -15,6 +15,7 @@ */ #include +#include #include #include #include @@ -73,7 +74,50 @@ fd_to_path(char *buf, size_t bufsz, int fd) return (readlink(path, buf, bufsz)); } - + +/* TODO: USE this to get events with name field */ +int +get_one_event(struct inotify_event *dst, int pfd) +{ + ssize_t n; + + dbg_puts("reading one inotify event"); + for (;;) { + n = read(pfd, dst, sizeof(*dst)); + if (n < 0) { + if (errno == EINTR) + continue; + dbg_perror("read"); + return (-1); + } else { + break; + } + } + dbg_printf("read(2) from inotify wd: %zu bytes", n); + + /* FIXME-TODO: if len > 0, read(len) */ + if (dst->len != 0) + abort(); + + + return (0); +} + +static int +delete_watch(int pfd, struct knote *kn) +{ + if (kn->kev.data < 0) + return (0); + if (inotify_rm_watch(pfd, kn->kev.data) < 0) { + dbg_printf("inotify_rm_watch(2): %s", strerror(errno)); + return (-1); + } + dbg_printf("wd %d removed", (int) kn->kev.data); + kn->kev.data = -1; + + return (0); +} + int evfilt_vnode_init(struct filter *filt) { @@ -95,67 +139,46 @@ int evfilt_vnode_copyin(struct filter *filt, struct knote *dst, const struct kevent *src) { - char path[1024]; //FIXME: maxpathlen - int rv; + char path[PATH_MAX]; uint32_t mask; - if (src->flags & EV_DELETE) { - dbg_puts("hi"); - if (inotify_rm_watch(filt->kf_pfd, dst->kev.data) < 0) { - dbg_printf("inotify_rm_watch(2): %s", strerror(errno)); - return (-1); - } else { - return (0); - } - } + if (src->flags & EV_DELETE || src->flags & EV_DISABLE) + return delete_watch(filt->kf_pfd, dst); if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) { memcpy(&dst->kev, src, sizeof(*src)); + dst->kev.flags |= EV_CLEAR; + dst->kev.data = -1; + } + + if (src->flags & EV_ADD || src->flags & EV_ENABLE) { + + /* Convert the fd to a pathname */ if (fd_to_path(&path[0], sizeof(path), src->ident) < 0) return (-1); /* Convert the fflags to the inotify mask */ mask = 0; - - /* FIXME: buggy inotify will not send IN_DELETE events - if the application has the file opened. -See: http://lists.schmorp.de/pipermail/libev/2008q4/000443.html - Need to proccess this case during copyout. - - Actually it seems that IN_DELETE | IN_DELETE_SELF is only - returned when watching directories; when watching - files, IN_ATTRIB seems to be returned only. - */ - if (src->fflags & NOTE_DELETE) - mask |= IN_ATTRIB | IN_DELETE | IN_DELETE_SELF; - if (src->fflags & NOTE_WRITE) + if (dst->kev.fflags & NOTE_DELETE) + mask |= IN_DELETE_SELF; + if (dst->kev.fflags & NOTE_WRITE) mask |= IN_MODIFY; - - if (src->flags & EV_ONESHOT) + if (dst->kev.fflags & NOTE_ATTRIB) + mask |= IN_ATTRIB; + if (dst->kev.fflags & NOTE_RENAME) + mask |= IN_MOVE_SELF; + if (dst->kev.flags & EV_ONESHOT) mask |= IN_ONESHOT; -#if FIXME - if (src->flags & EV_CLEAR) - ev.events |= EPOLLET; -#endif + dbg_printf("inotify_add_watch(2); inofd=%d, mask=%d, path=%s", filt->kf_pfd, mask, path); - rv = inotify_add_watch(filt->kf_pfd, path, mask); - if (rv < 0) { + dst->kev.data = inotify_add_watch(filt->kf_pfd, path, mask); + if (dst->kev.data < 0) { dbg_printf("inotify_add_watch(2): %s", strerror(errno)); return (-1); - } else { - dbg_printf("watch descriptor = %d", rv); - dst->kev.data = rv; - return (0); } - - } - if (src->flags & EV_ENABLE || src->flags & EV_DISABLE) { - abort(); - //FIXME todo } - //REFACTOR this return (0); } @@ -164,75 +187,48 @@ evfilt_vnode_copyout(struct filter *filt, struct kevent *dst, int nevents) { - struct inotify_event inevt[MAX_KEVENT]; + struct inotify_event evt; struct knote *kn; - struct stat sb; - ssize_t n; - int i; - dbg_puts("draining inotify events"); - for (;;) { - n = read(filt->kf_pfd, &inevt[0], nevents * sizeof(inevt[0])); - if (n < 0) { - if (errno == EINTR) - continue; - dbg_perror("read"); - return (-1); - } else { - break; - } + if (get_one_event(&evt, filt->kf_pfd) < 0) + return (-1); + + inotify_event_dump(&evt); + if (evt.mask & IN_IGNORED) { + /* TODO: possibly return error when fs is unmounted */ + return (0); } - dbg_printf("read(2) from inotify wd: %zu bytes", n); - for (i = 0, nevents = 0; i < n; i++) { - if (inevt[i].wd == 0) - break; - inotify_event_dump(&inevt[i]); - /* FIXME: support variable-length structures.. */ - if (inevt[i].len != 0) - abort(); - - kn = knote_lookup_data(filt, inevt[i].wd); - if (kn != NULL) { - kevent_dump(&kn->kev); - dst->ident = kn->kev.ident; - dst->filter = kn->kev.filter; - dst->udata = kn->kev.udata; - - if (inevt[i].events & IN_MODIFY && kn->kev.fflags & EV_WRITE) { - dst->flags |= EV_WRITE; - } - - /* FIXME: this is wrong. See the manpage */ - dst->flags = 0; - dst->fflags = 0; - dst->data = 0; - - /* NOTE: unavoidable filesystem race here */ - if (kn->kev.fflags & EV_DELETE) { - if (fstat(kn->kev.ident, &sb) < 0) { - /* TODO: handle signals */ - dbg_puts("woot!"); - dst->fflags = EV_DELETE; - } else { - dbg_printf("link count = %zu", sb.st_nlink); - if (sb.st_nlink == 0) { - dbg_puts("woot! woot!"); - dst->fflags = EV_DELETE; - } else { - /* FIXME: not delete.. maybe ATTRIB event */ - } - } - } - - nevents++; - dst++; - } else { - dbg_printf("no match for wd # %d", inevt[i].wd); - } + kn = knote_lookup_data(filt, evt.wd); + if (kn == NULL) { + dbg_printf("no match for wd # %d", evt.wd); + return (-1); } - return (nevents); + kevent_dump(&kn->kev); + dst->ident = kn->kev.ident; + dst->filter = kn->kev.filter; + dst->udata = kn->kev.udata; + dst->flags = 0; + dst->fflags = 0; + + if (evt.mask & IN_MODIFY && kn->kev.fflags & NOTE_WRITE) + dst->fflags |= NOTE_WRITE; + if (evt.mask & IN_ATTRIB && kn->kev.fflags & NOTE_ATTRIB) + dst->fflags |= NOTE_ATTRIB; + if (evt.mask & IN_MOVE_SELF && kn->kev.fflags & NOTE_RENAME) + dst->fflags |= NOTE_RENAME; + if (evt.mask & IN_DELETE_SELF && kn->kev.fflags & NOTE_DELETE) + dst->fflags |= NOTE_DELETE; + + if (kn->kev.flags & EV_DISPATCH) { + delete_watch(filt->kf_pfd, kn); /* TODO: error checking */ + KNOTE_DISABLE(kn); + } + if (kn->kev.flags & EV_ONESHOT) + knote_free(kn); + + return (1); } const struct filter evfilt_vnode = { diff --git a/vendor/libkqueue/private.h b/vendor/libkqueue/private.h index e6f9945fc..97b289e0b 100644 --- a/vendor/libkqueue/private.h +++ b/vendor/libkqueue/private.h @@ -50,6 +50,16 @@ LIST_HEAD(knotelist, knote); #define KNOTE_INSERT(knl, ent) LIST_INSERT_HEAD((knl), (ent), entries) #define KNOTE_EMPTY(ent) ((ent)->kev.filter == 0) +#define KNOTE_ENABLE(ent) do { \ + (ent)->kev.flags |= EV_ENABLE; \ + (ent)->kev.flags &= ~EV_DISABLE; \ +} while (0/*CONSTCOND*/) + +#define KNOTE_DISABLE(ent) do { \ + (ent)->kev.flags &= ~EV_ENABLE; \ + (ent)->kev.flags |= EV_DISABLE; \ +} while (0/*CONSTCOND*/) + struct filter { int kf_id; int (*kf_init)(struct filter *); diff --git a/vendor/libkqueue/test.c b/vendor/libkqueue/test.c index 2e2e4ba4d..dbbe3a38f 100644 --- a/vendor/libkqueue/test.c +++ b/vendor/libkqueue/test.c @@ -494,13 +494,10 @@ test_kevent_vnode_add(void) printf("vnode_fd = %d\n", vnode_fd); EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD, - NOTE_WRITE | NOTE_DELETE, 0, &sockfd[0]); + NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME | NOTE_DELETE, 0, &sockfd[0]); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - // XXX-causes an event.. - close(vnode_fd); - success(test_id); } @@ -513,12 +510,21 @@ test_kevent_vnode_note_delete(void) test_begin(test_id); + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* FIXME: workaround for linux behavior. if the file is open, + the delete event isn't registered; an IN_ATTRIB event is fired + instead. + */ + close(vnode_fd); if (unlink("/tmp/kqueue-test.tmp") < 0) err(1, "unlink"); nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); if (nfds < 1) - err(1, "%s", test_id); + err(1, "%s %d events", test_id, nfds); if (kev.ident != vnode_fd || kev.filter != EVFILT_VNODE || kev.fflags != NOTE_DELETE) @@ -537,9 +543,9 @@ test_kevent_vnode_note_write(void) test_begin(test_id); - //EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD, NOTE_WRITE, 0, &sockfd[0]); - //if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - // err(1, "%s", test_id); + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_WRITE, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); if (system("echo hello >> /tmp/kqueue-test.tmp") < 0) err(1, "system"); @@ -556,6 +562,65 @@ test_kevent_vnode_note_write(void) success(test_id); } +void +test_kevent_vnode_note_attrib(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, NOTE_ATTRIB)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + if (system("touch /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + if (kev.ident != vnode_fd || + kev.filter != EVFILT_VNODE || + kev.fflags != NOTE_ATTRIB) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + + success(test_id); +} + +void +test_kevent_vnode_note_rename(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, NOTE_RENAME)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_RENAME, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + if (system("mv /tmp/kqueue-test.tmp /tmp/kqueue-test2.tmp") < 0) + err(1, "system"); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + if (kev.ident != vnode_fd || + kev.filter != EVFILT_VNODE || + kev.fflags != NOTE_RENAME) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + + if (system("mv /tmp/kqueue-test2.tmp /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + + success(test_id); +} + void test_kevent_vnode_del(void) { @@ -571,6 +636,89 @@ test_kevent_vnode_del(void) success(test_id); } +void +test_kevent_vnode_disable_and_enable(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, EV_DISABLE and EV_ENABLE)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + test_no_kevents(); + + /* Add the watch and immediately disable it */ + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + kev.flags = EV_DISABLE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Confirm that the watch is disabled */ + if (system("touch /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + test_no_kevents(); + + /* Re-enable and check again */ + kev.flags = EV_ENABLE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + if (system("touch /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + if (kev.ident != vnode_fd || + kev.filter != EVFILT_VNODE || + kev.fflags != NOTE_ATTRIB) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + + success(test_id); +} + +void +test_kevent_vnode_dispatch(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, EV_DISPATCH)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + test_no_kevents(); + + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_DISPATCH, NOTE_ATTRIB, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + if (system("touch /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + if (kev.ident != vnode_fd || + kev.filter != EVFILT_VNODE || + kev.fflags != NOTE_ATTRIB) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + + /* Confirm that the watch is disabled automatically */ + puts("-- checking that watch is disabled"); + if (system("touch /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + test_no_kevents(); + + /* Delete the watch */ + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, NOTE_ATTRIB, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "remove watch failed: %s", test_id); + + success(test_id); +} + int main(int argc, char **argv) { @@ -620,11 +768,13 @@ main(int argc, char **argv) if (test_vnode) { test_kevent_vnode_add(); - /* XXX-FIXME - test_kevent_vnode_note_delete(); - */ - test_kevent_vnode_note_write(); test_kevent_vnode_del(); + test_kevent_vnode_disable_and_enable(); + test_kevent_vnode_dispatch(); + test_kevent_vnode_note_write(); + test_kevent_vnode_note_attrib(); + test_kevent_vnode_note_rename(); + test_kevent_vnode_note_delete(); } if (test_timer) { diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index a6548283b..63f1da1c1 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -37,6 +37,9 @@

Status

will block until SO_RCVLOWAT bytes are available."
+
  • The NOTE_DELETE flag is supported; however, the event will not be triggered if the program holds an open file descriptor to the file being monitored. This behavior isn't documented in any manpage; see here for discussion. +
  • +

    Links

    diff --git a/vendor/libkqueue/www/status.html b/vendor/libkqueue/www/status.html index fce9d0f05..e89a87662 100644 --- a/vendor/libkqueue/www/status.html +++ b/vendor/libkqueue/www/status.html @@ -46,10 +46,10 @@

    kevent.flags

    EVFILT_VNODE Yes Yes -No -No -No -No +Yes +Yes +Yes (set internally) +N/A @@ -96,13 +96,13 @@

    kevent.fflags

    READ / WRITE NOTE_LOWAT No -- Not supported by Linux VNODE - NOTE_DELETE No - NOTE_WRITE No + NOTE_DELETE Partial (fd must be closed) + NOTE_WRITE Yes NOTE_EXTEND No - NOTE_ATTRIB No + NOTE_ATTRIB Yes NOTE_LINK No - NOTE_RENAME No - NOTE_REVOKE N/A + NOTE_RENAME Yes + NOTE_REVOKE N/A -- Not available in Linux USER NOTE_FFNOP Ignore the input fflags. NOTE_FFAND Bitwise AND fflags. From 242e3e998dbe8c4367e389c28bcf7dc98f8dbb29 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 29 Oct 2009 05:26:08 +0000 Subject: [PATCH 0019/1120] fix socket disptach git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@19 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/os/linux/socket.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/os/linux/socket.c b/vendor/libkqueue/os/linux/socket.c index d8c95b704..6dcf404e4 100644 --- a/vendor/libkqueue/os/linux/socket.c +++ b/vendor/libkqueue/os/linux/socket.c @@ -199,13 +199,12 @@ evfilt_socket_copyout(struct filter *filt, dst->data = 0; } + if (kn->kev.flags & EV_DISPATCH) + KNOTE_DISABLE(kn); if (kn->kev.flags & EV_ONESHOT) { socket_knote_delete(filt->kf_pfd, kn->kev.ident); knote_free(kn); } - if (kn->kev.flags & EV_DISPATCH) { - /* NOOP: EPOLLONESHOT disables, does not delete */ - } nevents++; dst++; From a92ffef7256ee1cf2b8e8b0d46b9aac88ae05adf Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 29 Oct 2009 05:33:41 +0000 Subject: [PATCH 0020/1120] confirmed good: kevent(EVFILT_READ, EV_CLEAR) git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@20 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test.c | 40 ++++++++++++++++++++++++++++++++ vendor/libkqueue/www/status.html | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/test.c b/vendor/libkqueue/test.c index dbbe3a38f..e8dda6ba2 100644 --- a/vendor/libkqueue/test.c +++ b/vendor/libkqueue/test.c @@ -155,6 +155,45 @@ test_kevent_socket_get(void) success(test_id); } +void +test_kevent_socket_clear(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_CLEAR)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + test_no_kevents(); + + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + kevent_socket_fill(); + kevent_socket_fill(); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); + if ((int)kev.data != 2) + err(1, "incorrect data value %d", (int) kev.data); // FIXME: make part of KEV_CMP + + /* We filled twice, but drain once. Edge-triggered would not generate + additional events. + */ + kevent_socket_drain(); + test_no_kevents(); + + kevent_socket_drain(); + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + void test_kevent_socket_disable(void) { @@ -753,6 +792,7 @@ main(int argc, char **argv) test_kevent_socket_enable(); test_kevent_socket_del(); test_kevent_socket_oneshot(); + test_kevent_socket_clear(); test_kevent_socket_dispatch(); /* TODO: broken on linux: test_kevent_socket_lowat(); */ test_kevent_socket_eof(); diff --git a/vendor/libkqueue/www/status.html b/vendor/libkqueue/www/status.html index e89a87662..c71211296 100644 --- a/vendor/libkqueue/www/status.html +++ b/vendor/libkqueue/www/status.html @@ -33,7 +33,7 @@

    kevent.flags

    Yes Yes Yes -No +Yes Yes From 97876c266a4d5ed2aaa537c0512c60b1e1f104cf Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 30 Oct 2009 01:39:55 +0000 Subject: [PATCH 0021/1120] add oneshot/dispatch to signalfd git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@21 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/os/linux/signal.c | 35 +++++++++++++++++------- vendor/libkqueue/test.c | 43 +++++++++++++++++++++++++++++- vendor/libkqueue/www/status.html | 8 +++--- 3 files changed, 71 insertions(+), 15 deletions(-) diff --git a/vendor/libkqueue/os/linux/signal.c b/vendor/libkqueue/os/linux/signal.c index 97a931f81..f5b217f00 100644 --- a/vendor/libkqueue/os/linux/signal.c +++ b/vendor/libkqueue/os/linux/signal.c @@ -34,6 +34,20 @@ /* Highest signal number supported. POSIX standard signals are < 32 */ #define SIGNAL_MAX 32 +static int +update_sigmask(const struct filter *filt) +{ + int rv; + rv = signalfd(filt->kf_pfd, &filt->kf_sigmask, 0); + dbg_printf("signalfd = %d", filt->kf_pfd); + if (rv < 0 || rv != filt->kf_pfd) { + dbg_printf("signalfd(2): %s", strerror(errno)); + return (-1); + } + + return (0); +} + int evfilt_signal_init(struct filter *filt) { @@ -56,8 +70,6 @@ int evfilt_signal_copyin(struct filter *filt, struct knote *dst, const struct kevent *src) { - int rv; - if (src->ident >= SIGNAL_MAX) { dbg_printf("unsupported signal number %u", (u_int) src->ident); return (-1); @@ -72,14 +84,7 @@ evfilt_signal_copyin(struct filter *filt, if (src->flags & EV_DISABLE || src->flags & EV_DELETE) sigdelset(&filt->kf_sigmask, src->ident); - rv = signalfd(filt->kf_pfd, &filt->kf_sigmask, 0); - dbg_printf("signalfd = %d", filt->kf_pfd); - if (rv < 0 || rv != filt->kf_pfd) { - dbg_printf("signalfd(2): %s", strerror(errno)); - return (-1); - } - - return (0); + return (update_sigmask(filt)); } int @@ -119,6 +124,16 @@ evfilt_signal_copyout(struct filter *filt, dst->flags = 0; dst->fflags = 0; dst->data = 1; + + if (kn->kev.flags & EV_DISPATCH || kn->kev.flags & EV_ONESHOT) { + sigdelset(&filt->kf_sigmask, dst->ident); + update_sigmask(filt); /* TODO: error checking */ + } + if (kn->kev.flags & EV_DISPATCH) + KNOTE_DISABLE(kn); + if (kn->kev.flags & EV_ONESHOT) + knote_free(kn); + dst++; nevents++; } diff --git a/vendor/libkqueue/test.c b/vendor/libkqueue/test.c index e8dda6ba2..717dbefe2 100644 --- a/vendor/libkqueue/test.c +++ b/vendor/libkqueue/test.c @@ -516,6 +516,46 @@ test_kevent_signal_del(void) success(test_id); } +void +test_kevent_signal_oneshot(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "test failed: %s, retval %d", test_id, nfds); + if (kev.ident != SIGUSR1 || + kev.filter != EVFILT_SIGNAL || + kev.flags != 0) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + //FIXME: test kev->flags, fflags, data + + /* Send another one and make sure we get no events */ + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + test_no_kevents(); + + success(test_id); +} + void test_kevent_vnode_add(void) { @@ -762,7 +802,7 @@ int main(int argc, char **argv) { int test_socket = 1; - int test_signal = 0;//XXX-FIXME + int test_signal = 1;//XXX-FIXME int test_vnode = 1; int test_timer = 1; @@ -804,6 +844,7 @@ main(int argc, char **argv) test_kevent_signal_disable(); test_kevent_signal_enable(); test_kevent_signal_del(); + test_kevent_signal_oneshot(); } if (test_vnode) { diff --git a/vendor/libkqueue/www/status.html b/vendor/libkqueue/www/status.html index c71211296..0a99dd977 100644 --- a/vendor/libkqueue/www/status.html +++ b/vendor/libkqueue/www/status.html @@ -71,10 +71,10 @@

    kevent.flags

    EVFILT_SIGNAL Yes Yes -No -No -No -No +Yes +Yes +Yes (set internally) +N/A From 9e5f2596498d44c809343cf84af35c4d386397d1 Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 30 Oct 2009 02:04:40 +0000 Subject: [PATCH 0022/1120] initial attempt at evfilt_user git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@22 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/os/posix/user.c | 33 +++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/os/posix/user.c b/vendor/libkqueue/os/posix/user.c index 6a9204381..ff4e7edb8 100644 --- a/vendor/libkqueue/os/posix/user.c +++ b/vendor/libkqueue/os/posix/user.c @@ -46,7 +46,38 @@ int evfilt_user_copyin(struct filter *filt, struct knote *dst, const struct kevent *src) { - /* STUB */ + u_int ffctrl; + struct kevent *kev; + + if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) { + memcpy(&dst->kev, src, sizeof(*src)); + } + kev = &dst->kev; + + /* Based on sys/kern/kern_event.c in FreeBSD HEAD */ + ffctrl = kev->fflags & NOTE_FFCTRLMASK; + kev->fflags &= NOTE_FFLAGSMASK; + switch (ffctrl) { + case NOTE_FFNOP: + break; + + case NOTE_FFAND: + kev->fflags &= src->fflags; + break; + + case NOTE_FFOR: + kev->fflags |= src->fflags; + break; + + case NOTE_FFCOPY: + kev->fflags = kev->fflags; + break; + + default: + /* XXX Return error? */ + break; + } + return (-1); } From 76d276f902ed74a760763e4df4a64007e6acbf34 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 31 Oct 2009 02:41:47 +0000 Subject: [PATCH 0023/1120] small progress on timers git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@23 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/os/linux/timer.c | 24 ++++++++----- vendor/libkqueue/private.h | 1 + vendor/libkqueue/test.c | 59 +++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 8 deletions(-) diff --git a/vendor/libkqueue/os/linux/timer.c b/vendor/libkqueue/os/linux/timer.c index d4cee1839..31a2eb40f 100644 --- a/vendor/libkqueue/os/linux/timer.c +++ b/vendor/libkqueue/os/linux/timer.c @@ -49,11 +49,19 @@ update_timeres(struct filter *filt) struct itimerspec tval; u_int cur = filt->kf_timeres; + if (KNOTELIST_EMPTY(&filt->knl)) { + abort(); + } + + /* Find the smallest timeout interval */ + //FIXME not optimized KNOTELIST_FOREACH(kn, &filt->knl) { - if (kn->kev.data < cur) + dbg_printf("cur=%d new=%d", cur, (int) kn->kev.data); + if (cur == 0 || kn->kev.data < cur) cur = kn->kev.data; } + dbg_printf("cur=%d res=%d", cur, filt->kf_timeres); if (cur == filt->kf_timeres) return (0); @@ -75,19 +83,19 @@ static void timer_convert(struct itimerspec *dst, int src) { struct timespec now; - time_t x, y; + time_t sec, nsec; /* Set the interval */ /* XXX-FIXME: this is probably horribly wrong :) */ - x = src / 1000; - y = (src % 1000) * 1000000; - dst->it_interval.tv_sec = x; - dst->it_interval.tv_nsec = y; + sec = src / 1000; + nsec = (src % 1000) * 1000000; + dst->it_interval.tv_sec = sec; + dst->it_interval.tv_nsec = nsec; /* Set the initial expiration */ clock_gettime(CLOCK_MONOTONIC, &now); - dst->it_value.tv_sec = now.tv_sec + x; - dst->it_value.tv_nsec = now.tv_nsec + 7; + dst->it_value.tv_sec = now.tv_sec + sec; + dst->it_value.tv_nsec = now.tv_nsec + nsec; } int diff --git a/vendor/libkqueue/private.h b/vendor/libkqueue/private.h index 97b289e0b..9dae605c7 100644 --- a/vendor/libkqueue/private.h +++ b/vendor/libkqueue/private.h @@ -47,6 +47,7 @@ LIST_HEAD(knotelist, knote); /* TODO: This should be a red-black tree or a heap */ #define KNOTELIST_INIT(knl) LIST_INIT((knl)) #define KNOTELIST_FOREACH(ent,knl) LIST_FOREACH((ent),(knl), entries) +#define KNOTELIST_EMPTY(knl) LIST_EMPTY((knl)) #define KNOTE_INSERT(knl, ent) LIST_INSERT_HEAD((knl), (ent), entries) #define KNOTE_EMPTY(ent) ((ent)->kev.filter == 0) diff --git a/vendor/libkqueue/test.c b/vendor/libkqueue/test.c index 717dbefe2..1d3bd7674 100644 --- a/vendor/libkqueue/test.c +++ b/vendor/libkqueue/test.c @@ -798,6 +798,62 @@ test_kevent_vnode_dispatch(void) success(test_id); } +void +test_kevent_timer_add(void) +{ + const char *test_id = "kevent(EVFILT_TIMER, EV_ADD)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_timer_del(void) +{ + const char *test_id = "kevent(EVFILT_TIMER, EV_DELETE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_timer_get(void) +{ + const char *test_id = "kevent(EVFILT_TIMER, get)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + if (kev.ident != 1 || kev.filter != EVFILT_TIMER) + errx(1, "wrong event"); + + EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + int main(int argc, char **argv) { @@ -859,6 +915,9 @@ main(int argc, char **argv) } if (test_timer) { + test_kevent_timer_add(); + test_kevent_timer_del(); + test_kevent_timer_get(); } test_kqueue_close(); From f61971af0705a5cfd1eab212960fff716ceef18c Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 31 Oct 2009 03:18:38 +0000 Subject: [PATCH 0024/1120] signalfd does NOT consume signals that are not blocked git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@24 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/os/linux/signal.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/vendor/libkqueue/os/linux/signal.c b/vendor/libkqueue/os/linux/signal.c index f5b217f00..38e32da7a 100644 --- a/vendor/libkqueue/os/linux/signal.c +++ b/vendor/libkqueue/os/linux/signal.c @@ -97,8 +97,6 @@ evfilt_signal_copyout(struct filter *filt, int i; ssize_t n; - /* NOTE: This will consume the signals so they will not be delivered - * to the process. This differs from kqueue(2) behavior. */ n = read(filt->kf_pfd, &sig, nevents * sizeof(sig[0])); if (n < 0 || n < sizeof(sig[0])) { dbg_puts("invalid read from signalfd"); From c2fb677daa83121634564370b07e41d3f116008c Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 31 Oct 2009 15:11:10 +0000 Subject: [PATCH 0025/1120] remove kqueue-close-wait. build separate threadsafe and non-threadsafe libraries. define LIBKQUEUE. implement and export kqueue_free() git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@25 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 8 +++- vendor/libkqueue/filter.c | 1 - vendor/libkqueue/kevent.c | 1 - vendor/libkqueue/kqueue.c | 81 +++++++++++---------------------- vendor/libkqueue/sys/event.h | 3 ++ vendor/libkqueue/test.c | 1 + vendor/libkqueue/www/index.html | 32 +++++++++++++ 7 files changed, 68 insertions(+), 59 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index c2021992f..087686da8 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -27,11 +27,15 @@ build: gcc $(CFLAGS) -c *.c ar rcs libkqueue.a *.o gcc -shared -Wl,-soname,libkqueue.so -o libkqueue.so *.o + rm *.o + gcc -D_REENTRANT=1 $(CFLAGS) -c *.c + ar rcs libkqueue_r.a *.o + gcc -shared -Wl,-soname,libkqueue_r.so -o libkqueue_r.so *.o install: mkdir -p $(PREFIX)/include/kqueue/sys cp event.h $(PREFIX)/include/kqueue/sys - cp libkqueue.so $(PREFIX)/lib + cp libkqueue.so libkqueue_r.so $(PREFIX)/lib cp kqueue.2 $(PREFIX)/share/man/man2/kqueue.2 ln -s kqueue.2 $(PREFIX)/share/man/man2/kevent.2 @@ -41,7 +45,7 @@ check: ./a.out check-installed: - gcc -g -O0 -Wall -Werror -I$(PREFIX)/kqueue test.c -lkqueue -lpthread -lrt + gcc -g -O0 -Wall -Werror -I$(PREFIX)/kqueue test.c -lkqueue ./a.out dist: diff --git a/vendor/libkqueue/filter.c b/vendor/libkqueue/filter.c index a87942f50..33b716266 100644 --- a/vendor/libkqueue/filter.c +++ b/vendor/libkqueue/filter.c @@ -16,7 +16,6 @@ #include #include -#include #include #include #include diff --git a/vendor/libkqueue/kevent.c b/vendor/libkqueue/kevent.c index 9bd03baf0..bdefe5875 100644 --- a/vendor/libkqueue/kevent.c +++ b/vendor/libkqueue/kevent.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/vendor/libkqueue/kqueue.c b/vendor/libkqueue/kqueue.c index 242b18b96..adcbedeae 100644 --- a/vendor/libkqueue/kqueue.c +++ b/vendor/libkqueue/kqueue.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -31,9 +30,16 @@ #include "private.h" static LIST_HEAD(,kqueue) kqlist = LIST_HEAD_INITIALIZER(&kqlist); + +#if _REENTRANT +# include +# define kqlist_lock() pthread_mutex_lock(&kqlist_mtx) +# define kqlist_unlock() pthread_mutex_unlock(&kqlist_mtx) static pthread_mutex_t kqlist_mtx = PTHREAD_MUTEX_INITIALIZER; -#define kqlist_lock() pthread_mutex_lock(&kqlist_mtx) -#define kqlist_unlock() pthread_mutex_unlock(&kqlist_mtx) +#else +# define kqlist_lock() /**/ +# define kqlist_unlock() /**/ +#endif struct kqueue * kqueue_lookup(int kq) @@ -60,64 +66,24 @@ kqueue_shutdown(struct kqueue *kq) kqlist_unlock(); filter_unregister_all(kq); free(kq); - pthread_exit(NULL); -} - -static void * -kqueue_close_wait(void *arg) -{ - struct kqueue *kq = (struct kqueue *) arg; - struct pollfd fds[1]; - int n; - - /* Block all signals in this thread */ - sigset_t mask; - sigfillset(&mask); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) { - dbg_printf("sigprocmask: %s", strerror(errno)); - abort(); - } - - /* Watch for the close(2) of the kqueue fd */ - fds[0].fd = kq->kq_sockfd[0]; - fds[0].events = POLLIN; - - /* Almost solves a race condition when close(2) is called immediately - after kqueue(2). Also helps prevent signal races. - */ - kqlist_unlock(); - - for (;;) { - n = poll(&fds[0], 1, -1); - if (n == 0) - continue; /* Should never happen */ - if (n < 0) { - if (errno == EINTR) - continue; - dbg_printf("poll(2): %s", strerror(errno)); - abort(); //FIXME - } - } - dbg_puts("kqueue: fd closed"); - - kqueue_shutdown(kq); - - return (NULL); } - void kqueue_lock(struct kqueue *kq) { +#if _REENTRANT dbg_puts("kqueue_lock()"); pthread_mutex_lock(&kq->kq_mtx); +#endif } void kqueue_unlock(struct kqueue *kq) { +#if _REENTRANT dbg_puts("kqueue_unlock()"); pthread_mutex_unlock(&kq->kq_mtx); +#endif } int @@ -128,7 +94,9 @@ kqueue(void) kq = calloc(1, sizeof(*kq)); if (kq == NULL) return (-1); +#if _REENTRANT pthread_mutex_init(&kq->kq_mtx, NULL); +#endif if (filter_register_all(kq) < 0) return (-1); @@ -138,14 +106,6 @@ kqueue(void) return (-1); } - kqlist_lock(); - if (pthread_create(&kq->kq_close_tid, NULL, kqueue_close_wait, kq) != 0) { - close(kq->kq_sockfd[0]); - close(kq->kq_sockfd[1]); - free(kq); - return (-1); - } - kqlist_lock(); LIST_INSERT_HEAD(&kqlist, kq, entries); kqlist_unlock(); @@ -153,3 +113,14 @@ kqueue(void) dbg_printf("created kqueue: fd=%d", kq->kq_sockfd[1]); return (kq->kq_sockfd[1]); } + +void +kqueue_free(int kqfd) +{ + struct kqueue *kq; + + if ((kq = kqueue_lookup(kqfd)) == NULL) + return; + + kqueue_shutdown(kq); +} diff --git a/vendor/libkqueue/sys/event.h b/vendor/libkqueue/sys/event.h index 5de68469e..1e16f64a5 100644 --- a/vendor/libkqueue/sys/event.h +++ b/vendor/libkqueue/sys/event.h @@ -37,6 +37,8 @@ struct timespec; +/* Library version number */ +#define LIBKQUEUE 20091030 #define EVFILT_READ (-1) #define EVFILT_WRITE (-2) @@ -147,6 +149,7 @@ struct kevent { __BEGIN_DECLS int kqueue(void); +void kqueue_free(int); int kevent(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); diff --git a/vendor/libkqueue/test.c b/vendor/libkqueue/test.c index 1d3bd7674..bc6687c65 100644 --- a/vendor/libkqueue/test.c +++ b/vendor/libkqueue/test.c @@ -94,6 +94,7 @@ test_kqueue_close(void) test_begin("close(kq)"); if (close(kqfd) < 0) err(1, "close()"); + kqueue_free(kqfd); success("kqueue_close()"); } diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index 63f1da1c1..73168e7b8 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -42,6 +42,38 @@

    Status

    +

    Usage

    + +Assuming that libkqueue is installed under /usr/include: + +
      +
    1. Add -I/usr/lib/kqueue to the CFLAGS variable. +
    2. Add #include <sys/event.h> to the source code. +
    3. Link against the libkqueue library by appending -lkqueue for single-threaded programs, or -lkqueue_r for multi-threaded programs. +
    + +One major difference between libkqueue and the real kqueue is that +closing the kqueue descriptor will not free any of the resources +associated with the descriptor. The following example shows how to +close the descriptor and free the resources: +

    +

    +    int kqfd;
    +
    +    kqfd = kqueue();
    +
    +    /* ... */
    +
    +    close(kqfd);
    +    #if LIBKQUEUE
    +    kqueue_free(kqfd);
    +    #endif
    +
    + +If your program accesses an event queue from multiple threads, +you should link against the threadsafe version of the library (libkqueue_r). +This will provide reentrant versions of kqueue() and kevent(). +

    Links

      From 4684b5f410b6c0d715c877317c281053a237435d Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 31 Oct 2009 15:12:57 +0000 Subject: [PATCH 0026/1120] exclude test.o from the library git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@26 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 087686da8..384f112f3 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -25,10 +25,12 @@ include config.mk build: gcc $(CFLAGS) -c *.c + rm test.o ar rcs libkqueue.a *.o gcc -shared -Wl,-soname,libkqueue.so -o libkqueue.so *.o rm *.o gcc -D_REENTRANT=1 $(CFLAGS) -c *.c + rm test.o ar rcs libkqueue_r.a *.o gcc -shared -Wl,-soname,libkqueue_r.so -o libkqueue_r.so *.o @@ -41,7 +43,7 @@ install: check: make build CFLAGS="$(CFLAGS) -g -O0 -DKQUEUE_DEBUG -DUNIT_TEST" - gcc -g -O0 $(CFLAGS) test.c libkqueue.a -lpthread -lrt + gcc -g -O0 $(CFLAGS) test.c libkqueue.a ./a.out check-installed: From 2b606101fa0a23bb39dc1ad3dc8b9719617e81e0 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 31 Oct 2009 15:27:39 +0000 Subject: [PATCH 0027/1120] document requirements git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@27 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/www/index.html | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index 73168e7b8..d4547571b 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -42,6 +42,16 @@

      Status

      +

      Requirements

      + +libkqueue currently requires the following: + +
        +
      • GCC +
      • Linux 2.6.22 or higher +
      • glibc 2.8 or higher +
      +

      Usage

      Assuming that libkqueue is installed under /usr/include: From d8bb7351f1a61da046e50b5b01bd65c0debd26e0 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 31 Oct 2009 15:28:24 +0000 Subject: [PATCH 0028/1120] fix make clean target git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@28 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 384f112f3..7612167df 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -60,7 +60,7 @@ publish-www: rm -rf ~/public_html/libkqueue/ ; cp -R www ~/public_html/libkqueue/ clean: - rm -f a.out *.a *.o *.so $(FILTERS) + rm -f a.out *.a *.o *.so distclean: clean - rm -f *.tar.gz config.mk + rm -f *.tar.gz config.mk $(FILTERS) From d6bb8eb611865294ecb969a4b548568bd3016cd0 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 31 Oct 2009 15:49:44 +0000 Subject: [PATCH 0029/1120] undef unsupported notes. document unsupported ntoes. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@29 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/sys/event.h | 4 ++++ vendor/libkqueue/www/index.html | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/sys/event.h b/vendor/libkqueue/sys/event.h index 1e16f64a5..5792059cc 100644 --- a/vendor/libkqueue/sys/event.h +++ b/vendor/libkqueue/sys/event.h @@ -114,6 +114,7 @@ struct kevent { * data/hint flags for EVFILT_{READ|WRITE} */ #define NOTE_LOWAT 0x0001 /* low water mark */ +#undef NOTE_LOWAT /* Not supported on Linux */ /* * data/hint flags for EVFILT_VNODE @@ -121,10 +122,13 @@ struct kevent { #define NOTE_DELETE 0x0001 /* vnode was removed */ #define NOTE_WRITE 0x0002 /* data contents changed */ #define NOTE_EXTEND 0x0004 /* size increased */ +#undef NOTE_EXTEND /* Not supported on Linux */ #define NOTE_ATTRIB 0x0008 /* attributes changed */ #define NOTE_LINK 0x0010 /* link count changed */ +#undef NOTE_LINK /* Not supported on Linux */ #define NOTE_RENAME 0x0020 /* vnode was renamed */ #define NOTE_REVOKE 0x0040 /* vnode access was revoked */ +#undef NOTE_REVOKE /* Not supported on Linux */ /* * data/hint flags for EVFILT_PROC diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index d4547571b..576827ee6 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -37,7 +37,20 @@

      Status

      will block until SO_RCVLOWAT bytes are available."
    -
  • The NOTE_DELETE flag is supported; however, the event will not be triggered if the program holds an open file descriptor to the file being monitored. This behavior isn't documented in any manpage; see here for discussion. +
  • +The NOTE_REVOKE flag is not supported because Linux does not have +a revoke(2) system call. +
  • + +
  • +The NOTE_EXTEND flag for the EVFILT_VNODE filter is not supported. An alternative approach is to use a combination of stat(2) and NOTE_ATTRIB to keep track of changes to the file's st_size field. +
  • + +
  • +The NOTE_LINK flag for the EVFILT_VNODE filter is not supported. An alternative approach is to use a combination of stat(2) and NOTE_ATTRIB to keep track of changes to the file's st_nlink field. +
  • + +
  • The NOTE_DELETE flag is supported; however, the event will not be triggered if the program holds an open file descriptor to the file being monitored. This behavior isn't documented in any Linux manpage; see here for discussion. A workaround would be to close the file descriptor after setting the NOTE_DELETE watch.
  • From 81da83cfb8c72661a5805e326767b39c6db68683 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 1 Nov 2009 17:48:45 +0000 Subject: [PATCH 0030/1120] undo reentrant library creation. add uninstall target. add pkg-config data. disable lowat test. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@30 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 22 ++++++++++++++-------- vendor/libkqueue/libkqueue.pc | 13 +++++++++++++ vendor/libkqueue/os/linux/socket.c | 7 ++----- vendor/libkqueue/test.c | 13 ++----------- vendor/libkqueue/www/index.html | 8 +++----- 5 files changed, 34 insertions(+), 29 deletions(-) create mode 100644 vendor/libkqueue/libkqueue.pc diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 7612167df..bc365a5ba 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -18,7 +18,7 @@ INSTALL=/usr/bin/install PREFIX=/usr DISTFILES=*.c *.h kqueue.2 README Makefile configure os sys SOURCES=src/$(UNAME)/*.c -CFLAGS=-fPIC -I. -Wall -Werror -fvisibility=hidden +CFLAGS=-fPIC -D_REENTRANT -I. -Wall -Werror -fvisibility=hidden FILTERS=vnode.c timer.c signal.c socket.c user.c include config.mk @@ -28,22 +28,28 @@ build: rm test.o ar rcs libkqueue.a *.o gcc -shared -Wl,-soname,libkqueue.so -o libkqueue.so *.o - rm *.o - gcc -D_REENTRANT=1 $(CFLAGS) -c *.c - rm test.o - ar rcs libkqueue_r.a *.o - gcc -shared -Wl,-soname,libkqueue_r.so -o libkqueue_r.so *.o install: mkdir -p $(PREFIX)/include/kqueue/sys cp event.h $(PREFIX)/include/kqueue/sys - cp libkqueue.so libkqueue_r.so $(PREFIX)/lib + cp libkqueue.so $(PREFIX)/lib + cp libkqueue.pc $(PREFIX)/lib/pkgconfig cp kqueue.2 $(PREFIX)/share/man/man2/kqueue.2 ln -s kqueue.2 $(PREFIX)/share/man/man2/kevent.2 +uninstall: + rm $(PREFIX)/include/kqueue/sys/event.h + rmdir $(PREFIX)/include/kqueue/sys + rmdir $(PREFIX)/include/kqueue + rm $(PREFIX)/lib/libkqueue.so + rm $(PREFIX)/lib/pkgconfig/libkqueue.pc + rm $(PREFIX)/share/man/man2/kqueue.2 + rm $(PREFIX)/share/man/man2/kevent.2 + check: make build CFLAGS="$(CFLAGS) -g -O0 -DKQUEUE_DEBUG -DUNIT_TEST" - gcc -g -O0 $(CFLAGS) test.c libkqueue.a + gcc -c $(CFLAGS) test.c + gcc -g -O0 $(CFLAGS) test.c libkqueue.a -lpthread -lrt ./a.out check-installed: diff --git a/vendor/libkqueue/libkqueue.pc b/vendor/libkqueue/libkqueue.pc new file mode 100644 index 000000000..2ee7cda4a --- /dev/null +++ b/vendor/libkqueue/libkqueue.pc @@ -0,0 +1,13 @@ +prefix=/usr +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libkqueue +Description: Emulates FreeBSD kqueue(2) on other platforms +Version: 0.1g +Requires: +Libs: -L${libdir} -lkqueue +Libs.private: -lpthread -lrt +Cflags: -I${includedir} + diff --git a/vendor/libkqueue/os/linux/socket.c b/vendor/libkqueue/os/linux/socket.c index 6dcf404e4..71da32d9c 100644 --- a/vendor/libkqueue/os/linux/socket.c +++ b/vendor/libkqueue/os/linux/socket.c @@ -119,8 +119,8 @@ evfilt_socket_copyin(struct filter *filt, setting. */ +#if LINUX_SUPPORTS_SO_RCVLOWAT if (src->fflags & NOTE_LOWAT) { -#if EPOLL_IS_NOT_BROKEN const socklen_t optlen = sizeof(int); int sockopt; @@ -130,11 +130,8 @@ evfilt_socket_copyin(struct filter *filt, return (-1); } dbg_printf("Low watermark set to %d", sockopt); -#else - errno = ENOTSUP; - return (-1); -#endif } +#endif dbg_printf("epoll_ctl(2): epfd=%d, op=%d, fd=%d event=%s", filt->kf_pfd, diff --git a/vendor/libkqueue/test.c b/vendor/libkqueue/test.c index bc6687c65..c4112079d 100644 --- a/vendor/libkqueue/test.c +++ b/vendor/libkqueue/test.c @@ -14,8 +14,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifdef UNIT_TEST - #include #include #include @@ -323,6 +321,7 @@ test_kevent_socket_dispatch(void) success(test_id); } +#if BROKEN void test_kevent_socket_lowat(void) { @@ -354,6 +353,7 @@ test_kevent_socket_lowat(void) success(test_id); } +#endif void test_kevent_socket_eof(void) @@ -926,12 +926,3 @@ main(int argc, char **argv) puts("all tests completed."); return (0); } - -#else /* UNIT_TEST */ - -void __kqueue_dummy(void) -{ - /* STUB */ -} - -#endif /* ! UNIT_TEST */ diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index 576827ee6..40efe1403 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -67,12 +67,14 @@

    Requirements

    Usage

    +libkqueue is a multi-threaded library and kqueue() and kevent() are safe to be used from multiple threads. + Assuming that libkqueue is installed under /usr/include:
    1. Add -I/usr/lib/kqueue to the CFLAGS variable.
    2. Add #include <sys/event.h> to the source code. -
    3. Link against the libkqueue library by appending -lkqueue for single-threaded programs, or -lkqueue_r for multi-threaded programs. +
    4. Link against the libkqueue library by adding -lkqueue to the LDADD variable.
    One major difference between libkqueue and the real kqueue is that @@ -93,10 +95,6 @@

    Usage

    #endif
    -If your program accesses an event queue from multiple threads, -you should link against the threadsafe version of the library (libkqueue_r). -This will provide reentrant versions of kqueue() and kevent(). -

    Links

      From 18bf0a37e9e81e134caa4b2455208c44ded146cb Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 1 Nov 2009 19:06:43 +0000 Subject: [PATCH 0031/1120] improved build system. relocatable prefix. document pkg-config. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@31 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 28 +++---- vendor/libkqueue/configure | 75 ++++++++++++++++--- .../{libkqueue.pc => libkqueue.pc.in} | 12 +-- vendor/libkqueue/www/index.html | 7 +- 4 files changed, 88 insertions(+), 34 deletions(-) rename vendor/libkqueue/{libkqueue.pc => libkqueue.pc.in} (53%) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index bc365a5ba..1203adbcc 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -15,7 +15,6 @@ # PROGRAM=libkqueue INSTALL=/usr/bin/install -PREFIX=/usr DISTFILES=*.c *.h kqueue.2 README Makefile configure os sys SOURCES=src/$(UNAME)/*.c CFLAGS=-fPIC -D_REENTRANT -I. -Wall -Werror -fvisibility=hidden @@ -30,21 +29,22 @@ build: gcc -shared -Wl,-soname,libkqueue.so -o libkqueue.so *.o install: - mkdir -p $(PREFIX)/include/kqueue/sys - cp event.h $(PREFIX)/include/kqueue/sys - cp libkqueue.so $(PREFIX)/lib - cp libkqueue.pc $(PREFIX)/lib/pkgconfig - cp kqueue.2 $(PREFIX)/share/man/man2/kqueue.2 - ln -s kqueue.2 $(PREFIX)/share/man/man2/kevent.2 + $(INSTALL) -d -m 755 $(INCLUDEDIR)/kqueue + $(INSTALL) -d -m 755 $(INCLUDEDIR)/kqueue/sys + $(INSTALL) -d -m 755 $(MANDIR)/man2 + $(INSTALL) -m 644 sys/event.h $(INCLUDEDIR)/kqueue/sys/event.h + $(INSTALL) -m 644 libkqueue.so $(LIBDIR)/libkqueue.so + $(INSTALL) -m 644 libkqueue.pc $(LIBDIR)/pkgconfig + $(INSTALL) -m 644 kqueue.2 $(MANDIR)/man2/kqueue.2 + $(INSTALL) -m 644 kqueue.2 $(MANDIR)/man2/kevent.2 uninstall: - rm $(PREFIX)/include/kqueue/sys/event.h - rmdir $(PREFIX)/include/kqueue/sys - rmdir $(PREFIX)/include/kqueue - rm $(PREFIX)/lib/libkqueue.so - rm $(PREFIX)/lib/pkgconfig/libkqueue.pc - rm $(PREFIX)/share/man/man2/kqueue.2 - rm $(PREFIX)/share/man/man2/kevent.2 + rm -f $(INCLUDEDIR)/kqueue/sys/event.h + rm -f $(LIBDIR)/libkqueue.so + rm -f $(LIBDIR)/pkgconfig/libkqueue.pc + rm -f $(MANDIR)/man2/kqueue.2 + rm -f $(MANDIR)/man2/kevent.2 + rmdir $(INCLUDEDIR)/kqueue/sys $(INCLUDEDIR)/kqueue check: make build CFLAGS="$(CFLAGS) -g -O0 -DKQUEUE_DEBUG -DUNIT_TEST" diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index 7cb92d583..f8aed75f3 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -1,23 +1,70 @@ #!/bin/sh +program=libkqueue +version=0.1 + +finalize() { + eval "if [ \"\$$1\" = \"\" ] ; then $1=$2 ; fi" + + # Add the variable to config.mk and config.h + id=`echo $1 | tr 'a-z' 'A-Z'`; + eval "echo \"$id=\$$1\" >> config.mk" + eval "echo \"#define $id \\\"\$$1\\\"\" >> config.h" +} + +process_argv() { + for arg in $* + do + id=`echo "$arg" | sed 's/=.*//; s/^--//;'` + val=`echo "$arg" | sed 's/^.*=//'` + if [ "$val" = "" ] ; then val=1 ; fi + eval "$id=$val" + done +} + check_header() { sym=`echo "HAVE_$1" | tr a-z A-Z | sed 's,[./],_,g'` - if [ -f /usr/include/$1 ] ; then + path=$1 + + printf "checking for $path.. " + if [ -f "/usr/include/$path" ] ; then + echo "yes" echo "#define $sym" >> config.h return 0 else + echo "no" echo "#undef $sym" >> config.h return 1 fi } -echo "Checking operating system type... `uname`" -kernel=`uname -s | tr A-Z a-z` -target=$kernel +####################################################################### +# +# MAIN() +# +####################################################################### -echo "Creating config.h" -echo "# AUTOMATICALLY GENERATED -- DO NOT EDIT" > config.h -if [ $kernel = "linux" ] ; then +# Initialize the output files +# +for output_file in config.h config.mk $program.pc +do + rm -f $output_file + echo "# AUTOMATICALLY GENERATED -- DO NOT EDIT" > $output_file +done + +process_argv $* + +finalize program $program +finalize version $version +finalize target `uname -s | tr A-Z a-z` +finalize prefix /usr/local +finalize libdir "${prefix}/lib" +finalize includedir "${prefix}/include" +finalize mandir "${prefix}/share/man" + +echo "Checking operating system type... $target" +rm -f socket.c vnode.c signal.c timer.c user.c +if [ $target = "linux" ] ; then check_header sys/epoll.h && ln -s os/linux/socket.c \ || ln -s os/posix/socket.c check_header sys/inotify.h && ln -s os/linux/vnode.c \ @@ -28,7 +75,15 @@ if [ $kernel = "linux" ] ; then || ln -s os/posix/timer.c ln -s os/posix/user.c fi +echo "Creating config.h" -echo "Creating config.mk" -echo "# AUTOMATICALLY GENERATED -- DO NOT EDIT" > config.mk -echo "UNAME=$target" >> config.mk +echo "Creating $program.pc" +sed -e " + s,@@PROGRAM@@,$program,g; + s,@@VERSION@@,$version,g; + s,@@PREFIX@@,$prefix,g; + s,@@LIBDIR@@,$libdir,g; + s,@@INCLUDEDIR@@,$includedir,g; + s,@@MANDIR@@,$mandir,g; + " < $program.pc.in >> $program.pc +chmod 400 $program.pc diff --git a/vendor/libkqueue/libkqueue.pc b/vendor/libkqueue/libkqueue.pc.in similarity index 53% rename from vendor/libkqueue/libkqueue.pc rename to vendor/libkqueue/libkqueue.pc.in index 2ee7cda4a..ae2c644ed 100644 --- a/vendor/libkqueue/libkqueue.pc +++ b/vendor/libkqueue/libkqueue.pc.in @@ -1,13 +1,13 @@ -prefix=/usr +prefix=@@PREFIX@@ exec_prefix=${prefix} -libdir=${exec_prefix}/lib -includedir=${prefix}/include +libdir=@@LIBDIR@@ +includedir=@@INCLUDEDIR@@ -Name: libkqueue +Name: @@PROGRAM@@ Description: Emulates FreeBSD kqueue(2) on other platforms -Version: 0.1g +Version: @@VERSION@@ Requires: Libs: -L${libdir} -lkqueue Libs.private: -lpthread -lrt -Cflags: -I${includedir} +Cflags: -I${includedir}/kqueue diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index 40efe1403..50319b644 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -69,12 +69,11 @@

      Usage

      libkqueue is a multi-threaded library and kqueue() and kevent() are safe to be used from multiple threads. -Assuming that libkqueue is installed under /usr/include: - +Here are the steps to use libkqueue in your program:
        -
      1. Add -I/usr/lib/kqueue to the CFLAGS variable. +
      2. Add `pkg-config libkqueue --cflags` to the CFLAGS variable. +
      3. Add `pkg-config libkqueue --libs` to the LDADD variable.
      4. Add #include <sys/event.h> to the source code. -
      5. Link against the libkqueue library by adding -lkqueue to the LDADD variable.
      One major difference between libkqueue and the real kqueue is that From 131285197d4e1ee62ce784d6ecd25e5e7954d77a Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 1 Nov 2009 23:49:32 +0000 Subject: [PATCH 0032/1120] docfix git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@32 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index f8aed75f3..bbd24ca81 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -87,3 +87,5 @@ sed -e " s,@@MANDIR@@,$mandir,g; " < $program.pc.in >> $program.pc chmod 400 $program.pc + +echo "Creating config.mk" From c7a7da07958c23bd9c476254a203b376152a7d9d Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 2 Nov 2009 02:09:04 +0000 Subject: [PATCH 0033/1120] initial timerfd implementation. crashes due to errno invalid git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@33 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/os/linux/timer.c | 95 +++++++++++++++++++++++++------ vendor/libkqueue/private.h | 1 + vendor/libkqueue/test.c | 12 ++-- 3 files changed, 85 insertions(+), 23 deletions(-) diff --git a/vendor/libkqueue/os/linux/timer.c b/vendor/libkqueue/os/linux/timer.c index 31a2eb40f..c930d836b 100644 --- a/vendor/libkqueue/os/linux/timer.c +++ b/vendor/libkqueue/os/linux/timer.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -33,12 +34,9 @@ #include "sys/event.h" #include "private.h" +#if DEADWOOD static void timer_convert(struct itimerspec *dst, int src); -struct evfilt_data { - int dummy; -}; - /* * Determine the smallest interval used by active timers. */ @@ -49,10 +47,6 @@ update_timeres(struct filter *filt) struct itimerspec tval; u_int cur = filt->kf_timeres; - if (KNOTELIST_EMPTY(&filt->knl)) { - abort(); - } - /* Find the smallest timeout interval */ //FIXME not optimized KNOTELIST_FOREACH(kn, &filt->knl) { @@ -77,10 +71,11 @@ update_timeres(struct filter *filt) return (0); } +#endif /* Convert milliseconds into seconds+nanoseconds */ static void -timer_convert(struct itimerspec *dst, int src) +convert_msec_to_itimerspec(struct itimerspec *dst, int src, int oneshot) { struct timespec now; time_t sec, nsec; @@ -98,19 +93,79 @@ timer_convert(struct itimerspec *dst, int src) dst->it_value.tv_nsec = now.tv_nsec + nsec; } +static int +ktimer_create(struct filter *filt, struct knote *kn) +{ + struct epoll_event ev; + struct itimerspec *ts; + int tfd; + + tfd = timerfd_create(CLOCK_MONOTONIC, 0); + if (tfd < 0) { + dbg_printf("timerfd_create(2): %s", strerror(errno)); + return (-1); + } + dbg_printf("created timerfd %d", tfd); + + convert_msec_to_itimerspec(ts, kn->kev.data, kn->kev.flags & EV_ONESHOT); + if (timerfd_settime(tfd, 0, ts, NULL) < 0) { + dbg_printf("timerfd_settime(2): %s", strerror(errno)); + close(tfd); + return (-1); + } + + ev.events = EPOLLIN; + ev.data.fd = kn->kev.ident; + if (epoll_ctl(filt->kf_pfd, EPOLL_CTL_ADD, kn->kn_pfd, &ev) < 0) { + dbg_printf("epoll_ctl(2): %d", errno); + close(tfd); + return (-1); + } + + kn->kn_pfd = tfd; + return (0); +} + +static int +ktimer_delete(struct filter *filt, struct knote *kn) +{ + int rv = 0; + + dbg_printf("removing timerfd %d from %d", kn->kn_pfd, filt->kf_pfd); + if (close(kn->kn_pfd) < 0) { + dbg_printf("close(2): %s", strerror(errno)); + rv = -1; + } + if (epoll_ctl(filt->kf_pfd, EPOLL_CTL_DEL, kn->kn_pfd, NULL) < 0) { + dbg_printf("epoll_ctl(2): %s", strerror(errno)); + rv = -1; + } + + kn->kn_pfd = -1; + return (rv); +} + int evfilt_timer_init(struct filter *filt) { - filt->kf_pfd = timerfd_create(CLOCK_MONOTONIC, 0); - if (filt->kf_pfd < 0) + filt->kf_pfd = epoll_create(1); + if (filt->kf_pfd < 0) return (-1); + dbg_printf("timer epollfd = %d", filt->kf_pfd); return (0); } void evfilt_timer_destroy(struct filter *filt) { + struct knote *kn; + + /* Destroy all timerfds */ + KNOTELIST_FOREACH(kn, &filt->knl) { + close(kn->kn_pfd); + } + close (filt->kf_pfd); } @@ -122,12 +177,16 @@ evfilt_timer_copyin(struct filter *filt, memcpy(&dst->kev, src, sizeof(*src)); dst->kev.flags |= EV_CLEAR; } - if (src->flags & EV_ADD || src->flags & EV_ENABLE) { - if (update_timeres(filt) < 0) - return (-1); - } - if (src->flags & EV_DISABLE || src->flags & EV_DELETE) { - // TODO + if (src->flags & EV_ADD) + return ktimer_create(filt, dst); + if (src->flags & EV_DELETE) + return ktimer_delete(filt, dst); + if (src->flags & EV_ENABLE) + return ktimer_create(filt, dst); + if (src->flags & EV_DISABLE) { + // TODO: err checking + (void) ktimer_delete(filt, dst); + KNOTE_DISABLE(dst); } return (0); @@ -143,6 +202,8 @@ evfilt_timer_copyout(struct filter *filt, int i; ssize_t n; + abort(); //TBD + n = read(filt->kf_pfd, &buf, sizeof(buf)); if (n < 0 || n < sizeof(buf)) { dbg_puts("invalid read from timerfd"); diff --git a/vendor/libkqueue/private.h b/vendor/libkqueue/private.h index 9dae605c7..2faf0e84f 100644 --- a/vendor/libkqueue/private.h +++ b/vendor/libkqueue/private.h @@ -40,6 +40,7 @@ struct evfilt_data; struct knote { struct kevent kev; + int kn_pfd; /* Used by timerfd */ LIST_ENTRY(knote) entries; }; LIST_HEAD(knotelist, knote); diff --git a/vendor/libkqueue/test.c b/vendor/libkqueue/test.c index c4112079d..057f8247c 100644 --- a/vendor/libkqueue/test.c +++ b/vendor/libkqueue/test.c @@ -882,6 +882,12 @@ main(int argc, char **argv) test_kqueue(); + if (test_timer) { + test_kevent_timer_add(); + test_kevent_timer_del(); + test_kevent_timer_get(); + } + if (test_socket) { test_kevent_socket_add(); test_kevent_socket_get(); @@ -915,12 +921,6 @@ main(int argc, char **argv) test_kevent_vnode_note_delete(); } - if (test_timer) { - test_kevent_timer_add(); - test_kevent_timer_del(); - test_kevent_timer_get(); - } - test_kqueue_close(); puts("all tests completed."); From 8539a60b3e89ad03c201c2e44e591a65576e0ad5 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 2 Nov 2009 02:46:21 +0000 Subject: [PATCH 0034/1120] add valgrind target. fix major crashers in timer.c git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@34 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 8 ++++++++ vendor/libkqueue/os/linux/timer.c | 21 ++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 1203adbcc..832d9906d 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -52,6 +52,14 @@ check: gcc -g -O0 $(CFLAGS) test.c libkqueue.a -lpthread -lrt ./a.out +# NOTE: copy+paste of 'make check' +valgrind: + make build CFLAGS="$(CFLAGS) -g -O0 -DKQUEUE_DEBUG -DUNIT_TEST" + gcc -c $(CFLAGS) test.c + gcc -g -O0 $(CFLAGS) test.c libkqueue.a -lpthread -lrt + valgrind --tool=memcheck --leak-check=full --show-reachable=yes --num-callers=20 --track-fds=yes ./a.out + + check-installed: gcc -g -O0 -Wall -Werror -I$(PREFIX)/kqueue test.c -lkqueue ./a.out diff --git a/vendor/libkqueue/os/linux/timer.c b/vendor/libkqueue/os/linux/timer.c index c930d836b..f5deb5767 100644 --- a/vendor/libkqueue/os/linux/timer.c +++ b/vendor/libkqueue/os/linux/timer.c @@ -86,6 +86,9 @@ convert_msec_to_itimerspec(struct itimerspec *dst, int src, int oneshot) nsec = (src % 1000) * 1000000; dst->it_interval.tv_sec = sec; dst->it_interval.tv_nsec = nsec; + dbg_printf("timer val=%lu %lu", sec, nsec); + + /* FIXME: doesnt handle oneshot */ /* Set the initial expiration */ clock_gettime(CLOCK_MONOTONIC, &now); @@ -97,7 +100,7 @@ static int ktimer_create(struct filter *filt, struct knote *kn) { struct epoll_event ev; - struct itimerspec *ts; + struct itimerspec ts; int tfd; tfd = timerfd_create(CLOCK_MONOTONIC, 0); @@ -107,8 +110,8 @@ ktimer_create(struct filter *filt, struct knote *kn) } dbg_printf("created timerfd %d", tfd); - convert_msec_to_itimerspec(ts, kn->kev.data, kn->kev.flags & EV_ONESHOT); - if (timerfd_settime(tfd, 0, ts, NULL) < 0) { + convert_msec_to_itimerspec(&ts, kn->kev.data, kn->kev.flags & EV_ONESHOT); + if (timerfd_settime(tfd, 0, &ts, NULL) < 0) { dbg_printf("timerfd_settime(2): %s", strerror(errno)); close(tfd); return (-1); @@ -116,7 +119,7 @@ ktimer_create(struct filter *filt, struct knote *kn) ev.events = EPOLLIN; ev.data.fd = kn->kev.ident; - if (epoll_ctl(filt->kf_pfd, EPOLL_CTL_ADD, kn->kn_pfd, &ev) < 0) { + if (epoll_ctl(filt->kf_pfd, EPOLL_CTL_ADD, tfd, &ev) < 0) { dbg_printf("epoll_ctl(2): %d", errno); close(tfd); return (-1); @@ -129,17 +132,17 @@ ktimer_create(struct filter *filt, struct knote *kn) static int ktimer_delete(struct filter *filt, struct knote *kn) { - int rv = 0; + int rv = 0; dbg_printf("removing timerfd %d from %d", kn->kn_pfd, filt->kf_pfd); - if (close(kn->kn_pfd) < 0) { - dbg_printf("close(2): %s", strerror(errno)); - rv = -1; - } if (epoll_ctl(filt->kf_pfd, EPOLL_CTL_DEL, kn->kn_pfd, NULL) < 0) { dbg_printf("epoll_ctl(2): %s", strerror(errno)); rv = -1; } + if (close(kn->kn_pfd) < 0) { + dbg_printf("close(2): %s", strerror(errno)); + rv = -1; + } kn->kn_pfd = -1; return (rv); From b9b2d339b171358c05d5ff01d38b0746a9300963 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 2 Nov 2009 02:56:23 +0000 Subject: [PATCH 0035/1120] restore timers to the end git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@35 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/test.c b/vendor/libkqueue/test.c index 057f8247c..c4112079d 100644 --- a/vendor/libkqueue/test.c +++ b/vendor/libkqueue/test.c @@ -882,12 +882,6 @@ main(int argc, char **argv) test_kqueue(); - if (test_timer) { - test_kevent_timer_add(); - test_kevent_timer_del(); - test_kevent_timer_get(); - } - if (test_socket) { test_kevent_socket_add(); test_kevent_socket_get(); @@ -921,6 +915,12 @@ main(int argc, char **argv) test_kevent_vnode_note_delete(); } + if (test_timer) { + test_kevent_timer_add(); + test_kevent_timer_del(); + test_kevent_timer_get(); + } + test_kqueue_close(); puts("all tests completed."); From 2c5b6e1d2b70015ff808bef3ea95e2a9bf329a38 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 4 Nov 2009 22:07:39 +0000 Subject: [PATCH 0036/1120] initial split of test suite to separate directory git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@36 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/os/linux/timer.c | 3 +- vendor/libkqueue/test/Makefile | 7 + vendor/libkqueue/test/common.h | 57 ++ vendor/libkqueue/test/config.h | 11 + vendor/libkqueue/test/configure | 97 ++++ vendor/libkqueue/test/evfilt_read.c | 332 ++++++++++++ vendor/libkqueue/test/main.c | 161 ++++++ vendor/libkqueue/test/test.c | 784 ++++++++++++++++++++++++++++ 8 files changed, 1451 insertions(+), 1 deletion(-) create mode 100644 vendor/libkqueue/test/Makefile create mode 100644 vendor/libkqueue/test/common.h create mode 100644 vendor/libkqueue/test/config.h create mode 100755 vendor/libkqueue/test/configure create mode 100644 vendor/libkqueue/test/evfilt_read.c create mode 100644 vendor/libkqueue/test/main.c create mode 100644 vendor/libkqueue/test/test.c diff --git a/vendor/libkqueue/os/linux/timer.c b/vendor/libkqueue/os/linux/timer.c index f5deb5767..993496898 100644 --- a/vendor/libkqueue/os/linux/timer.c +++ b/vendor/libkqueue/os/linux/timer.c @@ -117,8 +117,9 @@ ktimer_create(struct filter *filt, struct knote *kn) return (-1); } + memset(&ev, 0, sizeof(ev)); ev.events = EPOLLIN; - ev.data.fd = kn->kev.ident; + ev.data.ptr = kn; if (epoll_ctl(filt->kf_pfd, EPOLL_CTL_ADD, tfd, &ev) < 0) { dbg_printf("epoll_ctl(2): %d", errno); close(tfd); diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile new file mode 100644 index 000000000..cb4fcbc36 --- /dev/null +++ b/vendor/libkqueue/test/Makefile @@ -0,0 +1,7 @@ +include config.mk + +all: evfilt_read.o main.o + cc $(CFLAGS) *.o $(LDADD) + +clean: + rm -f *.o diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h new file mode 100644 index 000000000..b212926c5 --- /dev/null +++ b/vendor/libkqueue/test/common.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _COMMON_H +#define _COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" + +extern char *cur_test_id; +int kqfd; +int vnode_fd; + +extern const char * kevent_to_str(struct kevent *); + +void kevent_cmp(struct kevent *, struct kevent *); + +/* DEPRECATED: */ +#define KEV_CMP(kev,_ident,_filter,_flags) do { \ + if (kev.ident != (_ident) || \ + kev.filter != (_filter) || \ + kev.flags != (_flags)) \ + err(1, "kevent mismatch: got [%d,%d,%d] but expecting [%d,%d,%d]", \ + (int)_ident, (int)_filter, (int)_flags,\ + (int)kev.ident, kev.filter, kev.flags);\ +} while (0); + +/* Checks if any events are pending, which is an error. */ +extern void test_no_kevents(void); + +extern void test_begin(const char *); +extern void success(const char *); + +#endif /* _COMMON_H */ diff --git a/vendor/libkqueue/test/config.h b/vendor/libkqueue/test/config.h new file mode 100644 index 000000000..e1b71ce33 --- /dev/null +++ b/vendor/libkqueue/test/config.h @@ -0,0 +1,11 @@ +/* AUTOMATICALLY GENERATED -- DO NOT EDIT */ +#define PROGRAM "libkqueue-test" +#define VERSION "0.1" +#define TARGET "linux" +#define PREFIX "/usr/local" +#define LIBDIR "/usr/local/lib" +#define INCLUDEDIR "/usr/local/include" +#define MANDIR "/usr/local/share/man" +#undef HAVE_SYS_EVENT_H +#define CFLAGS "-g -O0 -Wall -Werror -I.." +#define LDADD " ../libkqueue.a -lpthread -lrt" diff --git a/vendor/libkqueue/test/configure b/vendor/libkqueue/test/configure new file mode 100755 index 000000000..02ebd4ffa --- /dev/null +++ b/vendor/libkqueue/test/configure @@ -0,0 +1,97 @@ +#!/bin/sh + +program=libkqueue-test +version=0.1 + +finalize() { + eval "if [ \"\$$1\" = \"\" ] ; then $1=$2 ; fi" + + # Add the variable to config.mk and config.h + id=`echo $1 | tr 'a-z' 'A-Z'`; + eval "echo \"$id=\$$1\" >> config.mk" + eval "echo \"#define $id \\\"\$$1\\\"\" >> config.h" +} + +process_argv() { + for arg in $* + do + id=`echo "$arg" | sed 's/=.*//; s/^--//;'` + val=`echo "$arg" | sed 's/^.*=//'` + if [ "$val" = "" ] ; then val=1 ; fi + eval "$id=$val" + done +} + +check_header() { + sym=`echo "HAVE_$1" | tr a-z A-Z | sed 's,[./],_,g'` + path=$1 + + printf "checking for $path.. " + if [ -f "/usr/include/$path" ] ; then + echo "yes" + echo "#define $sym" >> config.h + return 0 + else + echo "no" + echo "#undef $sym" >> config.h + return 1 + fi +} + +check_symbol() { + header=$1 + symbol=$2 + + uc_symbol=`echo "HAVE_$symbol" | tr a-z A-Z | sed 's,[./],_,g'` + + printf "checking <$header> for $symbol.. " + if [ "`grep '#define $symbol' /usr/include/$header`" != "" ] ; then + echo "yes" + echo "#define $uc_symbol" >> config.h + return 0 + else + echo "no" + echo "#undef $uc_symbol" >> config.h + return 1 + fi +} + +####################################################################### +# +# MAIN() +# +####################################################################### + +# Initialize the output files +# +rm -f config.h +echo "/* AUTOMATICALLY GENERATED -- DO NOT EDIT */" > config.h +rm -f config.mk +echo "# AUTOMATICALLY GENERATED -- DO NOT EDIT" > config.mk + +process_argv $* + +finalize program $program +finalize version $version +finalize target `uname -s | tr A-Z a-z` +finalize prefix /usr/local +finalize libdir "${prefix}/lib" +finalize includedir "${prefix}/include" +finalize mandir "${prefix}/share/man" + +echo "Checking operating system type... $target" +check_header sys/event.h && { + check_symbol sys/event.h EVFILT_DISPATCH +} + +cflags="-g -O0 -Wall -Werror" +ldadd="" +if [ "`uname -s`" = "Linux" ] ; then + cflags="$cflags -I.." + ldadd="$ldadd ../libkqueue.a -lpthread -lrt" +fi +finalize cflags "" +finalize ldadd "" + +echo "Creating config.h" +echo "Creating config.mk" diff --git a/vendor/libkqueue/test/evfilt_read.c b/vendor/libkqueue/test/evfilt_read.c new file mode 100644 index 000000000..7e8a5419a --- /dev/null +++ b/vendor/libkqueue/test/evfilt_read.c @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "common.h" + +int sockfd[2]; + +static void +kevent_socket_drain(void) +{ + char buf[1]; + + /* Drain the read buffer, then make sure there are no more events. */ + puts("draining the read buffer"); + if (read(sockfd[0], &buf[0], 1) < 1) + err(1, "read(2)"); +} + +static void +kevent_socket_fill(void) +{ + puts("filling the read buffer"); + if (write(sockfd[1], ".", 1) < 1) + err(1, "write(2)"); +} + + +void +test_kevent_socket_add(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_ADD)"; + struct kevent kev; + + test_begin(test_id); + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_socket_get(void) +{ + const char *test_id = "kevent(EVFILT_READ) wait"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + kevent_socket_fill(); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s: nfds=%d", test_id, nfds); + KEV_CMP(kev, sockfd[0], EVFILT_READ, EV_ADD); + if ((int)kev.data != 1) + err(1, "incorrect data value %d", (int) kev.data); // FIXME: make part of KEV_CMP + + kevent_socket_drain(); + test_no_kevents(); + + success(test_id); +} + +void +test_kevent_socket_clear(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_CLEAR)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + test_no_kevents(); + + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + kevent_socket_fill(); + kevent_socket_fill(); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); + if ((int)kev.data != 2) + err(1, "incorrect data value %d", (int) kev.data); // FIXME: make part of KEV_CMP + + /* We filled twice, but drain once. Edge-triggered would not generate + additional events. + */ + kevent_socket_drain(); + test_no_kevents(); + + kevent_socket_drain(); + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_socket_disable(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_DISABLE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DISABLE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + kevent_socket_fill(); + test_no_kevents(); + kevent_socket_drain(); + + success(test_id); +} + +void +test_kevent_socket_enable(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_ENABLE)"; + struct kevent kev, ret; + int nfds; + + test_begin(test_id); + + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ENABLE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + kevent_socket_fill(); + nfds = kevent(kqfd, NULL, 0, &ret, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + kevent_cmp(&kev, &ret); + kevent_socket_drain(); + + success(test_id); +} + +void +test_kevent_socket_del(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_DELETE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + kevent_socket_fill(); + test_no_kevents(); + kevent_socket_drain(); + + success(test_id); +} + +void +test_kevent_socket_oneshot(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_ONESHOT)"; + struct kevent kev, ret; + + test_begin(test_id); + + /* Re-add the watch and make sure no events are pending */ + puts("-- re-adding knote"); + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + test_no_kevents(); + + puts("-- getting one event"); + kevent_socket_fill(); + if (kevent(kqfd, NULL, 0, &ret, 1, NULL) != 1) + err(1, "%s", test_id); + kevent_cmp(&kev, &ret); + + puts("-- checking knote disabled"); + test_no_kevents(); + + /* Try to delete the knote, it should already be deleted */ + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0) + err(1, "%s", test_id); + + kevent_socket_drain(); + + success(test_id); +} + + +void +test_kevent_socket_dispatch(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_DISPATCH)"; + + test_begin(test_id); + +#if HAVE_EV_DISPATCH + struct kevent kev; + + /* Re-add the watch and make sure no events are pending */ + puts("-- re-adding knote"); + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + test_no_kevents(); + + /* Since the knote is disabled, there are no events. */ + puts("-- checking if knote is disabled.."); + kevent_socket_fill(); + if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) + err(1, "%s", test_id); + KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); + test_no_kevents(); + + /* Since the knote is disabled, the EV_DELETE operation succeeds. */ + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + kevent_socket_drain(); + +#endif /* HAVE_EV_DISPATCH */ + + success(test_id); +} + +#if BROKEN +void +test_kevent_socket_lowat(void) +{ + const char *test_id = "kevent(EVFILT_READ, NOTE_LOWAT)"; + struct kevent kev; + + test_begin(test_id); + + /* Re-add the watch and make sure no events are pending */ + puts("-- re-adding knote, setting low watermark to 2 bytes"); + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + test_no_kevents(); + + puts("-- checking that one byte does not trigger an event.."); + kevent_socket_fill(); + test_no_kevents(); + + puts("-- checking that two bytes triggers an event.."); + kevent_socket_fill(); + if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) + err(1, "%s", test_id); + KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); + test_no_kevents(); + + kevent_socket_drain(); + kevent_socket_drain(); + + success(test_id); +} +#endif + +void +test_kevent_socket_eof(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_EOF)"; + struct kevent kev; + + test_begin(test_id); + + /* Re-add the watch and make sure no events are pending */ + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + test_no_kevents(); + + if (close(sockfd[1]) < 0) + err(1, "close(2)"); + + if (kevent(kqfd, NULL, 0, &kev, 1, NULL) < 1) + err(1, "%s", test_id); + KEV_CMP(kev, sockfd[0], EVFILT_READ, EV_EOF); + + /* Delete the watch */ + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_evfilt_read() +{ + /* Create a connected pair of full-duplex sockets for testing socket events */ + if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd) < 0) + abort(); + + test_kevent_socket_add(); + test_kevent_socket_get(); + test_kevent_socket_disable(); + test_kevent_socket_enable(); + test_kevent_socket_del(); + test_kevent_socket_oneshot(); + test_kevent_socket_clear(); + test_kevent_socket_dispatch(); + test_kevent_socket_eof(); +} diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c new file mode 100644 index 000000000..295613102 --- /dev/null +++ b/vendor/libkqueue/test/main.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "common.h" + +char *cur_test_id = "undef"; +int kqfd; + +extern void test_evfilt_read(); + +/* Checks if any events are pending, which is an error. */ +void +test_no_kevents(void) +{ + int nfds; + struct timespec timeo; + struct kevent kev; + + puts("confirming that there are no events pending"); + memset(&timeo, 0, sizeof(timeo)); + nfds = kevent(kqfd, NULL, 0, &kev, 1, &timeo); + if (nfds != 0) { + puts("\nUnexpected event:"); + puts(kevent_to_str(&kev)); + errx(1, "%d event(s) pending, but none expected:", nfds); + } +} + +/* Copied from ../kevent.c kevent_dump() */ +const char * +kevent_to_str(struct kevent *kev) +{ + char buf[512]; + snprintf(&buf[0], sizeof(buf), "[filter=%d,flags=%d,ident=%u,udata=%p]", + kev->filter, + kev->flags, + (u_int) kev->ident, + kev->udata); + return (strdup(buf)); +} + +void +kevent_cmp(struct kevent *k1, struct kevent *k2) +{ + if (memcmp(k1, k2, sizeof(*k1)) != 0) { + printf("kevent_cmp: mismatch: %s != %s\n", + kevent_to_str(k1), kevent_to_str(k2)); + abort(); + } +} + +void +test_begin(const char *func) +{ + static int testnum = 1; + cur_test_id = (char *) func; + printf("\n\nTest %d: %s\n", testnum++, func); +} + +void +success(const char *func) +{ + printf("%-70s %s\n", func, "passed"); +} +void +test_kqueue(void) +{ + test_begin("kqueue()"); + if ((kqfd = kqueue()) < 0) + err(1, "kqueue()"); + test_no_kevents(); + success("kqueue()"); +} + +void +test_kqueue_close(void) +{ + test_begin("close(kq)"); + if (close(kqfd) < 0) + err(1, "close()"); +#if LIBKQUEUE + kqueue_free(kqfd); +#endif + success("kqueue_close()"); +} + +int +main(int argc, char **argv) +{ + int test_socket = 1; + int test_signal = 1;//XXX-FIXME + int test_vnode = 1; + int test_timer = 1; + + while (argc) { + if (strcmp(argv[0], "--no-socket") == 0) + test_socket = 0; + if (strcmp(argv[0], "--no-timer") == 0) + test_timer = 0; + if (strcmp(argv[0], "--no-signal") == 0) + test_signal = 0; + if (strcmp(argv[0], "--no-vnode") == 0) + test_vnode = 0; + argv++; + argc--; + } + + test_kqueue(); + + if (test_socket) { + test_evfilt_read(); + } + +#if TODO + if (test_signal) { + test_kevent_signal_add(); + test_kevent_signal_get(); + test_kevent_signal_disable(); + test_kevent_signal_enable(); + test_kevent_signal_del(); + test_kevent_signal_oneshot(); + } + + if (test_vnode) { + test_kevent_vnode_add(); + test_kevent_vnode_del(); + test_kevent_vnode_disable_and_enable(); + test_kevent_vnode_dispatch(); + test_kevent_vnode_note_write(); + test_kevent_vnode_note_attrib(); + test_kevent_vnode_note_rename(); + test_kevent_vnode_note_delete(); + } + + if (test_timer) { + test_kevent_timer_add(); + test_kevent_timer_del(); + test_kevent_timer_get(); + } +#endif + + test_kqueue_close(); + + puts("all tests completed."); + return (0); +} diff --git a/vendor/libkqueue/test/test.c b/vendor/libkqueue/test/test.c new file mode 100644 index 000000000..771ffe5c8 --- /dev/null +++ b/vendor/libkqueue/test/test.c @@ -0,0 +1,784 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sys/event.h" + +char *cur_test_id = "undef"; +int kqfd; +int sockfd[2]; +int vnode_fd; + +/* In kevent.c */ +const char * kevent_dump(struct kevent *); + +#define KEV_CMP(kev,_ident,_filter,_flags) do { \ + if (kev.ident != (_ident) || \ + kev.filter != (_filter) || \ + kev.flags != (_flags)) \ + err(1, "kevent mismatch: got %s but expecting [%d,%d,%d]", \ + kevent_dump(&kev),\ + (int)kev.ident, kev.filter, kev.flags);\ +} while (0); + +void +test_kevent_socket_add(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_ADD)"; + struct kevent kev; + + test_begin(test_id); + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_socket_get(void) +{ + const char *test_id = "kevent(EVFILT_READ) wait"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + if (write(sockfd[1], ".", 1) < 1) + err(1, "write(2)"); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); + if ((int)kev.data != 1) + err(1, "incorrect data value %d", (int) kev.data); // FIXME: make part of KEV_CMP + + kevent_socket_drain(); + test_no_kevents(); + + success(test_id); +} + +void +test_kevent_socket_clear(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_CLEAR)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + test_no_kevents(); + + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + kevent_socket_fill(); + kevent_socket_fill(); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); + if ((int)kev.data != 2) + err(1, "incorrect data value %d", (int) kev.data); // FIXME: make part of KEV_CMP + + /* We filled twice, but drain once. Edge-triggered would not generate + additional events. + */ + kevent_socket_drain(); + test_no_kevents(); + + kevent_socket_drain(); + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_socket_disable(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_DISABLE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DISABLE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + kevent_socket_fill(); + test_no_kevents(); + kevent_socket_drain(); + + success(test_id); +} + +void +test_kevent_socket_enable(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_ENABLE)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ENABLE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + kevent_socket_fill(); + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); + kevent_socket_drain(); + + success(test_id); +} + +void +test_kevent_socket_del(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_DELETE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + kevent_socket_fill(); + test_no_kevents(); + kevent_socket_drain(); + + success(test_id); +} + +void +test_kevent_socket_oneshot(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_ONESHOT)"; + struct kevent kev; + + test_begin(test_id); + + /* Re-add the watch and make sure no events are pending */ + puts("-- re-adding knote"); + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + test_no_kevents(); + + puts("-- getting one event"); + kevent_socket_fill(); + if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) + err(1, "%s", test_id); + KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); + + puts("-- checking knote disabled"); + test_no_kevents(); + + /* Try to delete the knote, it should already be deleted */ + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0) + err(1, "%s", test_id); + + kevent_socket_drain(); + + success(test_id); +} + +void +test_kevent_socket_dispatch(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_DISPATCH)"; + struct kevent kev; + + test_begin(test_id); + + /* Re-add the watch and make sure no events are pending */ + puts("-- re-adding knote"); + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + test_no_kevents(); + + /* Since the knote is disabled, there are no events. */ + puts("-- checking if knote is disabled.."); + kevent_socket_fill(); + if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) + err(1, "%s", test_id); + KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); + test_no_kevents(); + + /* Since the knote is disabled, the EV_DELETE operation succeeds. */ + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + kevent_socket_drain(); + + success(test_id); +} + +#if BROKEN +void +test_kevent_socket_lowat(void) +{ + const char *test_id = "kevent(EVFILT_READ, NOTE_LOWAT)"; + struct kevent kev; + + test_begin(test_id); + + /* Re-add the watch and make sure no events are pending */ + puts("-- re-adding knote, setting low watermark to 2 bytes"); + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + test_no_kevents(); + + puts("-- checking that one byte does not trigger an event.."); + kevent_socket_fill(); + test_no_kevents(); + + puts("-- checking that two bytes triggers an event.."); + kevent_socket_fill(); + if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) + err(1, "%s", test_id); + KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); + test_no_kevents(); + + kevent_socket_drain(); + kevent_socket_drain(); + + success(test_id); +} +#endif + +void +test_kevent_socket_eof(void) +{ + const char *test_id = "kevent(EVFILT_READ, EV_EOF)"; + struct kevent kev; + + test_begin(test_id); + + /* Re-add the watch and make sure no events are pending */ + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + test_no_kevents(); + + if (close(sockfd[1]) < 0) + err(1, "close(2)"); + + if (kevent(kqfd, NULL, 0, &kev, 1, NULL) < 1) + err(1, "%s", test_id); + KEV_CMP(kev, sockfd[0], EVFILT_READ, EV_EOF); + + /* Delete the watch */ + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_signal_add(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, EV_ADD)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_signal_get(void) +{ + const char *test_id = "kevent(get signal)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "test failed: %s, retval %d", test_id, nfds); + if (kev.ident != SIGUSR1 || + kev.filter != EVFILT_SIGNAL || + kev.flags != 0) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + //FIXME: test kev->flags, fflags, data + + success(test_id); +} + +void +test_kevent_signal_disable(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + test_no_kevents(); + + success(test_id); +} + +void +test_kevent_signal_enable(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "test failed: %s, retval %d", test_id, nfds); + if (kev.ident != SIGUSR1 || + kev.filter != EVFILT_SIGNAL || + kev.flags != 0) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + + success(test_id); +} + +void +test_kevent_signal_del(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)"; + struct kevent kev; + + test_begin(test_id); + + /* Delete the kevent */ + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + test_no_kevents(); + success(test_id); +} + +void +test_kevent_signal_oneshot(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "test failed: %s, retval %d", test_id, nfds); + if (kev.ident != SIGUSR1 || + kev.filter != EVFILT_SIGNAL || + kev.flags != 0) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + //FIXME: test kev->flags, fflags, data + + /* Send another one and make sure we get no events */ + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + test_no_kevents(); + + success(test_id); +} + +void +test_kevent_vnode_add(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, EV_ADD)"; + const char *testfile = "/tmp/kqueue-test.tmp"; + struct kevent kev; + + test_begin(test_id); + + system("touch /tmp/kqueue-test.tmp"); + vnode_fd = open(testfile, O_RDONLY); + if (vnode_fd < 0) + err(1, "open of %s", testfile); + else + printf("vnode_fd = %d\n", vnode_fd); + + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD, + NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME | NOTE_DELETE, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_vnode_note_delete(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, NOTE_DELETE)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* FIXME: workaround for linux behavior. if the file is open, + the delete event isn't registered; an IN_ATTRIB event is fired + instead. + */ + close(vnode_fd); + if (unlink("/tmp/kqueue-test.tmp") < 0) + err(1, "unlink"); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s %d events", test_id, nfds); + if (kev.ident != vnode_fd || + kev.filter != EVFILT_VNODE || + kev.fflags != NOTE_DELETE) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + + success(test_id); +} + +void +test_kevent_vnode_note_write(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, NOTE_WRITE)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_WRITE, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + if (system("echo hello >> /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + if (kev.ident != vnode_fd || + kev.filter != EVFILT_VNODE || + kev.fflags != NOTE_WRITE) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + + success(test_id); +} + +void +test_kevent_vnode_note_attrib(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, NOTE_ATTRIB)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + if (system("touch /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + if (kev.ident != vnode_fd || + kev.filter != EVFILT_VNODE || + kev.fflags != NOTE_ATTRIB) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + + success(test_id); +} + +void +test_kevent_vnode_note_rename(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, NOTE_RENAME)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_RENAME, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + if (system("mv /tmp/kqueue-test.tmp /tmp/kqueue-test2.tmp") < 0) + err(1, "system"); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + if (kev.ident != vnode_fd || + kev.filter != EVFILT_VNODE || + kev.fflags != NOTE_RENAME) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + + if (system("mv /tmp/kqueue-test2.tmp /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + + success(test_id); +} + +void +test_kevent_vnode_del(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, EV_DELETE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_vnode_disable_and_enable(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, EV_DISABLE and EV_ENABLE)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + test_no_kevents(); + + /* Add the watch and immediately disable it */ + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + kev.flags = EV_DISABLE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Confirm that the watch is disabled */ + if (system("touch /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + test_no_kevents(); + + /* Re-enable and check again */ + kev.flags = EV_ENABLE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + if (system("touch /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + if (kev.ident != vnode_fd || + kev.filter != EVFILT_VNODE || + kev.fflags != NOTE_ATTRIB) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + + success(test_id); +} + +void +test_kevent_vnode_dispatch(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, EV_DISPATCH)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + test_no_kevents(); + + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_DISPATCH, NOTE_ATTRIB, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + if (system("touch /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + if (kev.ident != vnode_fd || + kev.filter != EVFILT_VNODE || + kev.fflags != NOTE_ATTRIB) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + + /* Confirm that the watch is disabled automatically */ + puts("-- checking that watch is disabled"); + if (system("touch /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + test_no_kevents(); + + /* Delete the watch */ + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, NOTE_ATTRIB, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "remove watch failed: %s", test_id); + + success(test_id); +} + +void +test_kevent_timer_add(void) +{ + const char *test_id = "kevent(EVFILT_TIMER, EV_ADD)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_timer_del(void) +{ + const char *test_id = "kevent(EVFILT_TIMER, EV_DELETE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_timer_get(void) +{ + const char *test_id = "kevent(EVFILT_TIMER, get)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + if (kev.ident != 1 || kev.filter != EVFILT_TIMER) + errx(1, "wrong event"); + + EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} From 5380f765cc8103fd572c0588fa088a83a808b802 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 4 Nov 2009 22:49:10 +0000 Subject: [PATCH 0037/1120] evfilt_read works, broken import of evfilt_socket git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@37 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/Makefile | 4 +- vendor/libkqueue/test/common.h | 7 +++- vendor/libkqueue/test/config.h | 10 +++-- vendor/libkqueue/test/configure | 1 + vendor/libkqueue/test/evfilt_read.c | 24 +++++++----- vendor/libkqueue/test/main.c | 57 ++++++++++++++++++++++------- 6 files changed, 71 insertions(+), 32 deletions(-) diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile index cb4fcbc36..f7141fbd3 100644 --- a/vendor/libkqueue/test/Makefile +++ b/vendor/libkqueue/test/Makefile @@ -1,7 +1,7 @@ include config.mk -all: evfilt_read.o main.o - cc $(CFLAGS) *.o $(LDADD) +all: + gcc $(CFLAGS) main.c evfilt_read.c evfilt_signal.c $(LDADD) clean: rm -f *.o diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index b212926c5..c81b42d55 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -17,6 +17,7 @@ #ifndef _COMMON_H #define _COMMON_H + #include #include #include @@ -24,14 +25,16 @@ #include #include #include -#include +#include #include +#include #include +#include + #include "config.h" extern char *cur_test_id; -int kqfd; int vnode_fd; extern const char * kevent_to_str(struct kevent *); diff --git a/vendor/libkqueue/test/config.h b/vendor/libkqueue/test/config.h index e1b71ce33..f83da8f39 100644 --- a/vendor/libkqueue/test/config.h +++ b/vendor/libkqueue/test/config.h @@ -1,11 +1,13 @@ /* AUTOMATICALLY GENERATED -- DO NOT EDIT */ #define PROGRAM "libkqueue-test" #define VERSION "0.1" -#define TARGET "linux" +#define TARGET "openbsd" #define PREFIX "/usr/local" #define LIBDIR "/usr/local/lib" #define INCLUDEDIR "/usr/local/include" #define MANDIR "/usr/local/share/man" -#undef HAVE_SYS_EVENT_H -#define CFLAGS "-g -O0 -Wall -Werror -I.." -#define LDADD " ../libkqueue.a -lpthread -lrt" +#define HAVE_SYS_EVENT_H +#undef HAVE_EVFILT_DISPATCH +#undef HAVE_EVFILT_RECEIPT +#define CFLAGS "-g -O0 -Wall -Werror" +#define LDADD "" diff --git a/vendor/libkqueue/test/configure b/vendor/libkqueue/test/configure index 02ebd4ffa..1c8327418 100755 --- a/vendor/libkqueue/test/configure +++ b/vendor/libkqueue/test/configure @@ -82,6 +82,7 @@ finalize mandir "${prefix}/share/man" echo "Checking operating system type... $target" check_header sys/event.h && { check_symbol sys/event.h EVFILT_DISPATCH + check_symbol sys/event.h EVFILT_RECEIPT } cflags="-g -O0 -Wall -Werror" diff --git a/vendor/libkqueue/test/evfilt_read.c b/vendor/libkqueue/test/evfilt_read.c index 7e8a5419a..adf0dd292 100644 --- a/vendor/libkqueue/test/evfilt_read.c +++ b/vendor/libkqueue/test/evfilt_read.c @@ -14,10 +14,9 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include - #include "common.h" +int kqfd; int sockfd[2]; static void @@ -82,7 +81,7 @@ void test_kevent_socket_clear(void) { const char *test_id = "kevent(EVFILT_READ, EV_CLEAR)"; - struct kevent kev; + struct kevent kev, ret; int nfds; test_begin(test_id); @@ -96,12 +95,11 @@ test_kevent_socket_clear(void) kevent_socket_fill(); kevent_socket_fill(); - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + nfds = kevent(kqfd, NULL, 0, &ret, 1, NULL); if (nfds < 1) err(1, "%s", test_id); - KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); - if ((int)kev.data != 2) - err(1, "incorrect data value %d", (int) kev.data); // FIXME: make part of KEV_CMP + kev.data = 2; + kevent_cmp(&kev,&ret); /* We filled twice, but drain once. Edge-triggered would not generate additional events. @@ -153,6 +151,8 @@ test_kevent_socket_enable(void) nfds = kevent(kqfd, NULL, 0, &ret, 1, NULL); if (nfds < 1) err(1, "%s", test_id); + kev.flags = EV_ADD; + kev.data = 1; kevent_cmp(&kev, &ret); kevent_socket_drain(); @@ -197,6 +197,7 @@ test_kevent_socket_oneshot(void) kevent_socket_fill(); if (kevent(kqfd, NULL, 0, &ret, 1, NULL) != 1) err(1, "%s", test_id); + kev.data = 1; kevent_cmp(&kev, &ret); puts("-- checking knote disabled"); @@ -288,7 +289,7 @@ void test_kevent_socket_eof(void) { const char *test_id = "kevent(EVFILT_READ, EV_EOF)"; - struct kevent kev; + struct kevent kev, ret; test_begin(test_id); @@ -301,9 +302,10 @@ test_kevent_socket_eof(void) if (close(sockfd[1]) < 0) err(1, "close(2)"); - if (kevent(kqfd, NULL, 0, &kev, 1, NULL) < 1) + if (kevent(kqfd, NULL, 0, &ret, 1, NULL) < 1) err(1, "%s", test_id); - KEV_CMP(kev, sockfd[0], EVFILT_READ, EV_EOF); + kev.flags |= EV_EOF; + kevent_cmp(&kev, &ret); /* Delete the watch */ EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); @@ -320,6 +322,7 @@ test_evfilt_read() if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd) < 0) abort(); + kqfd = kqueue(); test_kevent_socket_add(); test_kevent_socket_get(); test_kevent_socket_disable(); @@ -329,4 +332,5 @@ test_evfilt_read() test_kevent_socket_clear(); test_kevent_socket_dispatch(); test_kevent_socket_eof(); + close(kqfd); } diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 295613102..60783331b 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -22,6 +22,7 @@ char *cur_test_id = "undef"; int kqfd; extern void test_evfilt_read(); +extern void test_evfilt_signal(); /* Checks if any events are pending, which is an error. */ void @@ -41,15 +42,49 @@ test_no_kevents(void) } } -/* Copied from ../kevent.c kevent_dump() */ +char * +kevent_flags_dump(struct kevent *kev) +{ + char *buf; + +#define KEVFL_DUMP(attrib) \ + if (kev->flags & attrib) \ + strcat(buf, #attrib" "); + + if ((buf = calloc(1, 1024)) == NULL) + abort(); + + sprintf(buf, "flags = %d (", kev->flags); + KEVFL_DUMP(EV_ADD); + KEVFL_DUMP(EV_ENABLE); + KEVFL_DUMP(EV_DISABLE); + KEVFL_DUMP(EV_DELETE); + KEVFL_DUMP(EV_ONESHOT); + KEVFL_DUMP(EV_CLEAR); + KEVFL_DUMP(EV_EOF); + KEVFL_DUMP(EV_ERROR); +#if HAVE_EV_DISPATCH + KEVFL_DUMP(EV_DISPATCH); +#endif +#if HAVE_EV_RECEIPT + KEVFL_DUMP(EV_RECEIPT); +#endif + strcat(buf, ")"); + + return (buf); +} + +/* Copied from ../kevent.c kevent_dump() and improved */ const char * kevent_to_str(struct kevent *kev) { char buf[512]; - snprintf(&buf[0], sizeof(buf), "[filter=%d,flags=%d,ident=%u,udata=%p]", + snprintf(&buf[0], sizeof(buf), "[filter=%d,%s,fflags=%d,ident=%u,data=%d,udata=%p]", kev->filter, - kev->flags, + kevent_flags_dump(kev), + kev->fflags, (u_int) kev->ident, + kev->data, kev->udata); return (strdup(buf)); } @@ -58,7 +93,7 @@ void kevent_cmp(struct kevent *k1, struct kevent *k2) { if (memcmp(k1, k2, sizeof(*k1)) != 0) { - printf("kevent_cmp: mismatch: %s != %s\n", + printf("kevent_cmp: mismatch:\n %s !=\n %s\n", kevent_to_str(k1), kevent_to_str(k2)); abort(); } @@ -77,6 +112,7 @@ success(const char *func) { printf("%-70s %s\n", func, "passed"); } + void test_kqueue(void) { @@ -122,19 +158,12 @@ main(int argc, char **argv) test_kqueue(); - if (test_socket) { + if (test_socket) test_evfilt_read(); - } + if (test_signal) + test_evfilt_signal(); #if TODO - if (test_signal) { - test_kevent_signal_add(); - test_kevent_signal_get(); - test_kevent_signal_disable(); - test_kevent_signal_enable(); - test_kevent_signal_del(); - test_kevent_signal_oneshot(); - } if (test_vnode) { test_kevent_vnode_add(); From 26d7b8fafb1f051eec5f805d50e3636ae2ba9b42 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 4 Nov 2009 23:22:31 +0000 Subject: [PATCH 0038/1120] fixed evfilt_signal git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@38 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/common.h | 2 ++ vendor/libkqueue/test/main.c | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index c81b42d55..59808a7a2 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -38,6 +38,8 @@ extern char *cur_test_id; int vnode_fd; extern const char * kevent_to_str(struct kevent *); +struct kevent * kevent_get(int); + void kevent_cmp(struct kevent *, struct kevent *); diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 60783331b..39453305f 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -42,6 +42,23 @@ test_no_kevents(void) } } +/* Retrieve a single kevent */ +struct kevent * +kevent_get(int kqfd) +{ + int nfds; + struct kevent *kev; + + if ((kev = calloc(1, sizeof(*kev))) == NULL) + err(1, "out of memory"); + + nfds = kevent(kqfd, NULL, 0, kev, 1, NULL); + if (nfds < 1) + err(1, "kevent(2)"); + + return (kev); +} + char * kevent_flags_dump(struct kevent *kev) { @@ -157,6 +174,7 @@ main(int argc, char **argv) } test_kqueue(); + test_kqueue_close(); if (test_socket) test_evfilt_read(); @@ -183,7 +201,6 @@ main(int argc, char **argv) } #endif - test_kqueue_close(); puts("all tests completed."); return (0); From 4d68553c11e21ecdeec9d158150f0cef535697d1 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 5 Nov 2009 02:16:01 +0000 Subject: [PATCH 0039/1120] evfilt_vnode tests work git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@39 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/Makefile | 3 ++- vendor/libkqueue/test/main.c | 39 ++++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile index f7141fbd3..91e269f7b 100644 --- a/vendor/libkqueue/test/Makefile +++ b/vendor/libkqueue/test/Makefile @@ -1,7 +1,8 @@ include config.mk all: - gcc $(CFLAGS) main.c evfilt_read.c evfilt_signal.c $(LDADD) + gcc $(CFLAGS) main.c evfilt_read.c evfilt_signal.c \ + evfilt_vnode.c $(LDADD) clean: rm -f *.o diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 39453305f..ad3c52dc6 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -23,6 +23,7 @@ int kqfd; extern void test_evfilt_read(); extern void test_evfilt_signal(); +extern void test_evfilt_vnode(); /* Checks if any events are pending, which is an error. */ void @@ -59,6 +60,38 @@ kevent_get(int kqfd) return (kev); } +char * +kevent_fflags_dump(struct kevent *kev) +{ + char *buf; + +#define KEVFFL_DUMP(attrib) \ + if (kev->fflags & attrib) \ + strcat(buf, #attrib" "); + + if ((buf = calloc(1, 1024)) == NULL) + abort(); + + /* Not every filter has meaningful fflags */ + if (kev->filter != EVFILT_VNODE) { + sprintf(buf, "fflags = %d", kev->flags); + return (buf); + } + + sprintf(buf, "fflags = %d (", kev->fflags); + KEVFFL_DUMP(NOTE_DELETE); + KEVFFL_DUMP(NOTE_WRITE); + KEVFFL_DUMP(NOTE_EXTEND); + KEVFFL_DUMP(NOTE_TRUNCATE); + KEVFFL_DUMP(NOTE_ATTRIB); + KEVFFL_DUMP(NOTE_LINK); + KEVFFL_DUMP(NOTE_RENAME); + KEVFFL_DUMP(NOTE_REVOKE); + strcat(buf, ")"); + + return (buf); +} + char * kevent_flags_dump(struct kevent *kev) { @@ -96,10 +129,10 @@ const char * kevent_to_str(struct kevent *kev) { char buf[512]; - snprintf(&buf[0], sizeof(buf), "[filter=%d,%s,fflags=%d,ident=%u,data=%d,udata=%p]", + snprintf(&buf[0], sizeof(buf), "[filter=%d,%s,%s,ident=%u,data=%d,udata=%p]", kev->filter, kevent_flags_dump(kev), - kev->fflags, + kevent_fflags_dump(kev), (u_int) kev->ident, kev->data, kev->udata); @@ -180,6 +213,8 @@ main(int argc, char **argv) test_evfilt_read(); if (test_signal) test_evfilt_signal(); + if (test_vnode) + test_evfilt_vnode(); #if TODO From a6dabaa0ddbe95f4fd4c2fd117ff93bdb26f9ab3 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 5 Nov 2009 02:16:22 +0000 Subject: [PATCH 0040/1120] add missing files git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@40 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/evfilt_signal.c | 193 ++++++++++++++++++ vendor/libkqueue/test/evfilt_vnode.c | 275 ++++++++++++++++++++++++++ 2 files changed, 468 insertions(+) create mode 100644 vendor/libkqueue/test/evfilt_signal.c create mode 100644 vendor/libkqueue/test/evfilt_vnode.c diff --git a/vendor/libkqueue/test/evfilt_signal.c b/vendor/libkqueue/test/evfilt_signal.c new file mode 100644 index 000000000..b2f62a563 --- /dev/null +++ b/vendor/libkqueue/test/evfilt_signal.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "common.h" + +int kqfd; + +void +test_kevent_signal_add(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, EV_ADD)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_signal_get(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, wait)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + kev.flags |= EV_CLEAR; + kev.data = 1; + kevent_cmp(&kev, kevent_get(kqfd)); + + success(test_id); +} + +void +test_kevent_signal_disable(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + test_no_kevents(); + + success(test_id); +} + +void +test_kevent_signal_enable(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + kev.flags = EV_ADD | EV_CLEAR; + kev.data = 2; // one extra time from test_kevent_signal_disable() + kevent_cmp(&kev, kevent_get(kqfd)); + + /* Delete the watch */ + kev.flags = EV_DELETE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_signal_del(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)"; + struct kevent kev; + + test_begin(test_id); + + /* Delete the kevent */ + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + test_no_kevents(); + success(test_id); +} + +void +test_kevent_signal_oneshot(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + kev.flags |= EV_CLEAR; + kev.data = 1; + kevent_cmp(&kev, kevent_get(kqfd)); + + /* Send another one and make sure we get no events */ + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + test_no_kevents(); + + success(test_id); +} + +void +test_evfilt_signal() +{ + kqfd = kqueue(); + test_kevent_signal_add(); + test_kevent_signal_del(); + test_kevent_signal_get(); + test_kevent_signal_disable(); + test_kevent_signal_enable(); + test_kevent_signal_oneshot(); + close(kqfd); +} diff --git a/vendor/libkqueue/test/evfilt_vnode.c b/vendor/libkqueue/test/evfilt_vnode.c new file mode 100644 index 000000000..6363bd636 --- /dev/null +++ b/vendor/libkqueue/test/evfilt_vnode.c @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "common.h" + +int kqfd; +int vnode_fd; + +void +test_kevent_vnode_add(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, EV_ADD)"; + const char *testfile = "/tmp/kqueue-test.tmp"; + struct kevent kev; + + test_begin(test_id); + + system("touch /tmp/kqueue-test.tmp"); + vnode_fd = open(testfile, O_RDONLY); + if (vnode_fd < 0) + err(1, "open of %s", testfile); + else + printf("vnode_fd = %d\n", vnode_fd); + + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD, + NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME | NOTE_DELETE, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_vnode_note_delete(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, NOTE_DELETE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* FIXME: workaround for linux behavior. if the file is open, + the delete event isn't registered; an IN_ATTRIB event is fired + instead. + + Unfortunately, closing the descriptor causes BSD kqueue to + remove the knote, thus the event is never triggered. + */ +#if LIBKQUEUE + close(vnode_fd); +#endif + + if (unlink("/tmp/kqueue-test.tmp") < 0) + err(1, "unlink"); + + kevent_cmp(&kev, kevent_get(kqfd)); + + success(test_id); +} + +void +test_kevent_vnode_note_write(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, NOTE_WRITE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_WRITE, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + if (system("echo hello >> /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + + /* BSD kqueue adds NOTE_EXTEND even though it was not requested */ + /* BSD kqueue removes EV_ENABLE */ + kev.flags &= ~EV_ENABLE; // XXX-FIXME compatibility issue + kev.fflags |= NOTE_EXTEND; // XXX-FIXME compatibility issue + kevent_cmp(&kev, kevent_get(kqfd)); + + success(test_id); +} + +void +test_kevent_vnode_note_attrib(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, NOTE_ATTRIB)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + if (system("touch /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + if (kev.ident != vnode_fd || + kev.filter != EVFILT_VNODE || + kev.fflags != NOTE_ATTRIB) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + + success(test_id); +} + +void +test_kevent_vnode_note_rename(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, NOTE_RENAME)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_RENAME, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + if (system("mv /tmp/kqueue-test.tmp /tmp/kqueue-test2.tmp") < 0) + err(1, "system"); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + if (kev.ident != vnode_fd || + kev.filter != EVFILT_VNODE || + kev.fflags != NOTE_RENAME) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + + if (system("mv /tmp/kqueue-test2.tmp /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + + success(test_id); +} + +void +test_kevent_vnode_del(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, EV_DELETE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_vnode_disable_and_enable(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, EV_DISABLE and EV_ENABLE)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + test_no_kevents(); + + /* Add the watch and immediately disable it */ + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + kev.flags = EV_DISABLE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Confirm that the watch is disabled */ + if (system("touch /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + test_no_kevents(); + + /* Re-enable and check again */ + kev.flags = EV_ENABLE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + if (system("touch /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + if (kev.ident != vnode_fd || + kev.filter != EVFILT_VNODE || + kev.fflags != NOTE_ATTRIB) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + + success(test_id); +} + +#if HAVE_EV_DISPATCH +void +test_kevent_vnode_dispatch(void) +{ + const char *test_id = "kevent(EVFILT_VNODE, EV_DISPATCH)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + test_no_kevents(); + + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_DISPATCH, NOTE_ATTRIB, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + if (system("touch /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + if (kev.ident != vnode_fd || + kev.filter != EVFILT_VNODE || + kev.fflags != NOTE_ATTRIB) + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + + /* Confirm that the watch is disabled automatically */ + puts("-- checking that watch is disabled"); + if (system("touch /tmp/kqueue-test.tmp") < 0) + err(1, "system"); + test_no_kevents(); + + /* Delete the watch */ + EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, NOTE_ATTRIB, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "remove watch failed: %s", test_id); + + success(test_id); +} +#endif /* HAVE_EV_DISPATCH */ + +void +test_evfilt_vnode() +{ + kqfd = kqueue(); + test_kevent_vnode_add(); + test_kevent_vnode_del(); + test_kevent_vnode_disable_and_enable(); +#if HAVE_EV_DISPATCH + test_kevent_vnode_dispatch(); +#endif + test_kevent_vnode_note_write(); + test_kevent_vnode_note_attrib(); + test_kevent_vnode_note_rename(); + test_kevent_vnode_note_delete(); + close(kqfd); +} From b38242f259874c397ebf80f1be1dce706b7fc0c8 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 5 Nov 2009 02:20:57 +0000 Subject: [PATCH 0041/1120] All tests work under OpenBSD 4.4 amd64 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@41 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/Makefile | 3 +-- vendor/libkqueue/test/main.c | 24 +++---------------- .../libkqueue/test/{evfilt_read.c => read.c} | 0 .../test/{evfilt_signal.c => signal.c} | 0 .../test/{evfilt_vnode.c => vnode.c} | 0 5 files changed, 4 insertions(+), 23 deletions(-) rename vendor/libkqueue/test/{evfilt_read.c => read.c} (100%) rename vendor/libkqueue/test/{evfilt_signal.c => signal.c} (100%) rename vendor/libkqueue/test/{evfilt_vnode.c => vnode.c} (100%) diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile index 91e269f7b..dedae883c 100644 --- a/vendor/libkqueue/test/Makefile +++ b/vendor/libkqueue/test/Makefile @@ -1,8 +1,7 @@ include config.mk all: - gcc $(CFLAGS) main.c evfilt_read.c evfilt_signal.c \ - evfilt_vnode.c $(LDADD) + gcc $(CFLAGS) main.c read.c signal.c vnode.c timer.c $(LDADD) clean: rm -f *.o diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index ad3c52dc6..8c36a2be1 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -24,6 +24,7 @@ int kqfd; extern void test_evfilt_read(); extern void test_evfilt_signal(); extern void test_evfilt_vnode(); +extern void test_evfilt_timer(); /* Checks if any events are pending, which is an error. */ void @@ -215,27 +216,8 @@ main(int argc, char **argv) test_evfilt_signal(); if (test_vnode) test_evfilt_vnode(); - -#if TODO - - if (test_vnode) { - test_kevent_vnode_add(); - test_kevent_vnode_del(); - test_kevent_vnode_disable_and_enable(); - test_kevent_vnode_dispatch(); - test_kevent_vnode_note_write(); - test_kevent_vnode_note_attrib(); - test_kevent_vnode_note_rename(); - test_kevent_vnode_note_delete(); - } - - if (test_timer) { - test_kevent_timer_add(); - test_kevent_timer_del(); - test_kevent_timer_get(); - } -#endif - + if (test_timer) + test_evfilt_timer(); puts("all tests completed."); return (0); diff --git a/vendor/libkqueue/test/evfilt_read.c b/vendor/libkqueue/test/read.c similarity index 100% rename from vendor/libkqueue/test/evfilt_read.c rename to vendor/libkqueue/test/read.c diff --git a/vendor/libkqueue/test/evfilt_signal.c b/vendor/libkqueue/test/signal.c similarity index 100% rename from vendor/libkqueue/test/evfilt_signal.c rename to vendor/libkqueue/test/signal.c diff --git a/vendor/libkqueue/test/evfilt_vnode.c b/vendor/libkqueue/test/vnode.c similarity index 100% rename from vendor/libkqueue/test/evfilt_vnode.c rename to vendor/libkqueue/test/vnode.c From cdcb150f0002ed54f2400b587c07039095e27d62 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 5 Nov 2009 02:27:15 +0000 Subject: [PATCH 0042/1120] move testing to separate directory git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@42 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 17 +- vendor/libkqueue/test.c | 928 --------------------------------- vendor/libkqueue/test/Makefile | 38 ++ vendor/libkqueue/test/test.c | 784 ---------------------------- 4 files changed, 39 insertions(+), 1728 deletions(-) delete mode 100644 vendor/libkqueue/test.c delete mode 100644 vendor/libkqueue/test/test.c diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 832d9906d..078a1716f 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -47,22 +47,7 @@ uninstall: rmdir $(INCLUDEDIR)/kqueue/sys $(INCLUDEDIR)/kqueue check: - make build CFLAGS="$(CFLAGS) -g -O0 -DKQUEUE_DEBUG -DUNIT_TEST" - gcc -c $(CFLAGS) test.c - gcc -g -O0 $(CFLAGS) test.c libkqueue.a -lpthread -lrt - ./a.out - -# NOTE: copy+paste of 'make check' -valgrind: - make build CFLAGS="$(CFLAGS) -g -O0 -DKQUEUE_DEBUG -DUNIT_TEST" - gcc -c $(CFLAGS) test.c - gcc -g -O0 $(CFLAGS) test.c libkqueue.a -lpthread -lrt - valgrind --tool=memcheck --leak-check=full --show-reachable=yes --num-callers=20 --track-fds=yes ./a.out - - -check-installed: - gcc -g -O0 -Wall -Werror -I$(PREFIX)/kqueue test.c -lkqueue - ./a.out + cd test && ./configure && make check dist: mkdir $(PROGRAM) diff --git a/vendor/libkqueue/test.c b/vendor/libkqueue/test.c deleted file mode 100644 index c4112079d..000000000 --- a/vendor/libkqueue/test.c +++ /dev/null @@ -1,928 +0,0 @@ -/* - * Copyright (c) 2009 Mark Heily - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sys/event.h" - -char *cur_test_id = "undef"; -int kqfd; -int sockfd[2]; -int vnode_fd; - -/* In kevent.c */ -const char * kevent_dump(struct kevent *); - -#define KEV_CMP(kev,_ident,_filter,_flags) do { \ - if (kev.ident != (_ident) || \ - kev.filter != (_filter) || \ - kev.flags != (_flags)) \ - err(1, "kevent mismatch: got %s but expecting [%d,%d,%d]", \ - kevent_dump(&kev),\ - (int)kev.ident, kev.filter, kev.flags);\ -} while (0); - -/* Checks if any events are pending, which is an error. */ -void -test_no_kevents(void) -{ - int nfds; - struct timespec timeo; - struct kevent kev; - - puts("confirming that there are no events pending"); - memset(&timeo, 0, sizeof(timeo)); - nfds = kevent(kqfd, NULL, 0, &kev, 1, &timeo); - if (nfds != 0) { - puts("\nUnexpected event:"); - puts(kevent_dump(&kev)); - errx(1, "%d event(s) pending, but none expected:", nfds); - } -} - - -void -test_begin(const char *func) -{ - static int testnum = 1; - cur_test_id = (char *) func; - printf("\n\nTest %d: %s\n", testnum++, func); -} - -void -success(const char *func) -{ - printf("%-70s %s\n", func, "passed"); -} - -void -test_kqueue(void) -{ - test_begin("kqueue()"); - if ((kqfd = kqueue()) < 0) - err(1, "kqueue()"); - test_no_kevents(); - success("kqueue()"); -} - -void -test_kqueue_close(void) -{ - test_begin("close(kq)"); - if (close(kqfd) < 0) - err(1, "close()"); - kqueue_free(kqfd); - success("kqueue_close()"); -} - -static void -kevent_socket_drain(void) -{ - char buf[1]; - - /* Drain the read buffer, then make sure there are no more events. */ - puts("draining the read buffer"); - if (read(sockfd[0], &buf[0], 1) < 1) - err(1, "read(2)"); -} - -static void -kevent_socket_fill(void) -{ - puts("filling the read buffer"); - if (write(sockfd[1], ".", 1) < 1) - err(1, "write(2)"); -} - -void -test_kevent_socket_add(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_ADD)"; - struct kevent kev; - - test_begin(test_id); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} - -void -test_kevent_socket_get(void) -{ - const char *test_id = "kevent(EVFILT_READ) wait"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - if (write(sockfd[1], ".", 1) < 1) - err(1, "write(2)"); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); - if ((int)kev.data != 1) - err(1, "incorrect data value %d", (int) kev.data); // FIXME: make part of KEV_CMP - - kevent_socket_drain(); - test_no_kevents(); - - success(test_id); -} - -void -test_kevent_socket_clear(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_CLEAR)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - test_no_kevents(); - - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - kevent_socket_fill(); - kevent_socket_fill(); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); - if ((int)kev.data != 2) - err(1, "incorrect data value %d", (int) kev.data); // FIXME: make part of KEV_CMP - - /* We filled twice, but drain once. Edge-triggered would not generate - additional events. - */ - kevent_socket_drain(); - test_no_kevents(); - - kevent_socket_drain(); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} - -void -test_kevent_socket_disable(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_DISABLE)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DISABLE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - kevent_socket_fill(); - test_no_kevents(); - kevent_socket_drain(); - - success(test_id); -} - -void -test_kevent_socket_enable(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_ENABLE)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ENABLE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - kevent_socket_fill(); - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); - kevent_socket_drain(); - - success(test_id); -} - -void -test_kevent_socket_del(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_DELETE)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - kevent_socket_fill(); - test_no_kevents(); - kevent_socket_drain(); - - success(test_id); -} - -void -test_kevent_socket_oneshot(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_ONESHOT)"; - struct kevent kev; - - test_begin(test_id); - - /* Re-add the watch and make sure no events are pending */ - puts("-- re-adding knote"); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - test_no_kevents(); - - puts("-- getting one event"); - kevent_socket_fill(); - if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) - err(1, "%s", test_id); - KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); - - puts("-- checking knote disabled"); - test_no_kevents(); - - /* Try to delete the knote, it should already be deleted */ - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0) - err(1, "%s", test_id); - - kevent_socket_drain(); - - success(test_id); -} - -void -test_kevent_socket_dispatch(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_DISPATCH)"; - struct kevent kev; - - test_begin(test_id); - - /* Re-add the watch and make sure no events are pending */ - puts("-- re-adding knote"); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - test_no_kevents(); - - /* Since the knote is disabled, there are no events. */ - puts("-- checking if knote is disabled.."); - kevent_socket_fill(); - if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) - err(1, "%s", test_id); - KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); - test_no_kevents(); - - /* Since the knote is disabled, the EV_DELETE operation succeeds. */ - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - kevent_socket_drain(); - - success(test_id); -} - -#if BROKEN -void -test_kevent_socket_lowat(void) -{ - const char *test_id = "kevent(EVFILT_READ, NOTE_LOWAT)"; - struct kevent kev; - - test_begin(test_id); - - /* Re-add the watch and make sure no events are pending */ - puts("-- re-adding knote, setting low watermark to 2 bytes"); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - test_no_kevents(); - - puts("-- checking that one byte does not trigger an event.."); - kevent_socket_fill(); - test_no_kevents(); - - puts("-- checking that two bytes triggers an event.."); - kevent_socket_fill(); - if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) - err(1, "%s", test_id); - KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); - test_no_kevents(); - - kevent_socket_drain(); - kevent_socket_drain(); - - success(test_id); -} -#endif - -void -test_kevent_socket_eof(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_EOF)"; - struct kevent kev; - - test_begin(test_id); - - /* Re-add the watch and make sure no events are pending */ - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - test_no_kevents(); - - if (close(sockfd[1]) < 0) - err(1, "close(2)"); - - if (kevent(kqfd, NULL, 0, &kev, 1, NULL) < 1) - err(1, "%s", test_id); - KEV_CMP(kev, sockfd[0], EVFILT_READ, EV_EOF); - - /* Delete the watch */ - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} - -void -test_kevent_signal_add(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, EV_ADD)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} - -void -test_kevent_signal_get(void) -{ - const char *test_id = "kevent(get signal)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - /* Block SIGUSR1, then send it to ourselves */ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - err(1, "sigprocmask"); - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "test failed: %s, retval %d", test_id, nfds); - if (kev.ident != SIGUSR1 || - kev.filter != EVFILT_SIGNAL || - kev.flags != 0) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - //FIXME: test kev->flags, fflags, data - - success(test_id); -} - -void -test_kevent_signal_disable(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Block SIGUSR1, then send it to ourselves */ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - err(1, "sigprocmask"); - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - - test_no_kevents(); - - success(test_id); -} - -void -test_kevent_signal_enable(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Block SIGUSR1, then send it to ourselves */ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - err(1, "sigprocmask"); - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "test failed: %s, retval %d", test_id, nfds); - if (kev.ident != SIGUSR1 || - kev.filter != EVFILT_SIGNAL || - kev.flags != 0) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - - success(test_id); -} - -void -test_kevent_signal_del(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)"; - struct kevent kev; - - test_begin(test_id); - - /* Delete the kevent */ - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Block SIGUSR1, then send it to ourselves */ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - err(1, "sigprocmask"); - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - - test_no_kevents(); - success(test_id); -} - -void -test_kevent_signal_oneshot(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Block SIGUSR1, then send it to ourselves */ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - err(1, "sigprocmask"); - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "test failed: %s, retval %d", test_id, nfds); - if (kev.ident != SIGUSR1 || - kev.filter != EVFILT_SIGNAL || - kev.flags != 0) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - //FIXME: test kev->flags, fflags, data - - /* Send another one and make sure we get no events */ - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - test_no_kevents(); - - success(test_id); -} - -void -test_kevent_vnode_add(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, EV_ADD)"; - const char *testfile = "/tmp/kqueue-test.tmp"; - struct kevent kev; - - test_begin(test_id); - - system("touch /tmp/kqueue-test.tmp"); - vnode_fd = open(testfile, O_RDONLY); - if (vnode_fd < 0) - err(1, "open of %s", testfile); - else - printf("vnode_fd = %d\n", vnode_fd); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD, - NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME | NOTE_DELETE, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} - -void -test_kevent_vnode_note_delete(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, NOTE_DELETE)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* FIXME: workaround for linux behavior. if the file is open, - the delete event isn't registered; an IN_ATTRIB event is fired - instead. - */ - close(vnode_fd); - if (unlink("/tmp/kqueue-test.tmp") < 0) - err(1, "unlink"); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s %d events", test_id, nfds); - if (kev.ident != vnode_fd || - kev.filter != EVFILT_VNODE || - kev.fflags != NOTE_DELETE) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - - success(test_id); -} - -void -test_kevent_vnode_note_write(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, NOTE_WRITE)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_WRITE, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - if (system("echo hello >> /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - if (kev.ident != vnode_fd || - kev.filter != EVFILT_VNODE || - kev.fflags != NOTE_WRITE) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - - success(test_id); -} - -void -test_kevent_vnode_note_attrib(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, NOTE_ATTRIB)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - if (system("touch /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - if (kev.ident != vnode_fd || - kev.filter != EVFILT_VNODE || - kev.fflags != NOTE_ATTRIB) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - - success(test_id); -} - -void -test_kevent_vnode_note_rename(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, NOTE_RENAME)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_RENAME, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - if (system("mv /tmp/kqueue-test.tmp /tmp/kqueue-test2.tmp") < 0) - err(1, "system"); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - if (kev.ident != vnode_fd || - kev.filter != EVFILT_VNODE || - kev.fflags != NOTE_RENAME) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - - if (system("mv /tmp/kqueue-test2.tmp /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - - success(test_id); -} - -void -test_kevent_vnode_del(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, EV_DELETE)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} - -void -test_kevent_vnode_disable_and_enable(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, EV_DISABLE and EV_ENABLE)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - test_no_kevents(); - - /* Add the watch and immediately disable it */ - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - kev.flags = EV_DISABLE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Confirm that the watch is disabled */ - if (system("touch /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - test_no_kevents(); - - /* Re-enable and check again */ - kev.flags = EV_ENABLE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - if (system("touch /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - if (kev.ident != vnode_fd || - kev.filter != EVFILT_VNODE || - kev.fflags != NOTE_ATTRIB) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - - success(test_id); -} - -void -test_kevent_vnode_dispatch(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, EV_DISPATCH)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - test_no_kevents(); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_DISPATCH, NOTE_ATTRIB, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - if (system("touch /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - if (kev.ident != vnode_fd || - kev.filter != EVFILT_VNODE || - kev.fflags != NOTE_ATTRIB) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - - /* Confirm that the watch is disabled automatically */ - puts("-- checking that watch is disabled"); - if (system("touch /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - test_no_kevents(); - - /* Delete the watch */ - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, NOTE_ATTRIB, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "remove watch failed: %s", test_id); - - success(test_id); -} - -void -test_kevent_timer_add(void) -{ - const char *test_id = "kevent(EVFILT_TIMER, EV_ADD)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} - -void -test_kevent_timer_del(void) -{ - const char *test_id = "kevent(EVFILT_TIMER, EV_DELETE)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} - -void -test_kevent_timer_get(void) -{ - const char *test_id = "kevent(EVFILT_TIMER, get)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - if (kev.ident != 1 || kev.filter != EVFILT_TIMER) - errx(1, "wrong event"); - - EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} - -int -main(int argc, char **argv) -{ - int test_socket = 1; - int test_signal = 1;//XXX-FIXME - int test_vnode = 1; - int test_timer = 1; - - while (argc) { - if (strcmp(argv[0], "--no-socket") == 0) - test_socket = 0; - if (strcmp(argv[0], "--no-timer") == 0) - test_timer = 0; - if (strcmp(argv[0], "--no-signal") == 0) - test_signal = 0; - if (strcmp(argv[0], "--no-vnode") == 0) - test_vnode = 0; - argv++; - argc--; - } - - /* Create a connected pair of full-duplex sockets for testing socket events */ - if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd) < 0) - abort(); - - test_kqueue(); - - if (test_socket) { - test_kevent_socket_add(); - test_kevent_socket_get(); - test_kevent_socket_disable(); - test_kevent_socket_enable(); - test_kevent_socket_del(); - test_kevent_socket_oneshot(); - test_kevent_socket_clear(); - test_kevent_socket_dispatch(); - /* TODO: broken on linux: test_kevent_socket_lowat(); */ - test_kevent_socket_eof(); - } - - if (test_signal) { - test_kevent_signal_add(); - test_kevent_signal_get(); - test_kevent_signal_disable(); - test_kevent_signal_enable(); - test_kevent_signal_del(); - test_kevent_signal_oneshot(); - } - - if (test_vnode) { - test_kevent_vnode_add(); - test_kevent_vnode_del(); - test_kevent_vnode_disable_and_enable(); - test_kevent_vnode_dispatch(); - test_kevent_vnode_note_write(); - test_kevent_vnode_note_attrib(); - test_kevent_vnode_note_rename(); - test_kevent_vnode_note_delete(); - } - - if (test_timer) { - test_kevent_timer_add(); - test_kevent_timer_del(); - test_kevent_timer_get(); - } - - test_kqueue_close(); - - puts("all tests completed."); - return (0); -} diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile index dedae883c..f1cf42b39 100644 --- a/vendor/libkqueue/test/Makefile +++ b/vendor/libkqueue/test/Makefile @@ -1,7 +1,45 @@ +# +# Copyright (c) 2009 Mark Heily +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + include config.mk all: gcc $(CFLAGS) main.c read.c signal.c vnode.c timer.c $(LDADD) + ./a.out + +check: + cd .. && make build CFLAGS="$(CFLAGS) -g -O0 -DKQUEUE_DEBUG -DUNIT_TEST" + gcc -c $(CFLAGS) test.c + gcc $(CFLAGS) test.c libkqueue.a $(LDADD) + ./a.out + +# NOTE: copy+paste of 'make check' +valgrind: + cd .. && make build CFLAGS="$(CFLAGS) -g -O0 -DKQUEUE_DEBUG -DUNIT_TEST" + gcc -c $(CFLAGS) test.c + gcc -g -O0 $(CFLAGS) test.c libkqueue.a $(LDADD) + valgrind --tool=memcheck --leak-check=full --show-reachable=yes --num-callers=20 --track-fds=yes ./a.out + + +check-installed: + gcc $(CFLAGS) -I$(PREFIX)/kqueue test.c -lkqueue + ./a.out + +distclean: clean + rm -f config.mk config.h clean: rm -f *.o diff --git a/vendor/libkqueue/test/test.c b/vendor/libkqueue/test/test.c deleted file mode 100644 index 771ffe5c8..000000000 --- a/vendor/libkqueue/test/test.c +++ /dev/null @@ -1,784 +0,0 @@ -/* - * Copyright (c) 2009 Mark Heily - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sys/event.h" - -char *cur_test_id = "undef"; -int kqfd; -int sockfd[2]; -int vnode_fd; - -/* In kevent.c */ -const char * kevent_dump(struct kevent *); - -#define KEV_CMP(kev,_ident,_filter,_flags) do { \ - if (kev.ident != (_ident) || \ - kev.filter != (_filter) || \ - kev.flags != (_flags)) \ - err(1, "kevent mismatch: got %s but expecting [%d,%d,%d]", \ - kevent_dump(&kev),\ - (int)kev.ident, kev.filter, kev.flags);\ -} while (0); - -void -test_kevent_socket_add(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_ADD)"; - struct kevent kev; - - test_begin(test_id); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} - -void -test_kevent_socket_get(void) -{ - const char *test_id = "kevent(EVFILT_READ) wait"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - if (write(sockfd[1], ".", 1) < 1) - err(1, "write(2)"); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); - if ((int)kev.data != 1) - err(1, "incorrect data value %d", (int) kev.data); // FIXME: make part of KEV_CMP - - kevent_socket_drain(); - test_no_kevents(); - - success(test_id); -} - -void -test_kevent_socket_clear(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_CLEAR)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - test_no_kevents(); - - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - kevent_socket_fill(); - kevent_socket_fill(); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); - if ((int)kev.data != 2) - err(1, "incorrect data value %d", (int) kev.data); // FIXME: make part of KEV_CMP - - /* We filled twice, but drain once. Edge-triggered would not generate - additional events. - */ - kevent_socket_drain(); - test_no_kevents(); - - kevent_socket_drain(); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} - -void -test_kevent_socket_disable(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_DISABLE)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DISABLE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - kevent_socket_fill(); - test_no_kevents(); - kevent_socket_drain(); - - success(test_id); -} - -void -test_kevent_socket_enable(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_ENABLE)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ENABLE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - kevent_socket_fill(); - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); - kevent_socket_drain(); - - success(test_id); -} - -void -test_kevent_socket_del(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_DELETE)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - kevent_socket_fill(); - test_no_kevents(); - kevent_socket_drain(); - - success(test_id); -} - -void -test_kevent_socket_oneshot(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_ONESHOT)"; - struct kevent kev; - - test_begin(test_id); - - /* Re-add the watch and make sure no events are pending */ - puts("-- re-adding knote"); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - test_no_kevents(); - - puts("-- getting one event"); - kevent_socket_fill(); - if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) - err(1, "%s", test_id); - KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); - - puts("-- checking knote disabled"); - test_no_kevents(); - - /* Try to delete the knote, it should already be deleted */ - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0) - err(1, "%s", test_id); - - kevent_socket_drain(); - - success(test_id); -} - -void -test_kevent_socket_dispatch(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_DISPATCH)"; - struct kevent kev; - - test_begin(test_id); - - /* Re-add the watch and make sure no events are pending */ - puts("-- re-adding knote"); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - test_no_kevents(); - - /* Since the knote is disabled, there are no events. */ - puts("-- checking if knote is disabled.."); - kevent_socket_fill(); - if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) - err(1, "%s", test_id); - KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); - test_no_kevents(); - - /* Since the knote is disabled, the EV_DELETE operation succeeds. */ - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - kevent_socket_drain(); - - success(test_id); -} - -#if BROKEN -void -test_kevent_socket_lowat(void) -{ - const char *test_id = "kevent(EVFILT_READ, NOTE_LOWAT)"; - struct kevent kev; - - test_begin(test_id); - - /* Re-add the watch and make sure no events are pending */ - puts("-- re-adding knote, setting low watermark to 2 bytes"); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - test_no_kevents(); - - puts("-- checking that one byte does not trigger an event.."); - kevent_socket_fill(); - test_no_kevents(); - - puts("-- checking that two bytes triggers an event.."); - kevent_socket_fill(); - if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) - err(1, "%s", test_id); - KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); - test_no_kevents(); - - kevent_socket_drain(); - kevent_socket_drain(); - - success(test_id); -} -#endif - -void -test_kevent_socket_eof(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_EOF)"; - struct kevent kev; - - test_begin(test_id); - - /* Re-add the watch and make sure no events are pending */ - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - test_no_kevents(); - - if (close(sockfd[1]) < 0) - err(1, "close(2)"); - - if (kevent(kqfd, NULL, 0, &kev, 1, NULL) < 1) - err(1, "%s", test_id); - KEV_CMP(kev, sockfd[0], EVFILT_READ, EV_EOF); - - /* Delete the watch */ - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} - -void -test_kevent_signal_add(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, EV_ADD)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} - -void -test_kevent_signal_get(void) -{ - const char *test_id = "kevent(get signal)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - /* Block SIGUSR1, then send it to ourselves */ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - err(1, "sigprocmask"); - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "test failed: %s, retval %d", test_id, nfds); - if (kev.ident != SIGUSR1 || - kev.filter != EVFILT_SIGNAL || - kev.flags != 0) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - //FIXME: test kev->flags, fflags, data - - success(test_id); -} - -void -test_kevent_signal_disable(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Block SIGUSR1, then send it to ourselves */ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - err(1, "sigprocmask"); - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - - test_no_kevents(); - - success(test_id); -} - -void -test_kevent_signal_enable(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Block SIGUSR1, then send it to ourselves */ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - err(1, "sigprocmask"); - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "test failed: %s, retval %d", test_id, nfds); - if (kev.ident != SIGUSR1 || - kev.filter != EVFILT_SIGNAL || - kev.flags != 0) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - - success(test_id); -} - -void -test_kevent_signal_del(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)"; - struct kevent kev; - - test_begin(test_id); - - /* Delete the kevent */ - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Block SIGUSR1, then send it to ourselves */ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - err(1, "sigprocmask"); - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - - test_no_kevents(); - success(test_id); -} - -void -test_kevent_signal_oneshot(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Block SIGUSR1, then send it to ourselves */ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - err(1, "sigprocmask"); - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "test failed: %s, retval %d", test_id, nfds); - if (kev.ident != SIGUSR1 || - kev.filter != EVFILT_SIGNAL || - kev.flags != 0) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - //FIXME: test kev->flags, fflags, data - - /* Send another one and make sure we get no events */ - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - test_no_kevents(); - - success(test_id); -} - -void -test_kevent_vnode_add(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, EV_ADD)"; - const char *testfile = "/tmp/kqueue-test.tmp"; - struct kevent kev; - - test_begin(test_id); - - system("touch /tmp/kqueue-test.tmp"); - vnode_fd = open(testfile, O_RDONLY); - if (vnode_fd < 0) - err(1, "open of %s", testfile); - else - printf("vnode_fd = %d\n", vnode_fd); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD, - NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME | NOTE_DELETE, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} - -void -test_kevent_vnode_note_delete(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, NOTE_DELETE)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* FIXME: workaround for linux behavior. if the file is open, - the delete event isn't registered; an IN_ATTRIB event is fired - instead. - */ - close(vnode_fd); - if (unlink("/tmp/kqueue-test.tmp") < 0) - err(1, "unlink"); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s %d events", test_id, nfds); - if (kev.ident != vnode_fd || - kev.filter != EVFILT_VNODE || - kev.fflags != NOTE_DELETE) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - - success(test_id); -} - -void -test_kevent_vnode_note_write(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, NOTE_WRITE)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_WRITE, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - if (system("echo hello >> /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - if (kev.ident != vnode_fd || - kev.filter != EVFILT_VNODE || - kev.fflags != NOTE_WRITE) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - - success(test_id); -} - -void -test_kevent_vnode_note_attrib(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, NOTE_ATTRIB)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - if (system("touch /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - if (kev.ident != vnode_fd || - kev.filter != EVFILT_VNODE || - kev.fflags != NOTE_ATTRIB) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - - success(test_id); -} - -void -test_kevent_vnode_note_rename(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, NOTE_RENAME)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_RENAME, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - if (system("mv /tmp/kqueue-test.tmp /tmp/kqueue-test2.tmp") < 0) - err(1, "system"); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - if (kev.ident != vnode_fd || - kev.filter != EVFILT_VNODE || - kev.fflags != NOTE_RENAME) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - - if (system("mv /tmp/kqueue-test2.tmp /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - - success(test_id); -} - -void -test_kevent_vnode_del(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, EV_DELETE)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} - -void -test_kevent_vnode_disable_and_enable(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, EV_DISABLE and EV_ENABLE)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - test_no_kevents(); - - /* Add the watch and immediately disable it */ - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - kev.flags = EV_DISABLE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Confirm that the watch is disabled */ - if (system("touch /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - test_no_kevents(); - - /* Re-enable and check again */ - kev.flags = EV_ENABLE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - if (system("touch /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - if (kev.ident != vnode_fd || - kev.filter != EVFILT_VNODE || - kev.fflags != NOTE_ATTRIB) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - - success(test_id); -} - -void -test_kevent_vnode_dispatch(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, EV_DISPATCH)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - test_no_kevents(); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_DISPATCH, NOTE_ATTRIB, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - if (system("touch /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - if (kev.ident != vnode_fd || - kev.filter != EVFILT_VNODE || - kev.fflags != NOTE_ATTRIB) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - - /* Confirm that the watch is disabled automatically */ - puts("-- checking that watch is disabled"); - if (system("touch /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - test_no_kevents(); - - /* Delete the watch */ - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, NOTE_ATTRIB, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "remove watch failed: %s", test_id); - - success(test_id); -} - -void -test_kevent_timer_add(void) -{ - const char *test_id = "kevent(EVFILT_TIMER, EV_ADD)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} - -void -test_kevent_timer_del(void) -{ - const char *test_id = "kevent(EVFILT_TIMER, EV_DELETE)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} - -void -test_kevent_timer_get(void) -{ - const char *test_id = "kevent(EVFILT_TIMER, get)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - if (kev.ident != 1 || kev.filter != EVFILT_TIMER) - errx(1, "wrong event"); - - EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} From 48ee597eceebcaa627c4627c3fe6eda76803e8fa Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 5 Nov 2009 02:27:49 +0000 Subject: [PATCH 0043/1120] add timer git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@43 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/timer.c | 90 +++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 vendor/libkqueue/test/timer.c diff --git a/vendor/libkqueue/test/timer.c b/vendor/libkqueue/test/timer.c new file mode 100644 index 000000000..2e82f0b03 --- /dev/null +++ b/vendor/libkqueue/test/timer.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "common.h" + +int kqfd; + +void +test_kevent_timer_add(void) +{ + const char *test_id = "kevent(EVFILT_TIMER, EV_ADD)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_timer_del(void) +{ + const char *test_id = "kevent(EVFILT_TIMER, EV_DELETE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_timer_get(void) +{ + const char *test_id = "kevent(EVFILT_TIMER, get)"; + struct kevent kev; + int nfds; + + test_begin(test_id); + + EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) + err(1, "%s", test_id); + if (kev.ident != 1 || kev.filter != EVFILT_TIMER) + errx(1, "wrong event"); + + EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_evfilt_timer() +{ + kqfd = kqueue(); + test_kevent_timer_add(); + test_kevent_timer_del(); + test_kevent_timer_get(); +#if TODO + test_kevent_signal_disable(); + test_kevent_signal_enable(); + test_kevent_signal_oneshot(); +#endif + close(kqfd); +} From 2e7b5051f48543cd1694dc4815f9fc829e745f7b Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 6 Nov 2009 00:18:53 +0000 Subject: [PATCH 0044/1120] Build improvements as suggested by Mario Schwalbe git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@44 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 5 ++--- vendor/libkqueue/configure | 10 +++++----- vendor/libkqueue/test/config.h | 13 ------------- 3 files changed, 7 insertions(+), 21 deletions(-) delete mode 100644 vendor/libkqueue/test/config.h diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 078a1716f..af6ef4f06 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -24,17 +24,16 @@ include config.mk build: gcc $(CFLAGS) -c *.c - rm test.o ar rcs libkqueue.a *.o gcc -shared -Wl,-soname,libkqueue.so -o libkqueue.so *.o install: - $(INSTALL) -d -m 755 $(INCLUDEDIR)/kqueue $(INSTALL) -d -m 755 $(INCLUDEDIR)/kqueue/sys - $(INSTALL) -d -m 755 $(MANDIR)/man2 $(INSTALL) -m 644 sys/event.h $(INCLUDEDIR)/kqueue/sys/event.h $(INSTALL) -m 644 libkqueue.so $(LIBDIR)/libkqueue.so + $(INSTALL) -d -m 755 $(LIBDIR)/pkgconfig $(INSTALL) -m 644 libkqueue.pc $(LIBDIR)/pkgconfig + $(INSTALL) -d -m 755 $(MANDIR)/man2 $(INSTALL) -m 644 kqueue.2 $(MANDIR)/man2/kqueue.2 $(INSTALL) -m 644 kqueue.2 $(MANDIR)/man2/kevent.2 diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index bbd24ca81..a72cdc390 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -66,14 +66,14 @@ echo "Checking operating system type... $target" rm -f socket.c vnode.c signal.c timer.c user.c if [ $target = "linux" ] ; then check_header sys/epoll.h && ln -s os/linux/socket.c \ - || ln -s os/posix/socket.c + || ln -sf os/posix/socket.c check_header sys/inotify.h && ln -s os/linux/vnode.c \ - || ln -s os/posix/vnode.c + || ln -sf os/posix/vnode.c check_header sys/signalfd.h && ln -s os/linux/signal.c \ - || ln -s os/posix/signal.c + || ln -sf os/posix/signal.c check_header sys/timerfd.h && ln -s os/linux/timer.c \ - || ln -s os/posix/timer.c - ln -s os/posix/user.c + || ln -sf os/posix/timer.c + ln -sf os/posix/user.c fi echo "Creating config.h" diff --git a/vendor/libkqueue/test/config.h b/vendor/libkqueue/test/config.h deleted file mode 100644 index f83da8f39..000000000 --- a/vendor/libkqueue/test/config.h +++ /dev/null @@ -1,13 +0,0 @@ -/* AUTOMATICALLY GENERATED -- DO NOT EDIT */ -#define PROGRAM "libkqueue-test" -#define VERSION "0.1" -#define TARGET "openbsd" -#define PREFIX "/usr/local" -#define LIBDIR "/usr/local/lib" -#define INCLUDEDIR "/usr/local/include" -#define MANDIR "/usr/local/share/man" -#define HAVE_SYS_EVENT_H -#undef HAVE_EVFILT_DISPATCH -#undef HAVE_EVFILT_RECEIPT -#define CFLAGS "-g -O0 -Wall -Werror" -#define LDADD "" From 235d919298d2db0e7d176be0544e628b3870f8cd Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 6 Nov 2009 03:12:23 +0000 Subject: [PATCH 0045/1120] vnode fixes, build fixes. unit tests run under linux and openbsd. last checkin before 0.1 branch git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@45 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 1 - vendor/libkqueue/configure | 20 +++++-- vendor/libkqueue/os/linux/signal.c | 6 +- vendor/libkqueue/os/linux/socket.c | 6 +- vendor/libkqueue/os/linux/vnode.c | 95 +++++++++++++++++++++++++----- vendor/libkqueue/private.h | 5 ++ vendor/libkqueue/sys/event.h | 2 - vendor/libkqueue/test/Makefile | 11 ++-- vendor/libkqueue/test/main.c | 12 +++- vendor/libkqueue/test/read.c | 76 ++++++++++-------------- vendor/libkqueue/test/signal.c | 4 ++ vendor/libkqueue/test/vnode.c | 11 ---- vendor/libkqueue/www/index.html | 19 +++--- 13 files changed, 167 insertions(+), 101 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index af6ef4f06..171cb39d9 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -17,7 +17,6 @@ PROGRAM=libkqueue INSTALL=/usr/bin/install DISTFILES=*.c *.h kqueue.2 README Makefile configure os sys SOURCES=src/$(UNAME)/*.c -CFLAGS=-fPIC -D_REENTRANT -I. -Wall -Werror -fvisibility=hidden FILTERS=vnode.c timer.c signal.c socket.c user.c include config.mk diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index a72cdc390..1ce47522a 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -4,12 +4,12 @@ program=libkqueue version=0.1 finalize() { - eval "if [ \"\$$1\" = \"\" ] ; then $1=$2 ; fi" + eval "if [ \"\$$1\" = \"\" ] ; then $1=\"$2\" ; fi" # Add the variable to config.mk and config.h - id=`echo $1 | tr 'a-z' 'A-Z'`; - eval "echo \"$id=\$$1\" >> config.mk" - eval "echo \"#define $id \\\"\$$1\\\"\" >> config.h" + uc_id=`echo $1 | tr 'a-z' 'A-Z'`; + eval "echo \"$uc_id=\"\$$1\"\" >> config.mk" + eval "echo \"#define $uc_id \\\"\$$1\\\"\" >> config.h" } process_argv() { @@ -44,16 +44,25 @@ check_header() { # ####################################################################### +default_cflags="-fPIC -D_REENTRANT -I. -Wall -Werror" + # Initialize the output files # -for output_file in config.h config.mk $program.pc +for output_file in config.mk $program.pc do rm -f $output_file echo "# AUTOMATICALLY GENERATED -- DO NOT EDIT" > $output_file done +rm -f config.h +echo "/* AUTOMATICALLY GENERATED -- DO NOT EDIT */" > config.h process_argv $* +if [ "$debug" = "yes" ] +then + default_cflags="$default_cflags -DKQUEUE_DEBUG" +fi + finalize program $program finalize version $version finalize target `uname -s | tr A-Z a-z` @@ -61,6 +70,7 @@ finalize prefix /usr/local finalize libdir "${prefix}/lib" finalize includedir "${prefix}/include" finalize mandir "${prefix}/share/man" +finalize cflags "$default_cflags" echo "Checking operating system type... $target" rm -f socket.c vnode.c signal.c timer.c user.c diff --git a/vendor/libkqueue/os/linux/signal.c b/vendor/libkqueue/os/linux/signal.c index 38e32da7a..7451c9fc2 100644 --- a/vendor/libkqueue/os/linux/signal.c +++ b/vendor/libkqueue/os/linux/signal.c @@ -119,7 +119,7 @@ evfilt_signal_copyout(struct filter *filt, dst->ident = sig[i].ssi_signo; dst->filter = EVFILT_SIGNAL; dst->udata = kn->kev.udata; - dst->flags = 0; + dst->flags = EV_ADD | EV_CLEAR; dst->fflags = 0; dst->data = 1; @@ -129,8 +129,10 @@ evfilt_signal_copyout(struct filter *filt, } if (kn->kev.flags & EV_DISPATCH) KNOTE_DISABLE(kn); - if (kn->kev.flags & EV_ONESHOT) + if (kn->kev.flags & EV_ONESHOT) { + dst->flags |= EV_ONESHOT; knote_free(kn); + } dst++; nevents++; diff --git a/vendor/libkqueue/os/linux/socket.c b/vendor/libkqueue/os/linux/socket.c index 71da32d9c..be37a31bd 100644 --- a/vendor/libkqueue/os/linux/socket.c +++ b/vendor/libkqueue/os/linux/socket.c @@ -178,8 +178,12 @@ evfilt_socket_copyout(struct filter *filt, dst->ident = kn->kev.ident; dst->filter = kn->kev.filter; dst->udata = kn->kev.udata; - dst->flags = 0; + dst->flags = EV_ADD; dst->fflags = 0; + if (kn->kev.flags & EV_ONESHOT) /*TODO: move elsewhere */ + dst->flags |= EV_ONESHOT; + if (kn->kev.flags & EV_CLEAR) /*TODO: move elsewhere */ + dst->flags |= EV_CLEAR; if (ev->events & EPOLLRDHUP || ev->events & EPOLLHUP) dst->flags |= EV_EOF; if (ev->events & EPOLLERR) diff --git a/vendor/libkqueue/os/linux/vnode.c b/vendor/libkqueue/os/linux/vnode.c index bafa16fa6..121986df4 100644 --- a/vendor/libkqueue/os/linux/vnode.c +++ b/vendor/libkqueue/os/linux/vnode.c @@ -35,16 +35,18 @@ #include "sys/event.h" #include "private.h" +char * +inotify_mask_dump(uint32_t mask) +{ + char *buf; + #define INEVT_MASK_DUMP(attrib) \ - if (evt->mask & attrib) \ - fputs(#attrib, stdout); + if (mask & attrib) \ + strcat(buf, #attrib" "); -static void -inotify_event_dump(struct inotify_event *evt) -{ - fputs("[BEGIN: inotify_event dump]\n", stdout); - fprintf(stdout, " wd = %d\n", evt->wd); - fprintf(stdout, " mask = %o (", evt->mask); + if ((buf = calloc(1, 1024)) == NULL) + abort(); + sprintf(buf, "mask = %d (", mask); INEVT_MASK_DUMP(IN_ACCESS); INEVT_MASK_DUMP(IN_MODIFY); INEVT_MASK_DUMP(IN_ATTRIB); @@ -57,6 +59,18 @@ inotify_event_dump(struct inotify_event *evt) INEVT_MASK_DUMP(IN_DELETE); INEVT_MASK_DUMP(IN_DELETE_SELF); INEVT_MASK_DUMP(IN_MOVE_SELF); + buf[strlen(buf) - 1] = ')'; + + return (buf); +} + +static void +inotify_event_dump(struct inotify_event *evt) +{ + fputs("[BEGIN: inotify_event dump]\n", stdout); + fprintf(stdout, " wd = %d\n", evt->wd); + fprintf(stdout, " %s", inotify_mask_dump(evt->mask)); + fputs(")\n", stdout); fputs("[END: inotify_event dump]\n", stdout); fflush(stdout); @@ -140,6 +154,7 @@ evfilt_vnode_copyin(struct filter *filt, struct knote *dst, const struct kevent *src) { char path[PATH_MAX]; + struct stat sb; uint32_t mask; if (src->flags & EV_DELETE || src->flags & EV_DISABLE) @@ -147,7 +162,12 @@ evfilt_vnode_copyin(struct filter *filt, if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) { memcpy(&dst->kev, src, sizeof(*src)); - dst->kev.flags |= EV_CLEAR; + if (fstat(src->ident, &sb) < 0) { + dbg_puts("fstat failed"); + return (-1); + } + dst->kn_st_nlink = sb.st_nlink; + dst->kn_st_size = sb.st_size; dst->kev.data = -1; } @@ -160,18 +180,21 @@ evfilt_vnode_copyin(struct filter *filt, /* Convert the fflags to the inotify mask */ mask = 0; if (dst->kev.fflags & NOTE_DELETE) - mask |= IN_DELETE_SELF; - if (dst->kev.fflags & NOTE_WRITE) - mask |= IN_MODIFY; - if (dst->kev.fflags & NOTE_ATTRIB) + mask |= IN_ATTRIB | IN_DELETE_SELF; + if (dst->kev.fflags & NOTE_WRITE) + mask |= IN_MODIFY | IN_ATTRIB; + if (dst->kev.fflags & NOTE_EXTEND) + mask |= IN_MODIFY | IN_ATTRIB; + if ((dst->kev.fflags & NOTE_ATTRIB) || + (dst->kev.fflags & NOTE_LINK)) mask |= IN_ATTRIB; if (dst->kev.fflags & NOTE_RENAME) mask |= IN_MOVE_SELF; if (dst->kev.flags & EV_ONESHOT) mask |= IN_ONESHOT; - dbg_printf("inotify_add_watch(2); inofd=%d, mask=%d, path=%s", - filt->kf_pfd, mask, path); + dbg_printf("inotify_add_watch(2); inofd=%d, %s, path=%s", + filt->kf_pfd, inotify_mask_dump(mask), path); dst->kev.data = inotify_add_watch(filt->kf_pfd, path, mask); if (dst->kev.data < 0) { dbg_printf("inotify_add_watch(2): %s", strerror(errno)); @@ -188,6 +211,7 @@ evfilt_vnode_copyout(struct filter *filt, int nevents) { struct inotify_event evt; + struct stat sb; struct knote *kn; if (get_one_event(&evt, filt->kf_pfd) < 0) @@ -209,9 +233,48 @@ evfilt_vnode_copyout(struct filter *filt, dst->ident = kn->kev.ident; dst->filter = kn->kev.filter; dst->udata = kn->kev.udata; - dst->flags = 0; + dst->flags = kn->kev.flags; dst->fflags = 0; + /* No error checking because fstat(2) should rarely fail */ + if ((evt.mask & IN_ATTRIB || evt.mask & IN_MODIFY) + && fstat(kn->kev.ident, &sb) == 0) { + if (sb.st_nlink == 0 && kn->kev.fflags & NOTE_DELETE) + dst->fflags |= NOTE_DELETE; + if (sb.st_nlink != kn->kn_st_nlink && kn->kev.fflags & NOTE_LINK) + dst->fflags |= NOTE_LINK; +#if HAVE_NOTE_TRUNCATE + if (sb.st_nsize == 0 && kn->kev.fflags & NOTE_TRUNCATE) + dst->fflags |= NOTE_TRUNCATE; +#endif + if (sb.st_size > kn->kn_st_size && kn->kev.fflags & NOTE_WRITE) + dst->fflags |= NOTE_EXTEND; + kn->kn_st_nlink = sb.st_nlink; + kn->kn_st_size = sb.st_size; + } + + if (evt.mask & IN_MODIFY && kn->kev.fflags & NOTE_WRITE) + dst->fflags |= NOTE_WRITE; + if (evt.mask & IN_ATTRIB && kn->kev.fflags & NOTE_ATTRIB) + dst->fflags |= NOTE_ATTRIB; + if (evt.mask & IN_MOVE_SELF && kn->kev.fflags & NOTE_RENAME) + dst->fflags |= NOTE_RENAME; + if (evt.mask & IN_DELETE_SELF && kn->kev.fflags & NOTE_DELETE) + dst->fflags |= NOTE_DELETE; + + if (kn->kev.flags & EV_DISPATCH) { + delete_watch(filt->kf_pfd, kn); /* TODO: error checking */ + KNOTE_DISABLE(kn); +#if HAVE_NOTE_TRUNCATE + if (sb.st_size == 0 && kn->kev.fflags & NOTE_TRUNCATE) + dst->fflags |= NOTE_TRUNCATE; +#endif + if (sb.st_size > kn->kn_st_size && kn->kev.fflags & NOTE_WRITE) + dst->fflags |= NOTE_EXTEND; + kn->kn_st_nlink = sb.st_nlink; + kn->kn_st_size = sb.st_size; + } + if (evt.mask & IN_MODIFY && kn->kev.fflags & NOTE_WRITE) dst->fflags |= NOTE_WRITE; if (evt.mask & IN_ATTRIB && kn->kev.fflags & NOTE_ATTRIB) diff --git a/vendor/libkqueue/private.h b/vendor/libkqueue/private.h index 2faf0e84f..fe06721f5 100644 --- a/vendor/libkqueue/private.h +++ b/vendor/libkqueue/private.h @@ -38,9 +38,14 @@ struct kqueue; struct kevent; struct evfilt_data; +/* TODO: Make this a variable length structure and allow + each filter to add custom fields at the end. + */ struct knote { struct kevent kev; int kn_pfd; /* Used by timerfd */ + nlink_t kn_st_nlink; /* Used by vnode */ + off_t kn_st_size; /* Used by vnode */ LIST_ENTRY(knote) entries; }; LIST_HEAD(knotelist, knote); diff --git a/vendor/libkqueue/sys/event.h b/vendor/libkqueue/sys/event.h index 5792059cc..e16ddc8ba 100644 --- a/vendor/libkqueue/sys/event.h +++ b/vendor/libkqueue/sys/event.h @@ -122,10 +122,8 @@ struct kevent { #define NOTE_DELETE 0x0001 /* vnode was removed */ #define NOTE_WRITE 0x0002 /* data contents changed */ #define NOTE_EXTEND 0x0004 /* size increased */ -#undef NOTE_EXTEND /* Not supported on Linux */ #define NOTE_ATTRIB 0x0008 /* attributes changed */ #define NOTE_LINK 0x0010 /* link count changed */ -#undef NOTE_LINK /* Not supported on Linux */ #define NOTE_RENAME 0x0020 /* vnode was renamed */ #define NOTE_REVOKE 0x0040 /* vnode access was revoked */ #undef NOTE_REVOKE /* Not supported on Linux */ diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile index f1cf42b39..d7cff6767 100644 --- a/vendor/libkqueue/test/Makefile +++ b/vendor/libkqueue/test/Makefile @@ -16,14 +16,13 @@ include config.mk -all: - gcc $(CFLAGS) main.c read.c signal.c vnode.c timer.c $(LDADD) - ./a.out +SOURCES=main.c read.c signal.c vnode.c timer.c check: - cd .. && make build CFLAGS="$(CFLAGS) -g -O0 -DKQUEUE_DEBUG -DUNIT_TEST" - gcc -c $(CFLAGS) test.c - gcc $(CFLAGS) test.c libkqueue.a $(LDADD) + if [ ! -f /usr/include/sys/event.h ] ; then \ + cd .. && ./configure --debug=yes && make build ; \ + fi + gcc $(CFLAGS) $(SOURCES) $(LDADD) ./a.out # NOTE: copy+paste of 'make check' diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 8c36a2be1..ecb4223b8 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -83,12 +83,16 @@ kevent_fflags_dump(struct kevent *kev) KEVFFL_DUMP(NOTE_DELETE); KEVFFL_DUMP(NOTE_WRITE); KEVFFL_DUMP(NOTE_EXTEND); +#if HAVE_NOTE_TRUNCATE KEVFFL_DUMP(NOTE_TRUNCATE); +#endif KEVFFL_DUMP(NOTE_ATTRIB); KEVFFL_DUMP(NOTE_LINK); KEVFFL_DUMP(NOTE_RENAME); +#if HAVE_NOTE_REVOKE KEVFFL_DUMP(NOTE_REVOKE); - strcat(buf, ")"); +#endif + buf[strlen(buf) - 1] = ')'; return (buf); } @@ -120,7 +124,7 @@ kevent_flags_dump(struct kevent *kev) #if HAVE_EV_RECEIPT KEVFL_DUMP(EV_RECEIPT); #endif - strcat(buf, ")"); + buf[strlen(buf) - 1] = ')'; return (buf); } @@ -135,7 +139,7 @@ kevent_to_str(struct kevent *kev) kevent_flags_dump(kev), kevent_fflags_dump(kev), (u_int) kev->ident, - kev->data, + (int) kev->data, kev->udata); return (strdup(buf)); } @@ -216,8 +220,10 @@ main(int argc, char **argv) test_evfilt_signal(); if (test_vnode) test_evfilt_vnode(); +#if FIXME if (test_timer) test_evfilt_timer(); +#endif puts("all tests completed."); return (0); diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index adf0dd292..dfd0b400e 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -58,22 +58,25 @@ test_kevent_socket_get(void) { const char *test_id = "kevent(EVFILT_READ) wait"; struct kevent kev; - int nfds; test_begin(test_id); + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + kevent_socket_fill(); - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s: nfds=%d", test_id, nfds); - KEV_CMP(kev, sockfd[0], EVFILT_READ, EV_ADD); - if ((int)kev.data != 1) - err(1, "incorrect data value %d", (int) kev.data); // FIXME: make part of KEV_CMP + kev.data = 1; + kevent_cmp(&kev, kevent_get(kqfd)); kevent_socket_drain(); test_no_kevents(); + kev.flags = EV_DELETE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + success(test_id); } @@ -81,8 +84,7 @@ void test_kevent_socket_clear(void) { const char *test_id = "kevent(EVFILT_READ, EV_CLEAR)"; - struct kevent kev, ret; - int nfds; + struct kevent kev; test_begin(test_id); @@ -95,11 +97,8 @@ test_kevent_socket_clear(void) kevent_socket_fill(); kevent_socket_fill(); - nfds = kevent(kqfd, NULL, 0, &ret, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); kev.data = 2; - kevent_cmp(&kev,&ret); + kevent_cmp(&kev, kevent_get(kqfd)); /* We filled twice, but drain once. Edge-triggered would not generate additional events. @@ -116,46 +115,38 @@ test_kevent_socket_clear(void) } void -test_kevent_socket_disable(void) +test_kevent_socket_disable_and_enable(void) { const char *test_id = "kevent(EVFILT_READ, EV_DISABLE)"; struct kevent kev; test_begin(test_id); + /* Add an event, then disable it. */ + EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DISABLE, 0, 0, &sockfd[0]); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); kevent_socket_fill(); test_no_kevents(); - kevent_socket_drain(); - success(test_id); -} - -void -test_kevent_socket_enable(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_ENABLE)"; - struct kevent kev, ret; - int nfds; - - test_begin(test_id); - - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ENABLE, 0, 0, &sockfd[0]); + /* Re-enable the knote, then see if an event is generated */ + kev.flags = EV_ENABLE; if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - - kevent_socket_fill(); - nfds = kevent(kqfd, NULL, 0, &ret, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); kev.flags = EV_ADD; kev.data = 1; - kevent_cmp(&kev, &ret); + kevent_cmp(&kev, kevent_get(kqfd)); + kevent_socket_drain(); + kev.flags = EV_DELETE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + success(test_id); } @@ -182,7 +173,7 @@ void test_kevent_socket_oneshot(void) { const char *test_id = "kevent(EVFILT_READ, EV_ONESHOT)"; - struct kevent kev, ret; + struct kevent kev; test_begin(test_id); @@ -195,10 +186,8 @@ test_kevent_socket_oneshot(void) puts("-- getting one event"); kevent_socket_fill(); - if (kevent(kqfd, NULL, 0, &ret, 1, NULL) != 1) - err(1, "%s", test_id); kev.data = 1; - kevent_cmp(&kev, &ret); + kevent_cmp(&kev, kevent_get(kqfd)); puts("-- checking knote disabled"); test_no_kevents(); @@ -289,7 +278,7 @@ void test_kevent_socket_eof(void) { const char *test_id = "kevent(EVFILT_READ, EV_EOF)"; - struct kevent kev, ret; + struct kevent kev; test_begin(test_id); @@ -302,10 +291,8 @@ test_kevent_socket_eof(void) if (close(sockfd[1]) < 0) err(1, "close(2)"); - if (kevent(kqfd, NULL, 0, &ret, 1, NULL) < 1) - err(1, "%s", test_id); kev.flags |= EV_EOF; - kevent_cmp(&kev, &ret); + kevent_cmp(&kev, kevent_get(kqfd)); /* Delete the watch */ EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); @@ -324,10 +311,9 @@ test_evfilt_read() kqfd = kqueue(); test_kevent_socket_add(); - test_kevent_socket_get(); - test_kevent_socket_disable(); - test_kevent_socket_enable(); test_kevent_socket_del(); + test_kevent_socket_get(); + test_kevent_socket_disable_and_enable(); test_kevent_socket_oneshot(); test_kevent_socket_clear(); test_kevent_socket_dispatch(); diff --git a/vendor/libkqueue/test/signal.c b/vendor/libkqueue/test/signal.c index b2f62a563..fc5fff3fa 100644 --- a/vendor/libkqueue/test/signal.c +++ b/vendor/libkqueue/test/signal.c @@ -109,7 +109,11 @@ test_kevent_signal_enable(void) err(1, "kill"); kev.flags = EV_ADD | EV_CLEAR; +#if LIBKQUEUE + kev.data = 1; /* WORKAROUND */ +#else kev.data = 2; // one extra time from test_kevent_signal_disable() +#endif kevent_cmp(&kev, kevent_get(kqfd)); /* Delete the watch */ diff --git a/vendor/libkqueue/test/vnode.c b/vendor/libkqueue/test/vnode.c index 6363bd636..f9579ccb9 100644 --- a/vendor/libkqueue/test/vnode.c +++ b/vendor/libkqueue/test/vnode.c @@ -55,17 +55,6 @@ test_kevent_vnode_note_delete(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - /* FIXME: workaround for linux behavior. if the file is open, - the delete event isn't registered; an IN_ATTRIB event is fired - instead. - - Unfortunately, closing the descriptor causes BSD kqueue to - remove the knote, thus the event is never triggered. - */ -#if LIBKQUEUE - close(vnode_fd); -#endif - if (unlink("/tmp/kqueue-test.tmp") < 0) err(1, "unlink"); diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index 50319b644..36a57b489 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -23,8 +23,15 @@

      Download

      svn checkout svn://mark.heily.com/libkqueue +

      Mailing Lists

      + +There are two mailing lists: one for +general discussion, and one for +announcements only. +

      Status

      -The current implementation status is here. + +Most of the API is implemented, with the notable exception of EVFILT_TIMER and EVFILT_USER. More details about the current implementation status is here.

      There are several compatibility issues to be aware of when using this library under Linux:

        @@ -43,14 +50,8 @@

        Status

      1. -The NOTE_EXTEND flag for the EVFILT_VNODE filter is not supported. An alternative approach is to use a combination of stat(2) and NOTE_ATTRIB to keep track of changes to the file's st_size field. -
      2. - -
      3. -The NOTE_LINK flag for the EVFILT_VNODE filter is not supported. An alternative approach is to use a combination of stat(2) and NOTE_ATTRIB to keep track of changes to the file's st_nlink field. -
      4. - -
      5. The NOTE_DELETE flag is supported; however, the event will not be triggered if the program holds an open file descriptor to the file being monitored. This behavior isn't documented in any Linux manpage; see here for discussion. A workaround would be to close the file descriptor after setting the NOTE_DELETE watch. +When an EVFILT_SIGNAL event is generated, the data field +is set to 1 regardless of how many times the signal was received by the process.
      From cf9513e67d5b57b311159cef7bb3d3f49fa11dd2 Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 6 Nov 2009 03:27:02 +0000 Subject: [PATCH 0046/1120] better distclean git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@50 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 171cb39d9..ad45cd771 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -60,4 +60,4 @@ clean: rm -f a.out *.a *.o *.so distclean: clean - rm -f *.tar.gz config.mk $(FILTERS) + rm -f *.tar.gz config.mk config.h libkqueue.pc $(FILTERS) From 0a98f0f453dd03cf2ac572c8b9bc309cf630e3d7 Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 6 Nov 2009 04:03:26 +0000 Subject: [PATCH 0047/1120] make dist works now git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@52 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 21 ++++++++++++++------- vendor/libkqueue/test/Makefile | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index ad45cd771..847501a9f 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -13,10 +13,13 @@ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -PROGRAM=libkqueue INSTALL=/usr/bin/install -DISTFILES=*.c *.h kqueue.2 README Makefile configure os sys -SOURCES=src/$(UNAME)/*.c +SOURCES=filter.c kevent.c knote.c kqueue.c +MANS=kqueue.2 +HEADERS=private.h +EXTRA_DIST=*.in README +SUBDIRS=os sys test +DISTFILES=Makefile configure FILTERS=vnode.c timer.c signal.c socket.c user.c include config.mk @@ -48,10 +51,14 @@ check: cd test && ./configure && make check dist: - mkdir $(PROGRAM) - cp -R $(DISTFILES) $(PROGRAM) - tar zcvf $(PROGRAM)-`date +%y%m%d_%H%M`.tar.gz $(PROGRAM) - rm -rf $(PROGRAM) + mkdir $(PROGRAM)-$(VERSION) + cp Makefile configure \ + $(SOURCES) $(MANS) $(HEADERS) $(EXTRA_DIST) \ + $(PROGRAM)-$(VERSION) + cp -R $(SUBDIRS) $(PROGRAM)-$(VERSION) + rm -rf `find $(PROGRAM)-$(VERSION) -type d -name .svn` + tar zcf $(PROGRAM)-$(VERSION).tar.gz $(PROGRAM)-$(VERSION) + rm -rf $(PROGRAM)-$(VERSION) publish-www: rm -rf ~/public_html/libkqueue/ ; cp -R www ~/public_html/libkqueue/ diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile index d7cff6767..eb992d16a 100644 --- a/vendor/libkqueue/test/Makefile +++ b/vendor/libkqueue/test/Makefile @@ -38,7 +38,7 @@ check-installed: ./a.out distclean: clean - rm -f config.mk config.h + rm -f config.mk config.h a.out clean: rm -f *.o From 4e286aa352ecaf37c1d466a907efd923ca358787 Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 6 Nov 2009 04:07:43 +0000 Subject: [PATCH 0048/1120] note dist git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@55 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/www/index.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index 36a57b489..e6b0351f6 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -19,6 +19,8 @@

      libkqueue

      Download

      +Source code releases can be found here. + To checkout the SVN repository, run the following command:

      svn checkout svn://mark.heily.com/libkqueue From 1f83540d574d5e8124403ff8d40b051606e049fb Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 6 Nov 2009 04:09:31 +0000 Subject: [PATCH 0049/1120] fix dist git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@56 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 2 +- vendor/libkqueue/www/index.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 847501a9f..02765c90f 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -61,7 +61,7 @@ dist: rm -rf $(PROGRAM)-$(VERSION) publish-www: - rm -rf ~/public_html/libkqueue/ ; cp -R www ~/public_html/libkqueue/ + rm ~/public_html/libkqueue/*.html ; cp -R www/*.html ~/public_html/libkqueue/ clean: rm -f a.out *.a *.o *.so diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index e6b0351f6..30a47710a 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -20,7 +20,7 @@

      libkqueue

      Download

      Source code releases can be found here. - +

      To checkout the SVN repository, run the following command:

      svn checkout svn://mark.heily.com/libkqueue From 62f99fe8fccb7b48788af6d69dda065dc68011e9 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 7 Nov 2009 19:24:32 +0000 Subject: [PATCH 0050/1120] * Implement EVFILT_TIMER on Linux. * Fix another 'make install' problem reported by Mario Schwalbe. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@57 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 1 + vendor/libkqueue/os/linux/timer.c | 145 ++++++++++++++++-------------- vendor/libkqueue/test/main.c | 2 - vendor/libkqueue/test/timer.c | 116 ++++++++++++++++++++---- 4 files changed, 179 insertions(+), 85 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 02765c90f..f28f85105 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -32,6 +32,7 @@ build: install: $(INSTALL) -d -m 755 $(INCLUDEDIR)/kqueue/sys $(INSTALL) -m 644 sys/event.h $(INCLUDEDIR)/kqueue/sys/event.h + $(INSTALL) -d -m 755 $(LIBDIR) $(INSTALL) -m 644 libkqueue.so $(LIBDIR)/libkqueue.so $(INSTALL) -d -m 755 $(LIBDIR)/pkgconfig $(INSTALL) -m 644 libkqueue.pc $(LIBDIR)/pkgconfig diff --git a/vendor/libkqueue/os/linux/timer.c b/vendor/libkqueue/os/linux/timer.c index 993496898..04b937468 100644 --- a/vendor/libkqueue/os/linux/timer.c +++ b/vendor/libkqueue/os/linux/timer.c @@ -34,42 +34,24 @@ #include "sys/event.h" #include "private.h" -#if DEADWOOD -static void timer_convert(struct itimerspec *dst, int src); - -/* - * Determine the smallest interval used by active timers. - */ -static int -update_timeres(struct filter *filt) +#if KQUEUE_DEBUG +static char * +itimerspec_dump(struct itimerspec *ts) { - struct knote *kn; - struct itimerspec tval; - u_int cur = filt->kf_timeres; + char *buf; - /* Find the smallest timeout interval */ - //FIXME not optimized - KNOTELIST_FOREACH(kn, &filt->knl) { - dbg_printf("cur=%d new=%d", cur, (int) kn->kev.data); - if (cur == 0 || kn->kev.data < cur) - cur = kn->kev.data; - } - - dbg_printf("cur=%d res=%d", cur, filt->kf_timeres); - if (cur == filt->kf_timeres) - return (0); - - dbg_printf("new timer interval = %d", cur); - filt->kf_timeres = cur; + if ((buf = calloc(1, 1024)) == NULL) + abort(); - /* Convert from miliseconds to seconds+nanoseconds */ - timer_convert(&tval, cur); - if (timerfd_settime(filt->kf_pfd, 0, &tval, NULL) < 0) { - dbg_printf("signalfd(2): %s", strerror(errno)); - return (-1); - } + snprintf(buf, 1024, + "itimer: [ interval=%lu s %lu ns, next expire=%lu s %lu ns ]", + ts->it_interval.tv_sec, + ts->it_interval.tv_nsec, + ts->it_value.tv_sec, + ts->it_value.tv_nsec + ); - return (0); + return (buf); } #endif @@ -77,23 +59,24 @@ update_timeres(struct filter *filt) static void convert_msec_to_itimerspec(struct itimerspec *dst, int src, int oneshot) { - struct timespec now; time_t sec, nsec; - /* Set the interval */ - /* XXX-FIXME: this is probably horribly wrong :) */ sec = src / 1000; nsec = (src % 1000) * 1000000; - dst->it_interval.tv_sec = sec; - dst->it_interval.tv_nsec = nsec; - dbg_printf("timer val=%lu %lu", sec, nsec); - /* FIXME: doesnt handle oneshot */ + /* Set the interval */ + if (oneshot) { + dst->it_interval.tv_sec = 0; + dst->it_interval.tv_nsec = 0; + } else { + dst->it_interval.tv_sec = sec; + dst->it_interval.tv_nsec = nsec; + } /* Set the initial expiration */ - clock_gettime(CLOCK_MONOTONIC, &now); - dst->it_value.tv_sec = now.tv_sec + sec; - dst->it_value.tv_nsec = now.tv_nsec + nsec; + dst->it_value.tv_sec = sec; + dst->it_value.tv_nsec = nsec; + dbg_printf("%s", itimerspec_dump(dst)); } static int @@ -196,44 +179,70 @@ evfilt_timer_copyin(struct filter *filt, return (0); } +/* TODO: This entire function is copy+pasted from socket.c + with minor changes for timerfds. + Perhaps it could be refactored into a generic epoll_copyout() + that calls custom per-filter actions. + */ int evfilt_timer_copyout(struct filter *filt, struct kevent *dst, int nevents) { - //struct knote *kn; - uint64_t buf; - int i; + struct epoll_event epevt[MAX_KEVENT]; + struct epoll_event *ev; + struct knote *kn; + uint64_t expired; + int i, nret; ssize_t n; - abort(); //TBD - - n = read(filt->kf_pfd, &buf, sizeof(buf)); - if (n < 0 || n < sizeof(buf)) { - dbg_puts("invalid read from timerfd"); - return (-1); + for (;;) { + nret = epoll_wait(filt->kf_pfd, &epevt[0], nevents, 0); + if (nret < 0) { + if (errno == EINTR) + continue; + dbg_perror("epoll_wait"); + return (-1); + } else { + break; + } } - n = 1; // KLUDGE - - //KNOTELIST_FOREACH(kn, &filt->knl) { - - for (i = 0, nevents = 0; i < n; i++) { -#if FIXME - /* Want to have multiple timers, so maybe multiple timerfds... */ - kn = knote_lookup(filt, sig[i].ssi_signo); - if (kn == NULL) - continue; - /* TODO: dst->data should be the number of times the signal occurred */ - dst->ident = sig[i].ssi_signo; - dst->filter = EVFILT_SIGNAL; + for (i = 0, nevents = 0; i < nret; i++) { + ev = &epevt[i]; + /* TODO: put in generic debug.c: epoll_event_dump(ev); */ + kn = ev->data.ptr; + dst->ident = kn->kev.ident; + dst->filter = kn->kev.filter; dst->udata = kn->kev.udata; - dst->flags = 0; + dst->flags = EV_ADD; dst->fflags = 0; - dst->data = 1; - dst++; + if (kn->kev.flags & EV_ONESHOT) /*TODO: move elsewhere */ + dst->flags |= EV_ONESHOT; + if (kn->kev.flags & EV_CLEAR) /*TODO: move elsewhere */ + dst->flags |= EV_CLEAR; + if (ev->events & EPOLLERR) + dst->fflags = 1; /* FIXME: Return the actual timer error */ + + /* On return, data contains the number of times the + timer has been trigered. + */ + n = read(kn->kn_pfd, &expired, sizeof(expired)); + if (n < 0 || n < sizeof(expired)) { + dbg_puts("invalid read from timerfd"); + expired = 1; /* Fail gracefully */ + } + dst->data = expired; + + if (kn->kev.flags & EV_DISPATCH) + KNOTE_DISABLE(kn); + if (kn->kev.flags & EV_ONESHOT) { + ktimer_delete(filt, kn); + knote_free(kn); + } + nevents++; -#endif + dst++; } return (nevents); diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index ecb4223b8..8864a24b9 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -220,10 +220,8 @@ main(int argc, char **argv) test_evfilt_signal(); if (test_vnode) test_evfilt_vnode(); -#if FIXME if (test_timer) test_evfilt_timer(); -#endif puts("all tests completed."); return (0); diff --git a/vendor/libkqueue/test/timer.c b/vendor/libkqueue/test/timer.c index 2e82f0b03..50c8f03a6 100644 --- a/vendor/libkqueue/test/timer.c +++ b/vendor/libkqueue/test/timer.c @@ -45,15 +45,16 @@ test_kevent_timer_del(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); + test_no_kevents(); + success(test_id); } void test_kevent_timer_get(void) { - const char *test_id = "kevent(EVFILT_TIMER, get)"; + const char *test_id = "kevent(EVFILT_TIMER, wait)"; struct kevent kev; - int nfds; test_begin(test_id); @@ -61,11 +62,9 @@ test_kevent_timer_get(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - if (kev.ident != 1 || kev.filter != EVFILT_TIMER) - errx(1, "wrong event"); + kev.flags |= EV_CLEAR; + kev.data = 1; + kevent_cmp(&kev, kevent_get(kqfd)); EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) @@ -74,17 +73,104 @@ test_kevent_timer_get(void) success(test_id); } +static void +test_oneshot(void) +{ + const char *test_id = "kevent(EVFILT_TIMER, EV_ONESHOT)"; + struct kevent kev; + + test_begin(test_id); + + test_no_kevents(); + + EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 500,NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Retrieve the event */ + kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT; + kev.data = 1; + kevent_cmp(&kev, kevent_get(kqfd)); + + /* Check if the event occurs again */ + sleep(3); + test_no_kevents(); + + + success(test_id); +} + +static void +test_periodic(void) +{ + const char *test_id = "kevent(EVFILT_TIMER, periodic)"; + struct kevent kev; + + test_begin(test_id); + + test_no_kevents(); + + EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD, 0, 1000,NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Retrieve the event */ + kev.flags = EV_ADD | EV_CLEAR; + kev.data = 1; + kevent_cmp(&kev, kevent_get(kqfd)); + + /* Check if the event occurs again */ + sleep(1); + kevent_cmp(&kev, kevent_get(kqfd)); + + /* Delete the event */ + kev.flags = EV_DELETE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +static void +disable_and_enable(void) +{ + const char *test_id = "kevent(EVFILT_TIMER, EV_DISABLE and EV_ENABLE)"; + struct kevent kev; + + test_begin(test_id); + + test_no_kevents(); + + /* Add the watch and immediately disable it */ + EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 2000,NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + kev.flags = EV_DISABLE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + test_no_kevents(); + + /* Re-enable and check again */ + kev.flags = EV_ENABLE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT; + kev.data = 1; + kevent_cmp(&kev, kevent_get(kqfd)); + + success(test_id); +} + void test_evfilt_timer() { kqfd = kqueue(); - test_kevent_timer_add(); - test_kevent_timer_del(); - test_kevent_timer_get(); -#if TODO - test_kevent_signal_disable(); - test_kevent_signal_enable(); - test_kevent_signal_oneshot(); -#endif + test_kevent_timer_add(); + test_kevent_timer_del(); + test_kevent_timer_get(); + test_oneshot(); + test_periodic(); + disable_and_enable(); close(kqfd); } From d533dbce8900e92fb81ed7072d1fb1b8d864bf2f Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 7 Nov 2009 20:29:41 +0000 Subject: [PATCH 0051/1120] * Do not link the test program with the pthreads library. * pkg-config no longer requires linking with -lpthread and -lrt. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@58 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 4 ++++ vendor/libkqueue/Makefile | 7 +++++++ vendor/libkqueue/configure | 2 ++ vendor/libkqueue/libkqueue.pc.in | 2 +- vendor/libkqueue/test/configure | 2 +- vendor/libkqueue/www/index.html | 6 ++++-- vendor/libkqueue/www/status.html | 18 +++++++++--------- 7 files changed, 28 insertions(+), 13 deletions(-) create mode 100644 vendor/libkqueue/ChangeLog diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog new file mode 100644 index 000000000..1a68ed04e --- /dev/null +++ b/vendor/libkqueue/ChangeLog @@ -0,0 +1,4 @@ + +2009-05-05 v0.1 r49 + + * Initial stable release. diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index f28f85105..7f63eac5a 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -13,6 +13,7 @@ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # +REPOSITORY=svn+ssh://mark.heily.com/$$HOME/svn/$(PROGRAM) INSTALL=/usr/bin/install SOURCES=filter.c kevent.c knote.c kqueue.c MANS=kqueue.2 @@ -67,5 +68,11 @@ publish-www: clean: rm -f a.out *.a *.o *.so +merge: + svn diff $(REPOSITORY)/branches/stable $(REPOSITORY)/trunk | gvim - + @printf "Merge changes from the trunk to the stable branch [y/N]? " + @read x && test "$$x" = "y" + echo "ok" + distclean: clean rm -f *.tar.gz config.mk config.h libkqueue.pc $(FILTERS) diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index 1ce47522a..2b773151f 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -71,6 +71,7 @@ finalize libdir "${prefix}/lib" finalize includedir "${prefix}/include" finalize mandir "${prefix}/share/man" finalize cflags "$default_cflags" +finalize libdepends "" echo "Checking operating system type... $target" rm -f socket.c vnode.c signal.c timer.c user.c @@ -95,6 +96,7 @@ sed -e " s,@@LIBDIR@@,$libdir,g; s,@@INCLUDEDIR@@,$includedir,g; s,@@MANDIR@@,$mandir,g; + s,@@LIBDEPENDS@@,$libdepends,g; " < $program.pc.in >> $program.pc chmod 400 $program.pc diff --git a/vendor/libkqueue/libkqueue.pc.in b/vendor/libkqueue/libkqueue.pc.in index ae2c644ed..c8d36c541 100644 --- a/vendor/libkqueue/libkqueue.pc.in +++ b/vendor/libkqueue/libkqueue.pc.in @@ -8,6 +8,6 @@ Description: Emulates FreeBSD kqueue(2) on other platforms Version: @@VERSION@@ Requires: Libs: -L${libdir} -lkqueue -Libs.private: -lpthread -lrt +Libs.private: @@LIBDEPENDS@@ Cflags: -I${includedir}/kqueue diff --git a/vendor/libkqueue/test/configure b/vendor/libkqueue/test/configure index 1c8327418..5a37d61aa 100755 --- a/vendor/libkqueue/test/configure +++ b/vendor/libkqueue/test/configure @@ -89,7 +89,7 @@ cflags="-g -O0 -Wall -Werror" ldadd="" if [ "`uname -s`" = "Linux" ] ; then cflags="$cflags -I.." - ldadd="$ldadd ../libkqueue.a -lpthread -lrt" + ldadd="$ldadd ../libkqueue.a" fi finalize cflags "" finalize ldadd "" diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index 30a47710a..c42ac3d83 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -70,8 +70,6 @@

      Requirements

      Usage

      -libkqueue is a multi-threaded library and kqueue() and kevent() are safe to be used from multiple threads. - Here are the steps to use libkqueue in your program:
      1. Add `pkg-config libkqueue --cflags` to the CFLAGS variable. @@ -97,6 +95,10 @@

        Usage

        #endif +

        Threads

        + +libkqueue is a threadsafe library, and kqueue() and kevent() are safe to be used from multiple threads. libkqueue requires that the POSIX threads headers (pthread.h) be available, but does not require you to link against libpthread.so. This allows it to be used in both non-threaded and multi-threaded programs. +

        Links

          diff --git a/vendor/libkqueue/www/status.html b/vendor/libkqueue/www/status.html index 0a99dd977..8bb207c66 100644 --- a/vendor/libkqueue/www/status.html +++ b/vendor/libkqueue/www/status.html @@ -55,11 +55,11 @@

          kevent.flags

          EVFILT_TIMER
          Yes -No -No -No -No -No +Yes +Yes +Yes +Yes +N/A @@ -96,13 +96,13 @@

          kevent.fflags

          READ / WRITE NOTE_LOWAT No -- Not supported by Linux VNODE - NOTE_DELETE Partial (fd must be closed) + NOTE_DELETE Yes NOTE_WRITE Yes - NOTE_EXTEND No + NOTE_EXTEND Yes NOTE_ATTRIB Yes - NOTE_LINK No + NOTE_LINK Yes NOTE_RENAME Yes - NOTE_REVOKE N/A -- Not available in Linux + NOTE_REVOKE No -- Not available in Linux USER NOTE_FFNOP Ignore the input fflags. NOTE_FFAND Bitwise AND fflags. From 9312cdb8de8c24baca7e6dbcb375bd5ef3049aea Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 7 Nov 2009 20:55:22 +0000 Subject: [PATCH 0052/1120] v0.2 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@59 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 9 +++++++++ vendor/libkqueue/configure | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 1a68ed04e..f288ca94b 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,3 +1,12 @@ +2009-11-10 v0.2 r59 + + * Implement EVFILT_TIMER on Linux. + + * Fix another 'make install' problem reported by Mario Schwalbe. + + * Do not link the test program with the pthreads library. + + * pkg-config no longer requires linking with -lpthread and -lrt. 2009-05-05 v0.1 r49 diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index 2b773151f..9b652a7a3 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -1,7 +1,7 @@ #!/bin/sh program=libkqueue -version=0.1 +version=0.2 finalize() { eval "if [ \"\$$1\" = \"\" ] ; then $1=\"$2\" ; fi" From 909672af4222145511ecba92ce85667ac069f506 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 7 Nov 2009 20:59:21 +0000 Subject: [PATCH 0053/1120] attempt to merge git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@60 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 13 --- vendor/libkqueue/Makefile | 3 +- vendor/libkqueue/configure | 4 +- vendor/libkqueue/libkqueue.pc.in | 2 +- vendor/libkqueue/os/linux/timer.c | 145 ++++++++++++++---------------- vendor/libkqueue/test/configure | 2 +- vendor/libkqueue/test/main.c | 2 + vendor/libkqueue/test/timer.c | 116 ++++-------------------- vendor/libkqueue/www/index.html | 8 +- vendor/libkqueue/www/status.html | 18 ++-- 10 files changed, 101 insertions(+), 212 deletions(-) delete mode 100644 vendor/libkqueue/ChangeLog diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog deleted file mode 100644 index f288ca94b..000000000 --- a/vendor/libkqueue/ChangeLog +++ /dev/null @@ -1,13 +0,0 @@ -2009-11-10 v0.2 r59 - - * Implement EVFILT_TIMER on Linux. - - * Fix another 'make install' problem reported by Mario Schwalbe. - - * Do not link the test program with the pthreads library. - - * pkg-config no longer requires linking with -lpthread and -lrt. - -2009-05-05 v0.1 r49 - - * Initial stable release. diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 7f63eac5a..55ea2b368 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -72,7 +72,8 @@ merge: svn diff $(REPOSITORY)/branches/stable $(REPOSITORY)/trunk | gvim - @printf "Merge changes from the trunk to the stable branch [y/N]? " @read x && test "$$x" = "y" - echo "ok" + EDITOR=vi svn merge $(REPOSITORY)/trunk $(REPOSITORY)/branches/stable + cd ../branches/stable && svn up distclean: clean rm -f *.tar.gz config.mk config.h libkqueue.pc $(FILTERS) diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index 9b652a7a3..1ce47522a 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -1,7 +1,7 @@ #!/bin/sh program=libkqueue -version=0.2 +version=0.1 finalize() { eval "if [ \"\$$1\" = \"\" ] ; then $1=\"$2\" ; fi" @@ -71,7 +71,6 @@ finalize libdir "${prefix}/lib" finalize includedir "${prefix}/include" finalize mandir "${prefix}/share/man" finalize cflags "$default_cflags" -finalize libdepends "" echo "Checking operating system type... $target" rm -f socket.c vnode.c signal.c timer.c user.c @@ -96,7 +95,6 @@ sed -e " s,@@LIBDIR@@,$libdir,g; s,@@INCLUDEDIR@@,$includedir,g; s,@@MANDIR@@,$mandir,g; - s,@@LIBDEPENDS@@,$libdepends,g; " < $program.pc.in >> $program.pc chmod 400 $program.pc diff --git a/vendor/libkqueue/libkqueue.pc.in b/vendor/libkqueue/libkqueue.pc.in index c8d36c541..ae2c644ed 100644 --- a/vendor/libkqueue/libkqueue.pc.in +++ b/vendor/libkqueue/libkqueue.pc.in @@ -8,6 +8,6 @@ Description: Emulates FreeBSD kqueue(2) on other platforms Version: @@VERSION@@ Requires: Libs: -L${libdir} -lkqueue -Libs.private: @@LIBDEPENDS@@ +Libs.private: -lpthread -lrt Cflags: -I${includedir}/kqueue diff --git a/vendor/libkqueue/os/linux/timer.c b/vendor/libkqueue/os/linux/timer.c index 04b937468..993496898 100644 --- a/vendor/libkqueue/os/linux/timer.c +++ b/vendor/libkqueue/os/linux/timer.c @@ -34,24 +34,42 @@ #include "sys/event.h" #include "private.h" -#if KQUEUE_DEBUG -static char * -itimerspec_dump(struct itimerspec *ts) +#if DEADWOOD +static void timer_convert(struct itimerspec *dst, int src); + +/* + * Determine the smallest interval used by active timers. + */ +static int +update_timeres(struct filter *filt) { - char *buf; + struct knote *kn; + struct itimerspec tval; + u_int cur = filt->kf_timeres; - if ((buf = calloc(1, 1024)) == NULL) - abort(); + /* Find the smallest timeout interval */ + //FIXME not optimized + KNOTELIST_FOREACH(kn, &filt->knl) { + dbg_printf("cur=%d new=%d", cur, (int) kn->kev.data); + if (cur == 0 || kn->kev.data < cur) + cur = kn->kev.data; + } + + dbg_printf("cur=%d res=%d", cur, filt->kf_timeres); + if (cur == filt->kf_timeres) + return (0); + + dbg_printf("new timer interval = %d", cur); + filt->kf_timeres = cur; - snprintf(buf, 1024, - "itimer: [ interval=%lu s %lu ns, next expire=%lu s %lu ns ]", - ts->it_interval.tv_sec, - ts->it_interval.tv_nsec, - ts->it_value.tv_sec, - ts->it_value.tv_nsec - ); + /* Convert from miliseconds to seconds+nanoseconds */ + timer_convert(&tval, cur); + if (timerfd_settime(filt->kf_pfd, 0, &tval, NULL) < 0) { + dbg_printf("signalfd(2): %s", strerror(errno)); + return (-1); + } - return (buf); + return (0); } #endif @@ -59,24 +77,23 @@ itimerspec_dump(struct itimerspec *ts) static void convert_msec_to_itimerspec(struct itimerspec *dst, int src, int oneshot) { + struct timespec now; time_t sec, nsec; + /* Set the interval */ + /* XXX-FIXME: this is probably horribly wrong :) */ sec = src / 1000; nsec = (src % 1000) * 1000000; + dst->it_interval.tv_sec = sec; + dst->it_interval.tv_nsec = nsec; + dbg_printf("timer val=%lu %lu", sec, nsec); - /* Set the interval */ - if (oneshot) { - dst->it_interval.tv_sec = 0; - dst->it_interval.tv_nsec = 0; - } else { - dst->it_interval.tv_sec = sec; - dst->it_interval.tv_nsec = nsec; - } + /* FIXME: doesnt handle oneshot */ /* Set the initial expiration */ - dst->it_value.tv_sec = sec; - dst->it_value.tv_nsec = nsec; - dbg_printf("%s", itimerspec_dump(dst)); + clock_gettime(CLOCK_MONOTONIC, &now); + dst->it_value.tv_sec = now.tv_sec + sec; + dst->it_value.tv_nsec = now.tv_nsec + nsec; } static int @@ -179,70 +196,44 @@ evfilt_timer_copyin(struct filter *filt, return (0); } -/* TODO: This entire function is copy+pasted from socket.c - with minor changes for timerfds. - Perhaps it could be refactored into a generic epoll_copyout() - that calls custom per-filter actions. - */ int evfilt_timer_copyout(struct filter *filt, struct kevent *dst, int nevents) { - struct epoll_event epevt[MAX_KEVENT]; - struct epoll_event *ev; - struct knote *kn; - uint64_t expired; - int i, nret; + //struct knote *kn; + uint64_t buf; + int i; ssize_t n; - for (;;) { - nret = epoll_wait(filt->kf_pfd, &epevt[0], nevents, 0); - if (nret < 0) { - if (errno == EINTR) - continue; - dbg_perror("epoll_wait"); - return (-1); - } else { - break; - } + abort(); //TBD + + n = read(filt->kf_pfd, &buf, sizeof(buf)); + if (n < 0 || n < sizeof(buf)) { + dbg_puts("invalid read from timerfd"); + return (-1); } + n = 1; // KLUDGE + + //KNOTELIST_FOREACH(kn, &filt->knl) { + + for (i = 0, nevents = 0; i < n; i++) { +#if FIXME + /* Want to have multiple timers, so maybe multiple timerfds... */ + kn = knote_lookup(filt, sig[i].ssi_signo); + if (kn == NULL) + continue; - for (i = 0, nevents = 0; i < nret; i++) { - ev = &epevt[i]; - /* TODO: put in generic debug.c: epoll_event_dump(ev); */ - kn = ev->data.ptr; - dst->ident = kn->kev.ident; - dst->filter = kn->kev.filter; + /* TODO: dst->data should be the number of times the signal occurred */ + dst->ident = sig[i].ssi_signo; + dst->filter = EVFILT_SIGNAL; dst->udata = kn->kev.udata; - dst->flags = EV_ADD; + dst->flags = 0; dst->fflags = 0; - if (kn->kev.flags & EV_ONESHOT) /*TODO: move elsewhere */ - dst->flags |= EV_ONESHOT; - if (kn->kev.flags & EV_CLEAR) /*TODO: move elsewhere */ - dst->flags |= EV_CLEAR; - if (ev->events & EPOLLERR) - dst->fflags = 1; /* FIXME: Return the actual timer error */ - - /* On return, data contains the number of times the - timer has been trigered. - */ - n = read(kn->kn_pfd, &expired, sizeof(expired)); - if (n < 0 || n < sizeof(expired)) { - dbg_puts("invalid read from timerfd"); - expired = 1; /* Fail gracefully */ - } - dst->data = expired; - - if (kn->kev.flags & EV_DISPATCH) - KNOTE_DISABLE(kn); - if (kn->kev.flags & EV_ONESHOT) { - ktimer_delete(filt, kn); - knote_free(kn); - } - + dst->data = 1; + dst++; nevents++; - dst++; +#endif } return (nevents); diff --git a/vendor/libkqueue/test/configure b/vendor/libkqueue/test/configure index 5a37d61aa..1c8327418 100755 --- a/vendor/libkqueue/test/configure +++ b/vendor/libkqueue/test/configure @@ -89,7 +89,7 @@ cflags="-g -O0 -Wall -Werror" ldadd="" if [ "`uname -s`" = "Linux" ] ; then cflags="$cflags -I.." - ldadd="$ldadd ../libkqueue.a" + ldadd="$ldadd ../libkqueue.a -lpthread -lrt" fi finalize cflags "" finalize ldadd "" diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 8864a24b9..ecb4223b8 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -220,8 +220,10 @@ main(int argc, char **argv) test_evfilt_signal(); if (test_vnode) test_evfilt_vnode(); +#if FIXME if (test_timer) test_evfilt_timer(); +#endif puts("all tests completed."); return (0); diff --git a/vendor/libkqueue/test/timer.c b/vendor/libkqueue/test/timer.c index 50c8f03a6..2e82f0b03 100644 --- a/vendor/libkqueue/test/timer.c +++ b/vendor/libkqueue/test/timer.c @@ -45,16 +45,15 @@ test_kevent_timer_del(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - test_no_kevents(); - success(test_id); } void test_kevent_timer_get(void) { - const char *test_id = "kevent(EVFILT_TIMER, wait)"; + const char *test_id = "kevent(EVFILT_TIMER, get)"; struct kevent kev; + int nfds; test_begin(test_id); @@ -62,103 +61,16 @@ test_kevent_timer_get(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - kev.flags |= EV_CLEAR; - kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); - - EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} - -static void -test_oneshot(void) -{ - const char *test_id = "kevent(EVFILT_TIMER, EV_ONESHOT)"; - struct kevent kev; - - test_begin(test_id); - - test_no_kevents(); - - EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 500,NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Retrieve the event */ - kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT; - kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); - - /* Check if the event occurs again */ - sleep(3); - test_no_kevents(); - - - success(test_id); -} - -static void -test_periodic(void) -{ - const char *test_id = "kevent(EVFILT_TIMER, periodic)"; - struct kevent kev; - - test_begin(test_id); - - test_no_kevents(); - - EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD, 0, 1000,NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Retrieve the event */ - kev.flags = EV_ADD | EV_CLEAR; - kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); - - /* Check if the event occurs again */ - sleep(1); - kevent_cmp(&kev, kevent_get(kqfd)); - - /* Delete the event */ - kev.flags = EV_DELETE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(test_id); -} - -static void -disable_and_enable(void) -{ - const char *test_id = "kevent(EVFILT_TIMER, EV_DISABLE and EV_ENABLE)"; - struct kevent kev; - - test_begin(test_id); - - test_no_kevents(); - - /* Add the watch and immediately disable it */ - EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 2000,NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - kev.flags = EV_DISABLE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (nfds < 1) err(1, "%s", test_id); - test_no_kevents(); + if (kev.ident != 1 || kev.filter != EVFILT_TIMER) + errx(1, "wrong event"); - /* Re-enable and check again */ - kev.flags = EV_ENABLE; + EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT; - kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); - success(test_id); } @@ -166,11 +78,13 @@ void test_evfilt_timer() { kqfd = kqueue(); - test_kevent_timer_add(); - test_kevent_timer_del(); - test_kevent_timer_get(); - test_oneshot(); - test_periodic(); - disable_and_enable(); + test_kevent_timer_add(); + test_kevent_timer_del(); + test_kevent_timer_get(); +#if TODO + test_kevent_signal_disable(); + test_kevent_signal_enable(); + test_kevent_signal_oneshot(); +#endif close(kqfd); } diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index c42ac3d83..36a57b489 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -19,8 +19,6 @@

          libkqueue

          Download

          -Source code releases can be found here. -

          To checkout the SVN repository, run the following command:

          svn checkout svn://mark.heily.com/libkqueue @@ -70,6 +68,8 @@

          Requirements

          Usage

          +libkqueue is a multi-threaded library and kqueue() and kevent() are safe to be used from multiple threads. + Here are the steps to use libkqueue in your program:
          1. Add `pkg-config libkqueue --cflags` to the CFLAGS variable. @@ -95,10 +95,6 @@

            Usage

            #endif -

            Threads

            - -libkqueue is a threadsafe library, and kqueue() and kevent() are safe to be used from multiple threads. libkqueue requires that the POSIX threads headers (pthread.h) be available, but does not require you to link against libpthread.so. This allows it to be used in both non-threaded and multi-threaded programs. -

            Links

              diff --git a/vendor/libkqueue/www/status.html b/vendor/libkqueue/www/status.html index 8bb207c66..0a99dd977 100644 --- a/vendor/libkqueue/www/status.html +++ b/vendor/libkqueue/www/status.html @@ -55,11 +55,11 @@

              kevent.flags

              EVFILT_TIMER
              Yes -Yes -Yes -Yes -Yes -N/A +No +No +No +No +No @@ -96,13 +96,13 @@

              kevent.fflags

              READ / WRITE NOTE_LOWAT No -- Not supported by Linux VNODE - NOTE_DELETE Yes + NOTE_DELETE Partial (fd must be closed) NOTE_WRITE Yes - NOTE_EXTEND Yes + NOTE_EXTEND No NOTE_ATTRIB Yes - NOTE_LINK Yes + NOTE_LINK No NOTE_RENAME Yes - NOTE_REVOKE No -- Not available in Linux + NOTE_REVOKE N/A -- Not available in Linux USER NOTE_FFNOP Ignore the input fflags. NOTE_FFAND Bitwise AND fflags. From 0ca07de0097373073bac3b0cbe22b2c7fb37bcbf Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 7 Nov 2009 21:02:10 +0000 Subject: [PATCH 0054/1120] revert bad checkin #60 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@61 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 13 +++ vendor/libkqueue/Makefile | 3 +- vendor/libkqueue/configure | 4 +- vendor/libkqueue/libkqueue.pc.in | 2 +- vendor/libkqueue/os/linux/timer.c | 145 ++++++++++++++++-------------- vendor/libkqueue/test/configure | 2 +- vendor/libkqueue/test/main.c | 2 - vendor/libkqueue/test/timer.c | 116 ++++++++++++++++++++---- vendor/libkqueue/www/index.html | 8 +- vendor/libkqueue/www/status.html | 18 ++-- 10 files changed, 212 insertions(+), 101 deletions(-) create mode 100644 vendor/libkqueue/ChangeLog diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog new file mode 100644 index 000000000..f288ca94b --- /dev/null +++ b/vendor/libkqueue/ChangeLog @@ -0,0 +1,13 @@ +2009-11-10 v0.2 r59 + + * Implement EVFILT_TIMER on Linux. + + * Fix another 'make install' problem reported by Mario Schwalbe. + + * Do not link the test program with the pthreads library. + + * pkg-config no longer requires linking with -lpthread and -lrt. + +2009-05-05 v0.1 r49 + + * Initial stable release. diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 55ea2b368..7f63eac5a 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -72,8 +72,7 @@ merge: svn diff $(REPOSITORY)/branches/stable $(REPOSITORY)/trunk | gvim - @printf "Merge changes from the trunk to the stable branch [y/N]? " @read x && test "$$x" = "y" - EDITOR=vi svn merge $(REPOSITORY)/trunk $(REPOSITORY)/branches/stable - cd ../branches/stable && svn up + echo "ok" distclean: clean rm -f *.tar.gz config.mk config.h libkqueue.pc $(FILTERS) diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index 1ce47522a..9b652a7a3 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -1,7 +1,7 @@ #!/bin/sh program=libkqueue -version=0.1 +version=0.2 finalize() { eval "if [ \"\$$1\" = \"\" ] ; then $1=\"$2\" ; fi" @@ -71,6 +71,7 @@ finalize libdir "${prefix}/lib" finalize includedir "${prefix}/include" finalize mandir "${prefix}/share/man" finalize cflags "$default_cflags" +finalize libdepends "" echo "Checking operating system type... $target" rm -f socket.c vnode.c signal.c timer.c user.c @@ -95,6 +96,7 @@ sed -e " s,@@LIBDIR@@,$libdir,g; s,@@INCLUDEDIR@@,$includedir,g; s,@@MANDIR@@,$mandir,g; + s,@@LIBDEPENDS@@,$libdepends,g; " < $program.pc.in >> $program.pc chmod 400 $program.pc diff --git a/vendor/libkqueue/libkqueue.pc.in b/vendor/libkqueue/libkqueue.pc.in index ae2c644ed..c8d36c541 100644 --- a/vendor/libkqueue/libkqueue.pc.in +++ b/vendor/libkqueue/libkqueue.pc.in @@ -8,6 +8,6 @@ Description: Emulates FreeBSD kqueue(2) on other platforms Version: @@VERSION@@ Requires: Libs: -L${libdir} -lkqueue -Libs.private: -lpthread -lrt +Libs.private: @@LIBDEPENDS@@ Cflags: -I${includedir}/kqueue diff --git a/vendor/libkqueue/os/linux/timer.c b/vendor/libkqueue/os/linux/timer.c index 993496898..04b937468 100644 --- a/vendor/libkqueue/os/linux/timer.c +++ b/vendor/libkqueue/os/linux/timer.c @@ -34,42 +34,24 @@ #include "sys/event.h" #include "private.h" -#if DEADWOOD -static void timer_convert(struct itimerspec *dst, int src); - -/* - * Determine the smallest interval used by active timers. - */ -static int -update_timeres(struct filter *filt) +#if KQUEUE_DEBUG +static char * +itimerspec_dump(struct itimerspec *ts) { - struct knote *kn; - struct itimerspec tval; - u_int cur = filt->kf_timeres; + char *buf; - /* Find the smallest timeout interval */ - //FIXME not optimized - KNOTELIST_FOREACH(kn, &filt->knl) { - dbg_printf("cur=%d new=%d", cur, (int) kn->kev.data); - if (cur == 0 || kn->kev.data < cur) - cur = kn->kev.data; - } - - dbg_printf("cur=%d res=%d", cur, filt->kf_timeres); - if (cur == filt->kf_timeres) - return (0); - - dbg_printf("new timer interval = %d", cur); - filt->kf_timeres = cur; + if ((buf = calloc(1, 1024)) == NULL) + abort(); - /* Convert from miliseconds to seconds+nanoseconds */ - timer_convert(&tval, cur); - if (timerfd_settime(filt->kf_pfd, 0, &tval, NULL) < 0) { - dbg_printf("signalfd(2): %s", strerror(errno)); - return (-1); - } + snprintf(buf, 1024, + "itimer: [ interval=%lu s %lu ns, next expire=%lu s %lu ns ]", + ts->it_interval.tv_sec, + ts->it_interval.tv_nsec, + ts->it_value.tv_sec, + ts->it_value.tv_nsec + ); - return (0); + return (buf); } #endif @@ -77,23 +59,24 @@ update_timeres(struct filter *filt) static void convert_msec_to_itimerspec(struct itimerspec *dst, int src, int oneshot) { - struct timespec now; time_t sec, nsec; - /* Set the interval */ - /* XXX-FIXME: this is probably horribly wrong :) */ sec = src / 1000; nsec = (src % 1000) * 1000000; - dst->it_interval.tv_sec = sec; - dst->it_interval.tv_nsec = nsec; - dbg_printf("timer val=%lu %lu", sec, nsec); - /* FIXME: doesnt handle oneshot */ + /* Set the interval */ + if (oneshot) { + dst->it_interval.tv_sec = 0; + dst->it_interval.tv_nsec = 0; + } else { + dst->it_interval.tv_sec = sec; + dst->it_interval.tv_nsec = nsec; + } /* Set the initial expiration */ - clock_gettime(CLOCK_MONOTONIC, &now); - dst->it_value.tv_sec = now.tv_sec + sec; - dst->it_value.tv_nsec = now.tv_nsec + nsec; + dst->it_value.tv_sec = sec; + dst->it_value.tv_nsec = nsec; + dbg_printf("%s", itimerspec_dump(dst)); } static int @@ -196,44 +179,70 @@ evfilt_timer_copyin(struct filter *filt, return (0); } +/* TODO: This entire function is copy+pasted from socket.c + with minor changes for timerfds. + Perhaps it could be refactored into a generic epoll_copyout() + that calls custom per-filter actions. + */ int evfilt_timer_copyout(struct filter *filt, struct kevent *dst, int nevents) { - //struct knote *kn; - uint64_t buf; - int i; + struct epoll_event epevt[MAX_KEVENT]; + struct epoll_event *ev; + struct knote *kn; + uint64_t expired; + int i, nret; ssize_t n; - abort(); //TBD - - n = read(filt->kf_pfd, &buf, sizeof(buf)); - if (n < 0 || n < sizeof(buf)) { - dbg_puts("invalid read from timerfd"); - return (-1); + for (;;) { + nret = epoll_wait(filt->kf_pfd, &epevt[0], nevents, 0); + if (nret < 0) { + if (errno == EINTR) + continue; + dbg_perror("epoll_wait"); + return (-1); + } else { + break; + } } - n = 1; // KLUDGE - - //KNOTELIST_FOREACH(kn, &filt->knl) { - - for (i = 0, nevents = 0; i < n; i++) { -#if FIXME - /* Want to have multiple timers, so maybe multiple timerfds... */ - kn = knote_lookup(filt, sig[i].ssi_signo); - if (kn == NULL) - continue; - /* TODO: dst->data should be the number of times the signal occurred */ - dst->ident = sig[i].ssi_signo; - dst->filter = EVFILT_SIGNAL; + for (i = 0, nevents = 0; i < nret; i++) { + ev = &epevt[i]; + /* TODO: put in generic debug.c: epoll_event_dump(ev); */ + kn = ev->data.ptr; + dst->ident = kn->kev.ident; + dst->filter = kn->kev.filter; dst->udata = kn->kev.udata; - dst->flags = 0; + dst->flags = EV_ADD; dst->fflags = 0; - dst->data = 1; - dst++; + if (kn->kev.flags & EV_ONESHOT) /*TODO: move elsewhere */ + dst->flags |= EV_ONESHOT; + if (kn->kev.flags & EV_CLEAR) /*TODO: move elsewhere */ + dst->flags |= EV_CLEAR; + if (ev->events & EPOLLERR) + dst->fflags = 1; /* FIXME: Return the actual timer error */ + + /* On return, data contains the number of times the + timer has been trigered. + */ + n = read(kn->kn_pfd, &expired, sizeof(expired)); + if (n < 0 || n < sizeof(expired)) { + dbg_puts("invalid read from timerfd"); + expired = 1; /* Fail gracefully */ + } + dst->data = expired; + + if (kn->kev.flags & EV_DISPATCH) + KNOTE_DISABLE(kn); + if (kn->kev.flags & EV_ONESHOT) { + ktimer_delete(filt, kn); + knote_free(kn); + } + nevents++; -#endif + dst++; } return (nevents); diff --git a/vendor/libkqueue/test/configure b/vendor/libkqueue/test/configure index 1c8327418..5a37d61aa 100755 --- a/vendor/libkqueue/test/configure +++ b/vendor/libkqueue/test/configure @@ -89,7 +89,7 @@ cflags="-g -O0 -Wall -Werror" ldadd="" if [ "`uname -s`" = "Linux" ] ; then cflags="$cflags -I.." - ldadd="$ldadd ../libkqueue.a -lpthread -lrt" + ldadd="$ldadd ../libkqueue.a" fi finalize cflags "" finalize ldadd "" diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index ecb4223b8..8864a24b9 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -220,10 +220,8 @@ main(int argc, char **argv) test_evfilt_signal(); if (test_vnode) test_evfilt_vnode(); -#if FIXME if (test_timer) test_evfilt_timer(); -#endif puts("all tests completed."); return (0); diff --git a/vendor/libkqueue/test/timer.c b/vendor/libkqueue/test/timer.c index 2e82f0b03..50c8f03a6 100644 --- a/vendor/libkqueue/test/timer.c +++ b/vendor/libkqueue/test/timer.c @@ -45,15 +45,16 @@ test_kevent_timer_del(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); + test_no_kevents(); + success(test_id); } void test_kevent_timer_get(void) { - const char *test_id = "kevent(EVFILT_TIMER, get)"; + const char *test_id = "kevent(EVFILT_TIMER, wait)"; struct kevent kev; - int nfds; test_begin(test_id); @@ -61,11 +62,9 @@ test_kevent_timer_get(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - if (kev.ident != 1 || kev.filter != EVFILT_TIMER) - errx(1, "wrong event"); + kev.flags |= EV_CLEAR; + kev.data = 1; + kevent_cmp(&kev, kevent_get(kqfd)); EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) @@ -74,17 +73,104 @@ test_kevent_timer_get(void) success(test_id); } +static void +test_oneshot(void) +{ + const char *test_id = "kevent(EVFILT_TIMER, EV_ONESHOT)"; + struct kevent kev; + + test_begin(test_id); + + test_no_kevents(); + + EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 500,NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Retrieve the event */ + kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT; + kev.data = 1; + kevent_cmp(&kev, kevent_get(kqfd)); + + /* Check if the event occurs again */ + sleep(3); + test_no_kevents(); + + + success(test_id); +} + +static void +test_periodic(void) +{ + const char *test_id = "kevent(EVFILT_TIMER, periodic)"; + struct kevent kev; + + test_begin(test_id); + + test_no_kevents(); + + EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD, 0, 1000,NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Retrieve the event */ + kev.flags = EV_ADD | EV_CLEAR; + kev.data = 1; + kevent_cmp(&kev, kevent_get(kqfd)); + + /* Check if the event occurs again */ + sleep(1); + kevent_cmp(&kev, kevent_get(kqfd)); + + /* Delete the event */ + kev.flags = EV_DELETE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +static void +disable_and_enable(void) +{ + const char *test_id = "kevent(EVFILT_TIMER, EV_DISABLE and EV_ENABLE)"; + struct kevent kev; + + test_begin(test_id); + + test_no_kevents(); + + /* Add the watch and immediately disable it */ + EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 2000,NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + kev.flags = EV_DISABLE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + test_no_kevents(); + + /* Re-enable and check again */ + kev.flags = EV_ENABLE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT; + kev.data = 1; + kevent_cmp(&kev, kevent_get(kqfd)); + + success(test_id); +} + void test_evfilt_timer() { kqfd = kqueue(); - test_kevent_timer_add(); - test_kevent_timer_del(); - test_kevent_timer_get(); -#if TODO - test_kevent_signal_disable(); - test_kevent_signal_enable(); - test_kevent_signal_oneshot(); -#endif + test_kevent_timer_add(); + test_kevent_timer_del(); + test_kevent_timer_get(); + test_oneshot(); + test_periodic(); + disable_and_enable(); close(kqfd); } diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index 36a57b489..c42ac3d83 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -19,6 +19,8 @@

              libkqueue

              Download

              +Source code releases can be found here. +

              To checkout the SVN repository, run the following command:

              svn checkout svn://mark.heily.com/libkqueue @@ -68,8 +70,6 @@

              Requirements

              Usage

              -libkqueue is a multi-threaded library and kqueue() and kevent() are safe to be used from multiple threads. - Here are the steps to use libkqueue in your program:
              1. Add `pkg-config libkqueue --cflags` to the CFLAGS variable. @@ -95,6 +95,10 @@

                Usage

                #endif +

                Threads

                + +libkqueue is a threadsafe library, and kqueue() and kevent() are safe to be used from multiple threads. libkqueue requires that the POSIX threads headers (pthread.h) be available, but does not require you to link against libpthread.so. This allows it to be used in both non-threaded and multi-threaded programs. +

                Links

                  diff --git a/vendor/libkqueue/www/status.html b/vendor/libkqueue/www/status.html index 0a99dd977..8bb207c66 100644 --- a/vendor/libkqueue/www/status.html +++ b/vendor/libkqueue/www/status.html @@ -55,11 +55,11 @@

                  kevent.flags

                  EVFILT_TIMER
                  Yes -No -No -No -No -No +Yes +Yes +Yes +Yes +N/A @@ -96,13 +96,13 @@

                  kevent.fflags

                  READ / WRITE NOTE_LOWAT No -- Not supported by Linux VNODE - NOTE_DELETE Partial (fd must be closed) + NOTE_DELETE Yes NOTE_WRITE Yes - NOTE_EXTEND No + NOTE_EXTEND Yes NOTE_ATTRIB Yes - NOTE_LINK No + NOTE_LINK Yes NOTE_RENAME Yes - NOTE_REVOKE N/A -- Not available in Linux + NOTE_REVOKE No -- Not available in Linux USER NOTE_FFNOP Ignore the input fflags. NOTE_FFAND Bitwise AND fflags. From af783f88414a84abb079a347a99aafd84e62ab88 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 7 Nov 2009 21:13:59 +0000 Subject: [PATCH 0055/1120] new: dist-upload git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@64 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 7f63eac5a..eca9cc57c 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -14,6 +14,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # REPOSITORY=svn+ssh://mark.heily.com/$$HOME/svn/$(PROGRAM) +DIST=heily.com:$$HOME/public_html/$(PROGRAM)/dist INSTALL=/usr/bin/install SOURCES=filter.c kevent.c knote.c kqueue.c MANS=kqueue.2 @@ -53,6 +54,7 @@ check: cd test && ./configure && make check dist: + cd test && make distclean || true mkdir $(PROGRAM)-$(VERSION) cp Makefile configure \ $(SOURCES) $(MANS) $(HEADERS) $(EXTRA_DIST) \ @@ -62,6 +64,9 @@ dist: tar zcf $(PROGRAM)-$(VERSION).tar.gz $(PROGRAM)-$(VERSION) rm -rf $(PROGRAM)-$(VERSION) +dist-upload: dist + scp libkqueue-$(VERSION).tar.gz $(DIST) + publish-www: rm ~/public_html/libkqueue/*.html ; cp -R www/*.html ~/public_html/libkqueue/ From 3bc42188c357a2faea0b0b6f45e2dcd83d1800c8 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 8 Nov 2009 00:56:42 +0000 Subject: [PATCH 0056/1120] Eliminate the use of -D_REENTRANT git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@65 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure | 2 +- vendor/libkqueue/kqueue.c | 17 +++-------------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index 9b652a7a3..81cb31c3d 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -44,7 +44,7 @@ check_header() { # ####################################################################### -default_cflags="-fPIC -D_REENTRANT -I. -Wall -Werror" +default_cflags="-fPIC -I. -Wall -Werror" # Initialize the output files # diff --git a/vendor/libkqueue/kqueue.c b/vendor/libkqueue/kqueue.c index adcbedeae..4f5597e37 100644 --- a/vendor/libkqueue/kqueue.c +++ b/vendor/libkqueue/kqueue.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -31,15 +32,9 @@ static LIST_HEAD(,kqueue) kqlist = LIST_HEAD_INITIALIZER(&kqlist); -#if _REENTRANT -# include -# define kqlist_lock() pthread_mutex_lock(&kqlist_mtx) -# define kqlist_unlock() pthread_mutex_unlock(&kqlist_mtx) +#define kqlist_lock() pthread_mutex_lock(&kqlist_mtx) +#define kqlist_unlock() pthread_mutex_unlock(&kqlist_mtx) static pthread_mutex_t kqlist_mtx = PTHREAD_MUTEX_INITIALIZER; -#else -# define kqlist_lock() /**/ -# define kqlist_unlock() /**/ -#endif struct kqueue * kqueue_lookup(int kq) @@ -71,19 +66,15 @@ kqueue_shutdown(struct kqueue *kq) void kqueue_lock(struct kqueue *kq) { -#if _REENTRANT dbg_puts("kqueue_lock()"); pthread_mutex_lock(&kq->kq_mtx); -#endif } void kqueue_unlock(struct kqueue *kq) { -#if _REENTRANT dbg_puts("kqueue_unlock()"); pthread_mutex_unlock(&kq->kq_mtx); -#endif } int @@ -94,9 +85,7 @@ kqueue(void) kq = calloc(1, sizeof(*kq)); if (kq == NULL) return (-1); -#if _REENTRANT pthread_mutex_init(&kq->kq_mtx, NULL); -#endif if (filter_register_all(kq) < 0) return (-1); From 4a04a243918309b2721bff64ba8e7c6e14b06270 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 8 Nov 2009 00:59:36 +0000 Subject: [PATCH 0057/1120] move sys/ under include/ git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@66 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 4 ++-- vendor/libkqueue/configure | 2 +- vendor/libkqueue/{ => include}/sys/event.h | 0 vendor/libkqueue/test/configure | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename vendor/libkqueue/{ => include}/sys/event.h (100%) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index eca9cc57c..13cdd596c 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -20,7 +20,7 @@ SOURCES=filter.c kevent.c knote.c kqueue.c MANS=kqueue.2 HEADERS=private.h EXTRA_DIST=*.in README -SUBDIRS=os sys test +SUBDIRS=os include test DISTFILES=Makefile configure FILTERS=vnode.c timer.c signal.c socket.c user.c @@ -33,7 +33,7 @@ build: install: $(INSTALL) -d -m 755 $(INCLUDEDIR)/kqueue/sys - $(INSTALL) -m 644 sys/event.h $(INCLUDEDIR)/kqueue/sys/event.h + $(INSTALL) -m 644 include/sys/event.h $(INCLUDEDIR)/kqueue/sys/event.h $(INSTALL) -d -m 755 $(LIBDIR) $(INSTALL) -m 644 libkqueue.so $(LIBDIR)/libkqueue.so $(INSTALL) -d -m 755 $(LIBDIR)/pkgconfig diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index 81cb31c3d..81fed3a46 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -44,7 +44,7 @@ check_header() { # ####################################################################### -default_cflags="-fPIC -I. -Wall -Werror" +default_cflags="-fPIC -I./include -Wall -Werror" # Initialize the output files # diff --git a/vendor/libkqueue/sys/event.h b/vendor/libkqueue/include/sys/event.h similarity index 100% rename from vendor/libkqueue/sys/event.h rename to vendor/libkqueue/include/sys/event.h diff --git a/vendor/libkqueue/test/configure b/vendor/libkqueue/test/configure index 5a37d61aa..b1ea12c94 100755 --- a/vendor/libkqueue/test/configure +++ b/vendor/libkqueue/test/configure @@ -88,7 +88,7 @@ check_header sys/event.h && { cflags="-g -O0 -Wall -Werror" ldadd="" if [ "`uname -s`" = "Linux" ] ; then - cflags="$cflags -I.." + cflags="$cflags -I../include" ldadd="$ldadd ../libkqueue.a" fi finalize cflags "" From b24e774fc571e50cbab9045720eb7be371dc55b0 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 8 Nov 2009 02:04:16 +0000 Subject: [PATCH 0058/1120] major changes to internal build script git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@67 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 17 +-- vendor/libkqueue/config.inc | 31 +++++ vendor/libkqueue/configure | 129 ++++++++++++++------ vendor/libkqueue/{ => src/common}/filter.c | 0 vendor/libkqueue/{ => src/common}/kevent.c | 0 vendor/libkqueue/{ => src/common}/knote.c | 0 vendor/libkqueue/{ => src/common}/kqueue.c | 0 vendor/libkqueue/{ => src/common}/private.h | 0 vendor/libkqueue/{os => src}/linux/signal.c | 0 vendor/libkqueue/{os => src}/linux/socket.c | 0 vendor/libkqueue/{os => src}/linux/timer.c | 0 vendor/libkqueue/{os => src}/linux/vnode.c | 0 vendor/libkqueue/{os => src}/posix/signal.c | 0 vendor/libkqueue/{os => src}/posix/timer.c | 0 vendor/libkqueue/{os => src}/posix/user.c | 0 15 files changed, 126 insertions(+), 51 deletions(-) create mode 100644 vendor/libkqueue/config.inc rename vendor/libkqueue/{ => src/common}/filter.c (100%) rename vendor/libkqueue/{ => src/common}/kevent.c (100%) rename vendor/libkqueue/{ => src/common}/knote.c (100%) rename vendor/libkqueue/{ => src/common}/kqueue.c (100%) rename vendor/libkqueue/{ => src/common}/private.h (100%) rename vendor/libkqueue/{os => src}/linux/signal.c (100%) rename vendor/libkqueue/{os => src}/linux/socket.c (100%) rename vendor/libkqueue/{os => src}/linux/timer.c (100%) rename vendor/libkqueue/{os => src}/linux/vnode.c (100%) rename vendor/libkqueue/{os => src}/posix/signal.c (100%) rename vendor/libkqueue/{os => src}/posix/timer.c (100%) rename vendor/libkqueue/{os => src}/posix/user.c (100%) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 13cdd596c..4913e6bc2 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -13,21 +13,14 @@ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # + REPOSITORY=svn+ssh://mark.heily.com/$$HOME/svn/$(PROGRAM) DIST=heily.com:$$HOME/public_html/$(PROGRAM)/dist -INSTALL=/usr/bin/install -SOURCES=filter.c kevent.c knote.c kqueue.c -MANS=kqueue.2 -HEADERS=private.h -EXTRA_DIST=*.in README -SUBDIRS=os include test -DISTFILES=Makefile configure -FILTERS=vnode.c timer.c signal.c socket.c user.c include config.mk build: - gcc $(CFLAGS) -c *.c + $(CC) $(CFLAGS) -c $(SOURCES) ar rcs libkqueue.a *.o gcc -shared -Wl,-soname,libkqueue.so -o libkqueue.so *.o @@ -56,7 +49,7 @@ check: dist: cd test && make distclean || true mkdir $(PROGRAM)-$(VERSION) - cp Makefile configure \ + cp Makefile configure config.inc \ $(SOURCES) $(MANS) $(HEADERS) $(EXTRA_DIST) \ $(PROGRAM)-$(VERSION) cp -R $(SUBDIRS) $(PROGRAM)-$(VERSION) @@ -65,7 +58,7 @@ dist: rm -rf $(PROGRAM)-$(VERSION) dist-upload: dist - scp libkqueue-$(VERSION).tar.gz $(DIST) + scp $(PROGRAM)-$(VERSION).tar.gz $(DIST) publish-www: rm ~/public_html/libkqueue/*.html ; cp -R www/*.html ~/public_html/libkqueue/ @@ -80,4 +73,4 @@ merge: echo "ok" distclean: clean - rm -f *.tar.gz config.mk config.h libkqueue.pc $(FILTERS) + rm -f *.tar.gz config.mk config.h libkqueue.pc diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc new file mode 100644 index 000000000..864dc7b4f --- /dev/null +++ b/vendor/libkqueue/config.inc @@ -0,0 +1,31 @@ +program="libkqueue" +version="0.2" +cflags="-fPIC -I./include -Wall -Werror" +sources="src/common/*.c" +mans="kqueue.2" +headers="private.h" +extra_dist="*.in README" +subdirs="src include test" + +pre_configure_hook() { + if [ "$debug" = "yes" ] ; then + cflags="$cflags -DKQUEUE_DEBUG" + fi + + if [ $target = "linux" ] ; then + required_headers="sys/epoll.h sys/inotify.h" + optional_headers="sys/signalfd.h sys/timerfd.h" + fi +} + +post_configure_hook() { + if [ $target = "linux" ] ; then + if [ "$have_sys_signalfd_h" = "no" -o "$have_sys_timerfd_h" = "no" ] + then + echo "** NOTE: The Linux backend requires at least kernel 2.6.22 " + echo "** and glibc 2.8. Switching to the POSIX backend." + target=posix + fi + fi + finalize target "$target" +} diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index 81fed3a46..d4f052c9e 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -1,15 +1,44 @@ #!/bin/sh -program=libkqueue -version=0.2 +c_exports="program version target cflags" + +make_exports="program version target \ + prefix libdir includedir mandir \ + cflags ldflags libadd libdepends \ + sources mans headers extra_dist subdirs \ + install" + +required_headers= +optional_headers= + +pre_configure_hook() { + return +} + +post_configure_hook() { + return +} + +. ./config.inc + +export_to_make() { + for id in $* + do + uc_id=`echo $id | tr 'a-z' 'A-Z'`; + eval "echo \"$uc_id=\"\$$id\"\" >> config.mk" + done +} + +export_to_c() { + for id in $* + do + uc_id=`echo $id | tr 'a-z' 'A-Z'`; + eval "echo \"#define $uc_id \\\"\$$id\\\"\" >> config.h" + done +} finalize() { eval "if [ \"\$$1\" = \"\" ] ; then $1=\"$2\" ; fi" - - # Add the variable to config.mk and config.h - uc_id=`echo $1 | tr 'a-z' 'A-Z'`; - eval "echo \"$uc_id=\"\$$1\"\" >> config.mk" - eval "echo \"#define $uc_id \\\"\$$1\\\"\" >> config.h" } process_argv() { @@ -18,34 +47,58 @@ process_argv() { id=`echo "$arg" | sed 's/=.*//; s/^--//;'` val=`echo "$arg" | sed 's/^.*=//'` if [ "$val" = "" ] ; then val=1 ; fi - eval "$id=$val" + eval "$id=\"$val\"" done } check_header() { - sym=`echo "HAVE_$1" | tr a-z A-Z | sed 's,[./],_,g'` + sym=`echo "have_$1" | sed 's,[./],_,g'` + uc_sym=`echo "$sym" | tr a-z A-Z` path=$1 printf "checking for $path.. " if [ -f "/usr/include/$path" ] ; then echo "yes" - echo "#define $sym" >> config.h + echo "#define $uc_sym" >> config.h + eval "$sym=yes" return 0 else echo "no" - echo "#undef $sym" >> config.h + echo "#undef $uc_sym" >> config.h + eval "$sym=no" return 1 fi } +check_headers() { + for header in $* + do + check_header "$header" + done +} + +check_install() { + printf "checking for a BSD-compatible install.. " + if [ "`uname -s`" = "SunOS" ] ; then + default_install=/usr/ucb/install + else + default_install=/usr/bin/install + fi + finalize install "$default_install" + echo "$install" +} + +err() { + echo "*** ERROR *** $*" + exit 1 +} + ####################################################################### # # MAIN() # ####################################################################### -default_cflags="-fPIC -I./include -Wall -Werror" - # Initialize the output files # for output_file in config.mk $program.pc @@ -56,37 +109,31 @@ done rm -f config.h echo "/* AUTOMATICALLY GENERATED -- DO NOT EDIT */" > config.h -process_argv $* +process_argv "$*" -if [ "$debug" = "yes" ] -then - default_cflags="$default_cflags -DKQUEUE_DEBUG" -fi - -finalize program $program -finalize version $version +finalize program "$program" +finalize version "$version" finalize target `uname -s | tr A-Z a-z` -finalize prefix /usr/local +finalize prefix "/usr/local" finalize libdir "${prefix}/lib" finalize includedir "${prefix}/include" finalize mandir "${prefix}/share/man" -finalize cflags "$default_cflags" -finalize libdepends "" - -echo "Checking operating system type... $target" -rm -f socket.c vnode.c signal.c timer.c user.c -if [ $target = "linux" ] ; then - check_header sys/epoll.h && ln -s os/linux/socket.c \ - || ln -sf os/posix/socket.c - check_header sys/inotify.h && ln -s os/linux/vnode.c \ - || ln -sf os/posix/vnode.c - check_header sys/signalfd.h && ln -s os/linux/signal.c \ - || ln -sf os/posix/signal.c - check_header sys/timerfd.h && ln -s os/linux/timer.c \ - || ln -sf os/posix/timer.c - ln -sf os/posix/user.c -fi -echo "Creating config.h" +finalize cflags "$cflags" +finalize libdepends "$libdepends" +finalize cc "/usr/bin/cc" + +echo "checking operating system type.. $target" +check_install + +pre_configure_hook + +for header in $required_headers +do + check_header "$header" || err "$header is required, but cannot be found." +done +check_headers $optional_headers + +post_configure_hook echo "Creating $program.pc" sed -e " @@ -100,4 +147,8 @@ sed -e " " < $program.pc.in >> $program.pc chmod 400 $program.pc +echo "Creating config.h" +export_to_c $c_exports + echo "Creating config.mk" +export_to_make "$make_exports" diff --git a/vendor/libkqueue/filter.c b/vendor/libkqueue/src/common/filter.c similarity index 100% rename from vendor/libkqueue/filter.c rename to vendor/libkqueue/src/common/filter.c diff --git a/vendor/libkqueue/kevent.c b/vendor/libkqueue/src/common/kevent.c similarity index 100% rename from vendor/libkqueue/kevent.c rename to vendor/libkqueue/src/common/kevent.c diff --git a/vendor/libkqueue/knote.c b/vendor/libkqueue/src/common/knote.c similarity index 100% rename from vendor/libkqueue/knote.c rename to vendor/libkqueue/src/common/knote.c diff --git a/vendor/libkqueue/kqueue.c b/vendor/libkqueue/src/common/kqueue.c similarity index 100% rename from vendor/libkqueue/kqueue.c rename to vendor/libkqueue/src/common/kqueue.c diff --git a/vendor/libkqueue/private.h b/vendor/libkqueue/src/common/private.h similarity index 100% rename from vendor/libkqueue/private.h rename to vendor/libkqueue/src/common/private.h diff --git a/vendor/libkqueue/os/linux/signal.c b/vendor/libkqueue/src/linux/signal.c similarity index 100% rename from vendor/libkqueue/os/linux/signal.c rename to vendor/libkqueue/src/linux/signal.c diff --git a/vendor/libkqueue/os/linux/socket.c b/vendor/libkqueue/src/linux/socket.c similarity index 100% rename from vendor/libkqueue/os/linux/socket.c rename to vendor/libkqueue/src/linux/socket.c diff --git a/vendor/libkqueue/os/linux/timer.c b/vendor/libkqueue/src/linux/timer.c similarity index 100% rename from vendor/libkqueue/os/linux/timer.c rename to vendor/libkqueue/src/linux/timer.c diff --git a/vendor/libkqueue/os/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c similarity index 100% rename from vendor/libkqueue/os/linux/vnode.c rename to vendor/libkqueue/src/linux/vnode.c diff --git a/vendor/libkqueue/os/posix/signal.c b/vendor/libkqueue/src/posix/signal.c similarity index 100% rename from vendor/libkqueue/os/posix/signal.c rename to vendor/libkqueue/src/posix/signal.c diff --git a/vendor/libkqueue/os/posix/timer.c b/vendor/libkqueue/src/posix/timer.c similarity index 100% rename from vendor/libkqueue/os/posix/timer.c rename to vendor/libkqueue/src/posix/timer.c diff --git a/vendor/libkqueue/os/posix/user.c b/vendor/libkqueue/src/posix/user.c similarity index 100% rename from vendor/libkqueue/os/posix/user.c rename to vendor/libkqueue/src/posix/user.c From 1ceb6008d0496870531a9ba5f7d6471f7de28499 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 8 Nov 2009 02:21:03 +0000 Subject: [PATCH 0059/1120] final build changes to reorganize src/ git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@68 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/config.inc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index 864dc7b4f..ae82d1ef7 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -1,6 +1,6 @@ program="libkqueue" version="0.2" -cflags="-fPIC -I./include -Wall -Werror" +cflags="-fPIC -I./include -I./src/common -Wall -Werror" sources="src/common/*.c" mans="kqueue.2" headers="private.h" @@ -22,10 +22,12 @@ post_configure_hook() { if [ $target = "linux" ] ; then if [ "$have_sys_signalfd_h" = "no" -o "$have_sys_timerfd_h" = "no" ] then - echo "** NOTE: The Linux backend requires at least kernel 2.6.22 " - echo "** and glibc 2.8. Switching to the POSIX backend." - target=posix + echo "** ERROR: Your kernel and/or C library are too old." + echo "** At least kernel 2.6.22 and glibc 2.8 are required." + exit 1 fi fi + finalize target "$target" + sources="$sources src/$target/*.c" } From 7ed5029ac5cc3719f1ad60ff7c8e20a4671cf84a Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 8 Nov 2009 02:29:44 +0000 Subject: [PATCH 0060/1120] move user.c git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@69 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/{posix => common}/user.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename vendor/libkqueue/src/{posix => common}/user.c (100%) diff --git a/vendor/libkqueue/src/posix/user.c b/vendor/libkqueue/src/common/user.c similarity index 100% rename from vendor/libkqueue/src/posix/user.c rename to vendor/libkqueue/src/common/user.c From f16c4d155ada064bb263e60a67426e01ba3cffca Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 8 Nov 2009 04:59:18 +0000 Subject: [PATCH 0061/1120] EVFILT_USER implemented git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@70 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/config.inc | 13 +-- vendor/libkqueue/src/common/user.c | 98 ----------------- vendor/libkqueue/src/linux/user.c | 164 +++++++++++++++++++++++++++++ vendor/libkqueue/test/Makefile | 2 +- vendor/libkqueue/test/configure | 6 +- vendor/libkqueue/test/main.c | 13 ++- vendor/libkqueue/test/user.c | 134 +++++++++++++++++++++++ vendor/libkqueue/www/index.html | 10 +- vendor/libkqueue/www/status.html | 2 +- 9 files changed, 325 insertions(+), 117 deletions(-) delete mode 100644 vendor/libkqueue/src/common/user.c create mode 100644 vendor/libkqueue/src/linux/user.c create mode 100644 vendor/libkqueue/test/user.c diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index ae82d1ef7..f4b95f86c 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -13,21 +13,12 @@ pre_configure_hook() { fi if [ $target = "linux" ] ; then - required_headers="sys/epoll.h sys/inotify.h" - optional_headers="sys/signalfd.h sys/timerfd.h" + required_headers="sys/epoll.h sys/inotify.h + sys/signalfd.h sys/timerfd.h sys/eventfd.h" fi } post_configure_hook() { - if [ $target = "linux" ] ; then - if [ "$have_sys_signalfd_h" = "no" -o "$have_sys_timerfd_h" = "no" ] - then - echo "** ERROR: Your kernel and/or C library are too old." - echo "** At least kernel 2.6.22 and glibc 2.8 are required." - exit 1 - fi - fi - finalize target "$target" sources="$sources src/$target/*.c" } diff --git a/vendor/libkqueue/src/common/user.c b/vendor/libkqueue/src/common/user.c deleted file mode 100644 index ff4e7edb8..000000000 --- a/vendor/libkqueue/src/common/user.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2009 Mark Heily - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sys/event.h" -#include "private.h" - -int -evfilt_user_init(struct filter *filt) -{ - return filter_socketpair(filt); -} - -void -evfilt_user_destroy(struct filter *filt) -{ - close(filt->kf_wfd); /* TODO: do this in the parent */ - return; -} - -int -evfilt_user_copyin(struct filter *filt, - struct knote *dst, const struct kevent *src) -{ - u_int ffctrl; - struct kevent *kev; - - if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) { - memcpy(&dst->kev, src, sizeof(*src)); - } - kev = &dst->kev; - - /* Based on sys/kern/kern_event.c in FreeBSD HEAD */ - ffctrl = kev->fflags & NOTE_FFCTRLMASK; - kev->fflags &= NOTE_FFLAGSMASK; - switch (ffctrl) { - case NOTE_FFNOP: - break; - - case NOTE_FFAND: - kev->fflags &= src->fflags; - break; - - case NOTE_FFOR: - kev->fflags |= src->fflags; - break; - - case NOTE_FFCOPY: - kev->fflags = kev->fflags; - break; - - default: - /* XXX Return error? */ - break; - } - - return (-1); -} - -int -evfilt_user_copyout(struct filter *filt, - struct kevent *dst, - int nevents) -{ - return (0); -} - -const struct filter evfilt_user = { - EVFILT_USER, - evfilt_user_init, - evfilt_user_destroy, - evfilt_user_copyin, - evfilt_user_copyout, -}; diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c new file mode 100644 index 000000000..27bc5de28 --- /dev/null +++ b/vendor/libkqueue/src/linux/user.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sys/event.h" +#include "private.h" + +int +evfilt_user_init(struct filter *filt) +{ + if ((filt->kf_pfd = eventfd(0, 0)) < 0) + return (-1); + if (fcntl(filt->kf_pfd, F_SETFL, O_NONBLOCK) < 0) + return (-1); + + return (0); +} + +void +evfilt_user_destroy(struct filter *filt) +{ + close(filt->kf_pfd); /* TODO: do this in the parent */ + return; +} + +int +evfilt_user_copyin(struct filter *filt, + struct knote *dst, const struct kevent *src) +{ + u_int ffctrl; + struct kevent *kev; + uint64_t counter; + + if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) { + memcpy(&dst->kev, src, sizeof(*src)); + } + kev = &dst->kev; + if (src->flags & EV_ENABLE) { + dst->kev.flags &= ~EV_DISABLE; + /* FIXME: what happens if NOTE_TRIGGER is in fflags? + should the event fire? */ + } + if (src->flags & EV_DISABLE) + dst->kev.flags |= EV_DISABLE; + + /* FIXME: can oneshot be added after the knote is already created? */ + if (src->flags & EV_ONESHOT) + dst->kev.flags |= EV_ONESHOT; + + /* Excerpted from sys/kern/kern_event.c in FreeBSD HEAD */ + ffctrl = kev->fflags & NOTE_FFCTRLMASK; + kev->fflags &= NOTE_FFLAGSMASK; + switch (ffctrl) { + case NOTE_FFNOP: + break; + + case NOTE_FFAND: + kev->fflags &= src->fflags; + break; + + case NOTE_FFOR: + kev->fflags |= src->fflags; + break; + + case NOTE_FFCOPY: + kev->fflags = kev->fflags; + break; + + default: + /* XXX Return error? */ + break; + } + + if ((!(dst->kev.flags & EV_DISABLE)) && src->fflags & NOTE_TRIGGER) { + counter = 1; + if (write(filt->kf_pfd, &counter, sizeof(counter)) < 0) { + if (errno != EAGAIN) { + dbg_printf("write(2): %s", strerror(errno)); + return (-1); + } + } + dst->kev.fflags |= NOTE_TRIGGER; + dbg_puts("knote triggered"); + } + + return (0); +} + +int +evfilt_user_copyout(struct filter *filt, + struct kevent *dst, + int maxevents) +{ + struct knote *kn; + int nevents = 0; + uint64_t cur; + + /* Reset the counter */ + if (read(filt->kf_pfd, &cur, sizeof(cur)) < sizeof(cur)) { + dbg_printf("read(2): %s", strerror(errno)); + return (-1); + } + dbg_printf(" counter=%llu", (unsigned long long) cur); + + /* Scan for events that have been triggered */ + KNOTELIST_FOREACH(kn, &filt->knl) { + if (!(kn->kev.fflags & NOTE_TRIGGER)) + continue; + + dst->ident = kn->kev.ident; + dst->filter = kn->kev.filter; + dst->udata = kn->kev.udata; + dst->flags = EV_ADD; + dst->fflags = kn->kev.fflags; + dst->data = 0; + if (kn->kev.flags & EV_ONESHOT) /*TODO: move elsewhere */ + dst->flags |= EV_ONESHOT; + if (kn->kev.flags & EV_CLEAR) /*TODO: move elsewhere */ + dst->flags |= EV_CLEAR; + if (kn->kev.flags & EV_DISPATCH) + KNOTE_DISABLE(kn); + if (kn->kev.flags & EV_ONESHOT) + knote_free(kn); + + dst++; + if (++nevents == maxevents) + break; + } + + return (nevents); +} + +const struct filter evfilt_user = { + EVFILT_USER, + evfilt_user_init, + evfilt_user_destroy, + evfilt_user_copyin, + evfilt_user_copyout, +}; diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile index eb992d16a..27c22ce1b 100644 --- a/vendor/libkqueue/test/Makefile +++ b/vendor/libkqueue/test/Makefile @@ -16,7 +16,7 @@ include config.mk -SOURCES=main.c read.c signal.c vnode.c timer.c +SOURCES=main.c read.c signal.c vnode.c timer.c user.c check: if [ ! -f /usr/include/sys/event.h ] ; then \ diff --git a/vendor/libkqueue/test/configure b/vendor/libkqueue/test/configure index b1ea12c94..a6c02623c 100755 --- a/vendor/libkqueue/test/configure +++ b/vendor/libkqueue/test/configure @@ -81,8 +81,10 @@ finalize mandir "${prefix}/share/man" echo "Checking operating system type... $target" check_header sys/event.h && { - check_symbol sys/event.h EVFILT_DISPATCH - check_symbol sys/event.h EVFILT_RECEIPT + check_symbol sys/event.h EV_DISPATCH + check_symbol sys/event.h EV_RECEIPT + check_symbol sys/event.h EVFILT_USER + check_symbol sys/event.h EVFILT_TIMER } cflags="-g -O0 -Wall -Werror" diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 8864a24b9..71ff88340 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -18,6 +18,7 @@ #include "common.h" +int testnum = 1; char *cur_test_id = "undef"; int kqfd; @@ -25,6 +26,7 @@ extern void test_evfilt_read(); extern void test_evfilt_signal(); extern void test_evfilt_vnode(); extern void test_evfilt_timer(); +extern void test_evfilt_user(); /* Checks if any events are pending, which is an error. */ void @@ -157,7 +159,6 @@ kevent_cmp(struct kevent *k1, struct kevent *k2) void test_begin(const char *func) { - static int testnum = 1; cur_test_id = (char *) func; printf("\n\nTest %d: %s\n", testnum++, func); } @@ -194,9 +195,10 @@ int main(int argc, char **argv) { int test_socket = 1; - int test_signal = 1;//XXX-FIXME + int test_signal = 1; int test_vnode = 1; int test_timer = 1; + int test_user = 1; while (argc) { if (strcmp(argv[0], "--no-socket") == 0) @@ -207,6 +209,8 @@ main(int argc, char **argv) test_signal = 0; if (strcmp(argv[0], "--no-vnode") == 0) test_vnode = 0; + if (strcmp(argv[0], "--no-user") == 0) + test_user = 0; argv++; argc--; } @@ -220,9 +224,12 @@ main(int argc, char **argv) test_evfilt_signal(); if (test_vnode) test_evfilt_vnode(); + if (test_user) + test_evfilt_user(); if (test_timer) test_evfilt_timer(); - puts("all tests completed."); + printf("\n---\n" + "+OK All %d tests completed.\n", testnum - 1); return (0); } diff --git a/vendor/libkqueue/test/user.c b/vendor/libkqueue/test/user.c new file mode 100644 index 000000000..d947ec298 --- /dev/null +++ b/vendor/libkqueue/test/user.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "common.h" + +int kqfd; + +static void +add_and_delete(void) +{ + const char *test_id = "kevent(EVFILT_USER, EV_ADD and EV_DELETE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + test_no_kevents(); + + kev.flags = EV_DELETE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + test_no_kevents(); + + success(test_id); +} + +static void +event_wait(void) +{ + const char *test_id = "kevent(EVFILT_USER, wait)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + kev.fflags |= NOTE_TRIGGER; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + kevent_cmp(&kev, kevent_get(kqfd)); + + success(test_id); +} + +static void +disable_and_enable(void) +{ + const char *test_id = "kevent(EVFILT_USER, EV_DISABLE and EV_ENABLE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + kev.flags = EV_DISABLE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + kev.fflags |= NOTE_TRIGGER; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + test_no_kevents(); + + kev.flags = EV_ENABLE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + kev.flags = EV_ADD; + kevent_cmp(&kev, kevent_get(kqfd)); + + success(test_id); +} + +static void +oneshot(void) +{ + const char *test_id = "kevent(EVFILT_USER, EV_ONESHOT)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, 1, EVFILT_USER, EV_ADD | EV_ONESHOT, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + puts(" -- event 1"); + kev.fflags |= NOTE_TRIGGER; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + kevent_cmp(&kev, kevent_get(kqfd)); + + /* Try to trigger the event again. It is deleted, so that + should be an error. + */ + puts(" -- event 2 (should fail)"); + kev.flags = 0; + kev.fflags |= NOTE_TRIGGER; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_evfilt_user() +{ + kqfd = kqueue(); + + add_and_delete(); + event_wait(); + disable_and_enable(); + oneshot(); + /* TODO: try different fflags operations */ + + close(kqfd); +} diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index c42ac3d83..e15b8eda3 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -33,7 +33,15 @@

                  Mailing Lists

                  Status

                  -Most of the API is implemented, with the notable exception of EVFILT_TIMER and EVFILT_USER. More details about the current implementation status is here. +The kqueue and kevent functions are implemented, and most of the filters are working. The following filters are not yet implemented:

                  + +

                    +
                  • EVFILT_PROC +
                  • EVFILT_AIO +
                  • EVFILT_NETDEV +
                  + +More details about the current implementation status can be found here.

                  There are several compatibility issues to be aware of when using this library under Linux:

                    diff --git a/vendor/libkqueue/www/status.html b/vendor/libkqueue/www/status.html index 8bb207c66..29c3d0074 100644 --- a/vendor/libkqueue/www/status.html +++ b/vendor/libkqueue/www/status.html @@ -84,7 +84,7 @@

                    kevent.flags

                    EVFILT_USER
                    -No - stub +Yes From 19e8cf4c567ada66941e9d4bb3bf1260087f660a Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 8 Nov 2009 05:09:30 +0000 Subject: [PATCH 0062/1120] add check_symbol to configure git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@71 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index d4f052c9e..c8a773541 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -77,6 +77,26 @@ check_headers() { done } +check_symbol() { + header=$1 + symbol=$2 + + uc_symbol=`echo "HAVE_$symbol" | tr a-z A-Z | sed 's,[./],_,g'` + lc_symbol=`echo "have_$symbol" | tr A-Z a-z | sed 's,[./],_,g'` + + printf "checking <$header> for $symbol.. " + if [ "`grep '#define $symbol' /usr/include/$header`" != "" ] ; then + eval "$lc_symbol=yes" + echo "#define $uc_symbol" >> config.h + return 0 + else + eval "$lc_symbol=no" + echo "#undef $uc_symbol" >> config.h + return 1 + fi + echo "$sym" +} + check_install() { printf "checking for a BSD-compatible install.. " if [ "`uname -s`" = "SunOS" ] ; then From a9fe0644fb42ae6bb818d1dda32dc17da2f40f68 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 8 Nov 2009 05:09:49 +0000 Subject: [PATCH 0063/1120] remove old configure git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@72 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/configure | 100 -------------------------------- 1 file changed, 100 deletions(-) delete mode 100755 vendor/libkqueue/test/configure diff --git a/vendor/libkqueue/test/configure b/vendor/libkqueue/test/configure deleted file mode 100755 index a6c02623c..000000000 --- a/vendor/libkqueue/test/configure +++ /dev/null @@ -1,100 +0,0 @@ -#!/bin/sh - -program=libkqueue-test -version=0.1 - -finalize() { - eval "if [ \"\$$1\" = \"\" ] ; then $1=$2 ; fi" - - # Add the variable to config.mk and config.h - id=`echo $1 | tr 'a-z' 'A-Z'`; - eval "echo \"$id=\$$1\" >> config.mk" - eval "echo \"#define $id \\\"\$$1\\\"\" >> config.h" -} - -process_argv() { - for arg in $* - do - id=`echo "$arg" | sed 's/=.*//; s/^--//;'` - val=`echo "$arg" | sed 's/^.*=//'` - if [ "$val" = "" ] ; then val=1 ; fi - eval "$id=$val" - done -} - -check_header() { - sym=`echo "HAVE_$1" | tr a-z A-Z | sed 's,[./],_,g'` - path=$1 - - printf "checking for $path.. " - if [ -f "/usr/include/$path" ] ; then - echo "yes" - echo "#define $sym" >> config.h - return 0 - else - echo "no" - echo "#undef $sym" >> config.h - return 1 - fi -} - -check_symbol() { - header=$1 - symbol=$2 - - uc_symbol=`echo "HAVE_$symbol" | tr a-z A-Z | sed 's,[./],_,g'` - - printf "checking <$header> for $symbol.. " - if [ "`grep '#define $symbol' /usr/include/$header`" != "" ] ; then - echo "yes" - echo "#define $uc_symbol" >> config.h - return 0 - else - echo "no" - echo "#undef $uc_symbol" >> config.h - return 1 - fi -} - -####################################################################### -# -# MAIN() -# -####################################################################### - -# Initialize the output files -# -rm -f config.h -echo "/* AUTOMATICALLY GENERATED -- DO NOT EDIT */" > config.h -rm -f config.mk -echo "# AUTOMATICALLY GENERATED -- DO NOT EDIT" > config.mk - -process_argv $* - -finalize program $program -finalize version $version -finalize target `uname -s | tr A-Z a-z` -finalize prefix /usr/local -finalize libdir "${prefix}/lib" -finalize includedir "${prefix}/include" -finalize mandir "${prefix}/share/man" - -echo "Checking operating system type... $target" -check_header sys/event.h && { - check_symbol sys/event.h EV_DISPATCH - check_symbol sys/event.h EV_RECEIPT - check_symbol sys/event.h EVFILT_USER - check_symbol sys/event.h EVFILT_TIMER -} - -cflags="-g -O0 -Wall -Werror" -ldadd="" -if [ "`uname -s`" = "Linux" ] ; then - cflags="$cflags -I../include" - ldadd="$ldadd ../libkqueue.a" -fi -finalize cflags "" -finalize ldadd "" - -echo "Creating config.h" -echo "Creating config.mk" From 9b91c746dd4238a1ea5d3747646d6578cfd70aef Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 8 Nov 2009 05:12:51 +0000 Subject: [PATCH 0064/1120] configure fixes git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@73 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure | 27 +++++++++++++++------------ vendor/libkqueue/test/config.inc | 21 +++++++++++++++++++++ 2 files changed, 36 insertions(+), 12 deletions(-) create mode 100755 vendor/libkqueue/test/config.inc diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index c8a773541..188b54020 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -88,13 +88,14 @@ check_symbol() { if [ "`grep '#define $symbol' /usr/include/$header`" != "" ] ; then eval "$lc_symbol=yes" echo "#define $uc_symbol" >> config.h + echo "$sym" return 0 else eval "$lc_symbol=no" + echo "$sym" echo "#undef $uc_symbol" >> config.h return 1 fi - echo "$sym" } check_install() { @@ -155,17 +156,19 @@ check_headers $optional_headers post_configure_hook -echo "Creating $program.pc" -sed -e " - s,@@PROGRAM@@,$program,g; - s,@@VERSION@@,$version,g; - s,@@PREFIX@@,$prefix,g; - s,@@LIBDIR@@,$libdir,g; - s,@@INCLUDEDIR@@,$includedir,g; - s,@@MANDIR@@,$mandir,g; - s,@@LIBDEPENDS@@,$libdepends,g; - " < $program.pc.in >> $program.pc -chmod 400 $program.pc +if [ -f "$program.pc.in" ] ; then + echo "Creating $program.pc" + sed -e " + s,@@PROGRAM@@,$program,g; + s,@@VERSION@@,$version,g; + s,@@PREFIX@@,$prefix,g; + s,@@LIBDIR@@,$libdir,g; + s,@@INCLUDEDIR@@,$includedir,g; + s,@@MANDIR@@,$mandir,g; + s,@@LIBDEPENDS@@,$libdepends,g; + " < $program.pc.in >> $program.pc + chmod 400 $program.pc +fi echo "Creating config.h" export_to_c $c_exports diff --git a/vendor/libkqueue/test/config.inc b/vendor/libkqueue/test/config.inc new file mode 100755 index 000000000..3c4bc7976 --- /dev/null +++ b/vendor/libkqueue/test/config.inc @@ -0,0 +1,21 @@ +#!/bin/sh + +program=libkqueue-test +version=0.1 +cflags="-g -O0 -Wall -Werror" +sources="main.c read.c signal.c timer.c vnode.c" + +pre_configure_hook() { + check_header sys/event.h && { + check_symbol sys/event.h EV_DISPATCH + check_symbol sys/event.h EV_RECEIPT + check_symbol sys/event.h EVFILT_USER && \ + sources="$sources user.c" + check_symbol sys/event.h EVFILT_TIMER + } + + if [ "`uname -s`" = "Linux" ] ; then + cflags="$cflags -I../include" + ldadd="$ldadd ../libkqueue.a" + fi +} From ee82a6b51eefcc708b93110a555a698ad2da593a Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 8 Nov 2009 05:24:11 +0000 Subject: [PATCH 0065/1120] port to openbsd git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@74 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/Makefile | 2 -- vendor/libkqueue/test/config.inc | 1 + vendor/libkqueue/test/configure | 1 + vendor/libkqueue/test/main.c | 14 +++++++++----- 4 files changed, 11 insertions(+), 7 deletions(-) create mode 120000 vendor/libkqueue/test/configure diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile index 27c22ce1b..c49e7954c 100644 --- a/vendor/libkqueue/test/Makefile +++ b/vendor/libkqueue/test/Makefile @@ -16,8 +16,6 @@ include config.mk -SOURCES=main.c read.c signal.c vnode.c timer.c user.c - check: if [ ! -f /usr/include/sys/event.h ] ; then \ cd .. && ./configure --debug=yes && make build ; \ diff --git a/vendor/libkqueue/test/config.inc b/vendor/libkqueue/test/config.inc index 3c4bc7976..9fc67cf7c 100755 --- a/vendor/libkqueue/test/config.inc +++ b/vendor/libkqueue/test/config.inc @@ -9,6 +9,7 @@ pre_configure_hook() { check_header sys/event.h && { check_symbol sys/event.h EV_DISPATCH check_symbol sys/event.h EV_RECEIPT + check_symbol sys/event.h NOTE_TRUNCATE check_symbol sys/event.h EVFILT_USER && \ sources="$sources user.c" check_symbol sys/event.h EVFILT_TIMER diff --git a/vendor/libkqueue/test/configure b/vendor/libkqueue/test/configure new file mode 120000 index 000000000..c9d4efb4f --- /dev/null +++ b/vendor/libkqueue/test/configure @@ -0,0 +1 @@ +../configure \ No newline at end of file diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 71ff88340..e726571a5 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -26,7 +26,9 @@ extern void test_evfilt_read(); extern void test_evfilt_signal(); extern void test_evfilt_vnode(); extern void test_evfilt_timer(); +#if HAVE_EVFILT_USER extern void test_evfilt_user(); +#endif /* Checks if any events are pending, which is an error. */ void @@ -70,18 +72,18 @@ kevent_fflags_dump(struct kevent *kev) #define KEVFFL_DUMP(attrib) \ if (kev->fflags & attrib) \ - strcat(buf, #attrib" "); + strncat(buf, #attrib" ", 64); if ((buf = calloc(1, 1024)) == NULL) abort(); /* Not every filter has meaningful fflags */ if (kev->filter != EVFILT_VNODE) { - sprintf(buf, "fflags = %d", kev->flags); + snprintf(buf, 1024, "fflags = %d", kev->flags); return (buf); } - sprintf(buf, "fflags = %d (", kev->fflags); + snprintf(buf, 1024, "fflags = %d (", kev->fflags); KEVFFL_DUMP(NOTE_DELETE); KEVFFL_DUMP(NOTE_WRITE); KEVFFL_DUMP(NOTE_EXTEND); @@ -106,12 +108,12 @@ kevent_flags_dump(struct kevent *kev) #define KEVFL_DUMP(attrib) \ if (kev->flags & attrib) \ - strcat(buf, #attrib" "); + strncat(buf, #attrib" ", 64); if ((buf = calloc(1, 1024)) == NULL) abort(); - sprintf(buf, "flags = %d (", kev->flags); + snprintf(buf, 1024, "flags = %d (", kev->flags); KEVFL_DUMP(EV_ADD); KEVFL_DUMP(EV_ENABLE); KEVFL_DUMP(EV_DISABLE); @@ -224,8 +226,10 @@ main(int argc, char **argv) test_evfilt_signal(); if (test_vnode) test_evfilt_vnode(); +#if HAVE_EVFILT_USER if (test_user) test_evfilt_user(); +#endif if (test_timer) test_evfilt_timer(); From f106a44799c78d6505f6b88da381ac6d734c0e9b Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 8 Nov 2009 05:24:21 +0000 Subject: [PATCH 0066/1120] fix check_symbol git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@75 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index 188b54020..6e992d522 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -85,14 +85,14 @@ check_symbol() { lc_symbol=`echo "have_$symbol" | tr A-Z a-z | sed 's,[./],_,g'` printf "checking <$header> for $symbol.. " - if [ "`grep '#define $symbol' /usr/include/$header`" != "" ] ; then + if [ "`grep $symbol /usr/include/$header`" != "" ] ; then eval "$lc_symbol=yes" - echo "#define $uc_symbol" >> config.h - echo "$sym" + echo "#define $uc_symbol 1" >> config.h + echo "yes" return 0 else eval "$lc_symbol=no" - echo "$sym" + echo "no" echo "#undef $uc_symbol" >> config.h return 1 fi From abe9a85ce50478b0f482164a160f81fad060ed7f Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 8 Nov 2009 05:53:38 +0000 Subject: [PATCH 0067/1120] fix tests on linux git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@76 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure | 20 ++++++++++++++++---- vendor/libkqueue/test/Makefile | 2 +- vendor/libkqueue/test/config.inc | 26 ++++++++++++++------------ vendor/libkqueue/test/read.c | 15 +++++++-------- 4 files changed, 38 insertions(+), 25 deletions(-) diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index 6e992d522..5d5c32097 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -4,7 +4,7 @@ c_exports="program version target cflags" make_exports="program version target \ prefix libdir includedir mandir \ - cflags ldflags libadd libdepends \ + cflags ldflags ldadd libdepends \ sources mans headers extra_dist subdirs \ install" @@ -51,6 +51,7 @@ process_argv() { done } + check_header() { sym=`echo "have_$1" | sed 's,[./],_,g'` uc_sym=`echo "$sym" | tr a-z A-Z` @@ -83,9 +84,18 @@ check_symbol() { uc_symbol=`echo "HAVE_$symbol" | tr a-z A-Z | sed 's,[./],_,g'` lc_symbol=`echo "have_$symbol" | tr A-Z a-z | sed 's,[./],_,g'` - - printf "checking <$header> for $symbol.. " - if [ "`grep $symbol /usr/include/$header`" != "" ] ; then + + if [ -f "$header" ] ; then + path="$header" + elif [ -f "/usr/include/$header" ] ; then + path="/usr/include/$path" + else + echo "*** ERROR: Cannot find <$header>" + exit 1 + fi + + printf "checking $path for $symbol.. " + if [ "`grep $symbol $path`" != "" ] ; then eval "$lc_symbol=yes" echo "#define $uc_symbol 1" >> config.h echo "yes" @@ -141,6 +151,8 @@ finalize includedir "${prefix}/include" finalize mandir "${prefix}/share/man" finalize cflags "$cflags" finalize libdepends "$libdepends" +finalize ldadd "" +finalize ldflags "" finalize cc "/usr/bin/cc" echo "checking operating system type.. $target" diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile index c49e7954c..781cfe090 100644 --- a/vendor/libkqueue/test/Makefile +++ b/vendor/libkqueue/test/Makefile @@ -20,7 +20,7 @@ check: if [ ! -f /usr/include/sys/event.h ] ; then \ cd .. && ./configure --debug=yes && make build ; \ fi - gcc $(CFLAGS) $(SOURCES) $(LDADD) + $(CC) $(CFLAGS) $(SOURCES) $(LDADD) ./a.out # NOTE: copy+paste of 'make check' diff --git a/vendor/libkqueue/test/config.inc b/vendor/libkqueue/test/config.inc index 9fc67cf7c..60f7cac02 100755 --- a/vendor/libkqueue/test/config.inc +++ b/vendor/libkqueue/test/config.inc @@ -6,17 +6,19 @@ cflags="-g -O0 -Wall -Werror" sources="main.c read.c signal.c timer.c vnode.c" pre_configure_hook() { - check_header sys/event.h && { - check_symbol sys/event.h EV_DISPATCH - check_symbol sys/event.h EV_RECEIPT - check_symbol sys/event.h NOTE_TRUNCATE - check_symbol sys/event.h EVFILT_USER && \ - sources="$sources user.c" - check_symbol sys/event.h EVFILT_TIMER - } + + check_header "sys/event.h" \ + && sys_event_h="sys/event.h" \ + || { + sys_event_h="../include/sys/event.h" + cflags="$cflags -I../include" + ldadd="$ldadd ../libkqueue.a" + } - if [ "`uname -s`" = "Linux" ] ; then - cflags="$cflags -I../include" - ldadd="$ldadd ../libkqueue.a" - fi + check_symbol $sys_event_h EV_DISPATCH + check_symbol $sys_event_h EV_RECEIPT + check_symbol $sys_event_h NOTE_TRUNCATE + check_symbol $sys_event_h EVFILT_TIMER + check_symbol $sys_event_h EVFILT_USER && \ + sources="$sources user.c" } diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index dfd0b400e..106512bf2 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -203,6 +203,7 @@ test_kevent_socket_oneshot(void) } +#if HAVE_EV_DISPATCH void test_kevent_socket_dispatch(void) { @@ -210,7 +211,6 @@ test_kevent_socket_dispatch(void) test_begin(test_id); -#if HAVE_EV_DISPATCH struct kevent kev; /* Re-add the watch and make sure no events are pending */ @@ -220,12 +220,12 @@ test_kevent_socket_dispatch(void) err(1, "%s", test_id); test_no_kevents(); - /* Since the knote is disabled, there are no events. */ - puts("-- checking if knote is disabled.."); + /* The event will occur only once, even though EV_CLEAR is not + specified. */ kevent_socket_fill(); - if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) - err(1, "%s", test_id); - KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); + kev.flags = EV_ADD; /* FIXME: not sure what the proper behavior is */ + kev.data = 1; + kevent_cmp(&kev, kevent_get(kqfd)); test_no_kevents(); /* Since the knote is disabled, the EV_DELETE operation succeeds. */ @@ -235,10 +235,9 @@ test_kevent_socket_dispatch(void) kevent_socket_drain(); -#endif /* HAVE_EV_DISPATCH */ - success(test_id); } +#endif /* HAVE_EV_DISPATCH */ #if BROKEN void From ead5965e717158da7ae53670ae8c74690735081d Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 8 Nov 2009 05:56:34 +0000 Subject: [PATCH 0068/1120] fix obsd breakage git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@77 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure | 4 ++-- vendor/libkqueue/test/read.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index 5d5c32097..de4780529 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -88,13 +88,13 @@ check_symbol() { if [ -f "$header" ] ; then path="$header" elif [ -f "/usr/include/$header" ] ; then - path="/usr/include/$path" + path="/usr/include/$header" else echo "*** ERROR: Cannot find <$header>" exit 1 fi - printf "checking $path for $symbol.. " + printf "checking $header for $symbol.. " if [ "`grep $symbol $path`" != "" ] ; then eval "$lc_symbol=yes" echo "#define $uc_symbol 1" >> config.h diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 106512bf2..e3959a0d5 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -315,7 +315,9 @@ test_evfilt_read() test_kevent_socket_disable_and_enable(); test_kevent_socket_oneshot(); test_kevent_socket_clear(); +#if HAVE_EV_DISPATCH test_kevent_socket_dispatch(); +#endif test_kevent_socket_eof(); close(kqfd); } From 51b177f0915205a865e7ac4184df2080119be197 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 9 Nov 2009 01:24:49 +0000 Subject: [PATCH 0069/1120] reenable pthreads git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@78 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/config.inc | 2 ++ vendor/libkqueue/test/config.inc | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index f4b95f86c..47f24c873 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -2,6 +2,7 @@ program="libkqueue" version="0.2" cflags="-fPIC -I./include -I./src/common -Wall -Werror" sources="src/common/*.c" +libdepends="" mans="kqueue.2" headers="private.h" extra_dist="*.in README" @@ -13,6 +14,7 @@ pre_configure_hook() { fi if [ $target = "linux" ] ; then + libdepends="$libdepends -lpthread -lrt" required_headers="sys/epoll.h sys/inotify.h sys/signalfd.h sys/timerfd.h sys/eventfd.h" fi diff --git a/vendor/libkqueue/test/config.inc b/vendor/libkqueue/test/config.inc index 60f7cac02..fbef6d5ba 100755 --- a/vendor/libkqueue/test/config.inc +++ b/vendor/libkqueue/test/config.inc @@ -12,7 +12,7 @@ pre_configure_hook() { || { sys_event_h="../include/sys/event.h" cflags="$cflags -I../include" - ldadd="$ldadd ../libkqueue.a" + ldadd="$ldadd ../libkqueue.a -lpthread -lrt" } check_symbol $sys_event_h EV_DISPATCH From 78efd4621448e1d1d559359a86a93ba9b81292ea Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 9 Nov 2009 02:39:47 +0000 Subject: [PATCH 0070/1120] fix copy+paste error in vnode.c git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@79 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/linux/vnode.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 121986df4..f7c3a2b8c 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -262,19 +262,6 @@ evfilt_vnode_copyout(struct filter *filt, if (evt.mask & IN_DELETE_SELF && kn->kev.fflags & NOTE_DELETE) dst->fflags |= NOTE_DELETE; - if (kn->kev.flags & EV_DISPATCH) { - delete_watch(filt->kf_pfd, kn); /* TODO: error checking */ - KNOTE_DISABLE(kn); -#if HAVE_NOTE_TRUNCATE - if (sb.st_size == 0 && kn->kev.fflags & NOTE_TRUNCATE) - dst->fflags |= NOTE_TRUNCATE; -#endif - if (sb.st_size > kn->kn_st_size && kn->kev.fflags & NOTE_WRITE) - dst->fflags |= NOTE_EXTEND; - kn->kn_st_nlink = sb.st_nlink; - kn->kn_st_size = sb.st_size; - } - if (evt.mask & IN_MODIFY && kn->kev.fflags & NOTE_WRITE) dst->fflags |= NOTE_WRITE; if (evt.mask & IN_ATTRIB && kn->kev.fflags & NOTE_ATTRIB) From ad1dd8ec9ddddd5bb5c17e4319632f5b7628dde6 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 9 Nov 2009 05:27:06 +0000 Subject: [PATCH 0071/1120] * Undefine symbols in that are not implemented. * Incomplete implementation of EVFILT_PROC on Linux. * Do not set both EV_ENABLE and EV_DISABLE. * Block all signals while initializing filters in kqueue(). git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@80 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/include/sys/event.h | 13 +- vendor/libkqueue/src/common/filter.c | 2 + vendor/libkqueue/src/common/kqueue.c | 45 +++++- vendor/libkqueue/src/common/private.h | 3 +- vendor/libkqueue/src/linux/proc.c | 223 ++++++++++++++++++++++++++ 5 files changed, 272 insertions(+), 14 deletions(-) create mode 100644 vendor/libkqueue/src/linux/proc.c diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index e16ddc8ba..f74346b1b 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -37,20 +37,21 @@ struct timespec; -/* Library version number */ -#define LIBKQUEUE 20091030 +#define LIBKQUEUE 1 #define EVFILT_READ (-1) #define EVFILT_WRITE (-2) -#define EVFILT_AIO (-3) /* attached to aio requests */ #define EVFILT_VNODE (-4) /* attached to vnodes */ #define EVFILT_PROC (-5) /* attached to struct proc */ #define EVFILT_SIGNAL (-6) /* attached to struct proc */ #define EVFILT_TIMER (-7) /* timers */ +#define EVFILT_USER (-11) /* User events */ +#if !LIBKQUEUE +#define EVFILT_AIO (-3) /* attached to aio requests */ #define EVFILT_NETDEV (-8) /* network devices */ #define EVFILT_FS (-9) /* filesystem events */ #define EVFILT_LIO (-10) /* attached to lio requests */ -#define EVFILT_USER (-11) /* User events */ +#endif /* ! LIBKQUEUE */ #define EVFILT_SYSCOUNT 11 #define EV_SET(kevp_, a, b, c, d, e, f) do { \ @@ -132,6 +133,7 @@ struct kevent { * data/hint flags for EVFILT_PROC */ #define NOTE_EXIT 0x80000000 /* process exited */ +#if ! LIBKQUEUE #define NOTE_FORK 0x40000000 /* process forked */ #define NOTE_EXEC 0x20000000 /* process exec'd */ #define NOTE_PCTRLMASK 0xf0000000 /* mask for hint bits */ @@ -141,13 +143,16 @@ struct kevent { #define NOTE_TRACK 0x00000001 /* follow across forks */ #define NOTE_TRACKERR 0x00000002 /* could not track child */ #define NOTE_CHILD 0x00000004 /* am a child process */ +#endif /* ! LIBKQUEUE */ +#if ! LIBKQUEUE /* * data/hint flags for EVFILT_NETDEV */ #define NOTE_LINKUP 0x0001 /* link is up */ #define NOTE_LINKDOWN 0x0002 /* link is down */ #define NOTE_LINKINV 0x0004 /* link state is invalid */ +#endif /* ! LIBKQUEUE */ __BEGIN_DECLS int kqueue(void); diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index 33b716266..98b1bdf87 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -28,6 +28,7 @@ extern const struct filter evfilt_read; extern const struct filter evfilt_write; extern const struct filter evfilt_signal; extern const struct filter evfilt_vnode; +extern const struct filter evfilt_proc; extern const struct filter evfilt_timer; extern const struct filter evfilt_user; @@ -84,6 +85,7 @@ filter_register_all(struct kqueue *kq) rv += filter_register(kq, EVFILT_WRITE, &evfilt_write); rv += filter_register(kq, EVFILT_SIGNAL, &evfilt_signal); rv += filter_register(kq, EVFILT_VNODE, &evfilt_vnode); + rv += filter_register(kq, EVFILT_PROC, &evfilt_proc); rv += filter_register(kq, EVFILT_TIMER, &evfilt_timer); rv += filter_register(kq, EVFILT_USER, &evfilt_user); kq->kq_nfds++; diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 4f5597e37..2a92f8a59 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -35,6 +35,23 @@ static LIST_HEAD(,kqueue) kqlist = LIST_HEAD_INITIALIZER(&kqlist); #define kqlist_lock() pthread_mutex_lock(&kqlist_mtx) #define kqlist_unlock() pthread_mutex_unlock(&kqlist_mtx) static pthread_mutex_t kqlist_mtx = PTHREAD_MUTEX_INITIALIZER; +static sigset_t saved_sigmask; + +static void +mask_signals(void) +{ + sigset_t mask; + + sigemptyset (&mask); + if (pthread_sigmask(SIG_BLOCK, &mask, &saved_sigmask) != 0) + sigemptyset (&saved_sigmask); +} + +static void +unmask_signals(void) +{ + pthread_sigmask(SIG_SETMASK, &saved_sigmask, NULL); +} struct kqueue * kqueue_lookup(int kq) @@ -81,26 +98,38 @@ int kqueue(void) { struct kqueue *kq; + int rv; kq = calloc(1, sizeof(*kq)); if (kq == NULL) return (-1); pthread_mutex_init(&kq->kq_mtx, NULL); - if (filter_register_all(kq) < 0) - return (-1); - - if (socketpair(AF_LOCAL, SOCK_STREAM, 0, kq->kq_sockfd) < 0) { - free(kq); - return (-1); - } + if (socketpair(AF_LOCAL, SOCK_STREAM, 0, kq->kq_sockfd) < 0) + goto errout; kqlist_lock(); - LIST_INSERT_HEAD(&kqlist, kq, entries); + mask_signals(); + rv = filter_register_all(kq); + if (rv == 0) { + LIST_INSERT_HEAD(&kqlist, kq, entries); + } + unmask_signals(); kqlist_unlock(); + if (rv != 0) + goto errout; + dbg_printf("created kqueue: fd=%d", kq->kq_sockfd[1]); return (kq->kq_sockfd[1]); + +errout: + if (kq->kq_sockfd[0] != kq->kq_sockfd[1]) { + close(kq->kq_sockfd[0]); + close(kq->kq_sockfd[1]); + } + free(kq); + return (-1); } void diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index fe06721f5..09d12972d 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -17,6 +17,7 @@ #ifndef _KQUEUE_PRIVATE_H #define _KQUEUE_PRIVATE_H +#include #include #include #include "sys/event.h" @@ -58,12 +59,10 @@ LIST_HEAD(knotelist, knote); #define KNOTE_EMPTY(ent) ((ent)->kev.filter == 0) #define KNOTE_ENABLE(ent) do { \ - (ent)->kev.flags |= EV_ENABLE; \ (ent)->kev.flags &= ~EV_DISABLE; \ } while (0/*CONSTCOND*/) #define KNOTE_DISABLE(ent) do { \ - (ent)->kev.flags &= ~EV_ENABLE; \ (ent)->kev.flags |= EV_DISABLE; \ } while (0/*CONSTCOND*/) diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c new file mode 100644 index 000000000..a3cf72ec8 --- /dev/null +++ b/vendor/libkqueue/src/linux/proc.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "sys/event.h" +#include "private.h" + +struct proc_event { + pid_t pe_pid; + int pe_status; + LIST_ENTRY(proc_event) entries; +}; + +struct evfilt_data { + pthread_t wthr_id; + pthread_mutex_t wthr_mtx; + LIST_HEAD(proc_eventhead,proc_event) wthr_event; +}; + +static void * +wait_thread(void *arg) +{ + struct filter *filt = (struct filter *) arg; + uint64_t counter = 1; + const int options = WEXITED | WNOWAIT; + struct proc_event *evt; + siginfo_t si; + sigset_t sigmask; + + /* Block all signals */ + sigfillset (&sigmask); + pthread_sigmask(SIG_BLOCK, &sigmask, NULL); + + for (;;) { + + /* Wait for a child process to exit(2) */ + if (waitid(P_ALL, 0, &si, options) != 0) + break; + + /* Create a proc_event */ + if ((evt = malloc(sizeof(*evt))) == NULL) + continue; /* TODO: set filter error flag */ + if (si.si_code == CLD_EXITED) { + evt->pe_status = si.si_status; + } else if (si.si_code == CLD_KILLED) { + /* FIXME: probably not true on BSD */ + /* FIXME: arbitrary non-zero number */ + evt->pe_status = 254; + } else { + /* Should never happen. */ + continue; + } + + /* Add the event to the eventlist */ + pthread_mutex_lock(&filt->kf_data->wthr_mtx); + LIST_INSERT_HEAD(&filt->kf_data->wthr_event, evt, entries); + pthread_mutex_unlock(&filt->kf_data->wthr_mtx); + + /* Indicate read(2) readiness */ + if (write(filt->kf_pfd, &counter, sizeof(counter)) < 0) { + if (errno != EAGAIN) { + dbg_printf("write(2): %s", strerror(errno)); + /* TODO: set filter error flag */ + break; + } + } + } + + /* TODO: error handling */ + + return (NULL); +} + +int +evfilt_proc_init(struct filter *filt) +{ + struct evfilt_data *ed; + int efd = -1; + + if ((ed = calloc(1, sizeof(*ed))) == NULL) + return (-1); + pthread_mutex_init(&ed->wthr_mtx, NULL); + LIST_INIT(&ed->wthr_event); + + if ((efd = eventfd(0, 0)) < 0) + goto errout; + if (fcntl(filt->kf_pfd, F_SETFL, O_NONBLOCK) < 0) + goto errout; + if (pthread_create(&ed->wthr_id, NULL, wait_thread, filt) != 0) + goto errout; + + filt->kf_pfd = efd; + + return (0); + +errout: + if (efd >= 0) + close(efd); + free(ed); + close(filt->kf_pfd); + return (-1); +} + +void +evfilt_proc_destroy(struct filter *filt) +{ + pthread_cancel(filt->kf_data->wthr_id); + close(filt->kf_pfd); +} + +int +evfilt_proc_copyin(struct filter *filt, + struct knote *dst, const struct kevent *src) +{ + if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) + memcpy(&dst->kev, src, sizeof(*src)); + + if (src->flags & EV_ADD || src->flags & EV_ENABLE) { + /* Nothing to do.. */ + } + + return (0); +} + +int +evfilt_proc_copyout(struct filter *filt, + struct kevent *dst, + int maxevents) +{ + struct proc_eventhead evt; + struct proc_event *elm; + struct knote *kn; + int nevents = 0; + uint64_t cur; + + /* Reset the counter */ + if (read(filt->kf_pfd, &cur, sizeof(cur)) < sizeof(cur)) { + dbg_printf("read(2): %s", strerror(errno)); + return (-1); + } + dbg_printf(" counter=%llu", (unsigned long long) cur); + + /* Consume the eventlist */ + pthread_mutex_lock(&filt->kf_data->wthr_mtx); + evt = filt->kf_data->wthr_event; + LIST_INIT(&filt->kf_data->wthr_event); + pthread_mutex_unlock(&filt->kf_data->wthr_mtx); + + /* Scan for events that have been triggered */ + KNOTELIST_FOREACH(kn, &filt->knl) { + LIST_FOREACH(elm, &evt, entries) { + if (elm->pe_pid == kn->kev.ident) { + + kevent_dump(&kn->kev); + dst->ident = kn->kev.ident; + dst->filter = kn->kev.filter; + dst->udata = kn->kev.udata; + dst->flags = kn->kev.flags; + dst->fflags = NOTE_EXIT; + dst->data = elm->pe_status; + + if (kn->kev.flags & EV_DISPATCH) { + KNOTE_DISABLE(kn); + } + if (kn->kev.flags & EV_ONESHOT) + knote_free(kn); + + LIST_REMOVE(elm, entries); + free(elm); + + if (++nevents > maxevents) + break; + dst++; + } + } + } + + if (!LIST_EMPTY(&evt)) { + /* XXX-FIXME: If there are leftover events, put them back + onto the wthr_event list */ + abort(); + } + + return (nevents); +} + +const struct filter evfilt_proc = { + EVFILT_PROC, + evfilt_proc_init, + evfilt_proc_destroy, + evfilt_proc_copyin, + evfilt_proc_copyout, +}; From 641a0488d0982fb55f2a123e7d6481e39deb921f Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 10 Nov 2009 03:42:44 +0000 Subject: [PATCH 0072/1120] * More work on evfilt_proc, not finished. * Ressurect the kqueue free-on-close thread, try to make it have process scope. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@81 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kqueue.c | 77 ++++++++++++++++++ vendor/libkqueue/src/common/private.h | 4 +- vendor/libkqueue/src/linux/proc.c | 107 +++++++++++++++----------- 3 files changed, 143 insertions(+), 45 deletions(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 2a92f8a59..0f452961a 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -31,12 +31,19 @@ #include "private.h" static LIST_HEAD(,kqueue) kqlist = LIST_HEAD_INITIALIZER(&kqlist); +static size_t kqcount = 0; #define kqlist_lock() pthread_mutex_lock(&kqlist_mtx) #define kqlist_unlock() pthread_mutex_unlock(&kqlist_mtx) static pthread_mutex_t kqlist_mtx = PTHREAD_MUTEX_INITIALIZER; static sigset_t saved_sigmask; +static int kqgc_pfd[2]; +static pthread_once_t kqueue_init_ctl = PTHREAD_ONCE_INIT; +static pthread_cond_t kqueue_init_cond = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t kqueue_init_mtx = PTHREAD_MUTEX_INITIALIZER; +static int kqueue_init_status = 0; + static void mask_signals(void) { @@ -80,6 +87,72 @@ kqueue_shutdown(struct kqueue *kq) free(kq); } +static void * +kqueue_close_wait(void *arg) +{ + struct kqueue *kq; + struct pollfd fds[MAX_KQUEUE + 1]; + int n; + + pthread_mutex_lock(&kqueue_init_mtx); + + /* Block all signals in this thread */ + sigset_t mask; + sigfillset(&mask); + sigprocmask(SIG_BLOCK, &mask, NULL); + + pthread_cond_signal(&kqueue_init_cond); + pthread_mutex_unlock(&kqueue_init_mtx); + + for (;;) { + + /* This thread is woken up by writing to kqgc_pfd[1] */ + fds[0].fd = kqgc_pfd[0]; + fds[0].events = POLLIN; + n = 1; + + kqlist_lock(); + LIST_FOREACH(kq, &kqlist, entries) { + fds[n].fd = kq->kq_sockfd[0]; + fds[n].events = POLLIN; + n++; + } + kqlist_unlock(); + + n = poll(&fds[0], n, -1); + if (n == 0) + continue; /* Spurious wakeup */ + if (n < 0) { + dbg_printf("poll(2): %s", strerror(errno)); + abort(); //FIXME + } + + /* XXX-FIXME Check the result and free kqueues */ + } + dbg_puts("kqueue: fd closed"); + + kqueue_shutdown(kq); + + return (NULL); +} + +static void +kqueue_init(void) +{ + pthread_t tid; + + if (socketpair(AF_LOCAL, SOCK_STREAM, 0, kqgc_pfd) < 0) + goto errout; + + pthread_mutex_lock(&kqueue_init_mtx); + pthread_create(&tid, NULL, kqueue_close_wait, NULL); + pthread_cond_wait(&kqueue_init_cond, &kqueue_init_mtx); + pthread_mutex_unlock(&kqueue_init_mtx); + +errout: + kqueue_init_status = -1; +} + void kqueue_lock(struct kqueue *kq) { @@ -108,11 +181,14 @@ kqueue(void) if (socketpair(AF_LOCAL, SOCK_STREAM, 0, kq->kq_sockfd) < 0) goto errout; + (void) pthread_once(&kqueue_init_ctl, kqueue_init); + kqlist_lock(); mask_signals(); rv = filter_register_all(kq); if (rv == 0) { LIST_INSERT_HEAD(&kqlist, kq, entries); + kqcount++; } unmask_signals(); kqlist_unlock(); @@ -124,6 +200,7 @@ kqueue(void) return (kq->kq_sockfd[1]); errout: + //FIXME: unregister_all filters if (kq->kq_sockfd[0] != kq->kq_sockfd[1]) { close(kq->kq_sockfd[0]); close(kq->kq_sockfd[1]); diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 09d12972d..48eace032 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -22,6 +22,9 @@ #include #include "sys/event.h" +/* Maximum number of kqueue descriptors in a single process. */ +#define MAX_KQUEUE 1024 + /* Maximum events returnable in a single kevent() call */ #define MAX_KEVENT 512 @@ -85,7 +88,6 @@ struct filter { struct kqueue { int kq_sockfd[2]; - pthread_t kq_close_tid; struct filter kq_filt[EVFILT_SYSCOUNT]; fd_set kq_fds; int kq_nfds; diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index a3cf72ec8..e6e3d2931 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -35,16 +35,20 @@ #include "sys/event.h" #include "private.h" +LIST_HEAD(proc_eventhead, proc_event); + struct proc_event { - pid_t pe_pid; - int pe_status; + uint64_t pe_kqid; + pid_t pe_pid; + int pe_status; LIST_ENTRY(proc_event) entries; }; struct evfilt_data { pthread_t wthr_id; pthread_mutex_t wthr_mtx; - LIST_HEAD(proc_eventhead,proc_event) wthr_event; + struct proc_eventhead wthr_waitq; + struct proc_eventhead wthr_eventq; }; static void * @@ -67,9 +71,18 @@ wait_thread(void *arg) if (waitid(P_ALL, 0, &si, options) != 0) break; + /* Scan the wait queue to see if anyone is interested */ + pthread_mutex_lock(&filt->kf_data->wthr_mtx); + LIST_FOREACH(evt, &filt->kf_data->wthr_waitq, entries) { + if (evt->pe_pid == si.si_pid) + break; + } + if (evt == NULL) { + pthread_mutex_unlock(&filt->kf_data->wthr_mtx); + continue; + } + /* Create a proc_event */ - if ((evt = malloc(sizeof(*evt))) == NULL) - continue; /* TODO: set filter error flag */ if (si.si_code == CLD_EXITED) { evt->pe_status = si.si_status; } else if (si.si_code == CLD_KILLED) { @@ -78,12 +91,12 @@ wait_thread(void *arg) evt->pe_status = 254; } else { /* Should never happen. */ - continue; + evt->pe_status = 255; } /* Add the event to the eventlist */ - pthread_mutex_lock(&filt->kf_data->wthr_mtx); - LIST_INSERT_HEAD(&filt->kf_data->wthr_event, evt, entries); + LIST_REMOVE(evt, entries); + LIST_INSERT_HEAD(&filt->kf_data->wthr_eventq, evt, entries); pthread_mutex_unlock(&filt->kf_data->wthr_mtx); /* Indicate read(2) readiness */ @@ -101,6 +114,14 @@ wait_thread(void *arg) return (NULL); } +static int +watch_add(struct filter *filt, struct knote *kn) +{ + pthread_mutex_lock(&filt->kf_data->wthr_mtx); + abort(); /*XXX-TODO*/ + pthread_mutex_unlock(&filt->kf_data->wthr_mtx); +} + int evfilt_proc_init(struct filter *filt) { @@ -110,7 +131,8 @@ evfilt_proc_init(struct filter *filt) if ((ed = calloc(1, sizeof(*ed))) == NULL) return (-1); pthread_mutex_init(&ed->wthr_mtx, NULL); - LIST_INIT(&ed->wthr_event); + LIST_INIT(&ed->wthr_eventq); + LIST_INIT(&ed->wthr_waitq); if ((efd = eventfd(0, 0)) < 0) goto errout; @@ -134,7 +156,7 @@ evfilt_proc_init(struct filter *filt) void evfilt_proc_destroy(struct filter *filt) { - pthread_cancel(filt->kf_data->wthr_id); +//TODO: pthread_cancel(filt->kf_data->wthr_id); close(filt->kf_pfd); } @@ -142,8 +164,10 @@ int evfilt_proc_copyin(struct filter *filt, struct knote *dst, const struct kevent *src) { - if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) + if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) { memcpy(&dst->kev, src, sizeof(*src)); + watch_add(filt, dst); + } if (src->flags & EV_ADD || src->flags & EV_ENABLE) { /* Nothing to do.. */ @@ -157,7 +181,6 @@ evfilt_proc_copyout(struct filter *filt, struct kevent *dst, int maxevents) { - struct proc_eventhead evt; struct proc_event *elm; struct knote *kn; int nevents = 0; @@ -170,44 +193,40 @@ evfilt_proc_copyout(struct filter *filt, } dbg_printf(" counter=%llu", (unsigned long long) cur); - /* Consume the eventlist */ pthread_mutex_lock(&filt->kf_data->wthr_mtx); - evt = filt->kf_data->wthr_event; - LIST_INIT(&filt->kf_data->wthr_event); - pthread_mutex_unlock(&filt->kf_data->wthr_mtx); - - /* Scan for events that have been triggered */ - KNOTELIST_FOREACH(kn, &filt->knl) { - LIST_FOREACH(elm, &evt, entries) { - if (elm->pe_pid == kn->kev.ident) { - - kevent_dump(&kn->kev); - dst->ident = kn->kev.ident; - dst->filter = kn->kev.filter; - dst->udata = kn->kev.udata; - dst->flags = kn->kev.flags; - dst->fflags = NOTE_EXIT; - dst->data = elm->pe_status; - - if (kn->kev.flags & EV_DISPATCH) { - KNOTE_DISABLE(kn); - } - if (kn->kev.flags & EV_ONESHOT) - knote_free(kn); + LIST_FOREACH(elm, &filt->kf_data->wthr_eventq, entries) { + kn = knote_lookup(filt, elm->pe_pid); + if (kn == NULL) { + LIST_REMOVE(elm, entries); + free(elm); + continue; + } - LIST_REMOVE(elm, entries); - free(elm); + kevent_dump(&kn->kev); + dst->ident = kn->kev.ident; + dst->filter = kn->kev.filter; + dst->udata = kn->kev.udata; + dst->flags = kn->kev.flags; + dst->fflags = NOTE_EXIT; + dst->data = elm->pe_status; - if (++nevents > maxevents) - break; - dst++; - } + if (kn->kev.flags & EV_DISPATCH) { + KNOTE_DISABLE(kn); } + if (kn->kev.flags & EV_ONESHOT) + knote_free(kn); + + LIST_REMOVE(elm, entries); + free(elm); + + if (++nevents > maxevents) + break; + dst++; } - if (!LIST_EMPTY(&evt)) { - /* XXX-FIXME: If there are leftover events, put them back - onto the wthr_event list */ + if (!LIST_EMPTY(&filt->kf_data->wthr_eventq)) { + /* XXX-FIXME: If there are leftover events on the waitq, + re-arm the eventfd. list */ abort(); } From 37765ed1dc83f3b766217705980af2e798d388f0 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 11 Nov 2009 02:19:33 +0000 Subject: [PATCH 0073/1120] * Enough tests to decide that EVFILT_PROC is majorly broken. * Remove kqueue_free() and replace it with the gc thread. * Tested the gc thread and it looks good. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@82 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/include/sys/event.h | 1 - vendor/libkqueue/src/common/kqueue.c | 111 +++++++++++--- vendor/libkqueue/test/config.inc | 2 +- vendor/libkqueue/test/main.c | 14 +- vendor/libkqueue/test/proc.c | 221 +++++++++++++++++++++++++++ vendor/libkqueue/www/index.html | 28 +--- 6 files changed, 331 insertions(+), 46 deletions(-) create mode 100644 vendor/libkqueue/test/proc.c diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index f74346b1b..b7c76c02c 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -156,7 +156,6 @@ struct kevent { __BEGIN_DECLS int kqueue(void); -void kqueue_free(int); int kevent(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 0f452961a..cf129a428 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -75,24 +75,23 @@ kqueue_lookup(int kq) return (ent); } +/* SEE ALSO: kqueue_shutdown */ static void -kqueue_shutdown(struct kqueue *kq) +kqueue_destroy_unlocked(struct kqueue *kq) { - dbg_puts("shutdown invoked\n"); - - kqlist_lock(); LIST_REMOVE(kq, entries); - kqlist_unlock(); filter_unregister_all(kq); free(kq); } static void * -kqueue_close_wait(void *arg) +kqueue_close_wait(void *unused) { struct kqueue *kq; + char buf[1]; struct pollfd fds[MAX_KQUEUE + 1]; - int n; + int wake_flag; + int i, n; pthread_mutex_lock(&kqueue_init_mtx); @@ -101,6 +100,8 @@ kqueue_close_wait(void *arg) sigfillset(&mask); sigprocmask(SIG_BLOCK, &mask, NULL); + wake_flag = 0; + pthread_cond_signal(&kqueue_init_cond); pthread_mutex_unlock(&kqueue_init_mtx); @@ -119,6 +120,18 @@ kqueue_close_wait(void *arg) } kqlist_unlock(); + /* Inform the main thread that it can continue */ + if (wake_flag) { + if (write (kqgc_pfd[0], ".", 1) < 1) { + /* TODO: error checking */ + abort(); + } + wake_flag = 0; + } + + + dbg_printf("gc: waiting for events on %d kqfds", n - 1); + n = poll(&fds[0], n, -1); if (n == 0) continue; /* Spurious wakeup */ @@ -127,15 +140,79 @@ kqueue_close_wait(void *arg) abort(); //FIXME } - /* XXX-FIXME Check the result and free kqueues */ + dbg_printf("watcher: revents=%d", fds[0].revents); + if (fds[0].revents == POLLIN) { + dbg_puts("gc: waking up at user request"); + if (read(kqgc_pfd[0], &buf, 1) < 0) { + abort();//TODO: err handling + } + + wake_flag = 1; + } else { + /* Destroy any kqueue that close(2) has been called on */ + kqlist_lock(); + for (i = 1; i <= n; i++) { + dbg_printf("i=%d revents=%d", i, fds[n].revents); + if (fds[n].revents & POLLHUP) { + LIST_FOREACH(kq, &kqlist, entries) { + if (kq->kq_sockfd[0] == fds[n].fd) { + dbg_printf("gc: destroying kqueue; kqfd=%d", + kq->kq_sockfd[1]); + kqueue_destroy_unlocked(kq); + } + } + } + } + kqlist_unlock(); + } } - dbg_puts("kqueue: fd closed"); - kqueue_shutdown(kq); + /* NOTREACHED */ return (NULL); } +static void +kqgc_wakeup(void) +{ + char buf[1]; + ssize_t n; + + dbg_puts("main: requesting wakeup"); + n = write (kqgc_pfd[1], ".", 1); + if (n < 1) { + /* TODO: error checking */ + abort(); + } + + /* + * There is a race condition as follows: + * main_thread GC_thread + * ----------- --------- + * kqueue() called + * create kqueue + * wake GC_thread ... (sleeping) + * kqueue() returns + * .. .. + * close(2) kqueue fd . + * wake and update pollset + * + * This would prevent the resources for the kqueue from + * ever being deallocated. + * + * To prevent this, the main_thread will wait for the + * gc_thread to update it's pollset before continuing. + * + */ + dbg_puts("main: waiting for gc to refresh it's pollset"); + n = read(kqgc_pfd[1], &buf, 1); + if (n < 1) { + /* TODO: error checking */ + abort(); + } + dbg_puts("main: synchronization complete"); +} + static void kqueue_init(void) { @@ -196,6 +273,9 @@ kqueue(void) if (rv != 0) goto errout; + /* Force the GC thread to add the fd to it's pollset */ + kqgc_wakeup(); + dbg_printf("created kqueue: fd=%d", kq->kq_sockfd[1]); return (kq->kq_sockfd[1]); @@ -208,14 +288,3 @@ kqueue(void) free(kq); return (-1); } - -void -kqueue_free(int kqfd) -{ - struct kqueue *kq; - - if ((kq = kqueue_lookup(kqfd)) == NULL) - return; - - kqueue_shutdown(kq); -} diff --git a/vendor/libkqueue/test/config.inc b/vendor/libkqueue/test/config.inc index fbef6d5ba..7b9cc0caa 100755 --- a/vendor/libkqueue/test/config.inc +++ b/vendor/libkqueue/test/config.inc @@ -3,7 +3,7 @@ program=libkqueue-test version=0.1 cflags="-g -O0 -Wall -Werror" -sources="main.c read.c signal.c timer.c vnode.c" +sources="main.c proc.c read.c signal.c timer.c vnode.c" pre_configure_hook() { diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index e726571a5..f279522e4 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -26,6 +26,7 @@ extern void test_evfilt_read(); extern void test_evfilt_signal(); extern void test_evfilt_vnode(); extern void test_evfilt_timer(); +extern void test_evfilt_proc(); #if HAVE_EVFILT_USER extern void test_evfilt_user(); #endif @@ -187,15 +188,13 @@ test_kqueue_close(void) test_begin("close(kq)"); if (close(kqfd) < 0) err(1, "close()"); -#if LIBKQUEUE - kqueue_free(kqfd); -#endif success("kqueue_close()"); } int main(int argc, char **argv) { + int test_proc = 1; int test_socket = 1; int test_signal = 1; int test_vnode = 1; @@ -203,6 +202,8 @@ main(int argc, char **argv) int test_user = 1; while (argc) { + if (strcmp(argv[0], "--no-proc") == 0) + test_proc = 0; if (strcmp(argv[0], "--no-socket") == 0) test_socket = 0; if (strcmp(argv[0], "--no-timer") == 0) @@ -220,6 +221,13 @@ main(int argc, char **argv) test_kqueue(); test_kqueue_close(); +#if FIXME + if (test_proc) + test_evfilt_proc(); + puts("All proc tests OK"); + exit(0); +#endif + if (test_socket) test_evfilt_read(); if (test_signal) diff --git a/vendor/libkqueue/test/proc.c b/vendor/libkqueue/test/proc.c new file mode 100644 index 000000000..da9b10026 --- /dev/null +++ b/vendor/libkqueue/test/proc.c @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "common.h" + +int kqfd; +pid_t child; + +static void +add_and_delete(void) +{ + const char *test_id1 = "kevent(EVFILT_PROC, EV_ADD)"; + const char *test_id2 = "kevent(EVFILT_PROC, EV_ADD)"; + struct kevent kev; + + test_begin(test_id1); + + EV_SET(&kev, child, EVFILT_PROC, EV_ADD, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id1); + + success(test_id1); + + test_begin(test_id2); + + kev.flags = EV_DELETE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id2); + + success(test_id2); + +} + +#if TODO +void +test_kevent_signal_get(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, wait)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + kev.flags |= EV_CLEAR; + kev.data = 1; + kevent_cmp(&kev, kevent_get(kqfd)); + + success(test_id); +} + +void +test_kevent_signal_disable(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + test_no_kevents(); + + success(test_id); +} + +void +test_kevent_signal_enable(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + kev.flags = EV_ADD | EV_CLEAR; +#if LIBKQUEUE + kev.data = 1; /* WORKAROUND */ +#else + kev.data = 2; // one extra time from test_kevent_signal_disable() +#endif + kevent_cmp(&kev, kevent_get(kqfd)); + + /* Delete the watch */ + kev.flags = EV_DELETE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + success(test_id); +} + +void +test_kevent_signal_del(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)"; + struct kevent kev; + + test_begin(test_id); + + /* Delete the kevent */ + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + test_no_kevents(); + success(test_id); +} + +void +test_kevent_signal_oneshot(void) +{ + const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)"; + struct kevent kev; + + test_begin(test_id); + + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1, "%s", test_id); + + /* Block SIGUSR1, then send it to ourselves */ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + err(1, "sigprocmask"); + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + + kev.flags |= EV_CLEAR; + kev.data = 1; + kevent_cmp(&kev, kevent_get(kqfd)); + + /* Send another one and make sure we get no events */ + if (kill(getpid(), SIGUSR1) < 0) + err(1, "kill"); + test_no_kevents(); + + success(test_id); +} +#endif + +void +test_evfilt_proc() +{ + kqfd = kqueue(); + + /* Create a child that sleeps for a few seconds and then exits */ + child = fork(); + if (child == 0) { + sleep(3); + exit(123); + } + + add_and_delete(); +#if TODO + test_kevent_signal_add(); + test_kevent_signal_del(); + test_kevent_signal_get(); + test_kevent_signal_disable(); + test_kevent_signal_enable(); + test_kevent_signal_oneshot(); +#endif + close(kqfd); +} diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index e15b8eda3..7afec34bc 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -61,9 +61,15 @@

                    Status

                  1. When an EVFILT_SIGNAL event is generated, the data field -is set to 1 regardless of how many times the signal was received by the process. +is set to 1 regardless of how many times the signal was received by the process.
                  2. + +

                  Requirements

                  @@ -85,27 +91,9 @@

                  Usage

                • Add #include <sys/event.h> to the source code.
              -One major difference between libkqueue and the real kqueue is that -closing the kqueue descriptor will not free any of the resources -associated with the descriptor. The following example shows how to -close the descriptor and free the resources: -

              -

              -    int kqfd;
              -
              -    kqfd = kqueue();
              -
              -    /* ... */
              -
              -    close(kqfd);
              -    #if LIBKQUEUE
              -    kqueue_free(kqfd);
              -    #endif
              -
              -

              Threads

              -libkqueue is a threadsafe library, and kqueue() and kevent() are safe to be used from multiple threads. libkqueue requires that the POSIX threads headers (pthread.h) be available, but does not require you to link against libpthread.so. This allows it to be used in both non-threaded and multi-threaded programs. +libkqueue uses one or more helper threads, so all programs that link with libkqueue must also link against the pthreads library. Calls to kqueue() and kevent() are safe to be used from multiple threads.

              Links

              From 076d705b798b3c4384b2454588b7216a307d553a Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 11 Nov 2009 02:35:25 +0000 Subject: [PATCH 0074/1120] version 0.3 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@83 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 31 +++++++++++++++++++++++++++++-- vendor/libkqueue/config.inc | 2 +- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index f288ca94b..204633c7c 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,4 +1,31 @@ -2009-11-10 v0.2 r59 +2009-11-10 v0.3 r83 +------------------------------------------------------------------------ + + * The EVFILT_USER filter has been implemented, but needs additional + testing. + + * The EVFILT_PROC filter is partially implemented on Linux, but is + currently broken. + + * The unit tests have been moved to a separate subdirectory and now + function under OpenBSD 4.4 using the native kqueue(2) and kevent(2) + system calls. + + * The kqueue_free() function has been removed. + + * A helper thread performs garbage collection when close(2) is called + on the file descriptor returned by kqueue(). + + * All symbols in that are not implemented are now + undefined. + + * Major internal reorganization of the source tree. + + * A copy-and-paste error in vnode.c has been fixed. + + * The pthreads library is now required. + +2009-11-07 v0.2 r59 * Implement EVFILT_TIMER on Linux. @@ -8,6 +35,6 @@ * pkg-config no longer requires linking with -lpthread and -lrt. -2009-05-05 v0.1 r49 +2009-11-05 v0.1 r49 * Initial stable release. diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index 47f24c873..f920f51e0 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -1,5 +1,5 @@ program="libkqueue" -version="0.2" +version="0.3" cflags="-fPIC -I./include -I./src/common -Wall -Werror" sources="src/common/*.c" libdepends="" From ecef910b9476f272cb179cea78a74efc5c739379 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 11 Nov 2009 02:41:45 +0000 Subject: [PATCH 0075/1120] fix make dist; actual 0.3 is this one git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@84 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 2 +- vendor/libkqueue/Makefile | 4 +-- vendor/libkqueue/README | 51 ------------------------------------- vendor/libkqueue/config.inc | 4 +-- 4 files changed, 5 insertions(+), 56 deletions(-) delete mode 100644 vendor/libkqueue/README diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 204633c7c..21b4a1788 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,4 +1,4 @@ -2009-11-10 v0.3 r83 +2009-11-10 v0.3 r84 ------------------------------------------------------------------------ * The EVFILT_USER filter has been implemented, but needs additional diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 4913e6bc2..e7ad35c49 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -49,8 +49,8 @@ check: dist: cd test && make distclean || true mkdir $(PROGRAM)-$(VERSION) - cp Makefile configure config.inc \ - $(SOURCES) $(MANS) $(HEADERS) $(EXTRA_DIST) \ + cp Makefile ChangeLog configure config.inc \ + $(MANS) $(EXTRA_DIST) \ $(PROGRAM)-$(VERSION) cp -R $(SUBDIRS) $(PROGRAM)-$(VERSION) rm -rf `find $(PROGRAM)-$(VERSION) -type d -name .svn` diff --git a/vendor/libkqueue/README b/vendor/libkqueue/README deleted file mode 100644 index 407f94c78..000000000 --- a/vendor/libkqueue/README +++ /dev/null @@ -1,51 +0,0 @@ -libkqueue emulates the kqueue(2) kernel event notification mechanism -on platforms which do not provide it natively. Currently, the only -supported platform is Linux and the only tested platform is -Ubuntu x64 with kernel 2.6.28. - - - kevent.flags Implementation Status - - ADD DELETE ENABLE DISABLE DISPATCH ONESHOT CLEAR EOF - -READ/WRITE Y Y Y Y N Y N N -AIO N N N N N N N N -VNODE Y N N N N N N N -PROC NO -- Cannot fully implement on Linux -SIGNAL Y N N N N N N N -NETDEV NO -- Don't know how to implement on Linux -TIMER Y N N N N N N N -USER Totally broken - - kevent.fflags Implementation Status - - Status -READ - NOTE_LOWAT No - EV_EOF No -WRITE - NOTE_LOWAT No - EV_EOF No -VNODE - NOTE_DELETE No - NOTE_WRITE No - NOTE_EXTEND No - NOTE_ATTRIB No - NOTE_LINK No - NOTE_RENAME No - NOTE_REVOKE N/A -USER - NOTE_FFNOP Ignore the input fflags. - NOTE_FFAND Bitwise AND fflags. - NOTE_FFOR Bitwise OR fflags. - NOTE_COPY Copy fflags. - NOTE_FFCTRLMASK Control mask for fflags. - NOTE_FFLAGSMASK User defined flag mask for fflags. - NOTE_TRIGGER Cause the event to be triggered. - - Filter sets kevent.data structure when returning -EV_RECEIPT Yes -kevent.data No - --- -Mark Heily diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index f920f51e0..df26c818f 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -4,8 +4,8 @@ cflags="-fPIC -I./include -I./src/common -Wall -Werror" sources="src/common/*.c" libdepends="" mans="kqueue.2" -headers="private.h" -extra_dist="*.in README" +headers="src/common/private.h" +extra_dist="*.in" subdirs="src include test" pre_configure_hook() { From cf1bc7cab1610137e814290ed793c4e91f11c79f Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 11 Nov 2009 03:02:20 +0000 Subject: [PATCH 0076/1120] spiffy up website git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@86 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/www/index.html | 53 +++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index 7afec34bc..28f48bf9e 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -7,7 +7,33 @@ libkqueue @@ -19,11 +45,21 @@

              libkqueue

              Download

              -Source code releases can be found here. +Source code releases can be found here. There are no binary packages at the moment.

              -To checkout the SVN repository, run the following command: +To checkout the entire SVN repository, run the following command:

              -svn checkout svn://mark.heily.com/libkqueue +svn checkout svn://mark.heily.com/libkqueue +

              +You can checkout the trunk by using the following command: +

              +svn checkout svn://mark.heily.com/libkqueue/trunk libkqueue + +

              +There is heavy development on the trunk, and it may not always be in a usable state. If you want to be current, but not bleeding edge, there is also a stable branch. You can checkout the stable branch by using the following command: +

              +svn checkout svn://mark.heily.com/libkqueue/branches/stable libkqueue +

              Mailing Lists

              @@ -43,10 +79,11 @@

              Status

              More details about the current implementation status can be found here.

              -There are several compatibility issues to be aware of when using this library under Linux:

              +There are several compatibility issues to be aware of when using this library under Linux:
              +

                -
              1. The NOTE_LOWAT flag is not supported. According to socket(7),

                +

              2. The NOTE_LOWAT flag is not supported. According to socket(7),
                 "The select(2) and poll(2) system  calls  currently  do not respect the 
                 SO_RCVLOWAT setting on Linux, and mark a socket readable when even  a  
                @@ -109,5 +146,11 @@ 

                Links

                Contact

                For more information, contact Mark Heily. +

                +


                +
                +© 2009 Mark Heily. All rights reserved. +
                + From 2d43fa6e27b33d8621c16117108913aa353c08b6 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 12 Nov 2009 02:37:18 +0000 Subject: [PATCH 0077/1120] Use memcpy(3) in kf_copyout instead of manually setting each kevent field. Should fix the EV_DISPATCH test failure on OS X 10.6 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@87 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/linux/signal.c | 10 ++-------- vendor/libkqueue/src/linux/socket.c | 10 +--------- vendor/libkqueue/src/linux/timer.c | 10 +--------- vendor/libkqueue/src/linux/user.c | 11 +---------- vendor/libkqueue/src/linux/vnode.c | 8 ++------ vendor/libkqueue/test/main.c | 7 +++++-- vendor/libkqueue/test/read.c | 1 - 7 files changed, 12 insertions(+), 45 deletions(-) diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index 7451c9fc2..819ce749e 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -115,12 +115,8 @@ evfilt_signal_copyout(struct filter *filt, continue; dbg_printf("got signal %d", sig[i].ssi_signo); + memcpy(dst, &kn->kev, sizeof(*dst)); /* TODO: dst->data should be the number of times the signal occurred */ - dst->ident = sig[i].ssi_signo; - dst->filter = EVFILT_SIGNAL; - dst->udata = kn->kev.udata; - dst->flags = EV_ADD | EV_CLEAR; - dst->fflags = 0; dst->data = 1; if (kn->kev.flags & EV_DISPATCH || kn->kev.flags & EV_ONESHOT) { @@ -129,10 +125,8 @@ evfilt_signal_copyout(struct filter *filt, } if (kn->kev.flags & EV_DISPATCH) KNOTE_DISABLE(kn); - if (kn->kev.flags & EV_ONESHOT) { - dst->flags |= EV_ONESHOT; + if (kn->kev.flags & EV_ONESHOT) knote_free(kn); - } dst++; nevents++; diff --git a/vendor/libkqueue/src/linux/socket.c b/vendor/libkqueue/src/linux/socket.c index be37a31bd..1280e2059 100644 --- a/vendor/libkqueue/src/linux/socket.c +++ b/vendor/libkqueue/src/linux/socket.c @@ -175,15 +175,7 @@ evfilt_socket_copyout(struct filter *filt, epoll_event_dump(ev); kn = knote_lookup(filt, ev->data.fd); if (kn != NULL) { - dst->ident = kn->kev.ident; - dst->filter = kn->kev.filter; - dst->udata = kn->kev.udata; - dst->flags = EV_ADD; - dst->fflags = 0; - if (kn->kev.flags & EV_ONESHOT) /*TODO: move elsewhere */ - dst->flags |= EV_ONESHOT; - if (kn->kev.flags & EV_CLEAR) /*TODO: move elsewhere */ - dst->flags |= EV_CLEAR; + memcpy(dst, &kn->kev, sizeof(*dst)); if (ev->events & EPOLLRDHUP || ev->events & EPOLLHUP) dst->flags |= EV_EOF; if (ev->events & EPOLLERR) diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 04b937468..f1434d67b 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -212,15 +212,7 @@ evfilt_timer_copyout(struct filter *filt, ev = &epevt[i]; /* TODO: put in generic debug.c: epoll_event_dump(ev); */ kn = ev->data.ptr; - dst->ident = kn->kev.ident; - dst->filter = kn->kev.filter; - dst->udata = kn->kev.udata; - dst->flags = EV_ADD; - dst->fflags = 0; - if (kn->kev.flags & EV_ONESHOT) /*TODO: move elsewhere */ - dst->flags |= EV_ONESHOT; - if (kn->kev.flags & EV_CLEAR) /*TODO: move elsewhere */ - dst->flags |= EV_CLEAR; + memcpy(dst, &kn->kev, sizeof(*dst)); if (ev->events & EPOLLERR) dst->fflags = 1; /* FIXME: Return the actual timer error */ diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index 27bc5de28..c7c98ab62 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -132,16 +132,7 @@ evfilt_user_copyout(struct filter *filt, if (!(kn->kev.fflags & NOTE_TRIGGER)) continue; - dst->ident = kn->kev.ident; - dst->filter = kn->kev.filter; - dst->udata = kn->kev.udata; - dst->flags = EV_ADD; - dst->fflags = kn->kev.fflags; - dst->data = 0; - if (kn->kev.flags & EV_ONESHOT) /*TODO: move elsewhere */ - dst->flags |= EV_ONESHOT; - if (kn->kev.flags & EV_CLEAR) /*TODO: move elsewhere */ - dst->flags |= EV_CLEAR; + memcpy(dst, &kn->kev, sizeof(*dst)); if (kn->kev.flags & EV_DISPATCH) KNOTE_DISABLE(kn); if (kn->kev.flags & EV_ONESHOT) diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index f7c3a2b8c..32c6f7ea4 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -229,12 +229,8 @@ evfilt_vnode_copyout(struct filter *filt, return (-1); } - kevent_dump(&kn->kev); - dst->ident = kn->kev.ident; - dst->filter = kn->kev.filter; - dst->udata = kn->kev.udata; - dst->flags = kn->kev.flags; - dst->fflags = 0; + memcpy(dst, &kn->kev, sizeof(*dst)); + dst->data = 0; /* No error checking because fstat(2) should rarely fail */ if ((evt.mask & IN_ATTRIB || evt.mask & IN_MODIFY) diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index f279522e4..99e28aa93 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -139,13 +139,16 @@ const char * kevent_to_str(struct kevent *kev) { char buf[512]; - snprintf(&buf[0], sizeof(buf), "[filter=%d,%s,%s,ident=%u,data=%d,udata=%p]", + + snprintf(&buf[0], sizeof(buf), + "[ident=%d, filter=%d, %s, %s, data=%d, udata=%p]", + (u_int) kev->ident, kev->filter, kevent_flags_dump(kev), kevent_fflags_dump(kev), - (u_int) kev->ident, (int) kev->data, kev->udata); + return (strdup(buf)); } diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index e3959a0d5..874fc5d51 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -223,7 +223,6 @@ test_kevent_socket_dispatch(void) /* The event will occur only once, even though EV_CLEAR is not specified. */ kevent_socket_fill(); - kev.flags = EV_ADD; /* FIXME: not sure what the proper behavior is */ kev.data = 1; kevent_cmp(&kev, kevent_get(kqfd)); test_no_kevents(); From a9957448a8dc58183955b391f63bcd0e9a8ebd69 Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 13 Nov 2009 03:23:04 +0000 Subject: [PATCH 0078/1120] more mailing list info git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@88 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/www/index.html | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index 28f48bf9e..3d97b6a69 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -49,23 +49,29 @@

                Download

                To checkout the entire SVN repository, run the following command:

                -svn checkout svn://mark.heily.com/libkqueue +svn co svn://mark.heily.com/libkqueue

                You can checkout the trunk by using the following command:

                -svn checkout svn://mark.heily.com/libkqueue/trunk libkqueue +svn co svn://mark.heily.com/libkqueue/trunk libkqueue

                There is heavy development on the trunk, and it may not always be in a usable state. If you want to be current, but not bleeding edge, there is also a stable branch. You can checkout the stable branch by using the following command:

                -svn checkout svn://mark.heily.com/libkqueue/branches/stable libkqueue +svn co svn://mark.heily.com/libkqueue/branches/stable libkqueue

                Mailing Lists

                -There are two mailing lists: one for -general discussion, and one for -announcements only. +There are two mailing lists: one for general discussion, and one for announcements. If you subscribe to a mailing list through the web interface, you will need to sign up for a free Google account. If you prefer not to create a Google account, you can subscribe via email instead. +

                +To subscribe to the general discussion group, visit the group's web interface, or send an email to libkqueue+subscribe@googlegroups.com. +

                +To subscribe to the low-traffic annoucements-only group, visit the group's web interface, or send an email to libkqueue-announce+subscribe@googlegroups.com. +

                +Please note that if you use multiple email addresses, Google Groups does not allow you to choose which email address will receive messages. The address on the From: line of the subscribe request will be used as the destination address. +

                +To unsubscribe from either group, send an email to [group name]+unsubscribe@googlegroups.com. If you have any problems subscribing or unsubscribing, send a note to Mark Heily.

                Status

                @@ -144,7 +150,7 @@

                Links

            Contact

            -For more information, contact Mark Heily. +For more information, contact Mark Heily.


            From e8b2e8c5172645998fc035545cfa52ac34e4046f Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 13 Nov 2009 23:25:12 +0000 Subject: [PATCH 0079/1120] fix error in kevent_dump reported by Jean-Daniel Dupas git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@89 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 99e28aa93..c330fae72 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -80,7 +80,7 @@ kevent_fflags_dump(struct kevent *kev) /* Not every filter has meaningful fflags */ if (kev->filter != EVFILT_VNODE) { - snprintf(buf, 1024, "fflags = %d", kev->flags); + snprintf(buf, 1024, "fflags = %d", kev->fflags); return (buf); } From bb0bbe0870e7693c4179cc78ad7343935807865c Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 14 Nov 2009 19:13:12 +0000 Subject: [PATCH 0080/1120] port unit tests to FreeBSD 8.0-STABLE git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@90 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/main.c | 4 ++++ vendor/libkqueue/test/user.c | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index c330fae72..0874d7e9b 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -155,6 +155,10 @@ kevent_to_str(struct kevent *kev) void kevent_cmp(struct kevent *k1, struct kevent *k2) { +/* Workaround for inconsistent implementation of kevent(2) */ +#ifdef __FreeBSD__ + k2->flags |= EV_ADD; +#endif if (memcmp(k1, k2, sizeof(*k1)) != 0) { printf("kevent_cmp: mismatch:\n %s !=\n %s\n", kevent_to_str(k1), kevent_to_str(k2)); diff --git a/vendor/libkqueue/test/user.c b/vendor/libkqueue/test/user.c index d947ec298..f7da06ec0 100644 --- a/vendor/libkqueue/test/user.c +++ b/vendor/libkqueue/test/user.c @@ -55,6 +55,8 @@ event_wait(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); + kev.fflags &= ~NOTE_FFCTRLMASK; + kev.fflags &= ~NOTE_TRIGGER; kevent_cmp(&kev, kevent_get(kqfd)); success(test_id); @@ -84,6 +86,8 @@ disable_and_enable(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); kev.flags = EV_ADD; + kev.fflags &= ~NOTE_FFCTRLMASK; + kev.fflags &= ~NOTE_TRIGGER; kevent_cmp(&kev, kevent_get(kqfd)); success(test_id); @@ -105,8 +109,15 @@ oneshot(void) kev.fflags |= NOTE_TRIGGER; if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); + kev.flags = EV_ADD; // FIXME: Should have ONESHOT flag also + kev.fflags &= ~NOTE_FFCTRLMASK; + kev.fflags &= ~NOTE_TRIGGER; kevent_cmp(&kev, kevent_get(kqfd)); +#ifndef __FreeBSD__ + + /* FIXME: This does not actually produce an error */ + /* Try to trigger the event again. It is deleted, so that should be an error. */ @@ -116,6 +127,8 @@ oneshot(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0) err(1, "%s", test_id); +#endif + success(test_id); } From a651c485862fd7ad0a0b04bc36a7c3a946d8f15d Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 14 Nov 2009 19:52:24 +0000 Subject: [PATCH 0081/1120] port tests to linux, change behavior to match freebsd8 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@91 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kevent.c | 6 ++++++ vendor/libkqueue/src/linux/user.c | 13 ++++++++++--- vendor/libkqueue/test/user.c | 13 +++++-------- vendor/libkqueue/www/index.html | 25 +++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index bdefe5875..d7cb7e8ea 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -85,6 +85,12 @@ kevent_copyin(struct kqueue *kq, const struct kevent *src, int nchanges, status = -ENOENT; goto err_out; } else { + + /* Special case for EVFILT_USER: + Ignore user-generated events that are not of interest */ + if (src->fflags & NOTE_TRIGGER) + continue; + /* flags == 0 or no action */ status = -EINVAL; goto err_out; diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index c7c98ab62..8b5e256f5 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -56,9 +56,8 @@ evfilt_user_copyin(struct filter *filt, struct kevent *kev; uint64_t counter; - if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) { + if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) memcpy(&dst->kev, src, sizeof(*src)); - } kev = &dst->kev; if (src->flags & EV_ENABLE) { dst->kev.flags &= ~EV_DISABLE; @@ -133,10 +132,18 @@ evfilt_user_copyout(struct filter *filt, continue; memcpy(dst, &kn->kev, sizeof(*dst)); + dst->fflags &= ~NOTE_FFCTRLMASK; //FIXME: Not sure if needed + dst->fflags &= ~NOTE_TRIGGER; if (kn->kev.flags & EV_DISPATCH) KNOTE_DISABLE(kn); - if (kn->kev.flags & EV_ONESHOT) + if (kn->kev.flags & EV_ONESHOT) { + + /* NOTE: True on FreeBSD but not consistent behavior with + other filters. */ + dst->flags &= ~EV_ONESHOT; + knote_free(kn); + } dst++; if (++nevents == maxevents) diff --git a/vendor/libkqueue/test/user.c b/vendor/libkqueue/test/user.c index f7da06ec0..966428c81 100644 --- a/vendor/libkqueue/test/user.c +++ b/vendor/libkqueue/test/user.c @@ -114,20 +114,17 @@ oneshot(void) kev.fflags &= ~NOTE_TRIGGER; kevent_cmp(&kev, kevent_get(kqfd)); -#ifndef __FreeBSD__ - - /* FIXME: This does not actually produce an error */ - /* Try to trigger the event again. It is deleted, so that - should be an error. + should be an error. However, on FreeBSD 8 it is not an error, + so the event is ignored. */ - puts(" -- event 2 (should fail)"); + puts(" -- triggering an event that will be ignored"); kev.flags = 0; kev.fflags |= NOTE_TRIGGER; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0) + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); -#endif + test_no_kevents(); success(test_id); } diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index 3d97b6a69..1314f2e96 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -115,6 +115,31 @@

            Status

          +

          Portability of kevent(2) across BSD systems

          + +There are some differences in the behavior of the kevent(2) system call across the various BSD-based operating systems. Here are some of the differences to be aware of: + +
            + +
          1. FreeBSD 8 does not set the EV_ADD flag for kevents on the eventlist, but OpenBSD and Darwin do. This means you should never use the equality operator (==) to test the flags; use the logical AND operator instead. +
          2. + +
          3. The EVFILT_USER filter behaves differently from other filters with respect to the EV_ONESHOT flag. All other filters will preserve the flag when the event is triggered and placed on the eventlist. The EVFILT_USER filter does not preserve this flag. +
          4. + +
          5. +OpenBSD has the NOTE_TRUNCATE fflag, while FreeBSD and Darwin do not. +
          6. + + + +
          + +

          Requirements

          libkqueue currently requires the following: From 8f63262422c6eea37beaba8f8edaef8aaf2c9c8c Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 14 Nov 2009 21:37:07 +0000 Subject: [PATCH 0082/1120] tests: works on linux, more like freebsd git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@92 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/linux/user.c | 5 ++++ vendor/libkqueue/test/common.h | 11 +++++++- vendor/libkqueue/test/main.c | 36 ++++++++++++++++++++----- vendor/libkqueue/test/user.c | 44 ++++++++++++------------------- vendor/libkqueue/www/index.html | 4 +++ 5 files changed, 66 insertions(+), 34 deletions(-) diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index 8b5e256f5..cd9c7243a 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -136,6 +136,11 @@ evfilt_user_copyout(struct filter *filt, dst->fflags &= ~NOTE_TRIGGER; if (kn->kev.flags & EV_DISPATCH) KNOTE_DISABLE(kn); + if (kn->kev.flags & EV_ADD) { + /* NOTE: True on FreeBSD but not consistent behavior with + other filters. */ + dst->flags &= ~EV_ADD; + } if (kn->kev.flags & EV_ONESHOT) { /* NOTE: True on FreeBSD but not consistent behavior with diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 59808a7a2..6488c750a 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -43,6 +43,15 @@ struct kevent * kevent_get(int); void kevent_cmp(struct kevent *, struct kevent *); +void +kevent_add(int kqfd, struct kevent *kev, + uintptr_t ident, + short filter, + u_short flags, + u_int fflags, + intptr_t data, + void *udata); + /* DEPRECATED: */ #define KEV_CMP(kev,_ident,_filter,_flags) do { \ if (kev.ident != (_ident) || \ @@ -57,6 +66,6 @@ void kevent_cmp(struct kevent *, struct kevent *); extern void test_no_kevents(void); extern void test_begin(const char *); -extern void success(const char *); +extern void success(); #endif /* _COMMON_H */ diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 0874d7e9b..369f59440 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -19,7 +19,7 @@ #include "common.h" int testnum = 1; -char *cur_test_id = "undef"; +char *cur_test_id = NULL; int kqfd; extern void test_evfilt_read(); @@ -152,6 +152,23 @@ kevent_to_str(struct kevent *kev) return (strdup(buf)); } +void +kevent_add(int kqfd, struct kevent *kev, + uintptr_t ident, + short filter, + u_short flags, + u_int fflags, + intptr_t data, + void *udata) +{ + EV_SET(kev, ident, filter, flags, fflags, data, NULL); + if (kevent(kqfd, kev, 1, NULL, 0, NULL) < 0) { + printf("Unable to add the following kevent:\n%s\n", + kevent_to_str(kev)); + err(1, "kevent(): %s", strerror(errno)); + } +} + void kevent_cmp(struct kevent *k1, struct kevent *k2) { @@ -169,14 +186,21 @@ kevent_cmp(struct kevent *k1, struct kevent *k2) void test_begin(const char *func) { - cur_test_id = (char *) func; + if (cur_test_id) + free(cur_test_id); + cur_test_id = strdup(func); + if (!cur_test_id) + err(1, "strdup failed"); + printf("\n\nTest %d: %s\n", testnum++, func); } void -success(const char *func) +success(void) { - printf("%-70s %s\n", func, "passed"); + printf("%-70s %s\n", cur_test_id, "passed"); + free(cur_test_id); + cur_test_id = NULL; } void @@ -186,7 +210,7 @@ test_kqueue(void) if ((kqfd = kqueue()) < 0) err(1, "kqueue()"); test_no_kevents(); - success("kqueue()"); + success(); } void @@ -195,7 +219,7 @@ test_kqueue_close(void) test_begin("close(kq)"); if (close(kqfd) < 0) err(1, "close()"); - success("kqueue_close()"); + success(); } int diff --git a/vendor/libkqueue/test/user.c b/vendor/libkqueue/test/user.c index 966428c81..12a7ac7c4 100644 --- a/vendor/libkqueue/test/user.c +++ b/vendor/libkqueue/test/user.c @@ -47,18 +47,16 @@ event_wait(void) test_begin(test_id); - EV_SET(&kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - kev.fflags |= NOTE_TRIGGER; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); + /* Add the event, and then trigger it */ + kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL); + kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; kevent_cmp(&kev, kevent_get(kqfd)); + test_no_kevents(); + success(test_id); } @@ -70,22 +68,17 @@ disable_and_enable(void) test_begin(test_id); - EV_SET(&kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - kev.flags = EV_DISABLE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); + kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL); + kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_DISABLE, 0, 0, NULL); - kev.fflags |= NOTE_TRIGGER; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); + /* Trigger the event, but since it is disabled, nothing will happen. */ + kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); test_no_kevents(); - kev.flags = EV_ENABLE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - kev.flags = EV_ADD; + kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ENABLE, 0, 0, NULL); + kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + + kev.flags = 0; kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; kevent_cmp(&kev, kevent_get(kqfd)); @@ -101,15 +94,12 @@ oneshot(void) test_begin(test_id); - EV_SET(&kev, 1, EVFILT_USER, EV_ADD | EV_ONESHOT, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); + kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ADD | EV_ONESHOT, 0, 0, NULL); puts(" -- event 1"); - kev.fflags |= NOTE_TRIGGER; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - kev.flags = EV_ADD; // FIXME: Should have ONESHOT flag also + kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + + kev.flags = 0; kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; kevent_cmp(&kev, kevent_get(kqfd)); diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index 1314f2e96..63b61c479 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -174,6 +174,10 @@

          Links

        • Kqueues for Fun and Profit [Werner]
        +
      2. +XNU kqueue test program - Demonstrates use of EVFILT_USER +
      3. +

        Contact

        For more information, contact Mark Heily. From 3aa54dac2869ea7a2e7ee052f63d75541787bb41 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 14 Nov 2009 21:39:03 +0000 Subject: [PATCH 0083/1120] freebsd ev_add workaround git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@93 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 369f59440..ffc0f20e3 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -172,9 +172,12 @@ kevent_add(int kqfd, struct kevent *kev, void kevent_cmp(struct kevent *k1, struct kevent *k2) { -/* Workaround for inconsistent implementation of kevent(2) */ +/* XXX- + Workaround for inconsistent implementation of kevent(2) + */ #ifdef __FreeBSD__ - k2->flags |= EV_ADD; + if (k1->flags & EV_ADD) + k2->flags |= EV_ADD; #endif if (memcmp(k1, k2, sizeof(*k1)) != 0) { printf("kevent_cmp: mismatch:\n %s !=\n %s\n", From b704e17c0f9738047d4036cc62bf80c010dc5680 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 15 Nov 2009 23:59:02 +0000 Subject: [PATCH 0084/1120] doc updates, change internal test API function git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@94 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/common.h | 2 +- vendor/libkqueue/test/proc.c | 14 +++++++------- vendor/libkqueue/test/read.c | 18 +++++++++--------- vendor/libkqueue/test/signal.c | 12 ++++++------ vendor/libkqueue/test/timer.c | 12 ++++++------ vendor/libkqueue/test/user.c | 8 ++++---- vendor/libkqueue/test/vnode.c | 16 ++++++++-------- vendor/libkqueue/www/index.html | 3 +++ 8 files changed, 44 insertions(+), 41 deletions(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 6488c750a..ff239a6b7 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -66,6 +66,6 @@ kevent_add(int kqfd, struct kevent *kev, extern void test_no_kevents(void); extern void test_begin(const char *); -extern void success(); +extern void success(void); #endif /* _COMMON_H */ diff --git a/vendor/libkqueue/test/proc.c b/vendor/libkqueue/test/proc.c index da9b10026..21c4fe848 100644 --- a/vendor/libkqueue/test/proc.c +++ b/vendor/libkqueue/test/proc.c @@ -32,7 +32,7 @@ add_and_delete(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id1); - success(test_id1); + success(); test_begin(test_id2); @@ -40,7 +40,7 @@ add_and_delete(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id2); - success(test_id2); + success(); } @@ -70,7 +70,7 @@ test_kevent_signal_get(void) kev.data = 1; kevent_cmp(&kev, kevent_get(kqfd)); - success(test_id); + success(); } void @@ -96,7 +96,7 @@ test_kevent_signal_disable(void) test_no_kevents(); - success(test_id); + success(); } void @@ -133,7 +133,7 @@ test_kevent_signal_enable(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - success(test_id); + success(); } void @@ -159,7 +159,7 @@ test_kevent_signal_del(void) err(1, "kill"); test_no_kevents(); - success(test_id); + success(); } void @@ -192,7 +192,7 @@ test_kevent_signal_oneshot(void) err(1, "kill"); test_no_kevents(); - success(test_id); + success(); } #endif diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 874fc5d51..1e30a61d1 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -50,7 +50,7 @@ test_kevent_socket_add(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - success(test_id); + success(); } void @@ -77,7 +77,7 @@ test_kevent_socket_get(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - success(test_id); + success(); } void @@ -111,7 +111,7 @@ test_kevent_socket_clear(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - success(test_id); + success(); } void @@ -147,7 +147,7 @@ test_kevent_socket_disable_and_enable(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - success(test_id); + success(); } void @@ -166,7 +166,7 @@ test_kevent_socket_del(void) test_no_kevents(); kevent_socket_drain(); - success(test_id); + success(); } void @@ -199,7 +199,7 @@ test_kevent_socket_oneshot(void) kevent_socket_drain(); - success(test_id); + success(); } @@ -234,7 +234,7 @@ test_kevent_socket_dispatch(void) kevent_socket_drain(); - success(test_id); + success(); } #endif /* HAVE_EV_DISPATCH */ @@ -268,7 +268,7 @@ test_kevent_socket_lowat(void) kevent_socket_drain(); kevent_socket_drain(); - success(test_id); + success(); } #endif @@ -297,7 +297,7 @@ test_kevent_socket_eof(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - success(test_id); + success(); } void diff --git a/vendor/libkqueue/test/signal.c b/vendor/libkqueue/test/signal.c index fc5fff3fa..ccbcfde1e 100644 --- a/vendor/libkqueue/test/signal.c +++ b/vendor/libkqueue/test/signal.c @@ -30,7 +30,7 @@ test_kevent_signal_add(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - success(test_id); + success(); } void @@ -58,7 +58,7 @@ test_kevent_signal_get(void) kev.data = 1; kevent_cmp(&kev, kevent_get(kqfd)); - success(test_id); + success(); } void @@ -84,7 +84,7 @@ test_kevent_signal_disable(void) test_no_kevents(); - success(test_id); + success(); } void @@ -121,7 +121,7 @@ test_kevent_signal_enable(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - success(test_id); + success(); } void @@ -147,7 +147,7 @@ test_kevent_signal_del(void) err(1, "kill"); test_no_kevents(); - success(test_id); + success(); } void @@ -180,7 +180,7 @@ test_kevent_signal_oneshot(void) err(1, "kill"); test_no_kevents(); - success(test_id); + success(); } void diff --git a/vendor/libkqueue/test/timer.c b/vendor/libkqueue/test/timer.c index 50c8f03a6..1a6156978 100644 --- a/vendor/libkqueue/test/timer.c +++ b/vendor/libkqueue/test/timer.c @@ -30,7 +30,7 @@ test_kevent_timer_add(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - success(test_id); + success(); } void @@ -47,7 +47,7 @@ test_kevent_timer_del(void) test_no_kevents(); - success(test_id); + success(); } void @@ -70,7 +70,7 @@ test_kevent_timer_get(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - success(test_id); + success(); } static void @@ -97,7 +97,7 @@ test_oneshot(void) test_no_kevents(); - success(test_id); + success(); } static void @@ -128,7 +128,7 @@ test_periodic(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - success(test_id); + success(); } static void @@ -159,7 +159,7 @@ disable_and_enable(void) kev.data = 1; kevent_cmp(&kev, kevent_get(kqfd)); - success(test_id); + success(); } void diff --git a/vendor/libkqueue/test/user.c b/vendor/libkqueue/test/user.c index 12a7ac7c4..529a291a1 100644 --- a/vendor/libkqueue/test/user.c +++ b/vendor/libkqueue/test/user.c @@ -36,7 +36,7 @@ add_and_delete(void) err(1, "%s", test_id); test_no_kevents(); - success(test_id); + success(); } static void @@ -57,7 +57,7 @@ event_wait(void) test_no_kevents(); - success(test_id); + success(); } static void @@ -83,7 +83,7 @@ disable_and_enable(void) kev.fflags &= ~NOTE_TRIGGER; kevent_cmp(&kev, kevent_get(kqfd)); - success(test_id); + success(); } static void @@ -116,7 +116,7 @@ oneshot(void) test_no_kevents(); - success(test_id); + success(); } void diff --git a/vendor/libkqueue/test/vnode.c b/vendor/libkqueue/test/vnode.c index f9579ccb9..24df2310e 100644 --- a/vendor/libkqueue/test/vnode.c +++ b/vendor/libkqueue/test/vnode.c @@ -40,7 +40,7 @@ test_kevent_vnode_add(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - success(test_id); + success(); } void @@ -60,7 +60,7 @@ test_kevent_vnode_note_delete(void) kevent_cmp(&kev, kevent_get(kqfd)); - success(test_id); + success(); } void @@ -84,7 +84,7 @@ test_kevent_vnode_note_write(void) kev.fflags |= NOTE_EXTEND; // XXX-FIXME compatibility issue kevent_cmp(&kev, kevent_get(kqfd)); - success(test_id); + success(); } void @@ -112,7 +112,7 @@ test_kevent_vnode_note_attrib(void) err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - success(test_id); + success(); } void @@ -143,7 +143,7 @@ test_kevent_vnode_note_rename(void) if (system("mv /tmp/kqueue-test2.tmp /tmp/kqueue-test.tmp") < 0) err(1, "system"); - success(test_id); + success(); } void @@ -158,7 +158,7 @@ test_kevent_vnode_del(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "%s", test_id); - success(test_id); + success(); } void @@ -200,7 +200,7 @@ test_kevent_vnode_disable_and_enable(void) err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - success(test_id); + success(); } #if HAVE_EV_DISPATCH @@ -242,7 +242,7 @@ test_kevent_vnode_dispatch(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) err(1, "remove watch failed: %s", test_id); - success(test_id); + success(); } #endif /* HAVE_EV_DISPATCH */ diff --git a/vendor/libkqueue/www/index.html b/vendor/libkqueue/www/index.html index 63b61c479..6c796fc9d 100644 --- a/vendor/libkqueue/www/index.html +++ b/vendor/libkqueue/www/index.html @@ -131,6 +131,9 @@

        Portability of kevent(2) across BSD systems

        OpenBSD has the NOTE_TRUNCATE fflag, while FreeBSD and Darwin do not. +
      4. +EVFILT_FS is undocumented and only available on FreeBSD and Darwin. Here is the CVS commit log which could be helpful to document this filter. +
      5. - -
      - -

      Solaris

      -Here are the issues to be aware of when using this library under Solaris:
      - -
        - -
      1. -Solaris 10 or newer is required. It should work with OpenSolaris and other Solaris-based distributions, but has not been tested. -
      2. - -
      3. -The EVFILT_VNODE filter is not implemented. This will eventually be implemented -using the PORT_SOURCE_FILE mechanism described here. -
      4. - -
      5. The EVFILT_TIMER filter is implemented using high-resolution timers. In order to use high-resolution timers, the calling process must hold the PRIV_PROC_CLOCK_HIGHRES privilege. This privilege is not granted to ordinary users by default. It can be granted to individual users by running the following command as root:
        -
        -# usermod -K defaultpriv=basic,proc_clock_highres $user
        -
        -
      - -

      Portability of kevent(2) across BSD systems

      - -There are some differences in the behavior of the kevent(2) system call across the various BSD-based operating systems. Here are some of the differences to be aware of: - -
        - -
      1. FreeBSD 8 does not set the EV_ADD flag for kevents on the eventlist, but OpenBSD and Darwin do. This means you should never use the equality operator (==) to test the flags; use the logical AND operator instead. -
      2. - -
      3. The EVFILT_USER filter behaves differently from other filters with respect to the EV_ONESHOT flag. All other filters will preserve the flag when the event is triggered and placed on the eventlist. The EVFILT_USER filter does not preserve this flag. -
      4. - -
      5. -OpenBSD has the NOTE_TRUNCATE fflag, while FreeBSD and Darwin do not. -
      6. - -
      7. -EVFILT_FS is undocumented and only available on FreeBSD and Darwin. Here is the CVS commit log which could be helpful to document this filter. -
      8. - - -
      - - -

      Requirements

      - -libkqueue currently requires the following: - -
        -
      • GCC -
      • Linux 2.6.22 or higher -
      • glibc 2.8 or higher -
      - -The Solaris port requires Solaris 10 or higher, and uses the GNU compiler and toolchain. - -

      Nexenta

      - -To build on Nexenta, the gcc-multilib package is required. - -

      Usage

      - - -

      Ordinary Makefile

      - -Here are the steps to use libkqueue in your program if you use an ordinary Makefile: - -
        -
      1. Add `pkg-config libkqueue --cflags` to the CFLAGS variable. -
      2. Add `pkg-config libkqueue --libs` to the LDADD variable. -
      3. Add #include <sys/event.h> to the source code. -
      -

      - -

      Autoconf/Automake/Libtool

      - -If your program uses the GNU Autoconf/Automake/Libtool build system, the following steps will allow you to use libkqueue: - -
        - -
      1. Add the following to configure.ac: -
        -#
        -# Prefer native kqueue(2); otherwise use libkqueue if present.
        -#
        -AC_CHECK_HEADER(sys/event.h, [],
        -  [PKG_CHECK_MODULES(KQUEUE, libkqueue)]
        -)
        -
        -
      2. - -
      3. -Add the following to Makefile.am (assuming your program is named "foo"): -
        -foo_CFLAGS+=$(KQUEUE_CFLAGS)
        -foo_LDADD+=$(KQUEUE_LIBS)
        -
        -
      4. -
      - -

      Instead of using the $(KQUEUE_LIBS) variable, you could just add libkqueue.la to your programs LDADD variable. - -

      Threads

      - -libkqueue uses one or more helper threads, so all programs that link with libkqueue must also link against the pthreads library. Calls to kqueue() and kevent() are safe to be used from multiple threads. - - -

      Links

      - - - -

      Linux kernel event mechanisms

      - - - -

      Solaris kernel event mechanisms

      - - - - -

      Bugs

      - -If you suspect that you have found a bug in libkqueue, please send an email report to the mailing list. If you can reproduce the bug, write a simple testcase and enable debugging output by setting the KQUEUE_DEBUG=y environment variable. Provide this debugging output and the code for the testcase in your bug report. - -

      Contact

      -For more information, contact Mark Heily. - -

      -


      -
      -© 2009-2010 Mark Heily. All rights reserved. -
      - - - diff --git a/vendor/libkqueue/www/index.html.in b/vendor/libkqueue/www/index.html.in new file mode 100644 index 000000000..584ca574f --- /dev/null +++ b/vendor/libkqueue/www/index.html.in @@ -0,0 +1,28 @@ +m4_include(header.m4) + +

      Overview

      +libkqueue is a userspace implementation of the kqueue(2) kernel event notification mechanism. Initial efforts are focused on porting to the Linux 2.6 kernel. There is also an experimental Solaris port. + +

      +libkqueue acts as a translator between the kevent structure and the native kernel facilities of the host machine. The following diagram illustrates how this works under Linux: +

      + +

      + +

      + +Solaris has an event ports facility that is very similar to kqueue. On this platform, the kevent() function is mapped directly to the port_get() system call: + +

      + +

      + +

      Benchmarks

      +On Linux, libkqueue provides O(1) scalability relative to the number of concurrent client connections. This is an improvement over the traditional poll(2) system call which has O(N) scalability. For testing, two versions of the thttpd web server were compiled: one using libkqueue, and one using poll(2). The ApacheBench benchmarking utility was used to compare the performance of both versions. A custom script was used to create thousands of idle connections to the server, to simulate the use of HTTP Keepalives on a busy real-world server. +

      + +

      + + +m4_include(footer.m4) + diff --git a/vendor/libkqueue/www/install.html.in b/vendor/libkqueue/www/install.html.in new file mode 100644 index 000000000..4df1ea430 --- /dev/null +++ b/vendor/libkqueue/www/install.html.in @@ -0,0 +1,25 @@ +m4_include(header.m4) + +

      Installation

      + +Here are the instructions for building the source code on a variety of operating systems. + +

      Linux

      + +libkqueue currently requires the following: + +
        +
      • GCC +
      • Linux 2.6.22 or higher +
      • glibc 2.8 or higher +
      + +

      Solaris

      + +The Solaris port requires Solaris 10 or higher, and uses the GNU compiler and toolchain. + +

      Nexenta

      + +To build on Nexenta, the gcc-multilib package is required. + +m4_include(footer.m4) diff --git a/vendor/libkqueue/www/links.html.in b/vendor/libkqueue/www/links.html.in new file mode 100644 index 000000000..73843ca20 --- /dev/null +++ b/vendor/libkqueue/www/links.html.in @@ -0,0 +1,49 @@ + +m4_include(header.m4) + +

      Links

      + + + +

      Linux kernel event mechanisms

      + + + +

      Solaris kernel event mechanisms

      + + + +m4_include(footer.m4) diff --git a/vendor/libkqueue/www/support.html.in b/vendor/libkqueue/www/support.html.in new file mode 100644 index 000000000..dcb3c4d13 --- /dev/null +++ b/vendor/libkqueue/www/support.html.in @@ -0,0 +1,23 @@ + +m4_include(header.m4) + +

      Mailing Lists

      + +There are two mailing lists: one for general discussion, and one for announcements. If you subscribe to a mailing list through the web interface, you will need to sign up for a free Google account. If you prefer not to create a Google account, you can subscribe via email instead. +

      +To subscribe to the general discussion group, visit the group's web interface, or send an email to libkqueue+subscribe@googlegroups.com. +

      +To subscribe to the low-traffic annoucements-only group, visit the group's web interface, or send an email to libkqueue-announce+subscribe@googlegroups.com. +

      +Please note that if you use multiple email addresses, Google Groups does not allow you to choose which email address will receive messages. The address on the From: line of the subscribe request will be used as the destination address. +

      +To unsubscribe from either group, send an email to [group name]+unsubscribe@googlegroups.com. If you have any problems subscribing or unsubscribing, send a note to Mark Heily. + +

      Bugs

      + +If you suspect that you have found a bug in libkqueue, please send an email report to the mailing list. If you can reproduce the bug, write a simple testcase and enable debugging output by setting the KQUEUE_DEBUG=y environment variable. Provide this debugging output and the code for the testcase in your bug report. + +

      Contact

      +For more information, contact Mark Heily. + +m4_include(footer.m4) diff --git a/vendor/libkqueue/www/usage.html.in b/vendor/libkqueue/www/usage.html.in new file mode 100644 index 000000000..798773d8c --- /dev/null +++ b/vendor/libkqueue/www/usage.html.in @@ -0,0 +1,164 @@ +m4_include(header.m4) + +

      Usage

      + +Here are some issues to be aware of when using this library under any platform:
      + +
        + +
      1. +The EVFILT_PROC filter is not implemented. +
      2. + +
      3. +The EVFILT_AIO filter is not implemented. +
      4. + +
      5. When a kqueue descriptor is closed, it's resources are not immediately reclaimed. Instead, they will be freed the next time that the kqueue(2) function is called. +
      6. + +
      7. +A signal handler is implicitly installed when a EVFILT_SIGNAL kevent is created. For compatibility with kernel-based kqueue(2), programs must ignore signals that will generate kevents. After an EVFILT_SIGNAL kevent is created, a program must not modify the disposition of the associated signal. The following example shows the proper way to handle SIGUSR1 with a kevent:

        +

        +int main() {
        +  int kqfd;
        +  struct kevent kev;
        +
        +  kqfd = kqueue();
        +  signal(SIGUSR1, SIG_IGN);
        +  EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
        +  kevent(kqfd, &kev, 1, NULL, 0, NULL);
        +}
        +
        +
      + +

      Linux

      + +There are several compatibility issues to be aware of when using this library under Linux:
      + +
        + +
      1. The NOTE_LOWAT flag is not supported. According to socket(7),
        +
        +"The select(2) and poll(2) system  calls  currently  do not respect the 
        +SO_RCVLOWAT setting on Linux, and mark a socket readable when even  a  
        +single  byte  of data is available.  A subsequent read from the socket 
        +will block until SO_RCVLOWAT bytes are available."
        +
      2. + +
      3. +The NOTE_REVOKE flag is not supported because Linux does not have +a revoke(2) system call. +
      4. + +
      5. +When an EVFILT_SIGNAL event is generated, the data field +is set to 1 regardless of how many times the signal was received by the process. +
      6. + +
      7. +When an EVFILT_READ event occurs on a listening socket, the data field is set to 1 regardless of how many pending connections are available. + + + +
      + +

      Solaris

      +Here are the issues to be aware of when using this library under Solaris:
      + +
        + +
      1. +Solaris 10 or newer is required. It should work with OpenSolaris and other Solaris-based distributions, but has not been tested. +
      2. + +
      3. +The EVFILT_VNODE filter is not implemented. This will eventually be implemented +using the PORT_SOURCE_FILE mechanism described here. +
      4. + +
      5. The EVFILT_TIMER filter is implemented using high-resolution timers. In order to use high-resolution timers, the calling process must hold the PRIV_PROC_CLOCK_HIGHRES privilege. This privilege is not granted to ordinary users by default. It can be granted to individual users by running the following command as root:
        +
        +# usermod -K defaultpriv=basic,proc_clock_highres $user
        +
        +
      + +

      BSD-based systems

      + +There are some differences in the behavior of the kevent(2) system call across the various BSD-based operating systems. Here are some of the differences to be aware of: + +
        + +
      1. FreeBSD 8 does not set the EV_ADD flag for kevents on the eventlist, but OpenBSD and Darwin do. This means you should never use the equality operator (==) to test the flags; use the logical AND operator instead. +
      2. + +
      3. The EVFILT_USER filter behaves differently from other filters with respect to the EV_ONESHOT flag. All other filters will preserve the flag when the event is triggered and placed on the eventlist. The EVFILT_USER filter does not preserve this flag. +
      4. + +
      5. +OpenBSD has the NOTE_TRUNCATE fflag, while FreeBSD and Darwin do not. +
      6. + +
      7. +EVFILT_FS is undocumented and only available on FreeBSD and Darwin. Here is the CVS commit log which could be helpful to document this filter. +
      8. + + +
      + +

      Integration

      + +

      Ordinary Makefile

      + +Here are the steps to use libkqueue in your program if you use an ordinary Makefile: + +
        +
      1. Add ‘pkg-config libkqueue --cflags‘ to the CFLAGS variable. +
      2. Add ‘pkg-config libkqueue --libs‘ to the LDADD variable. +
      3. Add #include <sys/event.h> to the source code. +
      +

      + +

      Autoconf/Automake/Libtool

      + +If your program uses the GNU Autoconf/Automake/Libtool build system, the following steps will allow you to use libkqueue: + +
        + +
      1. Add the following to configure.ac: +
        +#
        +# Prefer native kqueue(2); otherwise use libkqueue if present.
        +#
        +AC_CHECK_HEADER(sys/event.h, [],
        +  [PKG_CHECK_MODULES(KQUEUE, libkqueue)]
        +)
        +
        +
      2. + +
      3. +Add the following to Makefile.am (assuming your program is named "foo"): +
        +foo_CFLAGS+=$(KQUEUE_CFLAGS)
        +foo_LDADD+=$(KQUEUE_LIBS)
        +
        +
      4. +
      + +

      Instead of using the $(KQUEUE_LIBS) variable, you could just add libkqueue.la to your programs LDADD variable. + +

      Threads

      + +libkqueue uses one or more helper threads, so all programs that link with libkqueue must also link against the pthreads library. Calls to kqueue() and kevent() are safe to be used from multiple threads. + +m4_include(footer.m4) + From e99c2f1df591d168a4a5a2a748d806687b81ca7d Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 12 Sep 2010 19:30:03 +0000 Subject: [PATCH 0305/1120] cleanup git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@325 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/www/Makefile | 5 +++++ vendor/libkqueue/www/foo.html.in | 0 2 files changed, 5 insertions(+) delete mode 100644 vendor/libkqueue/www/foo.html.in diff --git a/vendor/libkqueue/www/Makefile b/vendor/libkqueue/www/Makefile index 995acd2d9..170a8d74a 100644 --- a/vendor/libkqueue/www/Makefile +++ b/vendor/libkqueue/www/Makefile @@ -1,3 +1,8 @@ +# For information about using M4 to generate HTML, see: +# +# http://tldp.org/LDP/LG/issue22/using_m4.html +# + SOURCES=download.html index.html links.html usage.html support.html install.html all: clean $(SOURCES) diff --git a/vendor/libkqueue/www/foo.html.in b/vendor/libkqueue/www/foo.html.in deleted file mode 100644 index e69de29bb..000000000 From c56c6d7433915ba95322f5941f964af5e96c1797 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 12 Sep 2010 20:00:01 +0000 Subject: [PATCH 0306/1120] improve website git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@326 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 3 --- vendor/libkqueue/www/Makefile | 8 ++++++++ vendor/libkqueue/www/download.html.in | 2 +- vendor/libkqueue/www/footer.m4 | 3 +-- vendor/libkqueue/www/header.m4 | 6 +++--- vendor/libkqueue/www/index.html.in | 9 ++++----- vendor/libkqueue/www/links.html.in | 2 +- vendor/libkqueue/www/usage.html.in | 25 ++++++++++++------------- 8 files changed, 30 insertions(+), 28 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 9d4f41760..c1911d089 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -78,9 +78,6 @@ dist: dist-upload: dist scp $(PROGRAM)-$(VERSION).tar.gz $(DIST) -publish-www: - cp -R www/* ~/public_html/libkqueue/ - clean: rm -f tags *.a $(OBJS) *.so *.so.* rm -rf pkg diff --git a/vendor/libkqueue/www/Makefile b/vendor/libkqueue/www/Makefile index 170a8d74a..0af0e8572 100644 --- a/vendor/libkqueue/www/Makefile +++ b/vendor/libkqueue/www/Makefile @@ -9,7 +9,15 @@ all: clean $(SOURCES) %.html: m4 -P < $@.in > $@ + tidy -q -m $@ chmod 444 $@ clean: rm -f $(SOURCES) + +edit: + $(EDITOR) *.in + +install: + cp *.html *.css *.png ~/public_html/libkqueue/ + diff --git a/vendor/libkqueue/www/download.html.in b/vendor/libkqueue/www/download.html.in index 6de93c782..3f867d39b 100644 --- a/vendor/libkqueue/www/download.html.in +++ b/vendor/libkqueue/www/download.html.in @@ -13,7 +13,7 @@ The source code for each release can be downloaded from here.

      Unreleased Development Version

      To checkout the Subversion repository, run the following command: -

      + svn checkout svn://mark.heily.com/libkqueue/trunk libkqueue m4_include(footer.m4) diff --git a/vendor/libkqueue/www/footer.m4 b/vendor/libkqueue/www/footer.m4 index 4dd3bdbb6..b33f183ba 100644 --- a/vendor/libkqueue/www/footer.m4 +++ b/vendor/libkqueue/www/footer.m4 @@ -1,5 +1,4 @@ -

      -


      +
      © 2009-2010 Mark Heily. All rights reserved.
      diff --git a/vendor/libkqueue/www/header.m4 b/vendor/libkqueue/www/header.m4 index 77e4873de..6e47ea1cf 100644 --- a/vendor/libkqueue/www/header.m4 +++ b/vendor/libkqueue/www/header.m4 @@ -6,7 +6,7 @@ libkqueue - + @@ -14,7 +14,7 @@

      libkqueue

      -
      +
      Overview | Download | @@ -24,4 +24,4 @@ Links
      -
      +
      diff --git a/vendor/libkqueue/www/index.html.in b/vendor/libkqueue/www/index.html.in index 584ca574f..72d7d1646 100644 --- a/vendor/libkqueue/www/index.html.in +++ b/vendor/libkqueue/www/index.html.in @@ -1,28 +1,27 @@ m4_include(header.m4)

      Overview

      -libkqueue is a userspace implementation of the kqueue(2) kernel event notification mechanism. Initial efforts are focused on porting to the Linux 2.6 kernel. There is also an experimental Solaris port. +libkqueue is a userspace implementation of the kqueue(2) kernel event notification mechanism. Initial efforts are focused on porting to the Linux 2.6 kernel. There is also an experimental Solaris port.

      libkqueue acts as a translator between the kevent structure and the native kernel facilities of the host machine. The following diagram illustrates how this works under Linux:

      - +Linux implementation

      Solaris has an event ports facility that is very similar to kqueue. On this platform, the kevent() function is mapped directly to the port_get() system call:

      - +Solaris implementation

      Benchmarks

      On Linux, libkqueue provides O(1) scalability relative to the number of concurrent client connections. This is an improvement over the traditional poll(2) system call which has O(N) scalability. For testing, two versions of the thttpd web server were compiled: one using libkqueue, and one using poll(2). The ApacheBench benchmarking utility was used to compare the performance of both versions. A custom script was used to create thousands of idle connections to the server, to simulate the use of HTTP Keepalives on a busy real-world server.

      - +Scalability

      - m4_include(footer.m4) diff --git a/vendor/libkqueue/www/links.html.in b/vendor/libkqueue/www/links.html.in index 73843ca20..0a73cbc2b 100644 --- a/vendor/libkqueue/www/links.html.in +++ b/vendor/libkqueue/www/links.html.in @@ -36,7 +36,7 @@ m4_include(header.m4)
      • -Solaris 10 port_create(3C) manual page +Solaris 10 port_create(3C) manual page
      • diff --git a/vendor/libkqueue/www/usage.html.in b/vendor/libkqueue/www/usage.html.in index 798773d8c..6fbb40d4e 100644 --- a/vendor/libkqueue/www/usage.html.in +++ b/vendor/libkqueue/www/usage.html.in @@ -2,7 +2,8 @@ m4_include(header.m4)

        Usage

        -Here are some issues to be aware of when using this library under any platform:
        +Here are some issues to be aware of when using this library under any platform: +
          @@ -18,7 +19,8 @@ The EVFILT_AIO filter is not implemented.
        1. -A signal handler is implicitly installed when a EVFILT_SIGNAL kevent is created. For compatibility with kernel-based kqueue(2), programs must ignore signals that will generate kevents. After an EVFILT_SIGNAL kevent is created, a program must not modify the disposition of the associated signal. The following example shows the proper way to handle SIGUSR1 with a kevent:

          +A signal handler is implicitly installed when a EVFILT_SIGNAL kevent is created. For compatibility with kernel-based kqueue(2), programs must ignore signals that will generate kevents. After an EVFILT_SIGNAL kevent is created, a program must not modify the disposition of the associated signal. The following example shows the proper way to handle SIGUSR1 with a kevent: +

           int main() {
             int kqfd;
          @@ -26,19 +28,19 @@ int main() {
           
             kqfd = kqueue();
             signal(SIGUSR1, SIG_IGN);
          -  EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
          -  kevent(kqfd, &kev, 1, NULL, 0, NULL);
          +  EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
          +  kevent(kqfd, &kev, 1, NULL, 0, NULL);
           }
           

        Linux

        -There are several compatibility issues to be aware of when using this library under Linux:
        +There are several compatibility issues to be aware of when using this library under Linux:
          -
        1. The NOTE_LOWAT flag is not supported. According to socket(7),
          +
        2. The NOTE_LOWAT flag is not supported. According to socket(7),
           "The select(2) and poll(2) system  calls  currently  do not respect the 
           SO_RCVLOWAT setting on Linux, and mark a socket readable when even  a  
          @@ -68,7 +70,7 @@ The EVFILT_PROC filter only supports the NOTE_EXIT flag, and the ident
           
           

          Solaris

          -Here are the issues to be aware of when using this library under Solaris:
          +Here are the issues to be aware of when using this library under Solaris:
            @@ -78,11 +80,10 @@ Solaris 10 or newer is required. It should work with OpenSolaris and other Solar
          1. The EVFILT_VNODE filter is not implemented. This will eventually be implemented -using the PORT_SOURCE_FILE mechanism described here. +using the PORT_SOURCE_FILE mechanism described here.
          2. -
          3. The EVFILT_TIMER filter is implemented using high-resolution timers. In order to use high-resolution timers, the calling process must hold the PRIV_PROC_CLOCK_HIGHRES privilege. This privilege is not granted to ordinary users by default. It can be granted to individual users by running the following command as root:
            +
          4. The EVFILT_TIMER filter is implemented using high-resolution timers. In order to use high-resolution timers, the calling process must hold the PRIV_PROC_CLOCK_HIGHRES privilege. This privilege is not granted to ordinary users by default. It can be granted to individual users by running the following command as root:
             # usermod -K defaultpriv=basic,proc_clock_highres $user
             
            @@ -126,7 +127,6 @@ Here are the steps to use libkqueue in your program if you use an ordinary Makef
          5. Add ‘pkg-config libkqueue --libs‘ to the LDADD variable.
          6. Add #include <sys/event.h> to the source code.
          -

          Autoconf/Automake/Libtool

          @@ -154,11 +154,10 @@ foo_LDADD+=$(KQUEUE_LIBS)
        -

        Instead of using the $(KQUEUE_LIBS) variable, you could just add libkqueue.la to your programs LDADD variable. +Instead of using the $(KQUEUE_LIBS) variable, you could just add libkqueue.la to your programs LDADD variable.

        Threads

        libkqueue uses one or more helper threads, so all programs that link with libkqueue must also link against the pthreads library. Calls to kqueue() and kevent() are safe to be used from multiple threads. m4_include(footer.m4) - From e25b242ebbb8553762ee5653163ef1efdb1aa92e Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 14 Sep 2010 01:43:24 +0000 Subject: [PATCH 0307/1120] cosmetic website changes git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@327 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/www/Makefile | 8 +++++--- vendor/libkqueue/www/default.css | 4 ++-- vendor/libkqueue/www/download.html.in | 5 ++++- vendor/libkqueue/www/footer.m4 | 2 ++ vendor/libkqueue/www/header.m4 | 2 ++ 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/www/Makefile b/vendor/libkqueue/www/Makefile index 0af0e8572..79bffa304 100644 --- a/vendor/libkqueue/www/Makefile +++ b/vendor/libkqueue/www/Makefile @@ -3,9 +3,10 @@ # http://tldp.org/LDP/LG/issue22/using_m4.html # -SOURCES=download.html index.html links.html usage.html support.html install.html +OBJS=download.html index.html links.html usage.html support.html install.html +DESTDIR=~/public_html/libkqueue -all: clean $(SOURCES) +all: clean $(OBJS) %.html: m4 -P < $@.in > $@ @@ -13,11 +14,12 @@ all: clean $(SOURCES) chmod 444 $@ clean: - rm -f $(SOURCES) + rm -f $(OBJS) edit: $(EDITOR) *.in install: + cd $(DESTDIR) && rm -f $(OBJS) cp *.html *.css *.png ~/public_html/libkqueue/ diff --git a/vendor/libkqueue/www/default.css b/vendor/libkqueue/www/default.css index 6e2281db6..2878aa768 100644 --- a/vendor/libkqueue/www/default.css +++ b/vendor/libkqueue/www/default.css @@ -5,7 +5,7 @@ div.content { background: white; margin: 0 3em; - padding: 0 2em; + padding: 0 3em; } .blockquote { margin-right: 2em } code.block { @@ -20,7 +20,7 @@ text-align: center; } h2 { - margin-left: -1em; + //margin-left: -1em; padding-top: 0.5em; } ol { diff --git a/vendor/libkqueue/www/download.html.in b/vendor/libkqueue/www/download.html.in index 3f867d39b..8a361cc29 100644 --- a/vendor/libkqueue/www/download.html.in +++ b/vendor/libkqueue/www/download.html.in @@ -13,7 +13,10 @@ The source code for each release can be downloaded from here.

        Unreleased Development Version

        To checkout the Subversion repository, run the following command: +
        -svn checkout svn://mark.heily.com/libkqueue/trunk libkqueue +
        +svn checkout svn://mark.heily.com/libkqueue/trunk libkqueue
        +
        m4_include(footer.m4) diff --git a/vendor/libkqueue/www/footer.m4 b/vendor/libkqueue/www/footer.m4 index b33f183ba..b38ac43be 100644 --- a/vendor/libkqueue/www/footer.m4 +++ b/vendor/libkqueue/www/footer.m4 @@ -1,3 +1,5 @@ +
        +

        © 2009-2010 Mark Heily. All rights reserved. diff --git a/vendor/libkqueue/www/header.m4 b/vendor/libkqueue/www/header.m4 index 6e47ea1cf..c3196fa71 100644 --- a/vendor/libkqueue/www/header.m4 +++ b/vendor/libkqueue/www/header.m4 @@ -12,6 +12,7 @@
        +

        libkqueue


        @@ -25,3 +26,4 @@

        + From 3b62425c11b034579f5e47f680f3e80dc9da3bbb Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 14 Sep 2010 03:05:35 +0000 Subject: [PATCH 0308/1120] remove unimplemented solaris stuff git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@328 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/hook.c | 97 ---------- vendor/libkqueue/src/solaris/proc.c | 36 ---- vendor/libkqueue/src/solaris/signal.c | 198 --------------------- vendor/libkqueue/src/solaris/socket.c | 44 +---- vendor/libkqueue/src/solaris/timer.c | 2 +- vendor/libkqueue/src/solaris/vnode.c | 247 -------------------------- vendor/libkqueue/www/usage.html.in | 11 ++ 7 files changed, 13 insertions(+), 622 deletions(-) delete mode 100644 vendor/libkqueue/src/solaris/hook.c delete mode 100644 vendor/libkqueue/src/solaris/proc.c delete mode 100644 vendor/libkqueue/src/solaris/signal.c delete mode 100644 vendor/libkqueue/src/solaris/vnode.c diff --git a/vendor/libkqueue/src/solaris/hook.c b/vendor/libkqueue/src/solaris/hook.c deleted file mode 100644 index 610c0efe8..000000000 --- a/vendor/libkqueue/src/solaris/hook.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2009 Mark Heily - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include - -#include "sys/event.h" -#include "private.h" - -#define PORTEV_DUMP(pe) dbg_printf("port_event: events=%d source=%hu", \ - (pe)->portev_events, (pe)->portev_source) -int -kqueue_init_hook(void) -{ - return (0); -} - -int -kqueue_hook(struct kqueue *kq) -{ - if ((kq->kq_port = port_create()) < 0) { - dbg_perror("port_create(2)"); - return (-1); - } - - return (0); -} - -int -kevent_wait(struct kqueue *kq, const struct timespec *timeout) -{ - port_event_t pe[1]; - int rv, nget; - - dbg_printf("port_get: %d %lu %lu", - kq->kq_port, timeout->tv_sec, timeout->tv_nsec); - nget = 1; - rv = port_getn(kq->kq_port, pe, 1, &nget, (struct timespec *) timeout); - if (rv < 0) { - if (errno == EINTR) { - dbg_puts("signal caught"); - return (-1); - } - dbg_perror("port_getn(2)"); - return (-1); - } - if (nget > 0) { - dbg_printf(" -- event(s) pending: nget = %d", nget); - PORTEV_DUMP(&pe[0]); - } else { - dbg_puts(" -- no events --"); - } - - return (nget); -} - -int -kevent_copyout(struct kqueue *kq, int nready, - struct kevent *eventlist, int nevents) -{ - return (-1); -#if TODO - struct filter *filt; - int i, rv, nret; - - if (FD_ISSET(filt->kf_pfd, &kq->kq_rfds)) { - dbg_printf("event(s) for filter #%d", i); - filter_lock(filt); - rv = filt->kf_copyout(filt, eventlist, nevents); - if (rv < 0) { - filter_unlock(filt); - dbg_puts("kevent_copyout failed"); - return (-1); - } - nret += rv; - eventlist += rv; - nevents -= rv; - nready--; - filter_unlock(filt); - } - - return (nret); -#endif -} diff --git a/vendor/libkqueue/src/solaris/proc.c b/vendor/libkqueue/src/solaris/proc.c deleted file mode 100644 index be18350a4..000000000 --- a/vendor/libkqueue/src/solaris/proc.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2009 Mark Heily - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "sys/event.h" -#include "private.h" - -const struct filter evfilt_proc = { - 0, //XXX-FIXME broken: EVFILT_PROC, -}; diff --git a/vendor/libkqueue/src/solaris/signal.c b/vendor/libkqueue/src/solaris/signal.c deleted file mode 100644 index 4831a8ae8..000000000 --- a/vendor/libkqueue/src/solaris/signal.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 2009 Mark Heily - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sys/event.h" -#include "private.h" - -/* Highest signal number supported. POSIX standard signals are < 32 */ -#define SIGNAL_MAX 32 - -struct sentry { - size_t s_cnt; - struct filter *s_filt; - struct knote *s_knote; -}; - -static pthread_mutex_t sigtbl_mtx = PTHREAD_MUTEX_INITIALIZER; -static struct sentry sigtbl[SIGNAL_MAX]; - -static void -signal_handler(int sig) -{ - struct sentry *s = &sigtbl[sig]; - ssize_t n; - - dbg_printf("caught sig=%d", sig); - atomic_inc(&s->s_cnt); - n = write(s->s_filt->kf_wfd, &sig, sizeof(sig));//FIXME:errhandling -} - -static int -catch_signal(struct filter *filt, struct knote *kn) -{ - int sig; - struct sigaction sa; - - sig = kn->kev.ident; - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = signal_handler; - sa.sa_flags |= SA_RESTART; - sigfillset(&sa.sa_mask); - - if (sigaction(kn->kev.ident, &sa, NULL) == -1) { - dbg_perror("sigaction"); - return (-1); - } - /* FIXME: will clobber previous entry, if any */ - pthread_mutex_lock(&sigtbl_mtx); - sigtbl[kn->kev.ident].s_filt = filt; - sigtbl[kn->kev.ident].s_knote = kn; - pthread_mutex_unlock(&sigtbl_mtx); - - dbg_printf("installed handler for signal %d", sig); - return (0); -} - -static int -ignore_signal(int sig) -{ - struct sigaction sa; - - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = SIG_IGN; - sigemptyset(&sa.sa_mask); - - if (sigaction(sig, &sa, NULL) == -1) { - dbg_perror("sigaction"); - return (-1); - } - pthread_mutex_lock(&sigtbl_mtx); - sigtbl[sig].s_filt = NULL; - sigtbl[sig].s_knote = NULL; - pthread_mutex_unlock(&sigtbl_mtx); - - dbg_printf("removed handler for signal %d", sig); - return (0); -} - -int -evfilt_signal_init(struct filter *filt) -{ - return filter_socketpair(filt); -} - -void -evfilt_signal_destroy(struct filter *filt) -{ - close(filt->kf_pfd); -} - -int -evfilt_signal_knote_create(struct filter *filt, struct knote *kn) -{ - if (kn->kev.ident >= SIGNAL_MAX) { - dbg_printf("unsupported signal number %u", (u_int) kn->kev.ident); - return (-1); - } - - kn->kev.flags |= EV_CLEAR; - - return catch_signal(filt, kn); -} - -int -evfilt_signal_knote_modify(struct filter *filt, struct knote *kn, - const struct kevent *kev) -{ - kn->kev.flags = kev->flags | EV_CLEAR; - return (0); -} - -int -evfilt_signal_knote_delete(struct filter *filt, struct knote *kn) -{ - return ignore_signal(kn->kev.ident); -} - -int -evfilt_signal_knote_enable(struct filter *filt, struct knote *kn) -{ - return catch_signal(filt, kn); -} - -int -evfilt_signal_knote_disable(struct filter *filt, struct knote *kn) -{ - return ignore_signal(kn->kev.ident); -} - -int -evfilt_signal_copyout(struct filter *filt, - struct kevent *dst, - int nevents) -{ - struct sentry *s; - struct knote *kn; - int sig; - ssize_t n; - - n = read(filt->kf_pfd, &sig, sizeof(sig));//FIXME:errhandling - dbg_printf("got sig=%d", sig); - s = &sigtbl[sig]; - kn = s->s_knote; - //TODO: READ counter: s->s_knote->kev.data = ?; - /* TODO: dst->data should be the number of times the signal occurred */ - dst->ident = sig; - dst->filter = EVFILT_SIGNAL; - dst->udata = kn->kev.udata; - dst->flags = kn->kev.flags; - dst->fflags = 0; - dst->data = 1; - - if (kn->kev.flags & EV_DISPATCH) { - ignore_signal(kn->kev.ident); - KNOTE_DISABLE(kn); - } else if (kn->kev.flags & EV_ONESHOT) { - ignore_signal(kn->kev.ident); - knote_free(filt, kn); - } - - return (1); -} - -const struct filter evfilt_signal = { - EVFILT_SIGNAL, - evfilt_signal_init, - evfilt_signal_destroy, - evfilt_signal_copyout, - evfilt_signal_knote_create, - evfilt_signal_knote_modify, - evfilt_signal_knote_delete, - evfilt_signal_knote_enable, - evfilt_signal_knote_disable, -}; diff --git a/vendor/libkqueue/src/solaris/socket.c b/vendor/libkqueue/src/solaris/socket.c index 183660496..53647d49a 100644 --- a/vendor/libkqueue/src/solaris/socket.c +++ b/vendor/libkqueue/src/solaris/socket.c @@ -79,49 +79,6 @@ evfilt_socket_destroy(struct filter *filt) ; } -#if DEADWOOD -// split into multiple funcs -int -evfilt_socket_copyin(struct filter *filt, - struct knote *dst, const struct kevent *src) -{ - int port, events; - int rv; - - port = filt->kf_kqueue->kq_port; - - /* Not supported or not implemented */ - if (src->flags & EV_CLEAR) { - dbg_puts("attempt to use unsupported mechanism"); - return (-1); - } - - if (src->filter == EVFILT_READ) - events = POLLIN; - else - events = POLLOUT; - - if (src->flags & EV_DELETE || src->flags & EV_DISABLE) { - rv = port_dissociate(port, PORT_SOURCE_FD, src->ident); - if (rv < 0) { - dbg_perror("port_dissociate(2)"); - return (-1); - } - } - if (src->flags & EV_ENABLE || src->flags & EV_ADD) { - rv = port_associate(port, PORT_SOURCE_FD, - src->ident, events, src->udata); - if (rv < 0) { - dbg_perror("port_associate(2)"); - return (-1); - } - } - /* XXX-TODO support modifying an existing watch */ - - return (0); -} -#endif - int evfilt_socket_knote_create(struct filter *filt, struct knote *kn) { @@ -195,6 +152,7 @@ evfilt_socket_copyout(struct filter *filt, dst->data = 0; } #else + /* Workaround */ dst->data = 1; #endif } diff --git a/vendor/libkqueue/src/solaris/timer.c b/vendor/libkqueue/src/solaris/timer.c index f02079a18..be4c009d2 100644 --- a/vendor/libkqueue/src/solaris/timer.c +++ b/vendor/libkqueue/src/solaris/timer.c @@ -166,7 +166,7 @@ int evfilt_timer_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { - return (0); /* STUB */ + return (-1); /* STUB */ } int diff --git a/vendor/libkqueue/src/solaris/vnode.c b/vendor/libkqueue/src/solaris/vnode.c deleted file mode 100644 index 7f78ceaf0..000000000 --- a/vendor/libkqueue/src/solaris/vnode.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) 2009 Mark Heily - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "sys/event.h" -#include "private.h" - -int -evfilt_vnode_init(struct filter *filt) -{ - return (-1); -} - -void -evfilt_vnode_destroy(struct filter *filt) -{ - ; -} - -int -evfilt_vnode_copyin(struct filter *filt, - struct knote *dst, const struct kevent *src) -{ -#if TODO - char path[PATH_MAX]; - struct stat sb; - uint32_t mask; - - if (src->flags & EV_DELETE || src->flags & EV_DISABLE) - return delete_watch(filt->kf_pfd, dst); - - if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) { - memcpy(&dst->kev, src, sizeof(*src)); - if (fstat(src->ident, &sb) < 0) { - dbg_puts("fstat failed"); - return (-1); - } - dst->kn_st_nlink = sb.st_nlink; - dst->kn_st_size = sb.st_size; - dst->kev.data = -1; - } - - if (src->flags & EV_ADD || src->flags & EV_ENABLE) { - - /* Convert the fd to a pathname */ - if (fd_to_path(&path[0], sizeof(path), src->ident) < 0) - return (-1); - - /* Convert the fflags to the inotify mask */ - mask = 0; - if (dst->kev.fflags & NOTE_DELETE) - mask |= IN_ATTRIB | IN_DELETE_SELF; - if (dst->kev.fflags & NOTE_WRITE) - mask |= IN_MODIFY | IN_ATTRIB; - if (dst->kev.fflags & NOTE_EXTEND) - mask |= IN_MODIFY | IN_ATTRIB; - if ((dst->kev.fflags & NOTE_ATTRIB) || - (dst->kev.fflags & NOTE_LINK)) - mask |= IN_ATTRIB; - if (dst->kev.fflags & NOTE_RENAME) - mask |= IN_MOVE_SELF; - if (dst->kev.flags & EV_ONESHOT) - mask |= IN_ONESHOT; - - dbg_printf("inotify_add_watch(2); inofd=%d, %s, path=%s", - filt->kf_pfd, inotify_mask_dump(mask), path); - dst->kev.data = inotify_add_watch(filt->kf_pfd, path, mask); - if (dst->kev.data < 0) { - dbg_printf("inotify_add_watch(2): %s", strerror(errno)); - return (-1); - } - } - - return (0); -#endif - return (-1); -} - -int -evfilt_vnode_copyout(struct filter *filt, - struct kevent *dst, - int nevents) -{ -#if TODO - struct inotify_event evt; - struct stat sb; - struct knote *kn; - - if (get_one_event(&evt, filt->kf_pfd) < 0) - return (-1); - - inotify_event_dump(&evt); - if (evt.mask & IN_IGNORED) { - /* TODO: possibly return error when fs is unmounted */ - return (0); - } - - kn = knote_lookup_data(filt, evt.wd); - if (kn == NULL) { - dbg_printf("no match for wd # %d", evt.wd); - return (-1); - } - - memcpy(dst, &kn->kev, sizeof(*dst)); - dst->data = 0; - - /* No error checking because fstat(2) should rarely fail */ - if ((evt.mask & IN_ATTRIB || evt.mask & IN_MODIFY) - && fstat(kn->kev.ident, &sb) == 0) { - if (sb.st_nlink == 0 && kn->kev.fflags & NOTE_DELETE) - dst->fflags |= NOTE_DELETE; - if (sb.st_nlink != kn->kn_st_nlink && kn->kev.fflags & NOTE_LINK) - dst->fflags |= NOTE_LINK; -#if HAVE_NOTE_TRUNCATE - if (sb.st_nsize == 0 && kn->kev.fflags & NOTE_TRUNCATE) - dst->fflags |= NOTE_TRUNCATE; -#endif - if (sb.st_size > kn->kn_st_size && kn->kev.fflags & NOTE_WRITE) - dst->fflags |= NOTE_EXTEND; - kn->kn_st_nlink = sb.st_nlink; - kn->kn_st_size = sb.st_size; - } - - if (evt.mask & IN_MODIFY && kn->kev.fflags & NOTE_WRITE) - dst->fflags |= NOTE_WRITE; - if (evt.mask & IN_ATTRIB && kn->kev.fflags & NOTE_ATTRIB) - dst->fflags |= NOTE_ATTRIB; - if (evt.mask & IN_MOVE_SELF && kn->kev.fflags & NOTE_RENAME) - dst->fflags |= NOTE_RENAME; - if (evt.mask & IN_DELETE_SELF && kn->kev.fflags & NOTE_DELETE) - dst->fflags |= NOTE_DELETE; - - if (evt.mask & IN_MODIFY && kn->kev.fflags & NOTE_WRITE) - dst->fflags |= NOTE_WRITE; - if (evt.mask & IN_ATTRIB && kn->kev.fflags & NOTE_ATTRIB) - dst->fflags |= NOTE_ATTRIB; - if (evt.mask & IN_MOVE_SELF && kn->kev.fflags & NOTE_RENAME) - dst->fflags |= NOTE_RENAME; - if (evt.mask & IN_DELETE_SELF && kn->kev.fflags & NOTE_DELETE) - dst->fflags |= NOTE_DELETE; - - if (kn->kev.flags & EV_DISPATCH) { - delete_watch(filt->kf_pfd, kn); /* TODO: error checking */ - KNOTE_DISABLE(kn); - } - if (kn->kev.flags & EV_ONESHOT) - knote_free(kn); - - return (1); -#endif - return (-1); -} - -int -evfilt_vnode_knote_create(struct filter *filt, struct knote *kn) -{ -#if TODO - struct epoll_event ev; - - /* Convert the kevent into an epoll_event */ - if (kn->kev.filter == EVFILT_READ) - kn->kn_events = EPOLLIN | EPOLLRDHUP; - else - kn->kn_events = EPOLLOUT; - if (kn->kev.flags & EV_ONESHOT || kn->kev.flags & EV_DISPATCH) - kn->kn_events |= EPOLLONESHOT; - if (kn->kev.flags & EV_CLEAR) - kn->kn_events |= EPOLLET; - - memset(&ev, 0, sizeof(ev)); - ev.events = kn->kn_events; - ev.data.fd = kn->kev.ident; - - return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); -#endif - return (-1); -} - -int -evfilt_vnode_knote_modify(struct filter *filt, struct knote *kn, - const struct kevent *kev) -{ - return (-1); /* STUB */ -} - -int -evfilt_vnode_knote_delete(struct filter *filt, struct knote *kn) -{ -#if TODO - if (kn->kev.flags & EV_DISABLE) - return (0); - else - return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); -#else - return (-1); -#endif -} - -int -evfilt_vnode_knote_enable(struct filter *filt, struct knote *kn) -{ -#if TODO - struct epoll_event ev; - - memset(&ev, 0, sizeof(ev)); - ev.events = kn->kn_events; - ev.data.fd = kn->kev.ident; - - return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); -#else - return (-1); -#endif -} - -int -evfilt_vnode_knote_disable(struct filter *filt, struct knote *kn) -{ -#if TODO - return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); -#else - return (-1); -#endif -} - -const struct filter evfilt_vnode = { - 0, //EVFILT_VNODE, - evfilt_vnode_init, - evfilt_vnode_destroy, - evfilt_vnode_copyout, - evfilt_vnode_knote_create, - evfilt_vnode_knote_modify, - evfilt_vnode_knote_delete, - evfilt_vnode_knote_enable, - evfilt_vnode_knote_disable, -}; diff --git a/vendor/libkqueue/www/usage.html.in b/vendor/libkqueue/www/usage.html.in index 6fbb40d4e..978b72758 100644 --- a/vendor/libkqueue/www/usage.html.in +++ b/vendor/libkqueue/www/usage.html.in @@ -70,6 +70,7 @@ The EVFILT_PROC filter only supports the NOTE_EXIT flag, and the ident

        Solaris

        + Here are the issues to be aware of when using this library under Solaris:
          @@ -78,6 +79,16 @@ Here are the issues to be aware of when using this library under Solaris:
          Solaris 10 or newer is required. It should work with OpenSolaris and other Solaris-based distributions, but has not been tested. +
        1. +When an EVFILT_READ event is generated, the data field +is set to 1 regardless of how many bytes are available to read. +
        2. + +
        3. +When an EVFILT_TIMER event is generated, the data field +is set to 1 regardless of how many times the timer has been triggered. +
        4. +
        5. The EVFILT_VNODE filter is not implemented. This will eventually be implemented using the PORT_SOURCE_FILE mechanism described here. From c8e02822a08b35853c6d7baa9d4b71899df0e505 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 15 Sep 2010 00:41:11 +0000 Subject: [PATCH 0309/1120] new EVFILT_NOTIMPL initializer git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@329 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/private.h | 3 +++ vendor/libkqueue/src/solaris/kevent.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index bbe47f6d5..f4d9ecb3f 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -147,6 +147,9 @@ struct filter { struct kqueue *kf_kqueue; }; +/* Use this to declare a filter that is not implemented */ +#define EVFILT_NOTIMPL { -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + struct kqueue { int kq_sockfd[2]; struct filter kq_filt[EVFILT_SYSCOUNT]; diff --git a/vendor/libkqueue/src/solaris/kevent.c b/vendor/libkqueue/src/solaris/kevent.c index 57e528825..32699ffc4 100644 --- a/vendor/libkqueue/src/solaris/kevent.c +++ b/vendor/libkqueue/src/solaris/kevent.c @@ -21,6 +21,8 @@ #include "sys/event.h" #include "private.h" +const struct filter evfilt_vnode = EVFILT_NOTIMPL; + /* Dump a poll(2) events bitmask */ static char * poll_events_dump(short events) From 826a79aa260a7d044efae8c3064e3619e392cfd7 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 15 Sep 2010 00:55:52 +0000 Subject: [PATCH 0310/1120] evfilt proc notimpl git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@330 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/kevent.c | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/src/solaris/kevent.c b/vendor/libkqueue/src/solaris/kevent.c index 32699ffc4..811bfa2c8 100644 --- a/vendor/libkqueue/src/solaris/kevent.c +++ b/vendor/libkqueue/src/solaris/kevent.c @@ -22,6 +22,7 @@ #include "private.h" const struct filter evfilt_vnode = EVFILT_NOTIMPL; +const struct filter evfilt_proc = EVFILT_NOTIMPL; /* Dump a poll(2) events bitmask */ static char * From 9680ed97d2beb68c8beef33b1f0de20088b7a504 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 15 Sep 2010 00:56:52 +0000 Subject: [PATCH 0311/1120] config change git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@331 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/config.inc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index 98aad9f5b..9e462f360 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -75,6 +75,8 @@ post_configure_hook() { evfilt_signal="src/posix/signal.c" evfilt_timer="src/solaris/timer.c" evfilt_user="src/solaris/user.c" + evfilt_proc="" + evfilt_vnode="" eventfd="" fi From 680780bd02c23b6ad265eaff8e702deb1df64de0 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 15 Sep 2010 00:58:31 +0000 Subject: [PATCH 0312/1120] fix notimpl git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@332 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index f4d9ecb3f..ccdd41ee4 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -148,7 +148,7 @@ struct filter { }; /* Use this to declare a filter that is not implemented */ -#define EVFILT_NOTIMPL { -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } +#define EVFILT_NOTIMPL { 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } struct kqueue { int kq_sockfd[2]; From 851f42507be94be34ddfd0a26ec75b48aba247e2 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 15 Sep 2010 01:01:25 +0000 Subject: [PATCH 0313/1120] stub evfilt proc git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@333 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/linux/proc.c | 2 +- vendor/libkqueue/src/posix/kevent.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index b3e267aa7..9716aa293 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -230,7 +230,7 @@ evfilt_proc_knote_disable(struct filter *filt, struct knote *kn) return (0); /* STUB */ } -const struct filter evfilt_proc = { +const struct filter evfilt_proc_DEADWOOD = { 0, //XXX-FIXME broken: EVFILT_PROC, evfilt_proc_init, evfilt_proc_destroy, diff --git a/vendor/libkqueue/src/posix/kevent.c b/vendor/libkqueue/src/posix/kevent.c index 4479fa503..8a657c73b 100644 --- a/vendor/libkqueue/src/posix/kevent.c +++ b/vendor/libkqueue/src/posix/kevent.c @@ -19,6 +19,8 @@ #include "sys/event.h" #include "private.h" +const struct filter evfilt_proc = EVFILT_NOTIMPL; + int kevent_wait(struct kqueue *kq, const struct timespec *timeout) { From 048d2545cfd9eb6a9a27a80be6cd236f031ab330 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 15 Sep 2010 02:24:34 +0000 Subject: [PATCH 0314/1120] docfix git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@334 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 6 +++--- vendor/libkqueue/configure | 1 + vendor/libkqueue/rpm.spec.in | 22 +++++++++++++++------- vendor/libkqueue/www/install.html.in | 4 ++++ 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index c1911d089..d5903a67b 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -109,15 +109,15 @@ cscope: tags cscope $(SOURCES) $(HEADERS) rpm: clean $(DISTFILE) - rm -rf rpm *.rpm *.deb + mkdir -p pkg + rm -rf rpm mkdir -p rpm/BUILD rpm/RPMS rpm/SOURCES rpm/SPECS rpm/SRPMS mkdir -p rpm/RPMS/i386 rpm/RPMS/x86_64 cp $(DISTFILE) rpm/SOURCES - rpmbuild -bb rpm.spec + rpmbuild -bb --buildroot=`pwd`/rpm rpm.spec mv ./rpm/RPMS/* . rm -rf rpm rmdir i386 x86_64 # WORKAROUND: These aren't supposed to exist - fakeroot alien --scripts *.rpm deb: clean $(DISTFILE) mkdir pkg && cd pkg ; \ diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index f93ca0d12..5b3cbb798 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -248,6 +248,7 @@ subst_vars() { echo "Creating $outfile" rm -f $outfile sed -e " + s,@@CWD@@,`pwd`,g; s,@@PROGRAM@@,$program,g; s,@@VERSION@@,$version,g; s,@@PREFIX@@,$prefix,g; diff --git a/vendor/libkqueue/rpm.spec.in b/vendor/libkqueue/rpm.spec.in index e46377bdf..b091eb019 100644 --- a/vendor/libkqueue/rpm.spec.in +++ b/vendor/libkqueue/rpm.spec.in @@ -14,8 +14,13 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -%define _topdir ./rpm -%define _rpmfilename %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm +%define _topdir @@CWD@@/rpm +%define _builddir %{_topdir}/BUILD +%define _rpmdir %{_topdir}/RPMS +%define _sourcedir %{_topdir}/SOURCES +%define _specdir %{_topdir}/SPECS +%define _srcrpmdir %{_topdir}/SRPMS +%define _tmppath %{_topdir}/tmp Name: @@PROGRAM@@ Summary: @@PKG_SUMMARY@@ @@ -24,22 +29,23 @@ Release: 1 License: @@LICENSE@@ Vendor: @@AUTHOR@@ Group: System Environment/Libraries -Source0: %{name}-%version.tar.gz -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-build +Source0: %{name}-%version.tar.gz +#BuildRoot: %{_tmppath}/%{name}-%{version}-build %description @@PKG_DESCRIPTION@@ %prep -tar zxvf ../SOURCES/@@PROGRAM@@-@@VERSION@@.tar.gz -mv @@PROGRAM@@-@@VERSION@@/* . +%setup -q -n @@PROGRAM@@-@@VERSION@@ %build ./configure --prefix=/usr make %install -make DESTDIR=%buildroot install +make DESTDIR=$RPM_BUILD_ROOT install +gzip $RPM_BUILD_ROOT/usr/share/man/man2/kqueue.2 +gzip $RPM_BUILD_ROOT/usr/share/man/man2/kevent.2 %clean [ ${RPM_BUILD_ROOT} != "/" ] && rm -rf ${RPM_BUILD_ROOT} @@ -55,6 +61,8 @@ make DESTDIR=%buildroot install /usr/include/kqueue/sys/event.h /usr/lib/libkqueue.so +/usr/lib/libkqueue.so.0 +/usr/lib/libkqueue.so.0.0 /usr/lib/libkqueue.la /usr/lib/libkqueue.a /usr/lib/pkgconfig/libkqueue.pc diff --git a/vendor/libkqueue/www/install.html.in b/vendor/libkqueue/www/install.html.in index 4df1ea430..5a228369d 100644 --- a/vendor/libkqueue/www/install.html.in +++ b/vendor/libkqueue/www/install.html.in @@ -22,4 +22,8 @@ The Solaris port requires Solaris 10 or higher, and uses the GNU compiler and to To build on Nexenta, the gcc-multilib package is required. +

          RHEL 5

          + +Required packages: glibc-headers, gcc + m4_include(footer.m4) From 0135dffa777961faed5ee708e88911b175d5665a Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 15 Sep 2010 02:27:57 +0000 Subject: [PATCH 0315/1120] fix eventfd = no git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@335 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/config.inc | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index 9e462f360..e8a427250 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -48,7 +48,7 @@ post_configure_hook() { finalize target "$target" kevent="src/posix/kevent.c" - evfilt_signal="src/$target/signal.c" + evfilt_signal="src/posix/signal.c" evfilt_proc="src/$target/proc.c" evfilt_socket="src/$target/socket.c" evfilt_timer="src/$target/timer.c" @@ -57,14 +57,14 @@ post_configure_hook() { eventfd="src/posix/eventfd.c" if [ $target = "linux" ] ; then - if [ "$have_sys_signalfd_h" != "yes" ] ; then - evfilt_signal="src/posix/signal.c" - fi - evfilt_signal="src/posix/signal.c" #XXX-FIXME TESTING + # FIXME: not tested + #if [ "$have_sys_signalfd_h" = "yes" ] ; then + # evfilt_signal="src/linux/signal.c" + #fi if [ "$have_sys_timerfd_h" != "yes" ] ; then evfilt_timer="src/posix/timer.c" fi - if [ "$have_sys_eventfd_h" != "yes" ] ; then + if [ "$have_sys_eventfd_h" = "yes" ] ; then eventfd="src/linux/eventfd.c" fi fi @@ -72,7 +72,6 @@ post_configure_hook() { if [ $target = "solaris" ] ; then cflags="$cflags -D__EXTENSIONS__" kevent="src/solaris/kevent.c" - evfilt_signal="src/posix/signal.c" evfilt_timer="src/solaris/timer.c" evfilt_user="src/solaris/user.c" evfilt_proc="" From 5abb32a9442e10b14d570add4690ed316d44cd4a Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 15 Sep 2010 02:37:42 +0000 Subject: [PATCH 0316/1120] fix compilation errors on rhel5 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@336 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/config.inc | 9 ++++++--- vendor/libkqueue/src/linux/socket.c | 11 +++++++++++ vendor/libkqueue/src/posix/timer.c | 2 +- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index e8a427250..c2b6e1837 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -29,6 +29,9 @@ pre_configure_hook() { libdepends=" -L$libdir" if [ $target = "linux" ] ; then + + check_symbol sys/epoll.h EPOLLRDHUP + # Actually a GCC 4.X dependency cflags="$cflags -fvisibility=hidden" @@ -51,7 +54,7 @@ post_configure_hook() { evfilt_signal="src/posix/signal.c" evfilt_proc="src/$target/proc.c" evfilt_socket="src/$target/socket.c" - evfilt_timer="src/$target/timer.c" + evfilt_timer="src/posix/timer.c" evfilt_user="src/posix/user.c" evfilt_vnode="src/$target/vnode.c" eventfd="src/posix/eventfd.c" @@ -61,8 +64,8 @@ post_configure_hook() { #if [ "$have_sys_signalfd_h" = "yes" ] ; then # evfilt_signal="src/linux/signal.c" #fi - if [ "$have_sys_timerfd_h" != "yes" ] ; then - evfilt_timer="src/posix/timer.c" + if [ "$have_sys_timerfd_h" = "yes" ] ; then + evfilt_timer="src/linux/timer.c" fi if [ "$have_sys_eventfd_h" = "yes" ] ; then eventfd="src/linux/eventfd.c" diff --git a/vendor/libkqueue/src/linux/socket.c b/vendor/libkqueue/src/linux/socket.c index 1fff45670..e074230fb 100644 --- a/vendor/libkqueue/src/linux/socket.c +++ b/vendor/libkqueue/src/linux/socket.c @@ -49,7 +49,9 @@ epoll_event_dump(struct epoll_event *evt) snprintf(&buf[0], 128, " { data = %p, events = ", evt->data.ptr); EPEVT_DUMP(EPOLLIN); EPEVT_DUMP(EPOLLOUT); +#if defined(HAVE_EPOLLRDHUP) EPEVT_DUMP(EPOLLRDHUP); +#endif EPEVT_DUMP(EPOLLONESHOT); EPEVT_DUMP(EPOLLET); strcat(&buf[0], "}\n"); @@ -122,8 +124,13 @@ evfilt_socket_copyout(struct filter *filt, kn = knote_lookup(filt, ev->data.fd); if (kn != NULL) { memcpy(dst, &kn->kev, sizeof(*dst)); +#if defined(HAVE_EPOLLRDHUP) if (ev->events & EPOLLRDHUP || ev->events & EPOLLHUP) dst->flags |= EV_EOF; +#else + if (ev->events & EPOLLHUP) + dst->flags |= EV_EOF; +#endif if (ev->events & EPOLLERR) dst->fflags = 1; /* FIXME: Return the actual socket error */ @@ -171,7 +178,11 @@ evfilt_socket_knote_create(struct filter *filt, struct knote *kn) /* Convert the kevent into an epoll_event */ if (kn->kev.filter == EVFILT_READ) +#if defined(HAVE_EPOLLRDHUP) kn->data.events = EPOLLIN | EPOLLRDHUP; +#else + kn->data.events = EPOLLIN; +#endif else kn->data.events = EPOLLOUT; if (kn->kev.flags & EV_ONESHOT || kn->kev.flags & EV_DISPATCH) diff --git a/vendor/libkqueue/src/posix/timer.c b/vendor/libkqueue/src/posix/timer.c index e340ede62..d8e9ba0d1 100644 --- a/vendor/libkqueue/src/posix/timer.c +++ b/vendor/libkqueue/src/posix/timer.c @@ -43,7 +43,7 @@ static int update_timeres(struct filter *filt, struct knote *kn) { struct itimerspec tval; - u_int cur = filt->kf_timeres; + unsigned int cur = filt->kf_timeres; dbg_printf("new timer interval = %d", cur); filt->kf_timeres = cur; From 53dab043c9a2767b6b1f610789b63ea3308ae724 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 15 Sep 2010 02:50:30 +0000 Subject: [PATCH 0317/1120] improved rpm build git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@337 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 19 ++++++++++--------- vendor/libkqueue/rpm.spec.in | 10 +--------- vendor/libkqueue/www/install.html.in | 4 ++++ 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index d5903a67b..de090e5a6 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -108,16 +108,17 @@ edit: tags cscope: tags cscope $(SOURCES) $(HEADERS) -rpm: clean $(DISTFILE) +# Creates an ~/rpmbuild tree +rpmbuild: + mkdir -p $$HOME/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS} + grep _topdir $$HOME/.rpmmacros || \ + echo "%_topdir %(echo $$HOME/rpmbuild)" >> $$HOME/.rpmmacros + +rpm: rpmbuild clean $(DISTFILE) mkdir -p pkg - rm -rf rpm - mkdir -p rpm/BUILD rpm/RPMS rpm/SOURCES rpm/SPECS rpm/SRPMS - mkdir -p rpm/RPMS/i386 rpm/RPMS/x86_64 - cp $(DISTFILE) rpm/SOURCES - rpmbuild -bb --buildroot=`pwd`/rpm rpm.spec - mv ./rpm/RPMS/* . - rm -rf rpm - rmdir i386 x86_64 # WORKAROUND: These aren't supposed to exist + cp $(DISTFILE) $$HOME/rpmbuild/SOURCES + rpmbuild -bb rpm.spec + find $$HOME/rpmbuild -name '$(PROGRAM)-$(VERSION)*.rpm' -exec mv {} ./pkg \; deb: clean $(DISTFILE) mkdir pkg && cd pkg ; \ diff --git a/vendor/libkqueue/rpm.spec.in b/vendor/libkqueue/rpm.spec.in index b091eb019..6f9fa0060 100644 --- a/vendor/libkqueue/rpm.spec.in +++ b/vendor/libkqueue/rpm.spec.in @@ -14,14 +14,6 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -%define _topdir @@CWD@@/rpm -%define _builddir %{_topdir}/BUILD -%define _rpmdir %{_topdir}/RPMS -%define _sourcedir %{_topdir}/SOURCES -%define _specdir %{_topdir}/SPECS -%define _srcrpmdir %{_topdir}/SRPMS -%define _tmppath %{_topdir}/tmp - Name: @@PROGRAM@@ Summary: @@PKG_SUMMARY@@ Version: @@VERSION@@ @@ -30,7 +22,7 @@ License: @@LICENSE@@ Vendor: @@AUTHOR@@ Group: System Environment/Libraries Source0: %{name}-%version.tar.gz -#BuildRoot: %{_tmppath}/%{name}-%{version}-build +BuildRoot: %{_tmppath}/%{name}-%{version}-build %description @@PKG_DESCRIPTION@@ diff --git a/vendor/libkqueue/www/install.html.in b/vendor/libkqueue/www/install.html.in index 5a228369d..4911b5918 100644 --- a/vendor/libkqueue/www/install.html.in +++ b/vendor/libkqueue/www/install.html.in @@ -24,6 +24,10 @@ To build on Nexenta, the gcc-multilib package is required.

          RHEL 5

          +
           Required packages: glibc-headers, gcc
           
          +Recommended packages: rpm-build
          +
          + m4_include(footer.m4) From ee1fe96ff59feb541d5500ef8e51c9017a423750 Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 17 Sep 2010 02:02:31 +0000 Subject: [PATCH 0318/1120] fix posix timer.c git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@338 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 6 +- vendor/libkqueue/src/common/private.h | 10 +- vendor/libkqueue/src/posix/timer.c | 293 +++++++++++++++++--------- 3 files changed, 203 insertions(+), 106 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index de090e5a6..5ffc3544f 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -60,6 +60,9 @@ uninstall: check: $(PROGRAM).a cd test && ./configure && make check +debug-check: clean $(PROGRAM).a + cd test && ./configure && KQUEUE_DEBUG=y make check + $(DISTFILE): $(SOURCES) $(HEADERS) mkdir $(PROGRAM)-$(VERSION) cp Makefile ChangeLog configure config.inc \ @@ -110,7 +113,8 @@ cscope: tags # Creates an ~/rpmbuild tree rpmbuild: - mkdir -p $$HOME/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS} + mkdir -p $$HOME/rpmbuild + cd $$HOME/rpmbuild && mkdir -p BUILD RPMS SOURCES SPECS SRPMS grep _topdir $$HOME/.rpmmacros || \ echo "%_topdir %(echo $$HOME/rpmbuild)" >> $$HOME/.rpmmacros diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index ccdd41ee4..09c640a04 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -104,6 +104,7 @@ struct knote { off_t size; /* Used by vnode */ } vnode; timer_t timerid; + pthread_t tid; /* Used by posix/timer.c */ } data; TAILQ_ENTRY(knote) event_ent; /* Used by filter->kf_event */ RB_ENTRY(knote) kntree_ent; /* Used by filter->kntree */ @@ -139,12 +140,11 @@ struct filter { struct eventfd *kf_efd; /* Used by user.c */ int kf_pfd; /* fd to poll(2) for readiness */ int kf_wfd; /* fd to write when an event occurs */ - unsigned int kf_timeres; /* timer resolution, in miliseconds */ - sigset_t kf_sigmask; - struct evfilt_data *kf_data; /* filter-specific data */ + sigset_t kf_sigmask; + struct evfilt_data *kf_data; /* filter-specific data */ RB_HEAD(knt, knote) kf_knote; - TAILQ_HEAD(, knote) kf_event; /* events that have occurred */ - struct kqueue *kf_kqueue; + TAILQ_HEAD(, knote) kf_event; /* events that have occurred */ + struct kqueue *kf_kqueue; }; /* Use this to declare a filter that is not implemented */ diff --git a/vendor/libkqueue/src/posix/timer.c b/vendor/libkqueue/src/posix/timer.c index d8e9ba0d1..f0f9bc438 100644 --- a/vendor/libkqueue/src/posix/timer.c +++ b/vendor/libkqueue/src/posix/timer.c @@ -30,108 +30,243 @@ #include "sys/event.h" #include "private.h" -static void timer_convert(struct itimerspec *dst, int src); +/* A request to sleep for a certain time */ +struct sleepreq { + int pfd; /* fd to poll for ACKs */ + int wfd; /* fd to wake up when sleep is over */ + uintptr_t ident; /* from kevent */ + intptr_t interval; /* sleep time, in milliseconds */ + struct sleepstat *stat; +}; -struct evfilt_data { - int dummy; +/* Information about a successful sleep operation */ +struct sleepinfo { + uintptr_t ident; /* from kevent */ + uintptr_t counter; /* number of times the timer expired */ }; -/* - * Determine the smallest interval used by active timers. - */ -static int -update_timeres(struct filter *filt, struct knote *kn) +static void * +sleeper_thread(void *arg) { - struct itimerspec tval; - unsigned int cur = filt->kf_timeres; + struct sleepreq sr; + struct sleepinfo si; + struct timespec req, rem; + sigset_t mask; + ssize_t cnt; + bool cts = true; /* Clear To Send */ + char buf[1]; + + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + + /* Copyin the request */ + memcpy(&sr, arg, sizeof(sr)); + free(arg); + + /* Initialize the response */ + si.ident = sr.ident; + si.counter = 0; + + /* Convert milliseconds into seconds+nanoseconds */ + req.tv_sec = sr.interval / 1000; + req.tv_nsec = (sr.interval % 1000) * 1000000; + + /* Block all signals */ + sigfillset(&mask); + (void) pthread_sigmask(SIG_BLOCK, &mask, NULL); - dbg_printf("new timer interval = %d", cur); - filt->kf_timeres = cur; + for (;;) { + + /* Sleep */ + if (nanosleep(&req, &rem) < 0) { + //TODO: handle eintr, spurious wakeups + dbg_perror("nanosleep(2)"); + } + si.counter++; + dbg_printf(" -------- sleep over (CTS=%d)----------", cts); + + /* Test if the previous wakeup has been acknowledged */ + if (!cts) { + cnt = read(sr.wfd, &buf, 1); + if (cnt < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + ; + } else { + dbg_perror("read(2)"); + break; + } + } else if (cnt == 0) { + dbg_perror("short read(2)"); + break; + } else { + cts = true; + } + } + + /* Wake up kevent waiters if they are ready */ + if (cts) { + cnt = write(sr.wfd, &si, sizeof(si)); + if (cnt < 0) { + /* FIXME: handle EAGAIN and EINTR */ + dbg_perror("write(2)"); + } else if (cnt < sizeof(si)) { + dbg_puts("FIXME: handle short write"); + } + cts = false; + si.counter = 0; + } + } + + return (NULL); +} + +static int +_timer_create(struct filter *filt, struct knote *kn) +{ + pthread_attr_t attr; + struct sleepreq *req; + kn->kev.flags |= EV_CLEAR; - /* Convert from miliseconds to seconds+nanoseconds */ - timer_convert(&tval, cur); - //if (timerfd_settime(filt->kf_pfd, 0, &tval, NULL) < 0) { - // dbg_printf("signalfd(2): %s", strerror(errno)); - // return (-1); - // } + req = malloc(sizeof(*req)); + if (req == NULL) { + dbg_perror("malloc"); + return (-1); + } + req->pfd = filt->kf_pfd; + req->wfd = filt->kf_wfd; + req->ident = kn->kev.ident; + req->interval = kn->kev.data; - //FIXME + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + if (pthread_create(&kn->data.tid, &attr, sleeper_thread, req) != 0) { + dbg_perror("pthread_create"); + pthread_attr_destroy(&attr); + free(req); + return (-1); + } + pthread_attr_destroy(&attr); return (0); } -/* Convert milliseconds into seconds+nanoseconds */ -static void -timer_convert(struct itimerspec *dst, int src) +static int +_timer_delete(struct knote *kn) { - struct timespec now; - time_t x, y; - - /* Set the interval */ - /* XXX-FIXME: this is probably horribly wrong :) */ - x = src / 1000; - y = (src % 1000) * 1000000; - dst->it_interval.tv_sec = x; - dst->it_interval.tv_nsec = y; - - /* Set the initial expiration */ - clock_gettime(CLOCK_MONOTONIC, &now); - dst->it_value.tv_sec = now.tv_sec + x; - dst->it_value.tv_nsec = now.tv_nsec + 7; + if (pthread_cancel(kn->data.tid) != 0) { + /* Race condition: sleeper_thread exits before it is cancelled */ + if (errno == ENOENT) + return (0); + dbg_perror("pthread_cancel(3)"); + return (-1); + } + return (0); } int evfilt_timer_init(struct filter *filt) { - return filter_socketpair(filt); + int fd[2]; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0) { + dbg_perror("socketpair(3)"); + return (-1); + } + if (fcntl(fd[0], F_SETFL, O_NONBLOCK) < 0 + || fcntl(fd[1], F_SETFL, O_NONBLOCK) < 0) { + dbg_perror("fcntl(2)"); + close(fd[0]); + close(fd[1]); + return (-1); + } + + filt->kf_wfd = fd[0]; + filt->kf_pfd = fd[1]; + + return (0); } void evfilt_timer_destroy(struct filter *filt) { - close (filt->kf_pfd); + (void) close(filt->kf_wfd); + (void) close(filt->kf_pfd); } -#if DEADWOOD int -evfilt_timer_copyin(struct filter *filt, - struct knote *dst, const struct kevent *src) +evfilt_timer_copyout(struct filter *filt, + struct kevent *dst, + int nevents) { - if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) { - memcpy(&dst->kev, src, sizeof(*src)); - dst->kev.flags |= EV_CLEAR; - } - if (src->flags & EV_ADD || src->flags & EV_ENABLE) { - if (update_timeres(filt) < 0) - return (-1); + struct sleepinfo si; + ssize_t cnt; + struct knote *kn; + + /* Read the ident */ + cnt = read(filt->kf_pfd, &si, sizeof(si)); + if (cnt < 0) { + /* FIXME: handle EAGAIN and EINTR */ + dbg_printf("read(2): %s", strerror(errno)); + return (-1); + } else if (cnt < sizeof(si)) { + dbg_puts("error: short read"); + return (-1); } - if (src->flags & EV_DISABLE || src->flags & EV_DELETE) { - // TODO + + /* Acknowlege receipt */ + cnt = write(filt->kf_pfd, ".", 1); + if (cnt < 0) { + /* FIXME: handle EAGAIN and EINTR */ + dbg_printf("write(2): %s", strerror(errno)); + return (-1); + } else if (cnt < 1) { + dbg_puts("error: short write"); + return (-1); } - return (0); -} -#endif + kn = knote_lookup(filt, si.ident); + + /* Race condition: timer events remain queued even after + the knote is deleted. Ignore these events */ + if (kn == NULL) + return (0); + + dbg_printf("knote=%p", kn); + memcpy(dst, &kn->kev, sizeof(*dst)); + + dst->data = si.counter; + + if (kn->kev.flags & EV_DISPATCH) { + KNOTE_DISABLE(kn); + _timer_delete(kn); + } else if (kn->kev.flags & EV_ONESHOT) { + _timer_delete(kn); + knote_free(filt, kn); + } + return (1); +} int evfilt_timer_knote_create(struct filter *filt, struct knote *kn) { - kn->kev.flags |= EV_CLEAR; - return update_timeres(filt, kn); + return _timer_create(filt, kn); } int evfilt_timer_knote_modify(struct filter *filt, struct knote *kn, - const struct kevent *kev) + const struct kevent *kev) { - return (0); /* STUB */ + return (-1); /* STUB */ } int evfilt_timer_knote_delete(struct filter *filt, struct knote *kn) { - return (-1); /* STUB */ + if (kn->kev.flags & EV_DISABLE) + return (0); + + dbg_printf("deleting timer # %d", (int) kn->kev.ident); + return _timer_delete(kn); } int @@ -146,47 +281,6 @@ evfilt_timer_knote_disable(struct filter *filt, struct knote *kn) return evfilt_timer_knote_delete(filt, kn); } -int -evfilt_timer_copyout(struct filter *filt, - struct kevent *dst, - int nevents) -{ - //struct knote *kn; - uint64_t buf; - int i; - ssize_t n; - - n = read(filt->kf_pfd, &buf, sizeof(buf)); - if (n < 0 || n < sizeof(buf)) { - dbg_puts("invalid read from timerfd"); - return (-1); - } - n = 1; // KLUDGE - - //KNOTELIST_FOREACH(kn, &filt->knl) { - - for (i = 0, nevents = 0; i < n; i++) { -#if FIXME - /* Want to have multiple timers, so maybe multiple timerfds... */ - kn = knote_lookup(filt, sig[i].ssi_signo); - if (kn == NULL) - continue; - - /* TODO: dst->data should be the number of times the signal occurred */ - dst->ident = sig[i].ssi_signo; - dst->filter = EVFILT_SIGNAL; - dst->udata = kn->kev.udata; - dst->flags = 0; - dst->fflags = 0; - dst->data = 1; - dst++; - nevents++; -#endif - } - - return (nevents); -} - const struct filter evfilt_timer = { EVFILT_TIMER, evfilt_timer_init, @@ -197,5 +291,4 @@ const struct filter evfilt_timer = { evfilt_timer_knote_delete, evfilt_timer_knote_enable, evfilt_timer_knote_disable, - }; From 392766fd6f9a840ecc550427c92100c5e857b90c Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 18 Sep 2010 02:40:44 +0000 Subject: [PATCH 0319/1120] update manpage git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@339 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/kqueue.2 | 101 ++------------------------------------ 1 file changed, 4 insertions(+), 97 deletions(-) diff --git a/vendor/libkqueue/kqueue.2 b/vendor/libkqueue/kqueue.2 index 6a80875bd..22cca6ccb 100644 --- a/vendor/libkqueue/kqueue.2 +++ b/vendor/libkqueue/kqueue.2 @@ -1,4 +1,5 @@ .\" $FreeBSD: Revision: 197243$ +.\" Copyright (c) 2010 Mark Heily .\" Copyright (c) 2000 Jonathan Lemon .\" All rights reserved. .\" @@ -25,15 +26,13 @@ .\" .\" $FreeBSD$ .\" -.Dd September 15, 2009 +.Dd September 17, 2010 .Dt KQUEUE 2 .Os .Sh NAME .Nm kqueue , .Nm kevent .Nd kernel event notification mechanism -.Sh LIBRARY -.Lb libc .Sh SYNOPSIS .In sys/types.h .In sys/event.h @@ -319,26 +318,6 @@ Note that this filter is not supported for vnodes or BPF devices. .Pp For sockets, the low water mark and socket error handling is identical to the EVFILT_READ case. -.It EVFILT_AIO -The sigevent portion of the AIO request is filled in, with -.Va sigev_notify_kqueue -containing the descriptor of the kqueue that the event should -be attached to, -.Va sigev_value -containing the udata value, and -.Va sigev_notify -set to SIGEV_KEVENT. -When the -.Fn aio_* -system call is made, the event will be registered -with the specified kqueue, and the -.Va ident -argument set to the -.Fa struct aiocb -returned by the -.Fn aio_* -system call. -The filter returns under the same conditions as aio_error. .It EVFILT_VNODE Takes a file descriptor as the identifier and the events to watch for in .Va fflags , @@ -360,47 +339,6 @@ The file referenced by the descriptor had its attributes changed. The link count on the file changed. .It NOTE_RENAME The file referenced by the descriptor was renamed. -.It NOTE_REVOKE -Access to the file was revoked via -.Xr revoke 2 -or the underlying file system was unmounted. -.El -.Pp -On return, -.Va fflags -contains the events which triggered the filter. -.It EVFILT_PROC -Takes the process ID to monitor as the identifier and the events to watch for -in -.Va fflags , -and returns when the process performs one or more of the requested events. -If a process can normally see another process, it can attach an event to it. -The events to monitor are: -.Bl -tag -width XXNOTE_TRACKERR -.It NOTE_EXIT -The process has exited. -The exit status will be stored in -.Va data . -.It NOTE_FORK -The process has called -.Fn fork . -.It NOTE_EXEC -The process has executed a new process via -.Xr execve 2 -or similar call. -.It NOTE_TRACK -Follow a process across -.Fn fork -calls. -The parent process will return with NOTE_TRACK set in the -.Va fflags -field, while the child process will return with NOTE_CHILD set in -.Va fflags -and the parent PID in -.Va data . -.It NOTE_TRACKERR -This flag is returned if the system was unable to attach an event to -the child process, usually due to resource limitations. .El .Pp On return, @@ -409,16 +347,14 @@ contains the events which triggered the filter. .It EVFILT_SIGNAL Takes the signal number to monitor as the identifier and returns when the given signal is delivered to the process. -This coexists with the +This overrides the .Fn signal and .Fn sigaction -facilities, and has a lower precedence. +facilities, and has a higher precedence. The filter will record all attempts to deliver a signal to a process, even if the signal has been marked as SIG_IGN. -Event notification happens after normal -signal delivery processing. .Va data returns the number of times the signal has occurred since the last call to .Fn kevent . @@ -439,23 +375,6 @@ There is a system wide limit on the number of timers which is controlled by the .Va kern.kq_calloutmax sysctl. -.It Dv EVFILT_NETDEV -Takes a descriptor to a network interface as the identifier, and the events to watch for in -.Va fflags . -It returns, when one or more of the requested events occur on the descriptor. -The events to monitor are: -.Bl -tag -width XXNOTE_LINKDOWN -.It Dv NOTE_LINKUP -The link is up. -.It Dv NOTE_LINKDOWN -The link is down. -.It Dv NOTE_LINKINV -The link state is invalid. -.El -.Pp -On return, -.Va fflags -contains the events which triggered the filter. .It Dv EVFILT_USER Establishes a user event identified by .Va ident @@ -594,15 +513,3 @@ The .Fn kqueue system and this manual page were written by .An Jonathan Lemon Aq jlemon@FreeBSD.org . -.Sh BUGS -The -.Dv EVFILT_NETDEV -filter is currently only implemented for devices that use the -.Xr miibus 4 -driver for LINKUP and LINKDOWN operations. -Therefore, it will not work with many non-ethernet devices. -.Pp -The -.Fa timeout -value is limited to 24 hours; longer timeouts will be silently -reinterpreted as 24 hours. From 795014316bf71eee89d0c4bfa2731baf080de14f Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 18 Sep 2010 18:47:24 +0000 Subject: [PATCH 0320/1120] rel 1.0 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@340 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 13 +++++++++++++ vendor/libkqueue/TODO | 5 ----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index d0c38070e..3e6296895 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,3 +1,16 @@ +2010-09-18 v1.0 r340 +------------------------------------------------------------------------ + + * Support older Linux kernels that do not have the EPOLLRDHUP flag. + + * Add a portable implementation of the EVFILT_TIMER filter. + + * Add Solaris to the list of supported platforms. + + * Fixed the 'make rpm' target to work on CentOS 5. + + * Modified the manpage to remove unimplemented features. + 2010-08-05 v0.9.3 r309 ------------------------------------------------------------------------ diff --git a/vendor/libkqueue/TODO b/vendor/libkqueue/TODO index 70da6c2f1..1a3ecaea2 100644 --- a/vendor/libkqueue/TODO +++ b/vendor/libkqueue/TODO @@ -8,14 +8,9 @@ * Refactor kevent_copyin() to remove the goto statements. - * Ensure that kevent_copyout() on Solaris does not rely on having - the filter lock. Linux has already been converted. - * Fix the crasher w/ corruption in test/vnode.c * Add the kevent64() syscall as implemented on MacOS X. This guarantees that 64-bit values can be used in the 'udata' field on 32-bit platforms. - * Include or convert u_int to uint32_t in event.h - * Check other filters for the EV_DISPATCH bug that was fixed in r252. From 56b6846fe401d1de15a1330cdf6756ee030fd48b Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 18 Sep 2010 18:47:54 +0000 Subject: [PATCH 0321/1120] bump version git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@341 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 2 +- vendor/libkqueue/config.inc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 3e6296895..47db60a49 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,4 +1,4 @@ -2010-09-18 v1.0 r340 +2010-09-18 v1.0 r341 ------------------------------------------------------------------------ * Support older Linux kernels that do not have the EPOLLRDHUP flag. diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index c2b6e1837..7afdc8050 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -1,5 +1,5 @@ program="libkqueue" -version="0.9.3" +version="1.0" abi_major="0" abi_minor="0" abi_version="$abi_major.$abi_minor" From 9c3b40c464c50540394de6e5d9aa59fc9e92f432 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 18 Sep 2010 18:52:15 +0000 Subject: [PATCH 0322/1120] clean all .o files from tree git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@343 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 2 +- vendor/libkqueue/Makefile | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 47db60a49..dbc2405b8 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,4 +1,4 @@ -2010-09-18 v1.0 r341 +2010-09-18 v1.0 r342 ------------------------------------------------------------------------ * Support older Linux kernels that do not have the EPOLLRDHUP flag. diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 5ffc3544f..e18a7724c 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -78,11 +78,12 @@ dist: rm -f $(DISTFILE) make $(DISTFILE) -dist-upload: dist - scp $(PROGRAM)-$(VERSION).tar.gz $(DIST) +dist-upload: $(DISTFILE) + scp $(DISTFILE) $(DIST) clean: - rm -f tags *.a $(OBJS) *.so *.so.* + rm -f tags *.a *.so *.so.* + find src -name '*.o' -exec rm {} \; rm -rf pkg cd test && make clean || true From c03cf596abad93152a904c9fc69f5fba1e772eee Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 18 Sep 2010 18:52:29 +0000 Subject: [PATCH 0323/1120] fix cl git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@344 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index dbc2405b8..f46fafad8 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,4 +1,4 @@ -2010-09-18 v1.0 r342 +2010-09-18 v1.0 r344 ------------------------------------------------------------------------ * Support older Linux kernels that do not have the EPOLLRDHUP flag. From 2aaeb8a2eef49480e95f56d1416376af95236bfb Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 22 Sep 2010 00:53:14 +0000 Subject: [PATCH 0324/1120] bump to alpha git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@346 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/config.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index 7afdc8050..7c86753d0 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -1,5 +1,5 @@ program="libkqueue" -version="1.0" +version="1.0a" abi_major="0" abi_minor="0" abi_version="$abi_major.$abi_minor" From a3d6a72ffd0147bba8ce16456da4ae4bb03a78a0 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 22 Sep 2010 01:18:18 +0000 Subject: [PATCH 0325/1120] * Add a counter that increments on each each kevent() call. When printing debug information within kevent(), display the value of the counter. This will be helpful when debugging a multithreaded program that may have multiple kevent() calls executing in parallel. (Credit: Julien Blache) git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@347 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 8 ++++++++ vendor/libkqueue/src/common/kevent.c | 29 +++++++++++++++++++++------- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index f46fafad8..4e82ae47f 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,3 +1,11 @@ +HEAD +------------------------------------------------------------------------ + + * Add a counter that increments on each each kevent() call. When printing + debug information within kevent(), display the value of the counter. + This will be helpful when debugging a multithreaded program that may have + multiple kevent() calls executing in parallel. (Credit: Julien Blache) + 2010-09-18 v1.0 r344 ------------------------------------------------------------------------ diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 883df2366..297e304c9 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -237,23 +237,35 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout) { + static unsigned int _kevent_counter = 0; struct kqueue *kq; int rv, n, nret; + unsigned int myid; + + if (KQUEUE_DEBUG) { + myid = __sync_add_and_fetch(&_kevent_counter, 1); + dbg_printf("--- kevent %u ---", myid); + } else { + myid = 0; + } nret = 0; kq = kqueue_get(kqfd); if (kq == NULL) { errno = ENOENT; - return (-1); + nret = -1; + goto out2; } rv = kqueue_validate(kq); if (rv < 0) { - return (-1); + nret = -1; + goto out2; } else if (rv == 0) { errno = EBADF; - return (-1); + nret = -1; + goto out2; } /* @@ -263,7 +275,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, kqueue_lock(kq); rv = kevent_copyin(kq, changelist, nchanges, eventlist, nevents); kqueue_unlock(kq); - dbg_printf("changelist: rv=%d", rv); + dbg_printf("(%u) changelist: rv=%d", myid, rv); if (rv < 0) goto errout; if (rv > 0) { @@ -284,7 +296,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, /* Wait for one or more events. */ n = kevent_wait(kq, timeout); if (n < 0) { - dbg_puts("kevent_wait failed"); + dbg_printf("(%u) kevent_wait failed", myid); goto errout; } if (n == 0) @@ -297,9 +309,9 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, } if (KQUEUE_DEBUG) { - dbg_printf("returning %d events", nret); + dbg_printf("(%u) returning %d events", myid, nret); for (n = 0; n < nret; n++) { - dbg_printf("eventlist[%d] = %s", n, kevent_dump(&eventlist[n])); + dbg_printf("(%u) eventlist[%d] = %s", myid, n, kevent_dump(&eventlist[n])); } } @@ -310,5 +322,8 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, out: kqueue_put(kq); + +out2: + dbg_printf("--- END kevent %u ret %d ---", myid, nret); return (nret); } From 93aa87ad55a28b7b4810cdd6225e854a9e18551b Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 24 Dec 2010 17:34:51 +0000 Subject: [PATCH 0326/1120] create -devel RPM git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@348 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure | 1 + vendor/libkqueue/rpm.spec.in | 39 +++++++++++++++++++++++------------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index 5b3cbb798..ee004d8b4 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -257,6 +257,7 @@ subst_vars() { s,@@MANDIR@@,$mandir,g; s,@@LIBDEPENDS@@,$libdepends,g; s,@@PKG_SUMMARY@@,$pkg_summary,g; + s,@@RPM_DATE@@,`date +'%a %b %d %Y'`,g; s,@@PKG_DESCRIPTION@@,$pkg_description,g; s,@@LICENSE@@,$license,g; s,@@AUTHOR@@,$author,g; diff --git a/vendor/libkqueue/rpm.spec.in b/vendor/libkqueue/rpm.spec.in index 6f9fa0060..cfd006a30 100644 --- a/vendor/libkqueue/rpm.spec.in +++ b/vendor/libkqueue/rpm.spec.in @@ -1,5 +1,5 @@ # -# Copyright (c) 2009 Mark Heily +# Copyright (c) 2009-2010 Mark Heily # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above @@ -22,11 +22,20 @@ License: @@LICENSE@@ Vendor: @@AUTHOR@@ Group: System Environment/Libraries Source0: %{name}-%version.tar.gz -BuildRoot: %{_tmppath}/%{name}-%{version}-build %description @@PKG_DESCRIPTION@@ +%package devel +Summary: Header files, libraries and development documentation for %{name} +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel +This package contains the header files, static libraries and development +documentation for %{name}. If you like to develop programs using %{name}, +you will need to install %{name}-devel. + %prep %setup -q -n @@PROGRAM@@-@@VERSION@@ @@ -35,30 +44,32 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-build make %install -make DESTDIR=$RPM_BUILD_ROOT install +make DESTDIR=%{buildroot} install gzip $RPM_BUILD_ROOT/usr/share/man/man2/kqueue.2 gzip $RPM_BUILD_ROOT/usr/share/man/man2/kevent.2 %clean -[ ${RPM_BUILD_ROOT} != "/" ] && rm -rf ${RPM_BUILD_ROOT} - -%post -/sbin/ldconfig +[ %{buildroot} != "/" ] && rm -rf %{buildroot} -%postun -/sbin/ldconfig +%post -p /sbin/ldconfig +%postun -p /sbin/ldconfig %files %defattr(-,root,root) +/usr/lib/*.so +/usr/lib/*.so.* + +%files devel +%defattr(-,root,root) + /usr/include/kqueue/sys/event.h -/usr/lib/libkqueue.so -/usr/lib/libkqueue.so.0 -/usr/lib/libkqueue.so.0.0 -/usr/lib/libkqueue.la -/usr/lib/libkqueue.a /usr/lib/pkgconfig/libkqueue.pc /usr/share/man/man2/kqueue.2.gz /usr/share/man/man2/kevent.2.gz +%exclude /usr/lib/*.la +%exclude /usr/lib/*.a %changelog +* @@RPM_DATE@@ Mark Heily - @@VERSION@@-1 +- automatically generated spec file From 72a86737774558ca02c3889e2d532d1d5a7946ef Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 25 Dec 2010 14:41:32 +0000 Subject: [PATCH 0327/1120] rpm policy conformance git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@349 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/rpm.spec.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/rpm.spec.in b/vendor/libkqueue/rpm.spec.in index cfd006a30..41cf09f36 100644 --- a/vendor/libkqueue/rpm.spec.in +++ b/vendor/libkqueue/rpm.spec.in @@ -57,12 +57,12 @@ gzip $RPM_BUILD_ROOT/usr/share/man/man2/kevent.2 %files %defattr(-,root,root) -/usr/lib/*.so /usr/lib/*.so.* %files devel %defattr(-,root,root) +/usr/lib/*.so /usr/include/kqueue/sys/event.h /usr/lib/pkgconfig/libkqueue.pc /usr/share/man/man2/kqueue.2.gz From f98ac3744bd5a4cc0091325b7319b3ad0cce744e Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 25 Dec 2010 14:54:09 +0000 Subject: [PATCH 0328/1120] add BuildRequires git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@350 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/rpm.spec.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/rpm.spec.in b/vendor/libkqueue/rpm.spec.in index 41cf09f36..d3727117d 100644 --- a/vendor/libkqueue/rpm.spec.in +++ b/vendor/libkqueue/rpm.spec.in @@ -23,6 +23,8 @@ Vendor: @@AUTHOR@@ Group: System Environment/Libraries Source0: %{name}-%version.tar.gz +BuildRequires: make, glibc-devel + %description @@PKG_DESCRIPTION@@ From 19c559e6e037c7a78ae032f6b3e962d72296e55e Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 25 Dec 2010 18:09:58 +0000 Subject: [PATCH 0329/1120] use _libdir to get lib64 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@351 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/rpm.spec.in | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/rpm.spec.in b/vendor/libkqueue/rpm.spec.in index d3727117d..dc8baba34 100644 --- a/vendor/libkqueue/rpm.spec.in +++ b/vendor/libkqueue/rpm.spec.in @@ -42,7 +42,7 @@ you will need to install %{name}-devel. %setup -q -n @@PROGRAM@@-@@VERSION@@ %build -./configure --prefix=/usr +./configure --prefix=/usr --libdir=%{_libdir} make %install @@ -59,14 +59,14 @@ gzip $RPM_BUILD_ROOT/usr/share/man/man2/kevent.2 %files %defattr(-,root,root) -/usr/lib/*.so.* +%{_libdir}/*.so.* %files devel %defattr(-,root,root) -/usr/lib/*.so +%{_libdir}/*.so /usr/include/kqueue/sys/event.h -/usr/lib/pkgconfig/libkqueue.pc +%{_libdir}/pkgconfig/libkqueue.pc /usr/share/man/man2/kqueue.2.gz /usr/share/man/man2/kevent.2.gz %exclude /usr/lib/*.la From 3a4327d3b48fb65cfe9b8fe3bee18954d78400f3 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 25 Dec 2010 18:14:56 +0000 Subject: [PATCH 0330/1120] rpm fixes git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@352 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/rpm.spec.in | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/rpm.spec.in b/vendor/libkqueue/rpm.spec.in index dc8baba34..42e4bfb37 100644 --- a/vendor/libkqueue/rpm.spec.in +++ b/vendor/libkqueue/rpm.spec.in @@ -47,8 +47,8 @@ make %install make DESTDIR=%{buildroot} install -gzip $RPM_BUILD_ROOT/usr/share/man/man2/kqueue.2 -gzip $RPM_BUILD_ROOT/usr/share/man/man2/kevent.2 +gzip -f $RPM_BUILD_ROOT/usr/share/man/man2/kqueue.2 +gzip -f $RPM_BUILD_ROOT/usr/share/man/man2/kevent.2 %clean [ %{buildroot} != "/" ] && rm -rf %{buildroot} @@ -69,8 +69,8 @@ gzip $RPM_BUILD_ROOT/usr/share/man/man2/kevent.2 %{_libdir}/pkgconfig/libkqueue.pc /usr/share/man/man2/kqueue.2.gz /usr/share/man/man2/kevent.2.gz -%exclude /usr/lib/*.la -%exclude /usr/lib/*.a +%exclude %{_libdir}/*.la +%exclude %{_libdir}/*.a %changelog * @@RPM_DATE@@ Mark Heily - @@VERSION@@-1 From 6c55526ebe6723eb3aa3625cab545498a45d97d5 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 26 Dec 2010 04:15:36 +0000 Subject: [PATCH 0331/1120] remove "make" from build deps git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@353 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/rpm.spec.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/rpm.spec.in b/vendor/libkqueue/rpm.spec.in index 42e4bfb37..d889ee4a9 100644 --- a/vendor/libkqueue/rpm.spec.in +++ b/vendor/libkqueue/rpm.spec.in @@ -23,7 +23,7 @@ Vendor: @@AUTHOR@@ Group: System Environment/Libraries Source0: %{name}-%version.tar.gz -BuildRequires: make, glibc-devel +BuildRequires: glibc-devel %description @@PKG_DESCRIPTION@@ From ffc5f6ac7e1b2ab0ce6e518a8add26099076921a Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 8 Jan 2011 21:49:29 +0000 Subject: [PATCH 0332/1120] Improvements for the Solaris port. Fix for an improper use of TSD on Solaris as reported by Joakim Johansson git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@354 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 15 ++------- vendor/libkqueue/config.inc | 4 ++- vendor/libkqueue/src/common/kevent.c | 7 ++-- vendor/libkqueue/src/common/kqueue.c | 32 ++++--------------- vendor/libkqueue/src/common/private.h | 46 ++++++++++++++++++--------- vendor/libkqueue/src/posix/kevent.c | 7 ++-- vendor/libkqueue/src/posix/signal.c | 2 +- vendor/libkqueue/src/solaris/kevent.c | 21 ++++++++---- vendor/libkqueue/src/solaris/kqueue.c | 40 +++++++++++++++++++++++ vendor/libkqueue/src/solaris/socket.c | 2 +- vendor/libkqueue/src/solaris/timer.c | 2 +- vendor/libkqueue/test/config.inc | 15 +++++++-- vendor/libkqueue/test/vnode.c | 6 ++++ 13 files changed, 128 insertions(+), 71 deletions(-) create mode 100644 vendor/libkqueue/src/solaris/kqueue.c diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index e18a7724c..4c85d1e14 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -149,16 +149,7 @@ diff: (cd ../.. ; $(DIFF) branches/stable trunk | less) ; \ fi -# Copy to/from the host to the Solaris guest VM -# -solaris-push: - ssh -p 2222 localhost 'rm -rf /export/home/mheily/libkqueue' - cd .. ; scp -rq -P 2222 trunk localhost:/export/home/mheily/libkqueue - -solaris-test: solaris-push - ssh -p 2222 localhost 'cd /export/home/mheily/libkqueue && /usr/sfw/bin/gmake distclean && ./configure && /usr/sfw/bin/gmake clean all check' - -solaris-pull: - scp -rq -P 2222 localhost:/export/home/mheily/libkqueue/\* . -# +# Used for testing on a Solaris guest VM # +solaris-test: + make dist && scp -P 2222 libkqueue-1.0a.tar.gz localhost:/tmp && ssh -p 2222 localhost ". .profile ; cd /tmp ; rm -rf libkqueue-$(VERSION) ; gtar zxvf libkqueue-$(VERSION).tar.gz && cd libkqueue-$(VERSION) && ./configure && make && make check" diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index 7c86753d0..968e3dd6e 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -50,6 +50,7 @@ pre_configure_hook() { post_configure_hook() { finalize target "$target" + kqueue="" kevent="src/posix/kevent.c" evfilt_signal="src/posix/signal.c" evfilt_proc="src/$target/proc.c" @@ -74,6 +75,7 @@ post_configure_hook() { if [ $target = "solaris" ] ; then cflags="$cflags -D__EXTENSIONS__" + kqueue="src/solaris/kqueue.c" kevent="src/solaris/kevent.c" evfilt_timer="src/solaris/timer.c" evfilt_user="src/solaris/user.c" @@ -91,6 +93,6 @@ post_configure_hook() { evfilt_vnode="" fi - sources="$sources $kevent $eventfd $evfilt_signal $evfilt_proc + sources="$sources $kqueue $kevent $eventfd $evfilt_signal $evfilt_proc $evfilt_socket $evfilt_timer $evfilt_user $evfilt_vnode" } diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 297e304c9..9dece8254 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -238,12 +238,13 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, const struct timespec *timeout) { static unsigned int _kevent_counter = 0; + struct event_buf evbuf; struct kqueue *kq; int rv, n, nret; unsigned int myid; if (KQUEUE_DEBUG) { - myid = __sync_add_and_fetch(&_kevent_counter, 1); + myid = atomic_inc(&_kevent_counter); dbg_printf("--- kevent %u ---", myid); } else { myid = 0; @@ -294,7 +295,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, for (nret = 0; nret == 0;) { /* Wait for one or more events. */ - n = kevent_wait(kq, timeout); + n = kevent_wait(&evbuf, kq, timeout); if (n < 0) { dbg_printf("(%u) kevent_wait failed", myid); goto errout; @@ -304,7 +305,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, /* Copy the events to the caller */ kqueue_lock(kq); - nret = kevent_copyout(kq, n, eventlist, nevents); + nret = kevent_copyout(kq, n, eventlist, nevents, &evbuf); kqueue_unlock(kq); } diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 9b64d4710..38ad2dd58 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -51,13 +51,11 @@ kqueue_free(struct kqueue *kq) { RB_REMOVE(kqt, &kqtree, kq); filter_unregister_all(kq); -#if defined(__sun__) - port_event_t *pe = (port_event_t *) pthread_getspecific(kq->kq_port_event); - if (kq->kq_port > 0) - close(kq->kq_port); - free(pe); +#ifdef kqueue_free_hook + kqueue_free_hook(kq); #endif + free(kq); } @@ -145,26 +143,6 @@ kqueue_get(int kq) return (ent); } -/* Non-portable kqueue initalization code. */ -static int -kqueue_sys_init(struct kqueue *kq) -{ -#if defined(__sun__) - port_event_t *pe; - - if ((kq->kq_port = port_create()) < 0) { - dbg_perror("port_create(2)"); - return (-1); - } - if (pthread_key_create(&kq->kq_port_event, NULL) != 0) - abort(); - if ((pe = calloc(1, sizeof(*pe))) == NULL) - abort(); - if (pthread_setspecific(kq->kq_port_event, pe) != 0) - abort(); -#endif - return (0); -} int __attribute__((visibility("default"))) kqueue(void) @@ -187,8 +165,10 @@ kqueue(void) if (socketpair(AF_UNIX, SOCK_STREAM, 0, kq->kq_sockfd) < 0) goto errout_unlocked; - if (kqueue_sys_init(kq) < 0) +#ifdef kqueue_init_hook + if (kqueue_init_hook(kq) < 0) goto errout_unlocked; +#endif pthread_rwlock_wrlock(&kqtree_mtx); if (kqueue_gc() < 0) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 09c640a04..a297681ed 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -17,13 +17,9 @@ #ifndef _KQUEUE_PRIVATE_H #define _KQUEUE_PRIVATE_H -#if defined (__SVR4) && defined (__sun) -# define SOLARIS -# include - /* Used to set portev_events for PORT_SOURCE_USER */ -# define X_PORT_SOURCE_SIGNAL 101 -# define X_PORT_SOURCE_USER 102 -#endif +struct kqueue; +struct kevent; +struct evfilt_data; #include #include @@ -40,8 +36,8 @@ */ #ifdef __sun # include -# define atomic_inc atomic_inc_32 -# define atomic_dec atomic_dec_32 +# define atomic_inc atomic_inc_32_nv +# define atomic_dec atomic_dec_32_nv #else # define atomic_inc(p) __sync_add_and_fetch((p), 1) # define atomic_dec(p) __sync_sub_and_fetch((p), 1) @@ -80,10 +76,30 @@ extern int KQUEUE_DEBUG; # define reset_errno() ; #endif +#if defined (__SVR4) && defined (__sun) +# define SOLARIS +# include + /* Used to set portev_events for PORT_SOURCE_USER */ +# define X_PORT_SOURCE_SIGNAL 101 +# define X_PORT_SOURCE_USER 102 + +# define kqueue_free_hook solaris_kqueue_free +void solaris_kqueue_free(struct kqueue *); + +# define kqueue_init_hook solaris_kqueue_init +int solaris_kqueue_init(struct kqueue *); + +struct event_buf { + port_event_t pe; +}; + +#else + /* The event_buf structure is only needed by Solaris */ + struct event_buf { + int unused; + }; +#endif -struct kqueue; -struct kevent; -struct evfilt_data; /* * Flags used by knote->flags @@ -158,7 +174,7 @@ struct kqueue { pthread_mutex_t kq_mtx; #ifdef __sun__ int kq_port; /* see: port_create(2) */ - pthread_key_t kq_port_event; + port_event_t kq_port_event; #endif volatile uint32_t kq_ref; RB_ENTRY(kqueue) entries; @@ -192,8 +208,8 @@ const char *filter_name(short); int filter_lower(struct filter *); int filter_raise(struct filter *); -int kevent_wait(struct kqueue *, const struct timespec *); -int kevent_copyout(struct kqueue *, int, struct kevent *, int); +int kevent_wait(struct event_buf *, struct kqueue *, const struct timespec *); +int kevent_copyout(struct kqueue *, int, struct kevent *, int, struct event_buf *); void kevent_free(struct kqueue *); const char *kevent_dump(const struct kevent *); diff --git a/vendor/libkqueue/src/posix/kevent.c b/vendor/libkqueue/src/posix/kevent.c index 8a657c73b..1820c6b91 100644 --- a/vendor/libkqueue/src/posix/kevent.c +++ b/vendor/libkqueue/src/posix/kevent.c @@ -22,7 +22,10 @@ const struct filter evfilt_proc = EVFILT_NOTIMPL; int -kevent_wait(struct kqueue *kq, const struct timespec *timeout) +kevent_wait( + struct event_buf *evbuf, + struct kqueue *kq, + const struct timespec *timeout) { int n; @@ -43,7 +46,7 @@ kevent_wait(struct kqueue *kq, const struct timespec *timeout) int kevent_copyout(struct kqueue *kq, int nready, - struct kevent *eventlist, int nevents) + struct kevent *eventlist, int nevents, struct event_buf *evbuf) { struct filter *filt; int i, rv, nret; diff --git a/vendor/libkqueue/src/posix/signal.c b/vendor/libkqueue/src/posix/signal.c index b62a40d28..3d9ce7b86 100644 --- a/vendor/libkqueue/src/posix/signal.c +++ b/vendor/libkqueue/src/posix/signal.c @@ -171,7 +171,7 @@ evfilt_signal_copyout(struct filter *filt, ssize_t n; #if defined(__sun__) - port_event_t *pe = (port_event_t *) pthread_getspecific(filt->kf_kqueue->kq_port_event); + port_event_t *pe = &filt->kf_kqueue->kq_port_event; s = (struct sentry *) pe->portev_user; sig = s - &sigtbl[0]; diff --git a/vendor/libkqueue/src/solaris/kevent.c b/vendor/libkqueue/src/solaris/kevent.c index 811bfa2c8..f6df6b293 100644 --- a/vendor/libkqueue/src/solaris/kevent.c +++ b/vendor/libkqueue/src/solaris/kevent.c @@ -81,16 +81,18 @@ port_event_dump(port_event_t *evt) } int -kevent_wait(struct kqueue *kq, const struct timespec *timeout) +kevent_wait( + struct event_buf *evbuf, + struct kqueue *kq, + const struct timespec *timeout) { - port_event_t *pe = (port_event_t *) pthread_getspecific(kq->kq_port_event); - + port_event_t pe; int rv; uint_t nget = 1; reset_errno(); dbg_printf("waiting for events (timeout=%p)", timeout); - rv = port_getn(kq->kq_port, pe, 1, &nget, (struct timespec *) timeout); + rv = port_getn(kq->kq_port, &pe, 1, &nget, (struct timespec *) timeout); dbg_printf("rv=%d errno=%d (%s) nget=%d", rv, errno, strerror(errno), nget); if (rv < 0) { @@ -106,18 +108,23 @@ kevent_wait(struct kqueue *kq, const struct timespec *timeout) return (-1); } + memcpy(&evbuf->pe, &pe, sizeof(pe)); + return (nget); } int kevent_copyout(struct kqueue *kq, int nready, - struct kevent *eventlist, int nevents) + struct kevent *eventlist, int nevents, + struct event_buf *evbuf) { - port_event_t *pe = (port_event_t *) pthread_getspecific(kq->kq_port_event); + port_event_t *pe = &evbuf->pe; struct filter *filt; int rv; - dbg_printf("%s", port_event_dump(pe)); + memcpy(&kq->kq_port_event, pe, sizeof(*pe)); + + dbg_printf("kq_port_event=%s", port_event_dump(pe)); switch (pe->portev_source) { case PORT_SOURCE_FD: filt = pe->portev_user; diff --git a/vendor/libkqueue/src/solaris/kqueue.c b/vendor/libkqueue/src/solaris/kqueue.c new file mode 100644 index 000000000..8bd772d1a --- /dev/null +++ b/vendor/libkqueue/src/solaris/kqueue.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include "sys/event.h" +#include "private.h" + +void +solaris_kqueue_free(struct kqueue *kq) +{ + if (kq->kq_port > 0) + close(kq->kq_port); +} + +int +solaris_kqueue_init(struct kqueue *kq) +{ + if ((kq->kq_port = port_create()) < 0) { + dbg_perror("port_create(2)"); + return (-1); + } + return (0); +} diff --git a/vendor/libkqueue/src/solaris/socket.c b/vendor/libkqueue/src/solaris/socket.c index 53647d49a..d0bf5994c 100644 --- a/vendor/libkqueue/src/solaris/socket.c +++ b/vendor/libkqueue/src/solaris/socket.c @@ -120,7 +120,7 @@ evfilt_socket_copyout(struct filter *filt, struct kevent *dst, int nevents) { - port_event_t *pe = (port_event_t *) pthread_getspecific(filt->kf_kqueue->kq_port_event); + port_event_t *pe = &filt->kf_kqueue->kq_port_event; struct knote *kn; kn = knote_lookup(filt, pe->portev_object); diff --git a/vendor/libkqueue/src/solaris/timer.c b/vendor/libkqueue/src/solaris/timer.c index be4c009d2..2ebe26206 100644 --- a/vendor/libkqueue/src/solaris/timer.c +++ b/vendor/libkqueue/src/solaris/timer.c @@ -123,7 +123,7 @@ evfilt_timer_copyout(struct filter *filt, struct kevent *dst, int nevents) { - port_event_t *pe = (port_event_t *) pthread_getspecific(filt->kf_kqueue->kq_port_event); + port_event_t *pe = &filt->kf_kqueue->kq_port_event; long buf; timer_t timerid; struct knote *kn; diff --git a/vendor/libkqueue/test/config.inc b/vendor/libkqueue/test/config.inc index ab31fd372..4906ab355 100755 --- a/vendor/libkqueue/test/config.inc +++ b/vendor/libkqueue/test/config.inc @@ -17,8 +17,6 @@ pre_configure_hook() { } - test "$target" = "linux" && cflags="$cflags -rdynamic" - test "$target" = "solaris" && ldadd="$ldadd -lsocket -lnsl -m64" check_symbol $sys_event_h EV_DISPATCH check_symbol $sys_event_h EV_RECEIPT @@ -26,4 +24,17 @@ pre_configure_hook() { check_symbol $sys_event_h EVFILT_TIMER check_symbol $sys_event_h EVFILT_USER && \ sources="$sources user.c" + + if [ "$target" = "solaris" ] + then + ldadd="$ldadd -lsocket -lnsl -m64" + + check_symbol port.h PORT_SOURCE_FILE + fi + + if [ "$target" = "linux" ] + then + cflags="$cflags -rdynamic" + fi + } diff --git a/vendor/libkqueue/test/vnode.c b/vendor/libkqueue/test/vnode.c index 2893ab45b..f61c63e5b 100644 --- a/vendor/libkqueue/test/vnode.c +++ b/vendor/libkqueue/test/vnode.c @@ -242,6 +242,12 @@ test_kevent_vnode_dispatch(void) void test_evfilt_vnode(int _kqfd) { + +#if (defined(__sun) && !defined(HAVE_PORT_SOURCE_FILE)) + puts("**NOTE** EVFILT_VNODE is not supported on this version of Solaris"); + return; +#endif + snprintf(testfile, sizeof(testfile), "/tmp/kqueue-test%d.tmp", testing_make_uid()); From 070f323cebafd390d2737fd8fc3739f724e0dd37 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 12 Jan 2011 02:10:38 +0000 Subject: [PATCH 0333/1120] Add thread ID to debugging output [submitted by Joakim Johansson] git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@355 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/private.h | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index a297681ed..e0699749b 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -51,20 +51,31 @@ struct evfilt_data; extern int KQUEUE_DEBUG; +#ifdef __linux__ +# define _GNU_SOURCE +# include +# include +# include +extern long int syscall (long int __sysno, ...); +# define THREAD_ID ((pid_t) syscall(__NR_gettid)) +#else +# define THREAD_ID (pthread_self()) +#endif + #define dbg_puts(str) do { \ if (KQUEUE_DEBUG) \ - fprintf(stderr, "KQ: %s(): %s\n", __func__,str); \ + fprintf(stderr, "KQ [%d]: %s(): %s\n", THREAD_ID, __func__,str); \ } while (0) #define dbg_printf(fmt,...) do { \ if (KQUEUE_DEBUG) \ - fprintf(stderr, "KQ: %s(): "fmt"\n", __func__,__VA_ARGS__); \ + fprintf(stderr, "KQ [%d]: %s(): "fmt"\n", THREAD_ID, __func__,__VA_ARGS__); \ } while (0) #define dbg_perror(str) do { \ if (KQUEUE_DEBUG) \ - fprintf(stderr, "KQ: %s(): %s: %s (errno=%d)\n", \ - __func__, str, strerror(errno), errno); \ + fprintf(stderr, "KQ: [%d] %s(): %s: %s (errno=%d)\n", \ + THREAD_ID, __func__, str, strerror(errno), errno); \ } while (0) # define reset_errno() do { errno = 0; } while (0) From 2dbe33c8de1c2cee560767b4b914015be940d6a4 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 12 Jan 2011 04:46:40 +0000 Subject: [PATCH 0334/1120] Fix for a race condition accessing kq->kq_port_event git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@356 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kevent.c | 5 +- vendor/libkqueue/src/common/private.h | 9 ++-- vendor/libkqueue/src/posix/kevent.c | 3 +- vendor/libkqueue/src/posix/signal.c | 5 +- vendor/libkqueue/src/solaris/kevent.c | 73 +++++++++++++++++++++------ vendor/libkqueue/src/solaris/kqueue.c | 1 + vendor/libkqueue/src/solaris/socket.c | 11 ++-- vendor/libkqueue/src/solaris/timer.c | 6 ++- 8 files changed, 80 insertions(+), 33 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 9dece8254..d7ba5ec8f 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -238,7 +238,6 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, const struct timespec *timeout) { static unsigned int _kevent_counter = 0; - struct event_buf evbuf; struct kqueue *kq; int rv, n, nret; unsigned int myid; @@ -295,7 +294,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, for (nret = 0; nret == 0;) { /* Wait for one or more events. */ - n = kevent_wait(&evbuf, kq, timeout); + n = kevent_wait(kq, timeout); if (n < 0) { dbg_printf("(%u) kevent_wait failed", myid); goto errout; @@ -305,7 +304,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, /* Copy the events to the caller */ kqueue_lock(kq); - nret = kevent_copyout(kq, n, eventlist, nevents, &evbuf); + nret = kevent_copyout(kq, n, eventlist, nevents); kqueue_unlock(kq); } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index e0699749b..887ade481 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -100,8 +100,11 @@ void solaris_kqueue_free(struct kqueue *); # define kqueue_init_hook solaris_kqueue_init int solaris_kqueue_init(struct kqueue *); +void port_event_dequeue(port_event_t *, struct kqueue *); + struct event_buf { port_event_t pe; + TAILQ_ENTRY(event_buf) entries; }; #else @@ -185,7 +188,7 @@ struct kqueue { pthread_mutex_t kq_mtx; #ifdef __sun__ int kq_port; /* see: port_create(2) */ - port_event_t kq_port_event; + TAILQ_HEAD(event_buf_listhead,event_buf) kq_events; #endif volatile uint32_t kq_ref; RB_ENTRY(kqueue) entries; @@ -219,8 +222,8 @@ const char *filter_name(short); int filter_lower(struct filter *); int filter_raise(struct filter *); -int kevent_wait(struct event_buf *, struct kqueue *, const struct timespec *); -int kevent_copyout(struct kqueue *, int, struct kevent *, int, struct event_buf *); +int kevent_wait(struct kqueue *, const struct timespec *); +int kevent_copyout(struct kqueue *, int, struct kevent *, int); void kevent_free(struct kqueue *); const char *kevent_dump(const struct kevent *); diff --git a/vendor/libkqueue/src/posix/kevent.c b/vendor/libkqueue/src/posix/kevent.c index 1820c6b91..f72024708 100644 --- a/vendor/libkqueue/src/posix/kevent.c +++ b/vendor/libkqueue/src/posix/kevent.c @@ -23,7 +23,6 @@ const struct filter evfilt_proc = EVFILT_NOTIMPL; int kevent_wait( - struct event_buf *evbuf, struct kqueue *kq, const struct timespec *timeout) { @@ -46,7 +45,7 @@ kevent_wait( int kevent_copyout(struct kqueue *kq, int nready, - struct kevent *eventlist, int nevents, struct event_buf *evbuf) + struct kevent *eventlist, int nevents) { struct filter *filt; int i, rv, nret; diff --git a/vendor/libkqueue/src/posix/signal.c b/vendor/libkqueue/src/posix/signal.c index 3d9ce7b86..f55c12adc 100644 --- a/vendor/libkqueue/src/posix/signal.c +++ b/vendor/libkqueue/src/posix/signal.c @@ -171,9 +171,10 @@ evfilt_signal_copyout(struct filter *filt, ssize_t n; #if defined(__sun__) - port_event_t *pe = &filt->kf_kqueue->kq_port_event; + port_event_t pe; - s = (struct sentry *) pe->portev_user; + port_event_dequeue(&pe, filt->kf_kqueue); + s = (struct sentry *) pe.portev_user; sig = s - &sigtbl[0]; n = 0; //FIXME: Workaround #else diff --git a/vendor/libkqueue/src/solaris/kevent.c b/vendor/libkqueue/src/solaris/kevent.c index f6df6b293..c84bee76c 100644 --- a/vendor/libkqueue/src/solaris/kevent.c +++ b/vendor/libkqueue/src/solaris/kevent.c @@ -24,6 +24,44 @@ const struct filter evfilt_vnode = EVFILT_NOTIMPL; const struct filter evfilt_proc = EVFILT_NOTIMPL; +static char * port_event_dump(port_event_t *evt); + + +/* The caller must hold the kq_mtx */ +void +port_event_dequeue(port_event_t *pe, struct kqueue *kq) +{ + struct event_buf *ebp; + + ebp = TAILQ_FIRST(&kq->kq_events); + if (ebp == NULL) + abort(); /* Should never happen */ + memcpy(pe, &ebp->pe, sizeof(*pe)); + TAILQ_REMOVE(&kq->kq_events, ebp, entries); + free(ebp); +} + +/* The caller must not hold the kq_mtx */ +void +port_event_enqueue(struct kqueue *kq, port_event_t *pe) +{ + struct event_buf *ebp; + + ebp = calloc(1, sizeof(*ebp)); + if (ebp == NULL) { + dbg_perror("lost an event! malloc(2)"); + abort(); /* FIXME: use a freelist to prevent this*/ + } + memcpy(&ebp->pe, pe, sizeof(*pe)); + kqueue_lock(kq); + /* XXX-want to insert at the tail but this causes list corruption */ + /* Since multiple threads are consuming events from the list, + there is no guarantee that ordering will be preserved. + */ + TAILQ_INSERT_HEAD(&kq->kq_events, ebp, entries); + kqueue_unlock(kq); +} + /* Dump a poll(2) events bitmask */ static char * poll_events_dump(short events) @@ -56,8 +94,10 @@ port_event_dump(port_event_t *evt) { static char __thread buf[512]; - if (evt == NULL) - return "(null)"; + if (evt == NULL) { + snprintf(&buf[0], sizeof(buf), "NULL ?!?!\n"); + goto out; + } #define PE_DUMP(attrib) \ if (evt->portev_source == attrib) \ @@ -75,16 +115,14 @@ port_event_dump(port_event_t *evt) PE_DUMP(PORT_SOURCE_USER); PE_DUMP(PORT_SOURCE_ALERT); strcat(&buf[0], ") }\n"); +#undef PE_DUMP +out: return (&buf[0]); -#undef PE_DUMP } int -kevent_wait( - struct event_buf *evbuf, - struct kqueue *kq, - const struct timespec *timeout) +kevent_wait(struct kqueue *kq, const struct timespec *timeout) { port_event_t pe; int rv; @@ -108,26 +146,29 @@ kevent_wait( return (-1); } - memcpy(&evbuf->pe, &pe, sizeof(pe)); + port_event_enqueue(kq, &pe); return (nget); } int kevent_copyout(struct kqueue *kq, int nready, - struct kevent *eventlist, int nevents, - struct event_buf *evbuf) + struct kevent *eventlist, int nevents) { - port_event_t *pe = &evbuf->pe; + struct event_buf *ebp; struct filter *filt; int rv; - memcpy(&kq->kq_port_event, pe, sizeof(*pe)); + ebp = TAILQ_FIRST(&kq->kq_events); + if (ebp == NULL) { + dbg_puts("kq_events was empty"); + return (-1); + } - dbg_printf("kq_port_event=%s", port_event_dump(pe)); - switch (pe->portev_source) { + dbg_printf("event=%s", port_event_dump(&ebp->pe)); + switch (ebp->pe.portev_source) { case PORT_SOURCE_FD: - filt = pe->portev_user; + filt = ebp->pe.portev_user; rv = filt->kf_copyout(filt, eventlist, nevents); break; @@ -137,7 +178,7 @@ kevent_copyout(struct kqueue *kq, int nready, break; case PORT_SOURCE_USER: - switch (pe->portev_events) { + switch (ebp->pe.portev_events) { case X_PORT_SOURCE_SIGNAL: filter_lookup(&filt, kq, EVFILT_SIGNAL); rv = filt->kf_copyout(filt, eventlist, nevents); diff --git a/vendor/libkqueue/src/solaris/kqueue.c b/vendor/libkqueue/src/solaris/kqueue.c index 8bd772d1a..df6a1a2da 100644 --- a/vendor/libkqueue/src/solaris/kqueue.c +++ b/vendor/libkqueue/src/solaris/kqueue.c @@ -36,5 +36,6 @@ solaris_kqueue_init(struct kqueue *kq) dbg_perror("port_create(2)"); return (-1); } + TAILQ_INIT(&kq->kq_events); return (0); } diff --git a/vendor/libkqueue/src/solaris/socket.c b/vendor/libkqueue/src/solaris/socket.c index d0bf5994c..e7b68bfaf 100644 --- a/vendor/libkqueue/src/solaris/socket.c +++ b/vendor/libkqueue/src/solaris/socket.c @@ -120,20 +120,21 @@ evfilt_socket_copyout(struct filter *filt, struct kevent *dst, int nevents) { - port_event_t *pe = &filt->kf_kqueue->kq_port_event; + port_event_t pe; struct knote *kn; - kn = knote_lookup(filt, pe->portev_object); + port_event_dequeue(&pe, filt->kf_kqueue); + kn = knote_lookup(filt, pe.portev_object); if (kn == NULL) return (-1); memcpy(dst, &kn->kev, sizeof(*dst)); - if (pe->portev_events == 8) //XXX-FIXME Should be POLLHUP) + if (pe.portev_events == 8) //XXX-FIXME Should be POLLHUP) dst->flags |= EV_EOF; - else if (pe->portev_events & POLLERR) + else if (pe.portev_events & POLLERR) dst->fflags = 1; /* FIXME: Return the actual socket error */ - if (pe->portev_events & POLLIN) { + if (pe.portev_events & POLLIN) { if (kn->flags & KNFL_PASSIVE_SOCKET) { /* On return, data contains the length of the socket backlog. This is not available under Solaris (?). diff --git a/vendor/libkqueue/src/solaris/timer.c b/vendor/libkqueue/src/solaris/timer.c index 2ebe26206..c3a265757 100644 --- a/vendor/libkqueue/src/solaris/timer.c +++ b/vendor/libkqueue/src/solaris/timer.c @@ -123,13 +123,15 @@ evfilt_timer_copyout(struct filter *filt, struct kevent *dst, int nevents) { - port_event_t *pe = &filt->kf_kqueue->kq_port_event; + port_event_t pe; long buf; timer_t timerid; struct knote *kn; + port_event_dequeue(&pe, filt->kf_kqueue); + /* XXX-FIXME: danger here -- there has to be a better way */ - buf = (long) pe->portev_user; + buf = (long) pe.portev_user; timerid = (timer_t) buf; /* ^^^^^^^^^ */ kn = knote_lookup(filt, timerid); From edfa481f3158007bd853b7f0624d9e3c5b5705d4 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 12 Jan 2011 11:59:08 +0000 Subject: [PATCH 0335/1120] Prevent a knote from being enqueued() multiple times git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@357 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/knote.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index c16bf06bc..dc0978dd9 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -109,8 +109,9 @@ knote_lookup_data(struct filter *filt, intptr_t data) void knote_enqueue(struct filter *filt, struct knote *kn) { - /* XXX-FIXME: check if the knote is already on the eventlist */ - TAILQ_INSERT_TAIL(&filt->kf_event, kn, event_ent); + /* Prevent a knote from being enqueued() multiple times */ + if (kn->event_ent.tqe_next == NULL && kn->event_ent.tqe_prev == NULL) + TAILQ_INSERT_TAIL(&filt->kf_event, kn, event_ent); } struct knote * From 9a30ea2f682c23f4725210018c0b2efe8f539ceb Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 13 Jan 2011 01:19:06 +0000 Subject: [PATCH 0336/1120] windows portability tweak git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@358 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kevent.c | 1 - vendor/libkqueue/src/common/kqueue.c | 1 - vendor/libkqueue/src/common/private.h | 1 + vendor/libkqueue/src/common/queue.h | 621 ++++++++++++++++++++++++++ 4 files changed, 622 insertions(+), 2 deletions(-) create mode 100644 vendor/libkqueue/src/common/queue.h diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index d7ba5ec8f..20c0a69a8 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 38ad2dd58..72ac72f22 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 887ade481..7e88e5b41 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -30,6 +30,7 @@ struct evfilt_data; #include "../../include/sys/event.h" #include "tree.h" +#include "queue.h" /* GCC atomic builtins. * See: http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html diff --git a/vendor/libkqueue/src/common/queue.h b/vendor/libkqueue/src/common/queue.h new file mode 100644 index 000000000..c79c08a51 --- /dev/null +++ b/vendor/libkqueue/src/common/queue.h @@ -0,0 +1,621 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + * $FreeBSD: src/sys/sys/queue.h,v 1.72.2.1.2.1 2009/10/25 01:10:29 kensmith Exp $ + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +/* + * This file defines four types of data structures: singly-linked lists, + * singly-linked tail queues, lists and tail queues. + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * For details on the use of these macros, see the queue(3) manual page. + * + * + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - - - + + * _LAST - - + + + * _FOREACH + + + + + * _FOREACH_SAFE + + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_SAFE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT - - + + + * _REMOVE_AFTER + - + - + * _REMOVE_HEAD + - + - + * _REMOVE + + + + + * + */ +#ifdef QUEUE_MACRO_DEBUG +/* Store the last 2 places the queue element or head was altered */ +struct qm_trace { + char * lastfile; + int lastline; + char * prevfile; + int prevline; +}; + +#define TRACEBUF struct qm_trace trace; +#define TRASHIT(x) do {(x) = (void *)-1;} while (0) + +#define QMD_TRACE_HEAD(head) do { \ + (head)->trace.prevline = (head)->trace.lastline; \ + (head)->trace.prevfile = (head)->trace.lastfile; \ + (head)->trace.lastline = __LINE__; \ + (head)->trace.lastfile = __FILE__; \ +} while (0) + +#define QMD_TRACE_ELEM(elem) do { \ + (elem)->trace.prevline = (elem)->trace.lastline; \ + (elem)->trace.prevfile = (elem)->trace.lastfile; \ + (elem)->trace.lastline = __LINE__; \ + (elem)->trace.lastfile = __FILE__; \ +} while (0) + +#else +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define TRACEBUF +#define TRASHIT(x) +#endif /* QUEUE_MACRO_DEBUG */ + +/* + * Singly-linked List declarations. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) + +#define SLIST_FIRST(head) ((head)->slh_first) + +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST((head)); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != NULL; \ + (varp) = &SLIST_NEXT((var), field)) + +#define SLIST_INIT(head) do { \ + SLIST_FIRST((head)) = NULL; \ +} while (0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ + SLIST_NEXT((slistelm), field) = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ + SLIST_FIRST((head)) = (elm); \ +} while (0) + +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if (SLIST_FIRST((head)) == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = SLIST_FIRST((head)); \ + while (SLIST_NEXT(curelm, field) != (elm)) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_REMOVE_AFTER(curelm, field); \ + } \ + TRASHIT((elm)->field.sle_next); \ +} while (0) + +#define SLIST_REMOVE_AFTER(elm, field) do { \ + SLIST_NEXT(elm, field) = \ + SLIST_NEXT(SLIST_NEXT(elm, field), field); \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ +} while (0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first;/* first element */ \ + struct type **stqh_last;/* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (0) + +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) + +#define STAILQ_FIRST(head) ((head)->stqh_first) + +#define STAILQ_FOREACH(var, head, field) \ + for((var) = STAILQ_FIRST((head)); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_INIT(head) do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((tqelm), field) = (elm); \ +} while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ +} while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? \ + NULL : \ + ((struct type *)(void *) \ + ((char *)((head)->stqh_last) - __offsetof(struct type, field)))) + +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = STAILQ_FIRST((head)); \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + STAILQ_REMOVE_AFTER(head, curelm, field); \ + } \ + TRASHIT((elm)->field.stqe_next); \ +} while (0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ + if ((STAILQ_NEXT(elm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_SWAP(head1, head2, type) do { \ + struct type *swap_first = STAILQ_FIRST(head1); \ + struct type **swap_last = (head1)->stqh_last; \ + STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_FIRST(head2) = swap_first; \ + (head2)->stqh_last = swap_last; \ + if (STAILQ_EMPTY(head1)) \ + (head1)->stqh_last = &STAILQ_FIRST(head1); \ + if (STAILQ_EMPTY(head2)) \ + (head2)->stqh_last = &STAILQ_FIRST(head2); \ +} while (0) + + +/* + * List declarations. + * NOTE: LIST_HEAD conflicts with a Linux macro. + */ +#define FIXME_LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ + +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_LIST_CHECK_HEAD(head, field) do { \ + if (LIST_FIRST((head)) != NULL && \ + LIST_FIRST((head))->field.le_prev != \ + &LIST_FIRST((head))) \ + panic("Bad list head %p first->prev != head", (head)); \ +} while (0) + +#define QMD_LIST_CHECK_NEXT(elm, field) do { \ + if (LIST_NEXT((elm), field) != NULL && \ + LIST_NEXT((elm), field)->field.le_prev != \ + &((elm)->field.le_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +#define QMD_LIST_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.le_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_LIST_CHECK_HEAD(head, field) +#define QMD_LIST_CHECK_NEXT(elm, field) +#define QMD_LIST_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_FIRST(head) ((head)->lh_first) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_INIT(head) do { \ + LIST_FIRST((head)) = NULL; \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + QMD_LIST_CHECK_NEXT(listelm, field); \ + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_LIST_CHECK_PREV(listelm, field); \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + QMD_LIST_CHECK_HEAD((head), field); \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ +} while (0) + +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_REMOVE(elm, field) do { \ + QMD_LIST_CHECK_NEXT(elm, field); \ + QMD_LIST_CHECK_PREV(elm, field); \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ + TRASHIT((elm)->field.le_next); \ + TRASHIT((elm)->field.le_prev); \ +} while (0) + +#define LIST_SWAP(head1, head2, type, field) do { \ + struct type *swap_tmp = LIST_FIRST((head1)); \ + LIST_FIRST((head1)) = LIST_FIRST((head2)); \ + LIST_FIRST((head2)) = swap_tmp; \ + if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ + if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ +} while (0) + +/* + * Tail queue declarations. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +/* + * Tail queue functions. + */ +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ + if (!TAILQ_EMPTY(head) && \ + TAILQ_FIRST((head))->field.tqe_prev != \ + &TAILQ_FIRST((head))) \ + panic("Bad tailq head %p first->prev != head", (head)); \ +} while (0) + +#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ + if (*(head)->tqh_last != NULL) \ + panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ +} while (0) + +#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ + if (TAILQ_NEXT((elm), field) != NULL && \ + TAILQ_NEXT((elm), field)->field.tqe_prev != \ + &((elm)->field.tqe_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.tqe_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_TAILQ_CHECK_HEAD(head, field) +#define QMD_TAILQ_CHECK_TAIL(head, headname) +#define QMD_TAILQ_CHECK_NEXT(elm, field) +#define QMD_TAILQ_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + QMD_TRACE_HEAD(head1); \ + QMD_TRACE_HEAD(head2); \ + } \ +} while (0) + +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_FIRST(head) ((head)->tqh_first) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST((head)); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_INIT(head) do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + QMD_TAILQ_CHECK_NEXT(listelm, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_TAILQ_CHECK_PREV(listelm, field); \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + QMD_TAILQ_CHECK_HEAD(head, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + QMD_TAILQ_CHECK_TAIL(head, field); \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TAILQ_REMOVE(head, elm, field) do { \ + QMD_TAILQ_CHECK_NEXT(elm, field); \ + QMD_TAILQ_CHECK_PREV(elm, field); \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT((elm)->field.tqe_next); \ + TRASHIT((elm)->field.tqe_prev); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_SWAP(head1, head2, type, field) do { \ + struct type *swap_first = (head1)->tqh_first; \ + struct type **swap_last = (head1)->tqh_last; \ + (head1)->tqh_first = (head2)->tqh_first; \ + (head1)->tqh_last = (head2)->tqh_last; \ + (head2)->tqh_first = swap_first; \ + (head2)->tqh_last = swap_last; \ + if ((swap_first = (head1)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head1)->tqh_first; \ + else \ + (head1)->tqh_last = &(head1)->tqh_first; \ + if ((swap_first = (head2)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head2)->tqh_first; \ + else \ + (head2)->tqh_last = &(head2)->tqh_first; \ +} while (0) + +#endif /* !_SYS_QUEUE_H_ */ From 081e97125624e614c19ee2ab85bb9c9766e81f2c Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 13 Jan 2011 01:27:30 +0000 Subject: [PATCH 0337/1120] more portability git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@359 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/filter.c | 1 - vendor/libkqueue/src/common/kevent.c | 1 - vendor/libkqueue/src/common/knote.c | 1 - vendor/libkqueue/src/common/private.h | 7 +++++++ vendor/libkqueue/src/windows/platform.h | 23 +++++++++++++++++++++++ 5 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 vendor/libkqueue/src/windows/platform.h diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index bd233d27e..71837ec0a 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include "private.h" diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 20c0a69a8..6123fffff 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index dc0978dd9..1c4456053 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -16,7 +16,6 @@ #include #include -#include #include #include #include diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 7e88e5b41..ffba91c03 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -17,6 +17,13 @@ #ifndef _KQUEUE_PRIVATE_H #define _KQUEUE_PRIVATE_H +#if defined(_WIN32) +# include "../windows/platform.h" +#else +/* TODO: move to posix/platform.h */ +#include +#endif + struct kqueue; struct kevent; struct evfilt_data; diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h new file mode 100644 index 000000000..d4a3c8fbb --- /dev/null +++ b/vendor/libkqueue/src/windows/platform.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _KQUEUE_PLATFORM_H +#define _KQUEUE_PLATFORM_H + +#include +#include + +#endif /* ! _KQUEUE_PLATFORM_H */ From 9c96fd39bb2ead963a4df7579668a20c4b13cd5a Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 13 Jan 2011 01:32:18 +0000 Subject: [PATCH 0338/1120] more portability git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@360 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/filter.c | 1 - vendor/libkqueue/src/common/kevent.c | 2 -- vendor/libkqueue/src/common/knote.c | 2 -- vendor/libkqueue/src/common/kqueue.c | 3 --- vendor/libkqueue/src/common/private.h | 3 ++- 5 files changed, 2 insertions(+), 9 deletions(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index 71837ec0a..d8ab143cb 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -20,7 +20,6 @@ #include #include #include -#include #include "private.h" diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 6123fffff..5420145a0 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -23,10 +23,8 @@ #include #include #include -#include #include #include -#include #include "sys/event.h" #include "private.h" diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 1c4456053..3ce5b41e2 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -16,9 +16,7 @@ #include #include -#include #include -#include #include "private.h" diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 72ac72f22..e1b3d1915 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -17,14 +17,11 @@ #include #include #include -#include #include #include #include -#include #include #include -#include #include "sys/event.h" #include "private.h" diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index ffba91c03..0b473bfa1 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -21,7 +21,9 @@ # include "../windows/platform.h" #else /* TODO: move to posix/platform.h */ +#include #include +#include #endif struct kqueue; @@ -29,7 +31,6 @@ struct kevent; struct evfilt_data; #include -#include #include #include #include From eb765a2af3f46e4286d28289110f9d027059b1c1 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 13 Jan 2011 01:40:00 +0000 Subject: [PATCH 0339/1120] more win32 porting git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@361 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kevent.c | 1 - vendor/libkqueue/src/common/kqueue.c | 8 +++++--- vendor/libkqueue/src/common/private.h | 5 +++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 5420145a0..039fb6009 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -26,7 +26,6 @@ #include #include -#include "sys/event.h" #include "private.h" static char * diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index e1b3d1915..82e1dafef 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -16,20 +16,19 @@ #include #include -#include #include #include #include #include #include -#include "sys/event.h" #include "private.h" #ifndef NDEBUG int KQUEUE_DEBUG = 0; #endif + static RB_HEAD(kqt, kqueue) kqtree = RB_INITIALIZER(&kqtree); static pthread_rwlock_t kqtree_mtx = PTHREAD_RWLOCK_INITIALIZER; @@ -81,10 +80,12 @@ kqueue_gc(void) return (0); } - int kqueue_validate(struct kqueue *kq) { +#if defined(_WIN32) + return (0); /* FIXME */ +#else int rv; char buf[1]; struct pollfd pfd; @@ -111,6 +112,7 @@ kqueue_validate(struct kqueue *kq) } return (0); +#endif /* WIN32 */ } void diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 0b473bfa1..04c4c22c4 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -21,7 +21,9 @@ # include "../windows/platform.h" #else /* TODO: move to posix/platform.h */ +#include #include +#include #include #include #endif @@ -31,7 +33,6 @@ struct kevent; struct evfilt_data; #include -#include #include #include #include @@ -238,8 +239,8 @@ const char *kevent_dump(const struct kevent *); struct kqueue * kqueue_get(int); void kqueue_put(struct kqueue *); +int kqueue_validate(struct kqueue *); #define kqueue_lock(kq) pthread_mutex_lock(&(kq)->kq_mtx) #define kqueue_unlock(kq) pthread_mutex_unlock(&(kq)->kq_mtx) -int kqueue_validate(struct kqueue *); #endif /* ! _KQUEUE_PRIVATE_H */ From ae70706f31c58a9b747d68ce2d5e7203076fbc96 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 13 Jan 2011 01:48:10 +0000 Subject: [PATCH 0340/1120] mark sys/select.h nonportable git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@362 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/include/sys/event.h | 1 - vendor/libkqueue/src/common/private.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index 796e8eef8..5cc71d366 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -35,7 +35,6 @@ #ifdef __KERNEL__ #define intptr_t long #else -#include #include #include #define LIBKQUEUE 1 diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 04c4c22c4..ff4cc9292 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #endif @@ -35,7 +36,6 @@ struct evfilt_data; #include #include #include -#include #include "../../include/sys/event.h" #include "tree.h" From 303ea588334831b4b81e4dcac068e4003a88d67d Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 13 Jan 2011 02:32:15 +0000 Subject: [PATCH 0341/1120] move mutex init into a constructor function git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@363 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/include/sys/event.h | 1 + vendor/libkqueue/src/common/kqueue.c | 9 ++++++- vendor/libkqueue/src/common/private.h | 1 - vendor/libkqueue/src/windows/kqueue.c | 36 +++++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 vendor/libkqueue/src/windows/kqueue.c diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index 5cc71d366..1dcf0945b 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -38,6 +38,7 @@ #include #include #define LIBKQUEUE 1 +int _libkqueue_init(void) __attribute__ ((constructor)); #endif struct timespec; diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 82e1dafef..f19cd6d4d 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -30,7 +30,14 @@ int KQUEUE_DEBUG = 0; static RB_HEAD(kqt, kqueue) kqtree = RB_INITIALIZER(&kqtree); -static pthread_rwlock_t kqtree_mtx = PTHREAD_RWLOCK_INITIALIZER; +static pthread_rwlock_t kqtree_mtx; + +int __attribute__ ((constructor)) +_libkqueue_init(void) +{ + pthread_rwlock_init(&kqtree_mtx, NULL); + return (0); +} static int kqueue_cmp(struct kqueue *a, struct kqueue *b) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index ff4cc9292..ac60b8daa 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -149,7 +149,6 @@ struct knote { TAILQ_ENTRY(knote) event_ent; /* Used by filter->kf_event */ RB_ENTRY(knote) kntree_ent; /* Used by filter->kntree */ }; -LIST_HEAD(knotelist, knote); #define KNOTE_ENABLE(ent) do { \ (ent)->kev.flags &= ~EV_DISABLE; \ diff --git a/vendor/libkqueue/src/windows/kqueue.c b/vendor/libkqueue/src/windows/kqueue.c new file mode 100644 index 000000000..ac8371246 --- /dev/null +++ b/vendor/libkqueue/src/windows/kqueue.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "private.h" + +BOOL WINAPI DllMain( + HINSTANCE self, + DWORD reason, + LPVOID unused) +{ + switch (reason) { + case DLL_PROCESS_ATTACH: + /* TODO: initialize mutexes */ + break; + + case DLL_PROCESS_DETACH: + /* TODO: cleanup */ + break; + } + + return (TRUE); +} + From a63263284a84dd0a76637bbc0867d73b32a60775 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 13 Jan 2011 03:09:55 +0000 Subject: [PATCH 0342/1120] more win portability git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@364 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kevent.c | 2 +- vendor/libkqueue/src/common/kqueue.c | 4 ++-- vendor/libkqueue/src/common/private.h | 6 ++++++ vendor/libkqueue/src/common/queue.h | 3 +++ vendor/libkqueue/src/windows/platform.h | 27 +++++++++++++++++++++++++ 5 files changed, 39 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 039fb6009..4e62654f9 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -227,7 +227,7 @@ kevent_copyin(struct kqueue *kq, const struct kevent *src, int nchanges, return (nret); } -int __attribute__((visibility("default"))) +int VISIBLE kevent(int kqfd, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index f19cd6d4d..f0ec32b29 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -32,7 +32,7 @@ int KQUEUE_DEBUG = 0; static RB_HEAD(kqt, kqueue) kqtree = RB_INITIALIZER(&kqtree); static pthread_rwlock_t kqtree_mtx; -int __attribute__ ((constructor)) +CONSTRUCTOR _libkqueue_init(void) { pthread_rwlock_init(&kqtree_mtx, NULL); @@ -149,7 +149,7 @@ kqueue_get(int kq) } -int __attribute__((visibility("default"))) +int VISIBLE kqueue(void) { struct kqueue *kq; diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index ac60b8daa..59bbd64e5 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -21,6 +21,9 @@ # include "../windows/platform.h" #else /* TODO: move to posix/platform.h */ +#define CONSTRUCTOR int __attribute__ ((constructor)) +#define VISIBLE __attribute__((visibility("default"))) +#define HIDDEN __attribute__((visibility("hidden"))) #include #include #include @@ -48,6 +51,9 @@ struct evfilt_data; # include # define atomic_inc atomic_inc_32_nv # define atomic_dec atomic_dec_32_nv +#elif defined(_WIN32) +# define atomic_inc InterlockedIncrement +# define atomic_dec InterlockedDecrement #else # define atomic_inc(p) __sync_add_and_fetch((p), 1) # define atomic_dec(p) __sync_sub_and_fetch((p), 1) diff --git a/vendor/libkqueue/src/common/queue.h b/vendor/libkqueue/src/common/queue.h index c79c08a51..479207ff1 100644 --- a/vendor/libkqueue/src/common/queue.h +++ b/vendor/libkqueue/src/common/queue.h @@ -132,6 +132,7 @@ struct qm_trace { #define TRASHIT(x) #endif /* QUEUE_MACRO_DEBUG */ +#ifndef _WIN32 /* * Singly-linked List declarations. */ @@ -208,6 +209,8 @@ struct { \ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ } while (0) +#endif /* defined(_WIN32) */ + /* * Singly-linked Tail queue declarations. */ diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index d4a3c8fbb..49ee2815d 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -20,4 +20,31 @@ #include #include +/* DllMain() is the only available constructor function */ +#define CONSTRUCTOR int + +/* Function visibility macros */ +#define VISIBLE __declspec(dllexport) +#define HIDDEN + +/* For POSIX compatibility when compiling, not for actual use */ +typedef int nlink_t; +typedef int timer_t; +typedef int pthread_t; +typedef int sigset_t; + +/* Emulation of pthreads mutex functionality */ +typedef CRITICAL_SECTION pthread_mutex_t; +typedef CRITICAL_SECTION pthread_rwlock_t; +#define _cs_init(x) InitializeCriticalSection((x)) +#define _cs_lock(x) EnterCriticalSection ((x)) +#define _cs_unlock(x) LeaveCriticalSection ((x)) +#define pthread_mutex_lock _cs_lock +#define pthread_mutex_unlock _cs_unlock +#define pthread_mutex_init(x,y) _cs_init((x)) +#define pthread_rwlock_rdlock _cs_lock +#define pthread_rwlock_wrlock _cs_lock +#define pthread_rwlock_unlock _cs_unlock +#define pthread_rwlock_init(x,y) _cs_init((x)) + #endif /* ! _KQUEUE_PLATFORM_H */ From 1bc6199e7d2675ad04f5e2d6ae6a020b6b9f4d42 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 13 Jan 2011 04:45:16 +0000 Subject: [PATCH 0343/1120] Move platform-specific cruft into separate platform.h for each target git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@365 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kevent.c | 22 ++++---- vendor/libkqueue/src/common/kqueue.c | 11 ++++ vendor/libkqueue/src/common/private.h | 67 +++---------------------- vendor/libkqueue/src/linux/platform.h | 31 ++++++++++++ vendor/libkqueue/src/posix/platform.h | 40 +++++++++++++++ vendor/libkqueue/src/solaris/platform.h | 56 +++++++++++++++++++++ vendor/libkqueue/src/windows/kqueue.c | 7 ++- vendor/libkqueue/src/windows/platform.h | 23 +++++++-- 8 files changed, 182 insertions(+), 75 deletions(-) create mode 100644 vendor/libkqueue/src/linux/platform.h create mode 100644 vendor/libkqueue/src/posix/platform.h create mode 100644 vendor/libkqueue/src/solaris/platform.h diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 4e62654f9..c08156dc2 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -28,24 +28,24 @@ #include "private.h" -static char * +static const char * kevent_filter_dump(const struct kevent *kev) { static char __thread buf[64]; snprintf(&buf[0], sizeof(buf), "%d (%s)", kev->filter, filter_name(kev->filter)); - return (&buf[0]); + return ((const char *) &buf[0]); } -static char * +static const char * kevent_fflags_dump(const struct kevent *kev) { static char __thread buf[1024]; #define KEVFFL_DUMP(attrib) \ if (kev->fflags & attrib) \ - strncat(buf, #attrib" ", 64); + strncat((char *) &buf[0], #attrib" ", 64); snprintf(buf, sizeof(buf), "fflags=0x%04x (", kev->fflags); if (kev->filter == EVFILT_VNODE) { @@ -62,23 +62,23 @@ kevent_fflags_dump(const struct kevent *kev) KEVFFL_DUMP(NOTE_FFCOPY); KEVFFL_DUMP(NOTE_TRIGGER); } else { - strncat(buf, " ", 1); + strncat((char *) &buf[0], " ", 1); } buf[strlen(buf) - 1] = ')'; #undef KEVFFL_DUMP - return (buf); + return ((const char *) &buf[0]); } -static char * +static const char * kevent_flags_dump(const struct kevent *kev) { static char __thread buf[1024]; #define KEVFL_DUMP(attrib) \ if (kev->flags & attrib) \ - strncat(buf, #attrib" ", 64); + strncat((char *) &buf[0], #attrib" ", 64); snprintf(buf, sizeof(buf), "flags=0x%04x (", kev->flags); KEVFL_DUMP(EV_ADD); @@ -95,7 +95,7 @@ kevent_flags_dump(const struct kevent *kev) #undef KEVFL_DUMP - return (buf); + return ((const char *) &buf[0]); } const char * @@ -103,7 +103,7 @@ kevent_dump(const struct kevent *kev) { static char __thread buf[1024]; - snprintf(buf, sizeof(buf), + snprintf((char *) &buf[0], sizeof(buf), "{ ident=%d, filter=%s, %s, %s, data=%d, udata=%p }", (u_int) kev->ident, kevent_filter_dump(kev), @@ -112,7 +112,7 @@ kevent_dump(const struct kevent *kev) (int) kev->data, kev->udata); - return (buf); + return ((const char *) &buf[0]); } static int diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index f0ec32b29..dce2e5a32 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -167,8 +167,17 @@ kqueue(void) KQUEUE_DEBUG = (getenv("KQUEUE_DEBUG") == NULL) ? 0 : 1; #endif +#ifdef _WIN32 + static int kqueue_id = 0; + pthread_rwlock_wrlock(&kqtree_mtx); + kqueue_id++; + pthread_rwlock_unlock(&kqtree_mtx); + kq->kq_sockfd[0] = kqueue_id; + kq->kq_sockfd[1] = kqueue_id; +#else if (socketpair(AF_UNIX, SOCK_STREAM, 0, kq->kq_sockfd) < 0) goto errout_unlocked; +#endif #ifdef kqueue_init_hook if (kqueue_init_hook(kq) < 0) @@ -193,8 +202,10 @@ kqueue(void) errout_unlocked: if (kq->kq_sockfd[0] != kq->kq_sockfd[1]) { tmp = errno; +#ifndef _WIN32 (void)close(kq->kq_sockfd[0]); (void)close(kq->kq_sockfd[1]); +#endif errno = tmp; } #if defined(__sun__) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 59bbd64e5..a1615ddb8 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -19,17 +19,14 @@ #if defined(_WIN32) # include "../windows/platform.h" +#elif defined(__linux__) +# include "../posix/platform.h" +# include "../linux/platform.h" +#elif defined(__sun) +# include "../posix/platform.h" +# include "../solaris/platform.h" #else -/* TODO: move to posix/platform.h */ -#define CONSTRUCTOR int __attribute__ ((constructor)) -#define VISIBLE __attribute__((visibility("default"))) -#define HIDDEN __attribute__((visibility("hidden"))) -#include -#include -#include -#include -#include -#include +# error Unknown platform #endif struct kqueue; @@ -44,39 +41,13 @@ struct evfilt_data; #include "tree.h" #include "queue.h" -/* GCC atomic builtins. - * See: http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html - */ -#ifdef __sun -# include -# define atomic_inc atomic_inc_32_nv -# define atomic_dec atomic_dec_32_nv -#elif defined(_WIN32) -# define atomic_inc InterlockedIncrement -# define atomic_dec InterlockedDecrement -#else -# define atomic_inc(p) __sync_add_and_fetch((p), 1) -# define atomic_dec(p) __sync_sub_and_fetch((p), 1) -#endif - /* Maximum events returnable in a single kevent() call */ #define MAX_KEVENT 512 - #ifndef NDEBUG extern int KQUEUE_DEBUG; -#ifdef __linux__ -# define _GNU_SOURCE -# include -# include -# include -extern long int syscall (long int __sysno, ...); -# define THREAD_ID ((pid_t) syscall(__NR_gettid)) -#else -# define THREAD_ID (pthread_self()) -#endif #define dbg_puts(str) do { \ if (KQUEUE_DEBUG) \ @@ -103,32 +74,10 @@ extern long int syscall (long int __sysno, ...); # define reset_errno() ; #endif -#if defined (__SVR4) && defined (__sun) -# define SOLARIS -# include - /* Used to set portev_events for PORT_SOURCE_USER */ -# define X_PORT_SOURCE_SIGNAL 101 -# define X_PORT_SOURCE_USER 102 - -# define kqueue_free_hook solaris_kqueue_free -void solaris_kqueue_free(struct kqueue *); - -# define kqueue_init_hook solaris_kqueue_init -int solaris_kqueue_init(struct kqueue *); - -void port_event_dequeue(port_event_t *, struct kqueue *); - -struct event_buf { - port_event_t pe; - TAILQ_ENTRY(event_buf) entries; -}; - -#else /* The event_buf structure is only needed by Solaris */ - struct event_buf { + struct DEADWOOD_event_buf { int unused; }; -#endif /* diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h new file mode 100644 index 000000000..9ccdb44b6 --- /dev/null +++ b/vendor/libkqueue/src/linux/platform.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _KQUEUE_LINUX_PLATFORM_H +#define _KQUEUE_LINUX_PLATFORM_H + +/* + * Get the current thread ID + */ +# define _GNU_SOURCE +# include +# include +# include +extern long int syscall (long int __sysno, ...); +#define THREAD_ID ((pid_t) syscall(__NR_gettid)) + + +#endif /* ! _KQUEUE_LINUX_PLATFORM_H */ diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h new file mode 100644 index 000000000..17017e848 --- /dev/null +++ b/vendor/libkqueue/src/posix/platform.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _KQUEUE_POSIX_PLATFORM_H +#define _KQUEUE_POSIX_PLATFORM_H + +/* + * GCC-compatible atomic integer operations + */ +#ifndef _sun +#define atomic_inc(p) __sync_add_and_fetch((p), 1) +#define atomic_dec(p) __sync_sub_and_fetch((p), 1) +#endif + +#define CONSTRUCTOR int __attribute__ ((constructor)) +#define VISIBLE __attribute__((visibility("default"))) +#define HIDDEN __attribute__((visibility("hidden"))) + +#include +#include +#include +#include +#include +#include +#include + +#endif /* ! _KQUEUE_POSIX_PLATFORM_H */ diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h new file mode 100644 index 000000000..ba44ed6fc --- /dev/null +++ b/vendor/libkqueue/src/solaris/platform.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _KQUEUE_SOLARIS_PLATFORM_H +#define _KQUEUE_SOLARIS_PLATFORM_H + +#define THREAD_ID (pthread_self()) + +/* + * Atomic integer operations + */ +#include +#define atomic_inc atomic_inc_32_nv +#define atomic_dec atomic_dec_32_nv + +/* + * Event ports + */ +#include +/* Used to set portev_events for PORT_SOURCE_USER */ +#define X_PORT_SOURCE_SIGNAL 101 +#define X_PORT_SOURCE_USER 102 + +/* + * Hooks and prototypes + */ +#define kqueue_free_hook solaris_kqueue_free +void solaris_kqueue_free(struct kqueue *); + +#define kqueue_init_hook solaris_kqueue_init +int solaris_kqueue_init(struct kqueue *); + +void port_event_dequeue(port_event_t *, struct kqueue *); + +/* + * Data structures + */ +struct event_buf { + port_event_t pe; + TAILQ_ENTRY(event_buf) entries; +}; + +#endif /* ! _KQUEUE_SOLARIS_PLATFORM_H */ diff --git a/vendor/libkqueue/src/windows/kqueue.c b/vendor/libkqueue/src/windows/kqueue.c index ac8371246..277b6b530 100644 --- a/vendor/libkqueue/src/windows/kqueue.c +++ b/vendor/libkqueue/src/windows/kqueue.c @@ -23,11 +23,14 @@ BOOL WINAPI DllMain( { switch (reason) { case DLL_PROCESS_ATTACH: - /* TODO: initialize mutexes */ + /* XXX-FIXME: initialize kqtree mutex */ + if (WSAStartup(MAKEWORD(2,2), NULL) != 0) + return (FALSE); + /* TODO: bettererror handling */ break; case DLL_PROCESS_DETACH: - /* TODO: cleanup */ + WSACleanup(); break; } diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 49ee2815d..b36318884 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -14,12 +14,18 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifndef _KQUEUE_PLATFORM_H -#define _KQUEUE_PLATFORM_H +#ifndef _KQUEUE_WINDOWS_PLATFORM_H +#define _KQUEUE_WINDOWS_PLATFORM_H #include #include +/* + * Atomic integer operations + */ +#define atomic_inc InterlockedIncrement +#define atomic_dec InterlockedDecrement + /* DllMain() is the only available constructor function */ #define CONSTRUCTOR int @@ -27,12 +33,23 @@ #define VISIBLE __declspec(dllexport) #define HIDDEN +#ifndef __func__ +#define __func__ __FUNCDNAME__ +#endif + +#define snprintf _snprintf_s +#define ssize_t SSIZE_T + /* For POSIX compatibility when compiling, not for actual use */ +typedef int socklen_t; typedef int nlink_t; typedef int timer_t; typedef int pthread_t; typedef int sigset_t; +#define THREAD_ID (GetCurrentThreadId()) +#define __thread __declspec(thread) + /* Emulation of pthreads mutex functionality */ typedef CRITICAL_SECTION pthread_mutex_t; typedef CRITICAL_SECTION pthread_rwlock_t; @@ -47,4 +64,4 @@ typedef CRITICAL_SECTION pthread_rwlock_t; #define pthread_rwlock_unlock _cs_unlock #define pthread_rwlock_init(x,y) _cs_init((x)) -#endif /* ! _KQUEUE_PLATFORM_H */ +#endif /* ! _KQUEUE_WINDOWS_PLATFORM_H */ From c627998cd3339fb0724418b88a89e90bef055e99 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 13 Jan 2011 15:00:32 +0000 Subject: [PATCH 0344/1120] Portability fixes for Solaris (reported by Joakim Johansson) git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@366 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/private.h | 21 ++++++++++----------- vendor/libkqueue/src/linux/platform.h | 2 ++ vendor/libkqueue/src/posix/platform.h | 2 -- vendor/libkqueue/src/solaris/platform.h | 6 +++++- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index a1615ddb8..4dc83688e 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -17,6 +17,16 @@ #ifndef _KQUEUE_PRIVATE_H #define _KQUEUE_PRIVATE_H +#include +#include +#include +#include "../../include/sys/event.h" +#include "tree.h" + +struct kqueue; +struct kevent; +struct evfilt_data; + #if defined(_WIN32) # include "../windows/platform.h" #elif defined(__linux__) @@ -29,17 +39,6 @@ # error Unknown platform #endif -struct kqueue; -struct kevent; -struct evfilt_data; - -#include -#include -#include -#include "../../include/sys/event.h" - -#include "tree.h" -#include "queue.h" /* Maximum events returnable in a single kevent() call */ #define MAX_KEVENT 512 diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 9ccdb44b6..c40775af9 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -17,6 +17,8 @@ #ifndef _KQUEUE_LINUX_PLATFORM_H #define _KQUEUE_LINUX_PLATFORM_H +#include + /* * Get the current thread ID */ diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 17017e848..2d16c41f4 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -20,10 +20,8 @@ /* * GCC-compatible atomic integer operations */ -#ifndef _sun #define atomic_inc(p) __sync_add_and_fetch((p), 1) #define atomic_dec(p) __sync_sub_and_fetch((p), 1) -#endif #define CONSTRUCTOR int __attribute__ ((constructor)) #define VISIBLE __attribute__((visibility("default"))) diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index ba44ed6fc..2af6606b5 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -17,13 +17,17 @@ #ifndef _KQUEUE_SOLARIS_PLATFORM_H #define _KQUEUE_SOLARIS_PLATFORM_H +#include + #define THREAD_ID (pthread_self()) /* - * Atomic integer operations + * Atomic integer operations that override the ones in posix/platform.h */ #include +#undef atomic_inc #define atomic_inc atomic_inc_32_nv +#undef atomic_dec #define atomic_dec atomic_dec_32_nv /* From 3ea84935bb76267dd8213052a4e27d1bc5da8225 Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 14 Jan 2011 03:46:18 +0000 Subject: [PATCH 0345/1120] additional win32 stuff git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@368 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/include/sys/event.h | 1 - vendor/libkqueue/src/common/filter.c | 4 ++++ vendor/libkqueue/src/common/knote.c | 2 +- vendor/libkqueue/src/common/kqueue.c | 10 +++++++--- vendor/libkqueue/src/common/private.h | 1 + vendor/libkqueue/src/windows/kqueue.c | 2 +- vendor/libkqueue/src/windows/platform.h | 2 +- 7 files changed, 15 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index 1dcf0945b..5cc71d366 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -38,7 +38,6 @@ #include #include #define LIBKQUEUE 1 -int _libkqueue_init(void) __attribute__ ((constructor)); #endif struct timespec; diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index d8ab143cb..e10a38ca7 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -123,6 +123,7 @@ filter_unregister_all(struct kqueue *kq) int filter_socketpair(struct filter *filt) { +#ifndef _WIN32 int sockfd[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) @@ -131,6 +132,9 @@ filter_socketpair(struct filter *filt) fcntl(sockfd[0], F_SETFL, O_NONBLOCK); filt->kf_wfd = sockfd[0]; filt->kf_pfd = sockfd[1]; +#else +#warning FIXME function has no effect +#endif return (0); } diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 3ce5b41e2..6b707e3d0 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -149,7 +149,7 @@ knote_get_socket_type(struct knote *kn) slen = sizeof(lsock); lsock = 0; - i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_ACCEPTCONN, &lsock, &slen); + i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_ACCEPTCONN, (char *) &lsock, &slen); if (i < 0) { switch (errno) { case ENOTSOCK: /* same as lsock = 0 */ diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index dce2e5a32..2b02c8bc4 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -148,11 +148,13 @@ kqueue_get(int kq) return (ent); } - int VISIBLE kqueue(void) { - struct kqueue *kq; +#ifdef _WIN32 + static int kqueue_id = 0; +#endif + struct kqueue *kq; int tmp; kq = calloc(1, sizeof(*kq)); @@ -163,12 +165,14 @@ kqueue(void) #ifdef NDEBUG KQUEUE_DEBUG = 0; +#elif _WIN32 + /* Experimental port, always debug */ + KQUEUE_DEBUG = 1; #else KQUEUE_DEBUG = (getenv("KQUEUE_DEBUG") == NULL) ? 0 : 1; #endif #ifdef _WIN32 - static int kqueue_id = 0; pthread_rwlock_wrlock(&kqtree_mtx); kqueue_id++; pthread_rwlock_unlock(&kqtree_mtx); diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 4dc83688e..2f93feedf 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -29,6 +29,7 @@ struct evfilt_data; #if defined(_WIN32) # include "../windows/platform.h" +# include "../common/queue.h" #elif defined(__linux__) # include "../posix/platform.h" # include "../linux/platform.h" diff --git a/vendor/libkqueue/src/windows/kqueue.c b/vendor/libkqueue/src/windows/kqueue.c index 277b6b530..8a9c8b96f 100644 --- a/vendor/libkqueue/src/windows/kqueue.c +++ b/vendor/libkqueue/src/windows/kqueue.c @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "private.h" +#include "../common/private.h" BOOL WINAPI DllMain( HINSTANCE self, diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index b36318884..3e9d90770 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -37,7 +37,7 @@ #define __func__ __FUNCDNAME__ #endif -#define snprintf _snprintf_s +#define snprintf _snprintf #define ssize_t SSIZE_T /* For POSIX compatibility when compiling, not for actual use */ From cea7bf225ffecefd4f65ee62dcd8d5d89b68eb08 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 02:41:12 +0000 Subject: [PATCH 0346/1120] kqueue.h for win32 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@369 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/include/kqueue.h | 193 ++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 vendor/libkqueue/include/kqueue.h diff --git a/vendor/libkqueue/include/kqueue.h b/vendor/libkqueue/include/kqueue.h new file mode 100644 index 000000000..a438bc2e2 --- /dev/null +++ b/vendor/libkqueue/include/kqueue.h @@ -0,0 +1,193 @@ +/*- + * Copyright (c) 2009-2011 Mark Heily + * Copyright (c) 1999,2000,2001 Jonathan Lemon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD SVN Revision 197533$ + */ + +/* + + NOTE: This is the Win32 version of sys/event.h. + + The only differences are: + + * The linkage of kevent() and kqueue() is provided + * The HANDLE datatype (a.k.a. 'void *') is used instead of 'int' + +*/ +#ifndef _SYS_EVENT_H_ +#define _SYS_EVENT_H_ + +#include + +#ifdef __KERNEL__ +#define intptr_t long +#else +#include +#include +#define LIBKQUEUE 1 +#endif + +struct timespec; + +#define EVFILT_READ (-1) +#define EVFILT_WRITE (-2) +#define EVFILT_AIO (-3) /* attached to aio requests */ +#define EVFILT_VNODE (-4) /* attached to vnodes */ +#define EVFILT_PROC (-5) /* attached to struct proc */ +#define EVFILT_SIGNAL (-6) /* attached to struct proc */ +#define EVFILT_TIMER (-7) /* timers */ +#define EVFILT_NETDEV (-8) /* network devices */ +#define EVFILT_FS (-9) /* filesystem events */ +#define EVFILT_LIO (-10) /* attached to lio requests */ +#define EVFILT_USER (-11) /* User events */ +#define EVFILT_SYSCOUNT 11 + +#define EV_SET(kevp_, a, b, c, d, e, f) do { \ + struct kevent *kevp = (kevp_); \ + (kevp)->ident = (a); \ + (kevp)->filter = (b); \ + (kevp)->flags = (c); \ + (kevp)->fflags = (d); \ + (kevp)->data = (e); \ + (kevp)->udata = (f); \ +} while(0) + +struct kevent { + uintptr_t ident; /* identifier for this event */ + short filter; /* filter for event */ + unsigned short flags; + unsigned int fflags; + intptr_t data; + void *udata; /* opaque user data identifier */ +}; + +/* actions */ +#define EV_ADD 0x0001 /* add event to kq (implies enable) */ +#define EV_DELETE 0x0002 /* delete event from kq */ +#define EV_ENABLE 0x0004 /* enable event */ +#define EV_DISABLE 0x0008 /* disable event (not reported) */ + +/* flags */ +#define EV_ONESHOT 0x0010 /* only report one occurrence */ +#define EV_CLEAR 0x0020 /* clear event state after reporting */ +#define EV_RECEIPT 0x0040 /* force EV_ERROR on success, data=0 */ +#define EV_DISPATCH 0x0080 /* disable event after reporting */ + +#define EV_SYSFLAGS 0xF000 /* reserved by system */ +#define EV_FLAG1 0x2000 /* filter-specific flag */ + +/* returned values */ +#define EV_EOF 0x8000 /* EOF detected */ +#define EV_ERROR 0x4000 /* error, data contains errno */ + + /* + * data/hint flags/masks for EVFILT_USER + * + * On input, the top two bits of fflags specifies how the lower twenty four + * bits should be applied to the stored value of fflags. + * + * On output, the top two bits will always be set to NOTE_FFNOP and the + * remaining twenty four bits will contain the stored fflags value. + */ +#define NOTE_FFNOP 0x00000000 /* ignore input fflags */ +#define NOTE_FFAND 0x40000000 /* AND fflags */ +#define NOTE_FFOR 0x80000000 /* OR fflags */ +#define NOTE_FFCOPY 0xc0000000 /* copy fflags */ +#define NOTE_FFCTRLMASK 0xc0000000 /* masks for operations */ +#define NOTE_FFLAGSMASK 0x00ffffff + +#define NOTE_TRIGGER 0x01000000 /* Cause the event to be + triggered for output. */ + +/* + * data/hint flags for EVFILT_{READ|WRITE} + */ +#define NOTE_LOWAT 0x0001 /* low water mark */ +#undef NOTE_LOWAT /* Not supported on Linux */ + +/* + * data/hint flags for EVFILT_VNODE + */ +#define NOTE_DELETE 0x0001 /* vnode was removed */ +#define NOTE_WRITE 0x0002 /* data contents changed */ +#define NOTE_EXTEND 0x0004 /* size increased */ +#define NOTE_ATTRIB 0x0008 /* attributes changed */ +#define NOTE_LINK 0x0010 /* link count changed */ +#define NOTE_RENAME 0x0020 /* vnode was renamed */ +#define NOTE_REVOKE 0x0040 /* vnode access was revoked */ +#undef NOTE_REVOKE /* Not supported on Linux */ + +/* + * data/hint flags for EVFILT_PROC + */ +#define NOTE_EXIT 0x80000000 /* process exited */ +#define NOTE_FORK 0x40000000 /* process forked */ +#define NOTE_EXEC 0x20000000 /* process exec'd */ +#define NOTE_PCTRLMASK 0xf0000000 /* mask for hint bits */ +#define NOTE_PDATAMASK 0x000fffff /* mask for pid */ + +/* additional flags for EVFILT_PROC */ +#define NOTE_TRACK 0x00000001 /* follow across forks */ +#define NOTE_TRACKERR 0x00000002 /* could not track child */ +#define NOTE_CHILD 0x00000004 /* am a child process */ + +/* + * data/hint flags for EVFILT_NETDEV + */ +#define NOTE_LINKUP 0x0001 /* link is up */ +#define NOTE_LINKDOWN 0x0002 /* link is down */ +#define NOTE_LINKINV 0x0004 /* link state is invalid */ + +/* KLUDGE: This is from on FreeBSD and is used by + the EVFILT_FS filter. */ +/* vfsquery flags */ +#define VQ_NOTRESP 0x0001 /* server down */ +#define VQ_NEEDAUTH 0x0002 /* server bad auth */ +#define VQ_LOWDISK 0x0004 /* we're low on space */ +#define VQ_MOUNT 0x0008 /* new filesystem arrived */ +#define VQ_UNMOUNT 0x0010 /* filesystem has left */ +#define VQ_DEAD 0x0020 /* filesystem is dead, needs force unmount */ +#define VQ_ASSIST 0x0040 /* filesystem needs assistance from external + program */ +#define VQ_NOTRESPLOCK 0x0080 /* server lockd down */ + + +#ifndef __KERNEL__ +#ifdef __cplusplus +extern "C" { +#endif + +HANDLE kqueue(void) __declspec(dllexport); +int kevent(HANDLE kq, const struct kevent *changelist, int nchanges, + struct kevent *eventlist, int nevents, + const struct timespec *timeout) __declspec(dllexport); + +#ifdef __cplusplus +} +#endif +#endif /* !__KERNEL__* */ + +#endif /* !_SYS_EVENT_H_ */ From df33a96dcf4f89d841decb3e8745d229153136c3 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 02:42:44 +0000 Subject: [PATCH 0347/1120] fix win32 include git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@370 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/private.h | 1 - vendor/libkqueue/src/posix/platform.h | 2 ++ vendor/libkqueue/src/windows/platform.h | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 2f93feedf..40e82fbef 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -20,7 +20,6 @@ #include #include #include -#include "../../include/sys/event.h" #include "tree.h" struct kqueue; diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 2d16c41f4..44ded1937 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -17,6 +17,8 @@ #ifndef _KQUEUE_POSIX_PLATFORM_H #define _KQUEUE_POSIX_PLATFORM_H +#include "../../include/sys/event.h" + /* * GCC-compatible atomic integer operations */ diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 3e9d90770..b3261a82d 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -17,6 +17,8 @@ #ifndef _KQUEUE_WINDOWS_PLATFORM_H #define _KQUEUE_WINDOWS_PLATFORM_H +#include "../../include/kqueue.h" + #include #include From 464ea23a8445a7a236c5abb2e0726556832ed31f Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 02:44:45 +0000 Subject: [PATCH 0348/1120] win32 header ordering git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@371 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/windows/platform.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index b3261a82d..8301c222d 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -17,11 +17,11 @@ #ifndef _KQUEUE_WINDOWS_PLATFORM_H #define _KQUEUE_WINDOWS_PLATFORM_H -#include "../../include/kqueue.h" - #include #include +#include "../../include/kqueue.h" + /* * Atomic integer operations */ From 55f5458a718d21e59b6c54123637e72fb73debaf Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 03:27:46 +0000 Subject: [PATCH 0349/1120] more use of free() and init() hooks git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@372 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/config.inc | 6 ++-- vendor/libkqueue/src/common/kqueue.c | 30 +---------------- vendor/libkqueue/src/posix/kqueue.c | 47 +++++++++++++++++++++++++++ vendor/libkqueue/src/posix/platform.h | 10 ++++++ vendor/libkqueue/src/solaris/kqueue.c | 6 ++++ 5 files changed, 67 insertions(+), 32 deletions(-) create mode 100644 vendor/libkqueue/src/posix/kqueue.c diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index 968e3dd6e..a7496d076 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -50,7 +50,7 @@ pre_configure_hook() { post_configure_hook() { finalize target "$target" - kqueue="" + kqueue="src/posix/kqueue.c" kevent="src/posix/kevent.c" evfilt_signal="src/posix/signal.c" evfilt_proc="src/$target/proc.c" @@ -75,8 +75,8 @@ post_configure_hook() { if [ $target = "solaris" ] ; then cflags="$cflags -D__EXTENSIONS__" - kqueue="src/solaris/kqueue.c" - kevent="src/solaris/kevent.c" + kqueue="$kqueue src/solaris/kqueue.c" + kevent="$kevent src/solaris/kevent.c" evfilt_timer="src/solaris/timer.c" evfilt_user="src/solaris/user.c" evfilt_proc="" diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 2b02c8bc4..5220f6c59 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -151,11 +151,7 @@ kqueue_get(int kq) int VISIBLE kqueue(void) { -#ifdef _WIN32 - static int kqueue_id = 0; -#endif struct kqueue *kq; - int tmp; kq = calloc(1, sizeof(*kq)); if (kq == NULL) @@ -172,21 +168,8 @@ kqueue(void) KQUEUE_DEBUG = (getenv("KQUEUE_DEBUG") == NULL) ? 0 : 1; #endif -#ifdef _WIN32 - pthread_rwlock_wrlock(&kqtree_mtx); - kqueue_id++; - pthread_rwlock_unlock(&kqtree_mtx); - kq->kq_sockfd[0] = kqueue_id; - kq->kq_sockfd[1] = kqueue_id; -#else - if (socketpair(AF_UNIX, SOCK_STREAM, 0, kq->kq_sockfd) < 0) - goto errout_unlocked; -#endif - -#ifdef kqueue_init_hook if (kqueue_init_hook(kq) < 0) goto errout_unlocked; -#endif pthread_rwlock_wrlock(&kqtree_mtx); if (kqueue_gc() < 0) @@ -204,18 +187,7 @@ kqueue(void) pthread_rwlock_unlock(&kqtree_mtx); errout_unlocked: - if (kq->kq_sockfd[0] != kq->kq_sockfd[1]) { - tmp = errno; -#ifndef _WIN32 - (void)close(kq->kq_sockfd[0]); - (void)close(kq->kq_sockfd[1]); -#endif - errno = tmp; - } -#if defined(__sun__) - if (kq->kq_port > 0) - close(kq->kq_port); -#endif + kqueue_free_hook(kq); free(kq); return (-1); } diff --git a/vendor/libkqueue/src/posix/kqueue.c b/vendor/libkqueue/src/posix/kqueue.c new file mode 100644 index 000000000..b2e4f055b --- /dev/null +++ b/vendor/libkqueue/src/posix/kqueue.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "private.h" + +int +posix_kqueue_init(struct kqueue *kq) +{ + if (socketpair(AF_UNIX, SOCK_STREAM, 0, kq->kq_sockfd) < 0) { + dbg_perror("socketpair"); + kq->kq_sockfd[0] = -1; + kq->kq_sockfd[1] = -1; + return (-1); + } + + return (0); +} + +void +posix_kqueue_free(struct kqueue *kq) +{ + if (kq->kq_sockfd[0] != -1) + (void) close(kq->kq_sockfd[0]); + if (kq->kq_sockfd[1] != -1) + (void) close(kq->kq_sockfd[1]); +} diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 44ded1937..28c5dc3d0 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -19,6 +19,15 @@ #include "../../include/sys/event.h" +/* + * Hooks and prototypes + */ +#define kqueue_free_hook posix_kqueue_free +void posix_kqueue_free(struct kqueue *); + +#define kqueue_init_hook posix_kqueue_init +int posix_kqueue_init(struct kqueue *); + /* * GCC-compatible atomic integer operations */ @@ -38,3 +47,4 @@ #include #endif /* ! _KQUEUE_POSIX_PLATFORM_H */ + diff --git a/vendor/libkqueue/src/solaris/kqueue.c b/vendor/libkqueue/src/solaris/kqueue.c index df6a1a2da..50feaf78a 100644 --- a/vendor/libkqueue/src/solaris/kqueue.c +++ b/vendor/libkqueue/src/solaris/kqueue.c @@ -22,9 +22,13 @@ #include "sys/event.h" #include "private.h" +extern int posix_kqueue_init(struct kqueue *kq); +extern void posix_kqueue_free(struct kqueue *kq); + void solaris_kqueue_free(struct kqueue *kq) { + posix_kqueue_free(kq); if (kq->kq_port > 0) close(kq->kq_port); } @@ -32,6 +36,8 @@ solaris_kqueue_free(struct kqueue *kq) int solaris_kqueue_init(struct kqueue *kq) { + if (posix_kqueue_init(kq) < 0) + return (-1); if ((kq->kq_port = port_create()) < 0) { dbg_perror("port_create(2)"); return (-1); From ddc9508cab93298fc35493336a29abcac95be661 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 03:47:34 +0000 Subject: [PATCH 0350/1120] visibilty for win32 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@373 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/include/kqueue.h | 193 ------------------------ vendor/libkqueue/include/sys/event.h | 8 + vendor/libkqueue/src/common/kevent.c | 3 +- vendor/libkqueue/src/common/kqueue.c | 3 +- vendor/libkqueue/src/posix/platform.h | 8 +- vendor/libkqueue/src/windows/platform.h | 5 +- 6 files changed, 20 insertions(+), 200 deletions(-) delete mode 100644 vendor/libkqueue/include/kqueue.h diff --git a/vendor/libkqueue/include/kqueue.h b/vendor/libkqueue/include/kqueue.h deleted file mode 100644 index a438bc2e2..000000000 --- a/vendor/libkqueue/include/kqueue.h +++ /dev/null @@ -1,193 +0,0 @@ -/*- - * Copyright (c) 2009-2011 Mark Heily - * Copyright (c) 1999,2000,2001 Jonathan Lemon - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD SVN Revision 197533$ - */ - -/* - - NOTE: This is the Win32 version of sys/event.h. - - The only differences are: - - * The linkage of kevent() and kqueue() is provided - * The HANDLE datatype (a.k.a. 'void *') is used instead of 'int' - -*/ -#ifndef _SYS_EVENT_H_ -#define _SYS_EVENT_H_ - -#include - -#ifdef __KERNEL__ -#define intptr_t long -#else -#include -#include -#define LIBKQUEUE 1 -#endif - -struct timespec; - -#define EVFILT_READ (-1) -#define EVFILT_WRITE (-2) -#define EVFILT_AIO (-3) /* attached to aio requests */ -#define EVFILT_VNODE (-4) /* attached to vnodes */ -#define EVFILT_PROC (-5) /* attached to struct proc */ -#define EVFILT_SIGNAL (-6) /* attached to struct proc */ -#define EVFILT_TIMER (-7) /* timers */ -#define EVFILT_NETDEV (-8) /* network devices */ -#define EVFILT_FS (-9) /* filesystem events */ -#define EVFILT_LIO (-10) /* attached to lio requests */ -#define EVFILT_USER (-11) /* User events */ -#define EVFILT_SYSCOUNT 11 - -#define EV_SET(kevp_, a, b, c, d, e, f) do { \ - struct kevent *kevp = (kevp_); \ - (kevp)->ident = (a); \ - (kevp)->filter = (b); \ - (kevp)->flags = (c); \ - (kevp)->fflags = (d); \ - (kevp)->data = (e); \ - (kevp)->udata = (f); \ -} while(0) - -struct kevent { - uintptr_t ident; /* identifier for this event */ - short filter; /* filter for event */ - unsigned short flags; - unsigned int fflags; - intptr_t data; - void *udata; /* opaque user data identifier */ -}; - -/* actions */ -#define EV_ADD 0x0001 /* add event to kq (implies enable) */ -#define EV_DELETE 0x0002 /* delete event from kq */ -#define EV_ENABLE 0x0004 /* enable event */ -#define EV_DISABLE 0x0008 /* disable event (not reported) */ - -/* flags */ -#define EV_ONESHOT 0x0010 /* only report one occurrence */ -#define EV_CLEAR 0x0020 /* clear event state after reporting */ -#define EV_RECEIPT 0x0040 /* force EV_ERROR on success, data=0 */ -#define EV_DISPATCH 0x0080 /* disable event after reporting */ - -#define EV_SYSFLAGS 0xF000 /* reserved by system */ -#define EV_FLAG1 0x2000 /* filter-specific flag */ - -/* returned values */ -#define EV_EOF 0x8000 /* EOF detected */ -#define EV_ERROR 0x4000 /* error, data contains errno */ - - /* - * data/hint flags/masks for EVFILT_USER - * - * On input, the top two bits of fflags specifies how the lower twenty four - * bits should be applied to the stored value of fflags. - * - * On output, the top two bits will always be set to NOTE_FFNOP and the - * remaining twenty four bits will contain the stored fflags value. - */ -#define NOTE_FFNOP 0x00000000 /* ignore input fflags */ -#define NOTE_FFAND 0x40000000 /* AND fflags */ -#define NOTE_FFOR 0x80000000 /* OR fflags */ -#define NOTE_FFCOPY 0xc0000000 /* copy fflags */ -#define NOTE_FFCTRLMASK 0xc0000000 /* masks for operations */ -#define NOTE_FFLAGSMASK 0x00ffffff - -#define NOTE_TRIGGER 0x01000000 /* Cause the event to be - triggered for output. */ - -/* - * data/hint flags for EVFILT_{READ|WRITE} - */ -#define NOTE_LOWAT 0x0001 /* low water mark */ -#undef NOTE_LOWAT /* Not supported on Linux */ - -/* - * data/hint flags for EVFILT_VNODE - */ -#define NOTE_DELETE 0x0001 /* vnode was removed */ -#define NOTE_WRITE 0x0002 /* data contents changed */ -#define NOTE_EXTEND 0x0004 /* size increased */ -#define NOTE_ATTRIB 0x0008 /* attributes changed */ -#define NOTE_LINK 0x0010 /* link count changed */ -#define NOTE_RENAME 0x0020 /* vnode was renamed */ -#define NOTE_REVOKE 0x0040 /* vnode access was revoked */ -#undef NOTE_REVOKE /* Not supported on Linux */ - -/* - * data/hint flags for EVFILT_PROC - */ -#define NOTE_EXIT 0x80000000 /* process exited */ -#define NOTE_FORK 0x40000000 /* process forked */ -#define NOTE_EXEC 0x20000000 /* process exec'd */ -#define NOTE_PCTRLMASK 0xf0000000 /* mask for hint bits */ -#define NOTE_PDATAMASK 0x000fffff /* mask for pid */ - -/* additional flags for EVFILT_PROC */ -#define NOTE_TRACK 0x00000001 /* follow across forks */ -#define NOTE_TRACKERR 0x00000002 /* could not track child */ -#define NOTE_CHILD 0x00000004 /* am a child process */ - -/* - * data/hint flags for EVFILT_NETDEV - */ -#define NOTE_LINKUP 0x0001 /* link is up */ -#define NOTE_LINKDOWN 0x0002 /* link is down */ -#define NOTE_LINKINV 0x0004 /* link state is invalid */ - -/* KLUDGE: This is from on FreeBSD and is used by - the EVFILT_FS filter. */ -/* vfsquery flags */ -#define VQ_NOTRESP 0x0001 /* server down */ -#define VQ_NEEDAUTH 0x0002 /* server bad auth */ -#define VQ_LOWDISK 0x0004 /* we're low on space */ -#define VQ_MOUNT 0x0008 /* new filesystem arrived */ -#define VQ_UNMOUNT 0x0010 /* filesystem has left */ -#define VQ_DEAD 0x0020 /* filesystem is dead, needs force unmount */ -#define VQ_ASSIST 0x0040 /* filesystem needs assistance from external - program */ -#define VQ_NOTRESPLOCK 0x0080 /* server lockd down */ - - -#ifndef __KERNEL__ -#ifdef __cplusplus -extern "C" { -#endif - -HANDLE kqueue(void) __declspec(dllexport); -int kevent(HANDLE kq, const struct kevent *changelist, int nchanges, - struct kevent *eventlist, int nevents, - const struct timespec *timeout) __declspec(dllexport); - -#ifdef __cplusplus -} -#endif -#endif /* !__KERNEL__* */ - -#endif /* !_SYS_EVENT_H_ */ diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index 5cc71d366..e0f20e2f8 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -40,6 +40,11 @@ #define LIBKQUEUE 1 #endif +#ifndef _WIN32 +#define __declspec(x) /* */ +#define dllexport 0 +#endif + struct timespec; #define EVFILT_READ (-1) @@ -170,7 +175,10 @@ struct kevent { extern "C" { #endif +__declspec(dllexport) int kqueue(void); + +__declspec(dllexport) int kevent(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index c08156dc2..b5167dd5c 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -227,10 +227,11 @@ kevent_copyin(struct kqueue *kq, const struct kevent *src, int nchanges, return (nret); } -int VISIBLE +VISIBLE_DECL(int, kevent(int kqfd, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout) +) { static unsigned int _kevent_counter = 0; struct kqueue *kq; diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 5220f6c59..feccae680 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -148,8 +148,7 @@ kqueue_get(int kq) return (ent); } -int VISIBLE -kqueue(void) +VISIBLE_DECL(int, kqueue(void)) { struct kqueue *kq; diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 28c5dc3d0..1974bc0a6 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -17,8 +17,6 @@ #ifndef _KQUEUE_POSIX_PLATFORM_H #define _KQUEUE_POSIX_PLATFORM_H -#include "../../include/sys/event.h" - /* * Hooks and prototypes */ @@ -35,7 +33,7 @@ int posix_kqueue_init(struct kqueue *); #define atomic_dec(p) __sync_sub_and_fetch((p), 1) #define CONSTRUCTOR int __attribute__ ((constructor)) -#define VISIBLE __attribute__((visibility("default"))) +#define VISIBLE #define HIDDEN __attribute__((visibility("hidden"))) #include @@ -46,5 +44,9 @@ int posix_kqueue_init(struct kqueue *); #include #include +#define VISIBLE_DECL(t,x) t __attribute__((visibility("default"))) x + +#include "../../include/sys/event.h" + #endif /* ! _KQUEUE_POSIX_PLATFORM_H */ diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 8301c222d..4eff97164 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -20,7 +20,6 @@ #include #include -#include "../../include/kqueue.h" /* * Atomic integer operations @@ -66,4 +65,8 @@ typedef CRITICAL_SECTION pthread_rwlock_t; #define pthread_rwlock_unlock _cs_unlock #define pthread_rwlock_init(x,y) _cs_init((x)) +#define VISIBLE_DECL(t,x) __declspec(dllexport) t x + +#include "../../include/sys/event.h" + #endif /* ! _KQUEUE_WINDOWS_PLATFORM_H */ From b1bc1a111a4b6d8c99a8fd632bc2873ab3f0418a Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 04:09:36 +0000 Subject: [PATCH 0351/1120] build successful on win32, does not link git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@374 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/filter.c | 12 +++++++++--- vendor/libkqueue/src/common/knote.c | 2 +- vendor/libkqueue/src/common/kqueue.c | 3 --- vendor/libkqueue/src/common/private.h | 3 +-- vendor/libkqueue/src/windows/kqueue.c | 15 +++++++++++++++ vendor/libkqueue/src/windows/platform.h | 16 ++++++++++++++-- 6 files changed, 40 insertions(+), 11 deletions(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index e10a38ca7..c10886db2 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -123,17 +123,23 @@ filter_unregister_all(struct kqueue *kq) int filter_socketpair(struct filter *filt) { -#ifndef _WIN32 int sockfd[2]; +#ifdef _WIN32 + if (_pipe(sockfd, 512, _O_BINARY) == -1) { + dbg_puts("_pipe failed"); + return (-1); + } + /* FIXME: want nonblocking behavior for writer */ + filt->kf_wfd = sockfd[0]; + filt->kf_pfd = sockfd[1]; +#else if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) return (-1); fcntl(sockfd[0], F_SETFL, O_NONBLOCK); filt->kf_wfd = sockfd[0]; filt->kf_pfd = sockfd[1]; -#else -#warning FIXME function has no effect #endif return (0); } diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 6b707e3d0..5625f2189 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -156,7 +156,7 @@ knote_get_socket_type(struct knote *kn) return (0); break; default: - dbg_printf("getsockopt(3) failed: %s", strerror(errno)); + dbg_perror("getsockopt(3)"); return (-1); } } else { diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index feccae680..db6f6d144 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -24,10 +24,7 @@ #include "private.h" -#ifndef NDEBUG int KQUEUE_DEBUG = 0; -#endif - static RB_HEAD(kqt, kqueue) kqtree = RB_INITIALIZER(&kqtree); static pthread_rwlock_t kqtree_mtx; diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 40e82fbef..456c631c0 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -43,10 +43,9 @@ struct evfilt_data; /* Maximum events returnable in a single kevent() call */ #define MAX_KEVENT 512 -#ifndef NDEBUG - extern int KQUEUE_DEBUG; +#ifndef NDEBUG #define dbg_puts(str) do { \ if (KQUEUE_DEBUG) \ diff --git a/vendor/libkqueue/src/windows/kqueue.c b/vendor/libkqueue/src/windows/kqueue.c index 8a9c8b96f..ab9976b2f 100644 --- a/vendor/libkqueue/src/windows/kqueue.c +++ b/vendor/libkqueue/src/windows/kqueue.c @@ -37,3 +37,18 @@ BOOL WINAPI DllMain( return (TRUE); } +void +windows_kqueue_free(struct kqueue *kq) +{ +/*XXX-FIXME close the _pipe() */ +} + +int +windows_kqueue_init(struct kqueue *kq) +{ + if (_pipe(kq->kq_sockfd, 512, _O_BINARY) == -1) { + dbg_puts("_pipe failed"); + return (-1); + } + return (0); +} diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 4eff97164..bdeddabf2 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -17,9 +17,13 @@ #ifndef _KQUEUE_WINDOWS_PLATFORM_H #define _KQUEUE_WINDOWS_PLATFORM_H -#include -#include +#include +#include +#include +#include +#include +#pragma comment(lib, "Ws2_32.lib") /* * Atomic integer operations @@ -68,5 +72,13 @@ typedef CRITICAL_SECTION pthread_rwlock_t; #define VISIBLE_DECL(t,x) __declspec(dllexport) t x #include "../../include/sys/event.h" +/* + * Hooks and prototypes + */ +#define kqueue_free_hook windows_kqueue_free +void windows_kqueue_free(struct kqueue *); + +#define kqueue_init_hook windows_kqueue_init +int windows_kqueue_init(struct kqueue *); #endif /* ! _KQUEUE_WINDOWS_PLATFORM_H */ From d114f471c1ebcacdc31ea4b2a8ca7afaf9b5b9d4 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 04:38:47 +0000 Subject: [PATCH 0352/1120] try to fix win32 link errors git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@375 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/windows/kqueue.c | 54 ----------- vendor/libkqueue/src/windows/platform.c | 121 ++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 54 deletions(-) delete mode 100644 vendor/libkqueue/src/windows/kqueue.c create mode 100644 vendor/libkqueue/src/windows/platform.c diff --git a/vendor/libkqueue/src/windows/kqueue.c b/vendor/libkqueue/src/windows/kqueue.c deleted file mode 100644 index ab9976b2f..000000000 --- a/vendor/libkqueue/src/windows/kqueue.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2011 Mark Heily - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "../common/private.h" - -BOOL WINAPI DllMain( - HINSTANCE self, - DWORD reason, - LPVOID unused) -{ - switch (reason) { - case DLL_PROCESS_ATTACH: - /* XXX-FIXME: initialize kqtree mutex */ - if (WSAStartup(MAKEWORD(2,2), NULL) != 0) - return (FALSE); - /* TODO: bettererror handling */ - break; - - case DLL_PROCESS_DETACH: - WSACleanup(); - break; - } - - return (TRUE); -} - -void -windows_kqueue_free(struct kqueue *kq) -{ -/*XXX-FIXME close the _pipe() */ -} - -int -windows_kqueue_init(struct kqueue *kq) -{ - if (_pipe(kq->kq_sockfd, 512, _O_BINARY) == -1) { - dbg_puts("_pipe failed"); - return (-1); - } - return (0); -} diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c new file mode 100644 index 000000000..74ea0eace --- /dev/null +++ b/vendor/libkqueue/src/windows/platform.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "../common/private.h" + +/* FIXME: remove these as filters are implemented */ +const struct filter evfilt_proc = EVFILT_NOTIMPL; +const struct filter evfilt_vnode = EVFILT_NOTIMPL; +const struct filter evfilt_signal = EVFILT_NOTIMPL; +const struct filter evfilt_write = EVFILT_NOTIMPL; +const struct filter evfilt_read = EVFILT_NOTIMPL; +const struct filter evfilt_timer = EVFILT_NOTIMPL; +const struct filter evfilt_user = EVFILT_NOTIMPL; + +BOOL WINAPI DllMain( + HINSTANCE self, + DWORD reason, + LPVOID unused) +{ + switch (reason) { + case DLL_PROCESS_ATTACH: + /* XXX-FIXME: initialize kqtree mutex */ + if (WSAStartup(MAKEWORD(2,2), NULL) != 0) + return (FALSE); + /* TODO: bettererror handling */ + break; + + case DLL_PROCESS_DETACH: + WSACleanup(); + break; + } + + return (TRUE); +} + +void +windows_kqueue_free(struct kqueue *kq) +{ +/*XXX-FIXME close the _pipe() */ +} + +int +windows_kqueue_init(struct kqueue *kq) +{ + if (_pipe(kq->kq_sockfd, 512, _O_BINARY) == -1) { + dbg_puts("_pipe failed"); + return (-1); + } + return (0); +} + +int +kevent_wait( + struct kqueue *kq, + const struct timespec *timeout) +{ + return (0); +#if TODO + int n; + + dbg_puts("waiting for events"); + kq->kq_rfds = kq->kq_fds; + n = pselect(kq->kq_nfds, &kq->kq_rfds, NULL , NULL, timeout, NULL); + if (n < 0) { + if (errno == EINTR) { + dbg_puts("signal caught"); + return (-1); + } + dbg_perror("pselect(2)"); + return (-1); + } + + return (n); +#endif +} + +int +kevent_copyout(struct kqueue *kq, int nready, + struct kevent *eventlist, int nevents) +{ + return (0); +#if TODO + struct filter *filt; + int i, rv, nret; + + nret = 0; + for (i = 0; (i < EVFILT_SYSCOUNT && nready > 0 && nevents > 0); i++) { +// dbg_printf("eventlist: n = %d nevents = %d", nready, nevents); + filt = &kq->kq_filt[i]; +// dbg_printf("pfd[%d] = %d", i, filt->kf_pfd); + if (FD_ISSET(filt->kf_pfd, &kq->kq_rfds)) { + dbg_printf("pending events for filter %d (%s)", filt->kf_id, filter_name(filt->kf_id)); + rv = filt->kf_copyout(filt, eventlist, nevents); + if (rv < 0) { + dbg_puts("kevent_copyout failed"); + nret = -1; + break; + } + nret += rv; + eventlist += rv; + nevents -= rv; + nready--; + } + } + + return (nret); +#endif +} From 4d622d85119c2ee85acdbb4112fad309bec8eed2 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 04:51:20 +0000 Subject: [PATCH 0353/1120] Fix all compilation and linking issues on Win32. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@376 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/windows/platform.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index bdeddabf2..ce064d802 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -25,6 +25,10 @@ #pragma comment(lib, "Ws2_32.lib") +/* The #define doesn't seem to work, but the #pragma does.. */ +#define _CRT_SECURE_NO_WARNINGS 1 +#pragma warning( disable : 4996 ) + /* * Atomic integer operations */ From 5461d3e82302044eb2881625ec52871fc692b00e Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 05:08:54 +0000 Subject: [PATCH 0354/1120] fix solaris build failure git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@377 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 2 +- vendor/libkqueue/config.inc | 2 +- vendor/libkqueue/src/solaris/kqueue.c | 1 + vendor/libkqueue/src/solaris/platform.h | 2 ++ 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 4c85d1e14..a9ab863da 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -152,4 +152,4 @@ diff: # Used for testing on a Solaris guest VM # solaris-test: - make dist && scp -P 2222 libkqueue-1.0a.tar.gz localhost:/tmp && ssh -p 2222 localhost ". .profile ; cd /tmp ; rm -rf libkqueue-$(VERSION) ; gtar zxvf libkqueue-$(VERSION).tar.gz && cd libkqueue-$(VERSION) && ./configure && make && make check" + make dist && scp -P 2222 libkqueue-1.0a.tar.gz localhost:/tmp && ssh -p 2222 localhost ". .profile ; cd /tmp ; rm -rf libkqueue-$(VERSION) ; gtar zxvf libkqueue-$(VERSION).tar.gz && cd libkqueue-$(VERSION) && ./configure && make && KQUEUE_DEBUG=yes make check" diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index a7496d076..2b08f1a22 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -76,7 +76,7 @@ post_configure_hook() { if [ $target = "solaris" ] ; then cflags="$cflags -D__EXTENSIONS__" kqueue="$kqueue src/solaris/kqueue.c" - kevent="$kevent src/solaris/kevent.c" + kevent="src/solaris/kevent.c" evfilt_timer="src/solaris/timer.c" evfilt_user="src/solaris/user.c" evfilt_proc="" diff --git a/vendor/libkqueue/src/solaris/kqueue.c b/vendor/libkqueue/src/solaris/kqueue.c index 50feaf78a..a111aee3e 100644 --- a/vendor/libkqueue/src/solaris/kqueue.c +++ b/vendor/libkqueue/src/solaris/kqueue.c @@ -42,6 +42,7 @@ solaris_kqueue_init(struct kqueue *kq) dbg_perror("port_create(2)"); return (-1); } + dbg_printf("created event port: fd=%d", kq->kq_port); TAILQ_INIT(&kq->kq_events); return (0); } diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index 2af6606b5..9410d9421 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -41,9 +41,11 @@ /* * Hooks and prototypes */ +#undef kqueue_free_hook #define kqueue_free_hook solaris_kqueue_free void solaris_kqueue_free(struct kqueue *); +#undef kqueue_init_hook #define kqueue_init_hook solaris_kqueue_init int solaris_kqueue_init(struct kqueue *); From f94e3c911e641e06c0156781479847148624b7c9 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 05:17:43 +0000 Subject: [PATCH 0355/1120] add solaris failure note git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@378 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 4e82ae47f..f3df56c7e 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,6 +1,9 @@ HEAD ------------------------------------------------------------------------ + * NOTE: r368 is the last version to work properly on Solaris. + The HEAD fails the unit tests + * Add a counter that increments on each each kevent() call. When printing debug information within kevent(), display the value of the counter. This will be helpful when debugging a multithreaded program that may have From 95717931bc2de95a8689a2f1e3c5eaecc1661bf5 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 17:43:12 +0000 Subject: [PATCH 0356/1120] Rollback to r371 to eliminate kqtest failure on Solaris git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@379 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 3 - vendor/libkqueue/Makefile | 2 +- vendor/libkqueue/config.inc | 4 +- vendor/libkqueue/include/sys/event.h | 8 -- vendor/libkqueue/src/common/filter.c | 12 +-- vendor/libkqueue/src/common/kevent.c | 3 +- vendor/libkqueue/src/common/knote.c | 2 +- vendor/libkqueue/src/common/kqueue.c | 36 ++++++- vendor/libkqueue/src/common/private.h | 3 +- vendor/libkqueue/src/posix/kqueue.c | 47 --------- vendor/libkqueue/src/posix/platform.h | 16 +--- vendor/libkqueue/src/solaris/kqueue.c | 7 -- vendor/libkqueue/src/solaris/platform.h | 2 - vendor/libkqueue/src/windows/platform.c | 121 ------------------------ vendor/libkqueue/src/windows/platform.h | 25 +---- 15 files changed, 49 insertions(+), 242 deletions(-) delete mode 100644 vendor/libkqueue/src/posix/kqueue.c delete mode 100644 vendor/libkqueue/src/windows/platform.c diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index f3df56c7e..4e82ae47f 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,9 +1,6 @@ HEAD ------------------------------------------------------------------------ - * NOTE: r368 is the last version to work properly on Solaris. - The HEAD fails the unit tests - * Add a counter that increments on each each kevent() call. When printing debug information within kevent(), display the value of the counter. This will be helpful when debugging a multithreaded program that may have diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index a9ab863da..4c85d1e14 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -152,4 +152,4 @@ diff: # Used for testing on a Solaris guest VM # solaris-test: - make dist && scp -P 2222 libkqueue-1.0a.tar.gz localhost:/tmp && ssh -p 2222 localhost ". .profile ; cd /tmp ; rm -rf libkqueue-$(VERSION) ; gtar zxvf libkqueue-$(VERSION).tar.gz && cd libkqueue-$(VERSION) && ./configure && make && KQUEUE_DEBUG=yes make check" + make dist && scp -P 2222 libkqueue-1.0a.tar.gz localhost:/tmp && ssh -p 2222 localhost ". .profile ; cd /tmp ; rm -rf libkqueue-$(VERSION) ; gtar zxvf libkqueue-$(VERSION).tar.gz && cd libkqueue-$(VERSION) && ./configure && make && make check" diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index 2b08f1a22..968e3dd6e 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -50,7 +50,7 @@ pre_configure_hook() { post_configure_hook() { finalize target "$target" - kqueue="src/posix/kqueue.c" + kqueue="" kevent="src/posix/kevent.c" evfilt_signal="src/posix/signal.c" evfilt_proc="src/$target/proc.c" @@ -75,7 +75,7 @@ post_configure_hook() { if [ $target = "solaris" ] ; then cflags="$cflags -D__EXTENSIONS__" - kqueue="$kqueue src/solaris/kqueue.c" + kqueue="src/solaris/kqueue.c" kevent="src/solaris/kevent.c" evfilt_timer="src/solaris/timer.c" evfilt_user="src/solaris/user.c" diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index e0f20e2f8..5cc71d366 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -40,11 +40,6 @@ #define LIBKQUEUE 1 #endif -#ifndef _WIN32 -#define __declspec(x) /* */ -#define dllexport 0 -#endif - struct timespec; #define EVFILT_READ (-1) @@ -175,10 +170,7 @@ struct kevent { extern "C" { #endif -__declspec(dllexport) int kqueue(void); - -__declspec(dllexport) int kevent(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index c10886db2..e10a38ca7 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -123,23 +123,17 @@ filter_unregister_all(struct kqueue *kq) int filter_socketpair(struct filter *filt) { +#ifndef _WIN32 int sockfd[2]; -#ifdef _WIN32 - if (_pipe(sockfd, 512, _O_BINARY) == -1) { - dbg_puts("_pipe failed"); - return (-1); - } - /* FIXME: want nonblocking behavior for writer */ - filt->kf_wfd = sockfd[0]; - filt->kf_pfd = sockfd[1]; -#else if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) return (-1); fcntl(sockfd[0], F_SETFL, O_NONBLOCK); filt->kf_wfd = sockfd[0]; filt->kf_pfd = sockfd[1]; +#else +#warning FIXME function has no effect #endif return (0); } diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index b5167dd5c..c08156dc2 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -227,11 +227,10 @@ kevent_copyin(struct kqueue *kq, const struct kevent *src, int nchanges, return (nret); } -VISIBLE_DECL(int, +int VISIBLE kevent(int kqfd, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout) -) { static unsigned int _kevent_counter = 0; struct kqueue *kq; diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 5625f2189..6b707e3d0 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -156,7 +156,7 @@ knote_get_socket_type(struct knote *kn) return (0); break; default: - dbg_perror("getsockopt(3)"); + dbg_printf("getsockopt(3) failed: %s", strerror(errno)); return (-1); } } else { diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index db6f6d144..2b02c8bc4 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -24,7 +24,10 @@ #include "private.h" +#ifndef NDEBUG int KQUEUE_DEBUG = 0; +#endif + static RB_HEAD(kqt, kqueue) kqtree = RB_INITIALIZER(&kqtree); static pthread_rwlock_t kqtree_mtx; @@ -145,9 +148,14 @@ kqueue_get(int kq) return (ent); } -VISIBLE_DECL(int, kqueue(void)) +int VISIBLE +kqueue(void) { +#ifdef _WIN32 + static int kqueue_id = 0; +#endif struct kqueue *kq; + int tmp; kq = calloc(1, sizeof(*kq)); if (kq == NULL) @@ -164,8 +172,21 @@ VISIBLE_DECL(int, kqueue(void)) KQUEUE_DEBUG = (getenv("KQUEUE_DEBUG") == NULL) ? 0 : 1; #endif +#ifdef _WIN32 + pthread_rwlock_wrlock(&kqtree_mtx); + kqueue_id++; + pthread_rwlock_unlock(&kqtree_mtx); + kq->kq_sockfd[0] = kqueue_id; + kq->kq_sockfd[1] = kqueue_id; +#else + if (socketpair(AF_UNIX, SOCK_STREAM, 0, kq->kq_sockfd) < 0) + goto errout_unlocked; +#endif + +#ifdef kqueue_init_hook if (kqueue_init_hook(kq) < 0) goto errout_unlocked; +#endif pthread_rwlock_wrlock(&kqtree_mtx); if (kqueue_gc() < 0) @@ -183,7 +204,18 @@ VISIBLE_DECL(int, kqueue(void)) pthread_rwlock_unlock(&kqtree_mtx); errout_unlocked: - kqueue_free_hook(kq); + if (kq->kq_sockfd[0] != kq->kq_sockfd[1]) { + tmp = errno; +#ifndef _WIN32 + (void)close(kq->kq_sockfd[0]); + (void)close(kq->kq_sockfd[1]); +#endif + errno = tmp; + } +#if defined(__sun__) + if (kq->kq_port > 0) + close(kq->kq_port); +#endif free(kq); return (-1); } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 456c631c0..40e82fbef 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -43,9 +43,10 @@ struct evfilt_data; /* Maximum events returnable in a single kevent() call */ #define MAX_KEVENT 512 +#ifndef NDEBUG + extern int KQUEUE_DEBUG; -#ifndef NDEBUG #define dbg_puts(str) do { \ if (KQUEUE_DEBUG) \ diff --git a/vendor/libkqueue/src/posix/kqueue.c b/vendor/libkqueue/src/posix/kqueue.c deleted file mode 100644 index b2e4f055b..000000000 --- a/vendor/libkqueue/src/posix/kqueue.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2011 Mark Heily - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "private.h" - -int -posix_kqueue_init(struct kqueue *kq) -{ - if (socketpair(AF_UNIX, SOCK_STREAM, 0, kq->kq_sockfd) < 0) { - dbg_perror("socketpair"); - kq->kq_sockfd[0] = -1; - kq->kq_sockfd[1] = -1; - return (-1); - } - - return (0); -} - -void -posix_kqueue_free(struct kqueue *kq) -{ - if (kq->kq_sockfd[0] != -1) - (void) close(kq->kq_sockfd[0]); - if (kq->kq_sockfd[1] != -1) - (void) close(kq->kq_sockfd[1]); -} diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 1974bc0a6..44ded1937 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -17,14 +17,7 @@ #ifndef _KQUEUE_POSIX_PLATFORM_H #define _KQUEUE_POSIX_PLATFORM_H -/* - * Hooks and prototypes - */ -#define kqueue_free_hook posix_kqueue_free -void posix_kqueue_free(struct kqueue *); - -#define kqueue_init_hook posix_kqueue_init -int posix_kqueue_init(struct kqueue *); +#include "../../include/sys/event.h" /* * GCC-compatible atomic integer operations @@ -33,7 +26,7 @@ int posix_kqueue_init(struct kqueue *); #define atomic_dec(p) __sync_sub_and_fetch((p), 1) #define CONSTRUCTOR int __attribute__ ((constructor)) -#define VISIBLE +#define VISIBLE __attribute__((visibility("default"))) #define HIDDEN __attribute__((visibility("hidden"))) #include @@ -44,9 +37,4 @@ int posix_kqueue_init(struct kqueue *); #include #include -#define VISIBLE_DECL(t,x) t __attribute__((visibility("default"))) x - -#include "../../include/sys/event.h" - #endif /* ! _KQUEUE_POSIX_PLATFORM_H */ - diff --git a/vendor/libkqueue/src/solaris/kqueue.c b/vendor/libkqueue/src/solaris/kqueue.c index a111aee3e..df6a1a2da 100644 --- a/vendor/libkqueue/src/solaris/kqueue.c +++ b/vendor/libkqueue/src/solaris/kqueue.c @@ -22,13 +22,9 @@ #include "sys/event.h" #include "private.h" -extern int posix_kqueue_init(struct kqueue *kq); -extern void posix_kqueue_free(struct kqueue *kq); - void solaris_kqueue_free(struct kqueue *kq) { - posix_kqueue_free(kq); if (kq->kq_port > 0) close(kq->kq_port); } @@ -36,13 +32,10 @@ solaris_kqueue_free(struct kqueue *kq) int solaris_kqueue_init(struct kqueue *kq) { - if (posix_kqueue_init(kq) < 0) - return (-1); if ((kq->kq_port = port_create()) < 0) { dbg_perror("port_create(2)"); return (-1); } - dbg_printf("created event port: fd=%d", kq->kq_port); TAILQ_INIT(&kq->kq_events); return (0); } diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index 9410d9421..2af6606b5 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -41,11 +41,9 @@ /* * Hooks and prototypes */ -#undef kqueue_free_hook #define kqueue_free_hook solaris_kqueue_free void solaris_kqueue_free(struct kqueue *); -#undef kqueue_init_hook #define kqueue_init_hook solaris_kqueue_init int solaris_kqueue_init(struct kqueue *); diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c deleted file mode 100644 index 74ea0eace..000000000 --- a/vendor/libkqueue/src/windows/platform.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2011 Mark Heily - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "../common/private.h" - -/* FIXME: remove these as filters are implemented */ -const struct filter evfilt_proc = EVFILT_NOTIMPL; -const struct filter evfilt_vnode = EVFILT_NOTIMPL; -const struct filter evfilt_signal = EVFILT_NOTIMPL; -const struct filter evfilt_write = EVFILT_NOTIMPL; -const struct filter evfilt_read = EVFILT_NOTIMPL; -const struct filter evfilt_timer = EVFILT_NOTIMPL; -const struct filter evfilt_user = EVFILT_NOTIMPL; - -BOOL WINAPI DllMain( - HINSTANCE self, - DWORD reason, - LPVOID unused) -{ - switch (reason) { - case DLL_PROCESS_ATTACH: - /* XXX-FIXME: initialize kqtree mutex */ - if (WSAStartup(MAKEWORD(2,2), NULL) != 0) - return (FALSE); - /* TODO: bettererror handling */ - break; - - case DLL_PROCESS_DETACH: - WSACleanup(); - break; - } - - return (TRUE); -} - -void -windows_kqueue_free(struct kqueue *kq) -{ -/*XXX-FIXME close the _pipe() */ -} - -int -windows_kqueue_init(struct kqueue *kq) -{ - if (_pipe(kq->kq_sockfd, 512, _O_BINARY) == -1) { - dbg_puts("_pipe failed"); - return (-1); - } - return (0); -} - -int -kevent_wait( - struct kqueue *kq, - const struct timespec *timeout) -{ - return (0); -#if TODO - int n; - - dbg_puts("waiting for events"); - kq->kq_rfds = kq->kq_fds; - n = pselect(kq->kq_nfds, &kq->kq_rfds, NULL , NULL, timeout, NULL); - if (n < 0) { - if (errno == EINTR) { - dbg_puts("signal caught"); - return (-1); - } - dbg_perror("pselect(2)"); - return (-1); - } - - return (n); -#endif -} - -int -kevent_copyout(struct kqueue *kq, int nready, - struct kevent *eventlist, int nevents) -{ - return (0); -#if TODO - struct filter *filt; - int i, rv, nret; - - nret = 0; - for (i = 0; (i < EVFILT_SYSCOUNT && nready > 0 && nevents > 0); i++) { -// dbg_printf("eventlist: n = %d nevents = %d", nready, nevents); - filt = &kq->kq_filt[i]; -// dbg_printf("pfd[%d] = %d", i, filt->kf_pfd); - if (FD_ISSET(filt->kf_pfd, &kq->kq_rfds)) { - dbg_printf("pending events for filter %d (%s)", filt->kf_id, filter_name(filt->kf_id)); - rv = filt->kf_copyout(filt, eventlist, nevents); - if (rv < 0) { - dbg_puts("kevent_copyout failed"); - nret = -1; - break; - } - nret += rv; - eventlist += rv; - nevents -= rv; - nready--; - } - } - - return (nret); -#endif -} diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index ce064d802..8301c222d 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -17,17 +17,10 @@ #ifndef _KQUEUE_WINDOWS_PLATFORM_H #define _KQUEUE_WINDOWS_PLATFORM_H -#include -#include -#include -#include -#include +#include +#include -#pragma comment(lib, "Ws2_32.lib") - -/* The #define doesn't seem to work, but the #pragma does.. */ -#define _CRT_SECURE_NO_WARNINGS 1 -#pragma warning( disable : 4996 ) +#include "../../include/kqueue.h" /* * Atomic integer operations @@ -73,16 +66,4 @@ typedef CRITICAL_SECTION pthread_rwlock_t; #define pthread_rwlock_unlock _cs_unlock #define pthread_rwlock_init(x,y) _cs_init((x)) -#define VISIBLE_DECL(t,x) __declspec(dllexport) t x - -#include "../../include/sys/event.h" -/* - * Hooks and prototypes - */ -#define kqueue_free_hook windows_kqueue_free -void windows_kqueue_free(struct kqueue *); - -#define kqueue_init_hook windows_kqueue_init -int windows_kqueue_init(struct kqueue *); - #endif /* ! _KQUEUE_WINDOWS_PLATFORM_H */ From abd5e8e61137ec8ea5c6b1874f40b0fafe0e6ece Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 17:49:12 +0000 Subject: [PATCH 0357/1120] Add win32-specific API git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@380 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/include/sys/event.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index 5cc71d366..816b07feb 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -170,10 +170,25 @@ struct kevent { extern "C" { #endif +#ifdef _WIN32 + +__declspec(dllexport) HANDLE +CreateEventQueue(void); + +__declspec(dllexport) HANDLE +WaitForEventQueueObject(HANDLE kq, const struct kevent *changelist, int nchanges, + struct kevent *eventlist, int nevents, + const struct timespec *timeout); + +__declspec(dllexport) void +DestroyEventQueue(HANDLE); + +#else int kqueue(void); int kevent(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); +#endif #ifdef __cplusplus } From bcddc49d94d6e4870995866297e70e1c16aa6deb Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 17:51:18 +0000 Subject: [PATCH 0358/1120] Ensure that KQUEUE_DEBUG is always defined. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@381 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/knote.c | 2 +- vendor/libkqueue/src/common/kqueue.c | 2 -- vendor/libkqueue/src/common/private.h | 3 +-- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 6b707e3d0..5625f2189 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -156,7 +156,7 @@ knote_get_socket_type(struct knote *kn) return (0); break; default: - dbg_printf("getsockopt(3) failed: %s", strerror(errno)); + dbg_perror("getsockopt(3)"); return (-1); } } else { diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 2b02c8bc4..c22dc651e 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -24,9 +24,7 @@ #include "private.h" -#ifndef NDEBUG int KQUEUE_DEBUG = 0; -#endif static RB_HEAD(kqt, kqueue) kqtree = RB_INITIALIZER(&kqtree); diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 40e82fbef..c77d19ea3 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -43,11 +43,10 @@ struct evfilt_data; /* Maximum events returnable in a single kevent() call */ #define MAX_KEVENT 512 -#ifndef NDEBUG extern int KQUEUE_DEBUG; - +#ifndef NDEBUG #define dbg_puts(str) do { \ if (KQUEUE_DEBUG) \ fprintf(stderr, "KQ [%d]: %s(): %s\n", THREAD_ID, __func__,str); \ From d878b1f2799a65ff107c2174cdd8b6f4aedd862a Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 18:17:12 +0000 Subject: [PATCH 0359/1120] Use dynamic linking instead of static linking git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@382 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/config.inc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/test/config.inc b/vendor/libkqueue/test/config.inc index 4906ab355..885933a22 100755 --- a/vendor/libkqueue/test/config.inc +++ b/vendor/libkqueue/test/config.inc @@ -12,12 +12,10 @@ pre_configure_hook() { && sys_event_h="sys/event.h" \ || { sys_event_h="../include/sys/event.h" - cflags="$cflags -I../include" - ldadd="$ldadd ../libkqueue.a -lpthread -lrt" + cflags="$cflags -I../include -L.." + ldadd="$ldadd -lkqueue -lpthread -lrt" } - - check_symbol $sys_event_h EV_DISPATCH check_symbol $sys_event_h EV_RECEIPT check_symbol $sys_event_h NOTE_TRUNCATE From 88ac37e8c61121df97f69e4467317b1020675cde Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 18:39:22 +0000 Subject: [PATCH 0360/1120] Do not build a static library by default git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@383 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 4c85d1e14..700b2a232 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -22,7 +22,7 @@ include config.mk .PHONY :: install uninstall check dist dist-upload publish-www clean merge distclean fresh-build rpm edit cscope -all: $(PROGRAM).so $(PROGRAM).a +all: $(PROGRAM).so %.o: %.c $(DEPS) $(CC) -c -o $@ -I./include -I./src/common $(CFLAGS) $< From 36cf42a05a4e8ceea9bff0e5cf470c6dbce946b9 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 18:47:13 +0000 Subject: [PATCH 0361/1120] force the use of 32-bit libgcc (osol bug #6223255) git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@384 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile index 9759e8238..4db724f7b 100644 --- a/vendor/libkqueue/test/Makefile +++ b/vendor/libkqueue/test/Makefile @@ -22,7 +22,7 @@ kqtest: $(SOURCES) $(CC) -o kqtest $(CFLAGS) $(SOURCES) $(LDADD) check: kqtest - ./kqtest + LD_LIBRARY_PATH="..:/usr/sfw/lib/64" ./kqtest valgrind: kqtest valgrind --tool=memcheck --leak-check=full --show-reachable=yes --num-callers=20 --track-fds=yes ./kqtest From 22524a572a1e8918b8e8a12a4e18cdc474a4c4f1 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 18:47:48 +0000 Subject: [PATCH 0362/1120] ensure make clean before make check git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@385 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 700b2a232..eb14f5c74 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -57,7 +57,7 @@ uninstall: rm -f $(MANDIR)/man2/kevent.2 rmdir $(INCLUDEDIR)/kqueue/sys $(INCLUDEDIR)/kqueue -check: $(PROGRAM).a +check: clean $(PROGRAM).so cd test && ./configure && make check debug-check: clean $(PROGRAM).a From 98710043e1d63344f846c6953b79087df5792646 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 19:13:10 +0000 Subject: [PATCH 0363/1120] Build libkqueue.so.0.0 and create symlinks to it for libkqueue.so and libkqueue.so.0, instead of the other way around. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@386 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index eb14f5c74..85ac831a4 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -22,7 +22,7 @@ include config.mk .PHONY :: install uninstall check dist dist-upload publish-www clean merge distclean fresh-build rpm edit cscope -all: $(PROGRAM).so +all: $(PROGRAM).so.$(ABI_VERSION) %.o: %.c $(DEPS) $(CC) -c -o $@ -I./include -I./src/common $(CFLAGS) $< @@ -30,15 +30,17 @@ all: $(PROGRAM).so $(PROGRAM).a: $(OBJS) $(AR) rcs $(PROGRAM).a $(OBJS) -$(PROGRAM).so: $(OBJS) +$(PROGRAM).so.$(ABI_VERSION): $(OBJS) $(LD) $(LDFLAGS) $(OBJS) $(LDADD) + $(LN) -sf $(PROGRAM).so.$(ABI_VERSION) $(PROGRAM).so.$(ABI_MAJOR) $(LN) -sf $(PROGRAM).so.$(ABI_VERSION) $(PROGRAM).so -install: $(PROGRAM).so +install: $(PROGRAM).so.$(ABI_VERSION) $(INSTALL) -d -m 755 $(INCLUDEDIR)/kqueue/sys $(INSTALL) -m 644 include/sys/event.h $(INCLUDEDIR)/kqueue/sys/event.h $(INSTALL) -d -m 755 $(LIBDIR) $(INSTALL) -m 644 $(PROGRAM).so.$(ABI_VERSION) $(LIBDIR) + $(INSTALL) -m 644 $(PROGRAM).so.$(ABI_MAJOR) $(LIBDIR) $(LN) -sf $(PROGRAM).so.$(ABI_VERSION) $(LIBDIR)/$(PROGRAM).so.$(ABI_MAJOR) $(LN) -sf $(PROGRAM).so.$(ABI_VERSION) $(LIBDIR)/$(PROGRAM).so $(INSTALL) -m 644 $(PROGRAM).la $(LIBDIR) @@ -57,10 +59,10 @@ uninstall: rm -f $(MANDIR)/man2/kevent.2 rmdir $(INCLUDEDIR)/kqueue/sys $(INCLUDEDIR)/kqueue -check: clean $(PROGRAM).so +check: clean $(PROGRAM).so.$(ABI_VERSION) cd test && ./configure && make check -debug-check: clean $(PROGRAM).a +debug-check: clean cd test && ./configure && KQUEUE_DEBUG=y make check $(DISTFILE): $(SOURCES) $(HEADERS) @@ -82,7 +84,7 @@ dist-upload: $(DISTFILE) scp $(DISTFILE) $(DIST) clean: - rm -f tags *.a *.so *.so.* + rm -f tags *.a *.so *.so.* *.so.*.* find src -name '*.o' -exec rm {} \; rm -rf pkg cd test && make clean || true From fec7ef410ed0e5ba7ef9634ee2fd8a1ce3c151ad Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 19:17:44 +0000 Subject: [PATCH 0364/1120] improve CONSTRUCTOR git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@387 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kqueue.c | 3 ++- vendor/libkqueue/src/common/private.h | 2 ++ vendor/libkqueue/src/posix/platform.h | 2 +- vendor/libkqueue/src/windows/platform.h | 7 +++++-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index c22dc651e..40b1929c0 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -30,10 +30,11 @@ int KQUEUE_DEBUG = 0; static RB_HEAD(kqt, kqueue) kqtree = RB_INITIALIZER(&kqtree); static pthread_rwlock_t kqtree_mtx; -CONSTRUCTOR +int CONSTRUCTOR _libkqueue_init(void) { pthread_rwlock_init(&kqtree_mtx, NULL); + dbg_puts("library initialization complete"); return (0); } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index c77d19ea3..6727da8fc 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -195,4 +195,6 @@ int kqueue_validate(struct kqueue *); #define kqueue_lock(kq) pthread_mutex_lock(&(kq)->kq_mtx) #define kqueue_unlock(kq) pthread_mutex_unlock(&(kq)->kq_mtx) +int CONSTRUCTOR _libkqueue_init(void); + #endif /* ! _KQUEUE_PRIVATE_H */ diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 44ded1937..6847e4c97 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -25,7 +25,7 @@ #define atomic_inc(p) __sync_add_and_fetch((p), 1) #define atomic_dec(p) __sync_sub_and_fetch((p), 1) -#define CONSTRUCTOR int __attribute__ ((constructor)) +#define CONSTRUCTOR __attribute__ ((constructor)) #define VISIBLE __attribute__((visibility("default"))) #define HIDDEN __attribute__((visibility("hidden"))) diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 8301c222d..2d276f996 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -28,8 +28,11 @@ #define atomic_inc InterlockedIncrement #define atomic_dec InterlockedDecrement -/* DllMain() is the only available constructor function */ -#define CONSTRUCTOR int +/* Windows does not support this attribute. + DllMain() is the only available constructor function. + This means the constructor must be called from within DllMain(). + */ +#define CONSTRUCTOR /* Function visibility macros */ #define VISIBLE __declspec(dllexport) From f96e8cd44a0162aec94b2f7e13ebbf6e0a6dc595 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 15 Jan 2011 20:10:20 +0000 Subject: [PATCH 0365/1120] add win32 fixes back git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@388 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/filter.c | 13 ++- vendor/libkqueue/src/windows/platform.c | 121 ++++++++++++++++++++++++ vendor/libkqueue/src/windows/platform.h | 15 ++- 3 files changed, 143 insertions(+), 6 deletions(-) create mode 100644 vendor/libkqueue/src/windows/platform.c diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index e10a38ca7..06fa8aa72 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -123,18 +123,25 @@ filter_unregister_all(struct kqueue *kq) int filter_socketpair(struct filter *filt) { -#ifndef _WIN32 int sockfd[2]; +#ifdef _WIN32 + if (_pipe(sockfd, 512, _O_BINARY) == -1) { + dbg_puts("_pipe failed"); + return (-1); + } + /* FIXME: want nonblocking behavior for writer */ + filt->kf_wfd = sockfd[0]; + filt->kf_pfd = sockfd[1]; +#else if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) return (-1); fcntl(sockfd[0], F_SETFL, O_NONBLOCK); filt->kf_wfd = sockfd[0]; filt->kf_pfd = sockfd[1]; -#else -#warning FIXME function has no effect #endif + return (0); } diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c new file mode 100644 index 000000000..74ea0eace --- /dev/null +++ b/vendor/libkqueue/src/windows/platform.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "../common/private.h" + +/* FIXME: remove these as filters are implemented */ +const struct filter evfilt_proc = EVFILT_NOTIMPL; +const struct filter evfilt_vnode = EVFILT_NOTIMPL; +const struct filter evfilt_signal = EVFILT_NOTIMPL; +const struct filter evfilt_write = EVFILT_NOTIMPL; +const struct filter evfilt_read = EVFILT_NOTIMPL; +const struct filter evfilt_timer = EVFILT_NOTIMPL; +const struct filter evfilt_user = EVFILT_NOTIMPL; + +BOOL WINAPI DllMain( + HINSTANCE self, + DWORD reason, + LPVOID unused) +{ + switch (reason) { + case DLL_PROCESS_ATTACH: + /* XXX-FIXME: initialize kqtree mutex */ + if (WSAStartup(MAKEWORD(2,2), NULL) != 0) + return (FALSE); + /* TODO: bettererror handling */ + break; + + case DLL_PROCESS_DETACH: + WSACleanup(); + break; + } + + return (TRUE); +} + +void +windows_kqueue_free(struct kqueue *kq) +{ +/*XXX-FIXME close the _pipe() */ +} + +int +windows_kqueue_init(struct kqueue *kq) +{ + if (_pipe(kq->kq_sockfd, 512, _O_BINARY) == -1) { + dbg_puts("_pipe failed"); + return (-1); + } + return (0); +} + +int +kevent_wait( + struct kqueue *kq, + const struct timespec *timeout) +{ + return (0); +#if TODO + int n; + + dbg_puts("waiting for events"); + kq->kq_rfds = kq->kq_fds; + n = pselect(kq->kq_nfds, &kq->kq_rfds, NULL , NULL, timeout, NULL); + if (n < 0) { + if (errno == EINTR) { + dbg_puts("signal caught"); + return (-1); + } + dbg_perror("pselect(2)"); + return (-1); + } + + return (n); +#endif +} + +int +kevent_copyout(struct kqueue *kq, int nready, + struct kevent *eventlist, int nevents) +{ + return (0); +#if TODO + struct filter *filt; + int i, rv, nret; + + nret = 0; + for (i = 0; (i < EVFILT_SYSCOUNT && nready > 0 && nevents > 0); i++) { +// dbg_printf("eventlist: n = %d nevents = %d", nready, nevents); + filt = &kq->kq_filt[i]; +// dbg_printf("pfd[%d] = %d", i, filt->kf_pfd); + if (FD_ISSET(filt->kf_pfd, &kq->kq_rfds)) { + dbg_printf("pending events for filter %d (%s)", filt->kf_id, filter_name(filt->kf_id)); + rv = filt->kf_copyout(filt, eventlist, nevents); + if (rv < 0) { + dbg_puts("kevent_copyout failed"); + nret = -1; + break; + } + nret += rv; + eventlist += rv; + nevents -= rv; + nready--; + } + } + + return (nret); +#endif +} diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 2d276f996..7fa58ce57 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -17,10 +17,19 @@ #ifndef _KQUEUE_WINDOWS_PLATFORM_H #define _KQUEUE_WINDOWS_PLATFORM_H -#include -#include +#include +#include +#include +#include +#include -#include "../../include/kqueue.h" +#pragma comment(lib, "Ws2_32.lib") + +/* The #define doesn't seem to work, but the #pragma does.. */ +#define _CRT_SECURE_NO_WARNINGS 1 +#pragma warning( disable : 4996 ) + +#include "../../include/sys/event.h" /* * Atomic integer operations From 6b96cfb77e1d1093851713257344333cbf4eee56 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 16 Jan 2011 19:40:37 +0000 Subject: [PATCH 0366/1120] improve win32 api git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@389 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/include/sys/event.h | 10 +-- vendor/libkqueue/src/windows/platform.c | 90 ++++++++----------------- 2 files changed, 33 insertions(+), 67 deletions(-) diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index 816b07feb..8e3eee73d 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -172,16 +172,18 @@ extern "C" { #ifdef _WIN32 -__declspec(dllexport) HANDLE +#define EVENT_QUEUE struct event_queue * + +__declspec(dllexport) EVENT_QUEUE CreateEventQueue(void); -__declspec(dllexport) HANDLE -WaitForEventQueueObject(HANDLE kq, const struct kevent *changelist, int nchanges, +__declspec(dllexport) int +WaitForEventQueueObject(EVENT_QUEUE kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); __declspec(dllexport) void -DestroyEventQueue(HANDLE); +DestroyEventQueue(EVENT_QUEUE); #else int kqueue(void); diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 74ea0eace..c4ba8f2df 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -25,6 +25,12 @@ const struct filter evfilt_read = EVFILT_NOTIMPL; const struct filter evfilt_timer = EVFILT_NOTIMPL; const struct filter evfilt_user = EVFILT_NOTIMPL; +struct event_queue { + HANDLE notifier; + HANDLE events[MAXIMUM_WAIT_OBJECTS]; + size_t nevents; +}; + BOOL WINAPI DllMain( HINSTANCE self, DWORD reason, @@ -46,76 +52,34 @@ BOOL WINAPI DllMain( return (TRUE); } -void -windows_kqueue_free(struct kqueue *kq) +__declspec(dllexport) EVENT_QUEUE +CreateEventQueue(void) { -/*XXX-FIXME close the _pipe() */ -} + EVENT_QUEUE *evq; -int -windows_kqueue_init(struct kqueue *kq) -{ - if (_pipe(kq->kq_sockfd, 512, _O_BINARY) == -1) { - dbg_puts("_pipe failed"); - return (-1); - } - return (0); -} - -int -kevent_wait( - struct kqueue *kq, - const struct timespec *timeout) -{ - return (0); -#if TODO - int n; - - dbg_puts("waiting for events"); - kq->kq_rfds = kq->kq_fds; - n = pselect(kq->kq_nfds, &kq->kq_rfds, NULL , NULL, timeout, NULL); - if (n < 0) { - if (errno == EINTR) { - dbg_puts("signal caught"); - return (-1); - } - dbg_perror("pselect(2)"); - return (-1); + evq = calloc(1, sizeof(*evq)); + if (evq == NULL) + return (NULL); + evq->notifier = CreateEvent(NULL, FALSE, FALSE, NULL); + if (evq->notifier == NULL) { + free(evq); + return (NULL); } - return (n); -#endif + return (evq); } -int -kevent_copyout(struct kqueue *kq, int nready, - struct kevent *eventlist, int nevents) +__declspec(dllexport) int +WaitForEventQueueObject(EVENT_QUEUE kq, const struct kevent *changelist, int nchanges, + struct kevent *eventlist, int nevents, + const struct timespec *timeout) { return (0); -#if TODO - struct filter *filt; - int i, rv, nret; - - nret = 0; - for (i = 0; (i < EVFILT_SYSCOUNT && nready > 0 && nevents > 0); i++) { -// dbg_printf("eventlist: n = %d nevents = %d", nready, nevents); - filt = &kq->kq_filt[i]; -// dbg_printf("pfd[%d] = %d", i, filt->kf_pfd); - if (FD_ISSET(filt->kf_pfd, &kq->kq_rfds)) { - dbg_printf("pending events for filter %d (%s)", filt->kf_id, filter_name(filt->kf_id)); - rv = filt->kf_copyout(filt, eventlist, nevents); - if (rv < 0) { - dbg_puts("kevent_copyout failed"); - nret = -1; - break; - } - nret += rv; - eventlist += rv; - nevents -= rv; - nready--; - } - } +} - return (nret); -#endif +__declspec(dllexport) void +DestroyEventQueue(EVENT_QUEUE kq) +{ + CloseHandle(kq->notifier); + free(kq); } From 9d7e34438412758ecb02e408a0649d23c25e80be Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 16 Jan 2011 20:19:32 +0000 Subject: [PATCH 0367/1120] git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@390 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/windows/platform.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 7fa58ce57..c91a012b3 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -17,9 +17,14 @@ #ifndef _KQUEUE_WINDOWS_PLATFORM_H #define _KQUEUE_WINDOWS_PLATFORM_H +/* Reduces build time by omitting extra system headers */ +#define WIN32_LEAN_AND_MEAN + #include #include #include +#include +#include #include #include From 40f9883900aba702658bbf70bbb424b2384b9c73 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 16 Jan 2011 23:29:12 +0000 Subject: [PATCH 0368/1120] checkpoint of win32 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@391 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/include/sys/event.h | 2 +- vendor/libkqueue/libkqueue.vcxproj | 88 +++++++++++++++++++++++++ vendor/libkqueue/src/common/private.h | 1 + vendor/libkqueue/src/windows/platform.c | 21 +++--- vendor/libkqueue/src/windows/platform.h | 8 +++ 5 files changed, 110 insertions(+), 10 deletions(-) create mode 100644 vendor/libkqueue/libkqueue.vcxproj diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index 8e3eee73d..9f9f13e8e 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -172,7 +172,7 @@ extern "C" { #ifdef _WIN32 -#define EVENT_QUEUE struct event_queue * +#define EVENT_QUEUE struct kqueue * __declspec(dllexport) EVENT_QUEUE CreateEventQueue(void); diff --git a/vendor/libkqueue/libkqueue.vcxproj b/vendor/libkqueue/libkqueue.vcxproj new file mode 100644 index 000000000..9da03dd9f --- /dev/null +++ b/vendor/libkqueue/libkqueue.vcxproj @@ -0,0 +1,88 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + Win32Proj + + + + DynamicLibrary + true + + + DynamicLibrary + false + + + + + + + + + + + + + true + + + true + + + + WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBKQUEUE_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + + + MachineX86 + true + Windows + + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBKQUEUE_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + MachineX86 + true + Windows + true + true + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 6727da8fc..6377043b8 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -148,6 +148,7 @@ struct kqueue { fd_set kq_fds, kq_rfds; int kq_nfds; pthread_mutex_t kq_mtx; +KQUEUE_PLATFORM_SPECIFIC; #ifdef __sun__ int kq_port; /* see: port_create(2) */ TAILQ_HEAD(event_buf_listhead,event_buf) kq_events; diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index c4ba8f2df..cb6ff112d 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -25,12 +25,6 @@ const struct filter evfilt_read = EVFILT_NOTIMPL; const struct filter evfilt_timer = EVFILT_NOTIMPL; const struct filter evfilt_user = EVFILT_NOTIMPL; -struct event_queue { - HANDLE notifier; - HANDLE events[MAXIMUM_WAIT_OBJECTS]; - size_t nevents; -}; - BOOL WINAPI DllMain( HINSTANCE self, DWORD reason, @@ -41,6 +35,8 @@ BOOL WINAPI DllMain( /* XXX-FIXME: initialize kqtree mutex */ if (WSAStartup(MAKEWORD(2,2), NULL) != 0) return (FALSE); + if (_libkqueue_init() < 0) + return (FALSE); /* TODO: bettererror handling */ break; @@ -55,13 +51,20 @@ BOOL WINAPI DllMain( __declspec(dllexport) EVENT_QUEUE CreateEventQueue(void) { - EVENT_QUEUE *evq; + EVENT_QUEUE evq; + int kqfd; + + kqfd = kqueue(); + if (kqfd < 0) + return (NULL); + + evq = calloc(1, sizeof(*evq)); if (evq == NULL) return (NULL); - evq->notifier = CreateEvent(NULL, FALSE, FALSE, NULL); - if (evq->notifier == NULL) { + evq->kq_handle = CreateEvent(NULL, FALSE, FALSE, NULL); + if (evq->kq_handle == NULL) { free(evq); return (NULL); } diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index c91a012b3..8b598d6ba 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -42,6 +42,14 @@ #define atomic_inc InterlockedIncrement #define atomic_dec InterlockedDecrement +/* + * Additional members of struct kqueue + */ +#define KQUEUE_PLATFORM_SPECIFIC \ + HANDLE kq_handle; \ + HANDLE kq_events[MAXIMUM_WAIT_OBJECTS]; \ + size_t kq_nevents + /* Windows does not support this attribute. DllMain() is the only available constructor function. This means the constructor must be called from within DllMain(). From 00b5490f8df1194185599d5abe403babbf57bfe8 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 17 Jan 2011 01:05:25 +0000 Subject: [PATCH 0369/1120] more win32 stuff git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@392 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/include/sys/event.h | 11 ++----- vendor/libkqueue/src/common/kqueue.c | 11 +------ vendor/libkqueue/src/common/private.h | 8 ++---- vendor/libkqueue/src/linux/platform.h | 1 + vendor/libkqueue/src/solaris/platform.h | 7 +++++ vendor/libkqueue/src/windows/platform.c | 38 ++++++------------------- vendor/libkqueue/src/windows/platform.h | 10 +++++++ 7 files changed, 33 insertions(+), 53 deletions(-) diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index 9f9f13e8e..f72bce6e3 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -172,19 +172,14 @@ extern "C" { #ifdef _WIN32 -#define EVENT_QUEUE struct kqueue * - -__declspec(dllexport) EVENT_QUEUE -CreateEventQueue(void); +__declspec(dllexport) int +kqueue(void); __declspec(dllexport) int -WaitForEventQueueObject(EVENT_QUEUE kq, const struct kevent *changelist, int nchanges, +kevent(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); -__declspec(dllexport) void -DestroyEventQueue(EVENT_QUEUE); - #else int kqueue(void); int kevent(int kq, const struct kevent *changelist, int nchanges, diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 40b1929c0..311288d92 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -150,9 +150,6 @@ kqueue_get(int kq) int VISIBLE kqueue(void) { -#ifdef _WIN32 - static int kqueue_id = 0; -#endif struct kqueue *kq; int tmp; @@ -171,13 +168,7 @@ kqueue(void) KQUEUE_DEBUG = (getenv("KQUEUE_DEBUG") == NULL) ? 0 : 1; #endif -#ifdef _WIN32 - pthread_rwlock_wrlock(&kqtree_mtx); - kqueue_id++; - pthread_rwlock_unlock(&kqtree_mtx); - kq->kq_sockfd[0] = kqueue_id; - kq->kq_sockfd[1] = kqueue_id; -#else +#ifndef _WIN32 if (socketpair(AF_UNIX, SOCK_STREAM, 0, kq->kq_sockfd) < 0) goto errout_unlocked; #endif diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 6377043b8..a1dee3a15 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -148,12 +148,8 @@ struct kqueue { fd_set kq_fds, kq_rfds; int kq_nfds; pthread_mutex_t kq_mtx; -KQUEUE_PLATFORM_SPECIFIC; -#ifdef __sun__ - int kq_port; /* see: port_create(2) */ - TAILQ_HEAD(event_buf_listhead,event_buf) kq_events; -#endif - volatile uint32_t kq_ref; + volatile uint32_t kq_ref; + KQUEUE_PLATFORM_SPECIFIC; RB_ENTRY(kqueue) entries; }; diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index c40775af9..62363c3d1 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -29,5 +29,6 @@ extern long int syscall (long int __sysno, ...); #define THREAD_ID ((pid_t) syscall(__NR_gettid)) +#define KQUEUE_PLATFORM_SPECIFIC // #endif /* ! _KQUEUE_LINUX_PLATFORM_H */ diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index 2af6606b5..ea43a2b4f 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -49,6 +49,13 @@ int solaris_kqueue_init(struct kqueue *); void port_event_dequeue(port_event_t *, struct kqueue *); +/* + * Additional members of struct kqueue + */ +#define KQUEUE_PLATFORM_SPECIFIC \ + int kq_port; \ + TAILQ_HEAD(event_buf_listhead,event_buf) kq_events + /* * Data structures */ diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index cb6ff112d..c04a22242 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -48,41 +48,21 @@ BOOL WINAPI DllMain( return (TRUE); } -__declspec(dllexport) EVENT_QUEUE -CreateEventQueue(void) +int +windows_kqueue_init(struct kqueue *kq) { - EVENT_QUEUE evq; - int kqfd; - - kqfd = kqueue(); - if (kqfd < 0) - return (NULL); - - - - evq = calloc(1, sizeof(*evq)); - if (evq == NULL) - return (NULL); - evq->kq_handle = CreateEvent(NULL, FALSE, FALSE, NULL); - if (evq->kq_handle == NULL) { - free(evq); - return (NULL); + kq->kq_handle = CreateEvent(NULL, FALSE, FALSE, NULL); + if (kq->kq_handle == NULL) { + dbg_perror("CreatEvent()"); + return (-1); } - return (evq); -} - -__declspec(dllexport) int -WaitForEventQueueObject(EVENT_QUEUE kq, const struct kevent *changelist, int nchanges, - struct kevent *eventlist, int nevents, - const struct timespec *timeout) -{ return (0); } -__declspec(dllexport) void -DestroyEventQueue(EVENT_QUEUE kq) +void +windows_kqueue_free(struct kqueue *kq) { - CloseHandle(kq->notifier); + CloseHandle(kq->kq_handle); free(kq); } diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 8b598d6ba..2fc6e22f6 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -50,6 +50,16 @@ HANDLE kq_events[MAXIMUM_WAIT_OBJECTS]; \ size_t kq_nevents +/* + * Hooks and prototypes + */ +#define kqueue_free_hook windows_kqueue_free +void windows_kqueue_free(struct kqueue *); + +#define kqueue_init_hook windows_kqueue_init +int windows_kqueue_init(struct kqueue *); + + /* Windows does not support this attribute. DllMain() is the only available constructor function. This means the constructor must be called from within DllMain(). From 44e89bf09bd314a68896c646d65c466670a61297 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 17 Jan 2011 01:16:00 +0000 Subject: [PATCH 0370/1120] successful win32 compile + link using POSIX API. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@393 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/windows/platform.c | 91 +++++++++++++++++++++++++ vendor/libkqueue/src/windows/platform.h | 6 ++ 2 files changed, 97 insertions(+) diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index c04a22242..c320182cd 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -66,3 +66,94 @@ windows_kqueue_free(struct kqueue *kq) CloseHandle(kq->kq_handle); free(kq); } + + +int +windows_kevent_wait(struct kqueue *kq, const struct timespec *timeout) +{ +#if FIXME + port_event_t pe; + int rv; + uint_t nget = 1; + + reset_errno(); + dbg_printf("waiting for events (timeout=%p)", timeout); + rv = port_getn(kq->kq_port, &pe, 1, &nget, (struct timespec *) timeout); + dbg_printf("rv=%d errno=%d (%s) nget=%d", + rv, errno, strerror(errno), nget); + if (rv < 0) { + if (errno == ETIME) { + dbg_puts("no events within the given timeout"); + return (0); + } + if (errno == EINTR) { + dbg_puts("signal caught"); + return (-1); + } + dbg_perror("port_get(2)"); + return (-1); + } + + port_event_enqueue(kq, &pe); + + return (nget); +#endif + return 0; +} + +int +windows_kevent_copyout(struct kqueue *kq, int nready, + struct kevent *eventlist, int nevents) +{ +#if FIXME + struct event_buf *ebp; + struct filter *filt; + int rv; + + ebp = TAILQ_FIRST(&kq->kq_events); + if (ebp == NULL) { + dbg_puts("kq_events was empty"); + return (-1); + } + + dbg_printf("event=%s", port_event_dump(&ebp->pe)); + switch (ebp->pe.portev_source) { + case PORT_SOURCE_FD: + filt = ebp->pe.portev_user; + rv = filt->kf_copyout(filt, eventlist, nevents); + break; + + case PORT_SOURCE_TIMER: + filter_lookup(&filt, kq, EVFILT_TIMER); + rv = filt->kf_copyout(filt, eventlist, nevents); + break; + + case PORT_SOURCE_USER: + switch (ebp->pe.portev_events) { + case X_PORT_SOURCE_SIGNAL: + filter_lookup(&filt, kq, EVFILT_SIGNAL); + rv = filt->kf_copyout(filt, eventlist, nevents); + break; + case X_PORT_SOURCE_USER: + filter_lookup(&filt, kq, EVFILT_USER); + rv = filt->kf_copyout(filt, eventlist, nevents); + break; + default: + dbg_puts("unsupported portev_events"); + abort(); + } + break; + + default: + dbg_puts("unsupported source"); + abort(); + } + if (rv < 0) { + dbg_puts("kevent_copyout failed"); + return (-1); + } + +#endif + return (1); +} + diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 2fc6e22f6..0413f5729 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -59,6 +59,12 @@ void windows_kqueue_free(struct kqueue *); #define kqueue_init_hook windows_kqueue_init int windows_kqueue_init(struct kqueue *); +#define kevent_wait windows_kevent_wait +int windows_kevent_wait(struct kqueue *, const struct timespec *); + +#define kevent_copyout windows_kevent_copyout +int +windows_kevent_copyout(struct kqueue *, int, struct kevent *, int); /* Windows does not support this attribute. DllMain() is the only available constructor function. From 33fb6fd73d06b89d937f77ca3f2b86530dae7d6e Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 17 Jan 2011 02:23:12 +0000 Subject: [PATCH 0371/1120] port unit tests to win32 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@394 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/include/sys/event.h | 5 ++ vendor/libkqueue/src/common/kqueue.c | 2 +- vendor/libkqueue/src/windows/platform.c | 5 +- vendor/libkqueue/src/windows/platform.h | 2 + vendor/libkqueue/test/common.h | 11 +++- vendor/libkqueue/test/kqtest.vcxproj | 88 +++++++++++++++++++++++++ vendor/libkqueue/test/main.c | 9 ++- vendor/libkqueue/test/proc.c | 2 +- vendor/libkqueue/test/read.c | 7 +- vendor/libkqueue/test/test.c | 19 +++--- 10 files changed, 132 insertions(+), 18 deletions(-) create mode 100644 vendor/libkqueue/test/kqtest.vcxproj diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index f72bce6e3..a4362428f 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -172,6 +172,11 @@ extern "C" { #ifdef _WIN32 +struct timespec { + time_t tv_sec; + long tv_nsec; +}; + __declspec(dllexport) int kqueue(void); diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 311288d92..e18ebffd7 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -90,7 +90,7 @@ int kqueue_validate(struct kqueue *kq) { #if defined(_WIN32) - return (0); /* FIXME */ + return (1); /* FIXME: should scan kqlist to verify fd is valid? */ #else int rv; char buf[1]; diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index c320182cd..1cbae5d2b 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -32,9 +32,12 @@ BOOL WINAPI DllMain( { switch (reason) { case DLL_PROCESS_ATTACH: - /* XXX-FIXME: initialize kqtree mutex */ + +#if XXX + //move to EVFILT_READ? if (WSAStartup(MAKEWORD(2,2), NULL) != 0) return (FALSE); +#endif if (_libkqueue_init() < 0) return (FALSE); /* TODO: bettererror handling */ diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 0413f5729..a5bf6f155 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -82,6 +82,7 @@ windows_kevent_copyout(struct kqueue *, int, struct kevent *, int); #define snprintf _snprintf #define ssize_t SSIZE_T +#define sleep(x) Sleep((x) * 1000) /* For POSIX compatibility when compiling, not for actual use */ typedef int socklen_t; @@ -89,6 +90,7 @@ typedef int nlink_t; typedef int timer_t; typedef int pthread_t; typedef int sigset_t; +typedef int pid_t; #define THREAD_ID (GetCurrentThreadId()) #define __thread __declspec(thread) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index c871f87d5..7448313db 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -38,13 +38,20 @@ #include #include #include + +#ifndef _WIN32 #include #include #include - #include - +#include #include "config.h" +#else +#include "../include/sys/event.h" +#include "../src/windows/platform.h" +#pragma comment(lib, "../Debug/libkqueue.lib") +#endif + void test_evfilt_read(int); void test_evfilt_signal(int); diff --git a/vendor/libkqueue/test/kqtest.vcxproj b/vendor/libkqueue/test/kqtest.vcxproj new file mode 100644 index 000000000..876aac881 --- /dev/null +++ b/vendor/libkqueue/test/kqtest.vcxproj @@ -0,0 +1,88 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + Win32Proj + + + + Application + true + + + Application + false + + + + + + + + + + + + + true + + + true + + + + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + + + MachineX86 + true + Console + + + + + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + MachineX86 + true + Console + true + true + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index cc88caa9e..cef0b4d19 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -15,7 +15,7 @@ */ #include -#include + #include "common.h" @@ -32,6 +32,10 @@ struct unit_test { static void test_peer_close_detection(void) { +#ifdef _WIN32 + return; + //FIXME +#else int sockfd[2]; char buf[1]; struct pollfd pfd; @@ -53,6 +57,7 @@ test_peer_close_detection(void) if (recv(sockfd[0], buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT) != 0) die("failed to detect peer shutdown"); } +#endif } void @@ -95,7 +100,9 @@ main(int argc, char **argv) { struct unit_test tests[] = { { "socket", 1, test_evfilt_read }, +#ifndef _WIN32 { "signal", 1, test_evfilt_signal }, +#endif #if FIXME { "proc", 1, test_evfilt_proc }, #endif diff --git a/vendor/libkqueue/test/proc.c b/vendor/libkqueue/test/proc.c index d0bab8bde..eae913d1a 100644 --- a/vendor/libkqueue/test/proc.c +++ b/vendor/libkqueue/test/proc.c @@ -18,7 +18,7 @@ static int sigusr1_caught = 0; static pid_t pid; -static int __thread kqfd; +static int kqfd; static void sig_handler(int signum) diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 5a31ae262..79f9de65e 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -14,8 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include + #include "common.h" static int __thread kqfd; @@ -317,9 +316,13 @@ test_kevent_socket_eof(void) void test_evfilt_read(int _kqfd) { +#ifdef _WIN32 + die("XXX-FIXME"); +#else /* Create a connected pair of full-duplex sockets for testing socket events */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) die("socketpair"); +#endif kqfd = _kqfd; test(kevent_socket_add); diff --git a/vendor/libkqueue/test/test.c b/vendor/libkqueue/test/test.c index 77f2c14ba..9dc9482d2 100644 --- a/vendor/libkqueue/test/test.c +++ b/vendor/libkqueue/test/test.c @@ -19,13 +19,12 @@ #endif #include #include -#include #include "common.h" -static int __thread testnum = 1; -static int __thread error_flag = 1; -static char __thread * cur_test_id = NULL; +static int testnum = 1; +static int error_flag = 1; +static char * cur_test_id = NULL; /* FIXME: not portable beyond linux */ static void @@ -76,10 +75,9 @@ test_end(void) void testing_begin(void) { +#ifndef _WIN32 struct sigaction sa; - atexit(testing_atexit); - /* Install a signal handler for crashes and hangs */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = error_handler; @@ -87,6 +85,10 @@ testing_begin(void) sigaction(SIGSEGV, &sa, NULL); sigaction(SIGABRT, &sa, NULL); sigaction(SIGINT, &sa, NULL); +#endif + + atexit(testing_atexit); + } void @@ -99,14 +101,11 @@ testing_end(void) int testing_make_uid(void) { - static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; static int id = 0; - pthread_mutex_lock(&mtx); if (id == INT_MAX) abort(); id++; - pthread_mutex_unlock(&mtx); - + return (id); } From 672c10dbd011c335b4af5d257a24b13a74e4ba21 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 17 Jan 2011 03:44:17 +0000 Subject: [PATCH 0372/1120] bugfix kqtest git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@395 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/common.h | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 7448313db..1b91c4817 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -45,6 +45,7 @@ #include #include #include +#include #include "config.h" #else #include "../include/sys/event.h" From 4c037d45c05222f4a06263bb9890bc47ae3d053b Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 17 Jan 2011 05:22:29 +0000 Subject: [PATCH 0373/1120] fill in win32 stubs git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@396 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/filter.c | 13 ++- vendor/libkqueue/src/common/private.h | 1 + vendor/libkqueue/src/windows/platform.c | 134 +++++++++++------------- vendor/libkqueue/src/windows/platform.h | 29 +++-- 4 files changed, 99 insertions(+), 78 deletions(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index 06fa8aa72..78faaac61 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -77,6 +77,12 @@ filter_register(struct kqueue *kq, short filter, const struct filter *src) } dbg_printf("filter %d (%s) registered", filter, filter_name(filter)); + /* FIXME: should totally remove const from src */ +#if defined(filter_init_hook) + if (filter_init_hook(kq, (struct filter *) src) < 0) + return (-1); +#endif + return (0); } @@ -116,7 +122,12 @@ filter_unregister_all(struct kqueue *kq) kq->kq_filt[i].kf_destroy(&kq->kq_filt[i]); knote_free_all(&kq->kq_filt[i]); - } + +#if defined(filter_free_hook) + filter_free_hook(kq, &kq->kq_filt[i]); +#endif + + } memset(&kq->kq_filt[0], 0, sizeof(kq->kq_filt)); } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index a1dee3a15..2345d3f15 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -137,6 +137,7 @@ struct filter { RB_HEAD(knt, knote) kf_knote; TAILQ_HEAD(, knote) kf_event; /* events that have occurred */ struct kqueue *kf_kqueue; + FILTER_PLATFORM_SPECIFIC; }; /* Use this to declare a filter that is not implemented */ diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 1cbae5d2b..52203b3f1 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -40,7 +40,6 @@ BOOL WINAPI DllMain( #endif if (_libkqueue_init() < 0) return (FALSE); - /* TODO: bettererror handling */ break; case DLL_PROCESS_DETACH: @@ -70,93 +69,88 @@ windows_kqueue_free(struct kqueue *kq) free(kq); } - int windows_kevent_wait(struct kqueue *kq, const struct timespec *timeout) { -#if FIXME - port_event_t pe; - int rv; - uint_t nget = 1; - - reset_errno(); - dbg_printf("waiting for events (timeout=%p)", timeout); - rv = port_getn(kq->kq_port, &pe, 1, &nget, (struct timespec *) timeout); - dbg_printf("rv=%d errno=%d (%s) nget=%d", - rv, errno, strerror(errno), nget); - if (rv < 0) { - if (errno == ETIME) { - dbg_puts("no events within the given timeout"); - return (0); - } - if (errno == EINTR) { - dbg_puts("signal caught"); - return (-1); - } - dbg_perror("port_get(2)"); - return (-1); - } + int retval; + DWORD rv, timeout_ms; + + /* Convert timeout to milliseconds */ + /* NOTE: loss of precision for timeout values less than 1ms */ + if (timeout == NULL) { + timeout_ms = INFINITE; + } else { + timeout_ms = 0; + if (timeout->tv_sec > 0) + timeout_ms += ((DWORD)timeout->tv_sec) / 1000; + if (timeout->tv_sec > 0) + timeout_ms += timeout->tv_nsec / 1000000; + } + + /* Wait for an event */ + dbg_printf("waiting for events (timeout=%u ms)", timeout_ms); + rv = WaitForMultipleObjects(kq->kq_filt_count, kq->kq_filt_handle, FALSE, timeout_ms); + switch (rv) { + case WAIT_TIMEOUT: + dbg_puts("no events within the given timeout"); + retval = 0; + break; + + case WAIT_FAILED: + dbg_perror("WaitForMultipleEvents()"); + /* TODO: Use GetLastError() for details */ + retval = -1; - port_event_enqueue(kq, &pe); + default: + kq->kq_filt_signalled = rv; + retval = 1; + } - return (nget); -#endif - return 0; + return (retval); } int windows_kevent_copyout(struct kqueue *kq, int nready, struct kevent *eventlist, int nevents) { -#if FIXME - struct event_buf *ebp; struct filter *filt; int rv; - ebp = TAILQ_FIRST(&kq->kq_events); - if (ebp == NULL) { - dbg_puts("kq_events was empty"); + /* KLUDGE: We are abusing the WAIT_FAILED constant to mean + that there are no filters with pending events. + */ + if (kq->kq_filt_signalled == WAIT_FAILED) + return (0); + filt = kq->kq_filt_ref[kq->kq_filt_signalled]; + kq->kq_filt_signalled = WAIT_FAILED; + rv = filt->kf_copyout(filt, eventlist, nevents); + if (rv < 0) { + dbg_puts("kevent_copyout failed"); return (-1); } + return (1); +} - dbg_printf("event=%s", port_event_dump(&ebp->pe)); - switch (ebp->pe.portev_source) { - case PORT_SOURCE_FD: - filt = ebp->pe.portev_user; - rv = filt->kf_copyout(filt, eventlist, nevents); - break; - - case PORT_SOURCE_TIMER: - filter_lookup(&filt, kq, EVFILT_TIMER); - rv = filt->kf_copyout(filt, eventlist, nevents); - break; - - case PORT_SOURCE_USER: - switch (ebp->pe.portev_events) { - case X_PORT_SOURCE_SIGNAL: - filter_lookup(&filt, kq, EVFILT_SIGNAL); - rv = filt->kf_copyout(filt, eventlist, nevents); - break; - case X_PORT_SOURCE_USER: - filter_lookup(&filt, kq, EVFILT_USER); - rv = filt->kf_copyout(filt, eventlist, nevents); - break; - default: - dbg_puts("unsupported portev_events"); - abort(); - } - break; - - default: - dbg_puts("unsupported source"); - abort(); - } - if (rv < 0) { - dbg_puts("kevent_copyout failed"); - return (-1); +int +windows_filter_init(struct kqueue *kq, struct filter *kf) +{ + kf->kf_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL); + if (kf->kf_event_handle == NULL) { + dbg_perror("CreateEvent()"); + return (-1); } -#endif - return (1); + /* Add the handle to the kqueue filter table */ + kq->kq_filt_handle[kq->kq_filt_count] = kf->kf_event_handle; + kq->kq_filt_ref[kq->kq_filt_count] = (struct filter *) kf; + kq->kq_filt_count++; + + return (0); } +void +windows_filter_free(struct kqueue *kq, struct filter *kf) +{ + CloseHandle(kf->kf_event_handle); + /* FIXME: Remove the handle from the kqueue filter table */ +} \ No newline at end of file diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index a5bf6f155..3c9c54c97 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -44,27 +44,42 @@ /* * Additional members of struct kqueue + * FIXME: This forces a thread-per-filter model + * Would be better to */ #define KQUEUE_PLATFORM_SPECIFIC \ HANDLE kq_handle; \ - HANDLE kq_events[MAXIMUM_WAIT_OBJECTS]; \ - size_t kq_nevents + HANDLE kq_filt_handle[EVFILT_SYSCOUNT]; \ + struct filter *kq_filt_ref[EVFILT_SYSCOUNT]; \ + size_t kq_filt_count; \ + DWORD kq_filt_signalled /* - * Hooks and prototypes + * Additional members of struct filter */ -#define kqueue_free_hook windows_kqueue_free -void windows_kqueue_free(struct kqueue *); +#define FILTER_PLATFORM_SPECIFIC \ + HANDLE kf_event_handle +/* + * Hooks and prototypes + */ #define kqueue_init_hook windows_kqueue_init int windows_kqueue_init(struct kqueue *); +#define kqueue_free_hook windows_kqueue_free +void windows_kqueue_free(struct kqueue *); + #define kevent_wait windows_kevent_wait int windows_kevent_wait(struct kqueue *, const struct timespec *); #define kevent_copyout windows_kevent_copyout -int -windows_kevent_copyout(struct kqueue *, int, struct kevent *, int); +int windows_kevent_copyout(struct kqueue *, int, struct kevent *, int); + +#define filter_init_hook windows_filter_init +int windows_filter_init(struct kqueue *, struct filter *); + +#define filter_free_hook windows_filter_free +void windows_filter_free(struct kqueue *, struct filter *); /* Windows does not support this attribute. DllMain() is the only available constructor function. From aade3498727e9bd4815f3b3ef199fa76bcb884c0 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 17 Jan 2011 05:25:40 +0000 Subject: [PATCH 0374/1120] bugfix win32 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@397 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/private.h | 4 ++++ vendor/libkqueue/src/linux/platform.h | 2 -- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 2345d3f15..7ab2ce28f 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -137,7 +137,9 @@ struct filter { RB_HEAD(knt, knote) kf_knote; TAILQ_HEAD(, knote) kf_event; /* events that have occurred */ struct kqueue *kf_kqueue; +#if defined(FILTER_PLATFORM_SPECIFIC) FILTER_PLATFORM_SPECIFIC; +#endif }; /* Use this to declare a filter that is not implemented */ @@ -150,7 +152,9 @@ struct kqueue { int kq_nfds; pthread_mutex_t kq_mtx; volatile uint32_t kq_ref; +#if defined(KQUEUE_PLATFORM_SPECIFIC) KQUEUE_PLATFORM_SPECIFIC; +#endif RB_ENTRY(kqueue) entries; }; diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 62363c3d1..7ddacd165 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -29,6 +29,4 @@ extern long int syscall (long int __sysno, ...); #define THREAD_ID ((pid_t) syscall(__NR_gettid)) -#define KQUEUE_PLATFORM_SPECIFIC // - #endif /* ! _KQUEUE_LINUX_PLATFORM_H */ From bc6398d00d110de4766d51a72ae2da48bf543313 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 17 Jan 2011 16:15:44 +0000 Subject: [PATCH 0375/1120] Do not install the static library. Credit: Joakim Johansson git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@398 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 85ac831a4..81f7a8217 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -44,7 +44,6 @@ install: $(PROGRAM).so.$(ABI_VERSION) $(LN) -sf $(PROGRAM).so.$(ABI_VERSION) $(LIBDIR)/$(PROGRAM).so.$(ABI_MAJOR) $(LN) -sf $(PROGRAM).so.$(ABI_VERSION) $(LIBDIR)/$(PROGRAM).so $(INSTALL) -m 644 $(PROGRAM).la $(LIBDIR) - $(INSTALL) -m 644 $(PROGRAM).a $(LIBDIR) $(INSTALL) -d -m 755 $(LIBDIR)/pkgconfig $(INSTALL) -m 644 libkqueue.pc $(LIBDIR)/pkgconfig $(INSTALL) -d -m 755 $(MANDIR)/man2 From cd59e8dd6de03cf46600f3892ebce49f349ec385 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 17 Jan 2011 18:09:43 +0000 Subject: [PATCH 0376/1120] add additional debugging around kqueue_free() git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@399 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kqueue.c | 7 +++++-- vendor/libkqueue/src/common/private.h | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index e18ebffd7..fbcb91d9f 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -76,8 +76,11 @@ kqueue_gc(void) kqueue_free(n1); } else { rv = kqueue_validate(n1); - if (rv == 0) + if (rv == 0) { + dbg_printf("kqueue %d is no longer valid, will be freed", + kqueue_id(n1)); kqueue_free(n1); + } else if (rv < 0) return (-1); } @@ -187,7 +190,7 @@ kqueue(void) RB_INSERT(kqt, &kqtree, kq); pthread_rwlock_unlock(&kqtree_mtx); - dbg_printf("created kqueue, fd=%d", kq->kq_sockfd[1]); + dbg_printf("created kqueue, fd=%d", kqueue_id(kq)); return (kq->kq_sockfd[1]); errout: diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 7ab2ce28f..e69320456 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -196,6 +196,7 @@ void kqueue_put(struct kqueue *); int kqueue_validate(struct kqueue *); #define kqueue_lock(kq) pthread_mutex_lock(&(kq)->kq_mtx) #define kqueue_unlock(kq) pthread_mutex_unlock(&(kq)->kq_mtx) +#define kqueue_id(kq) ((kq)->kq_sockfd[1]) int CONSTRUCTOR _libkqueue_init(void); From 7807fbb165dd7111c903e9031125625d0d29caa9 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 17 Jan 2011 19:23:30 +0000 Subject: [PATCH 0377/1120] Disable kqueue_gc() because of the problem with file descriptor reuse after close(). Convert from hook functions to a global kqops vtable. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@400 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 1 + vendor/libkqueue/config.inc | 10 +++-- vendor/libkqueue/src/common/filter.c | 11 ++--- vendor/libkqueue/src/common/kqueue.c | 43 +++++++------------ vendor/libkqueue/src/common/private.h | 8 ++++ vendor/libkqueue/src/linux/platform.c | 23 ++++++++++ vendor/libkqueue/src/posix/platform.c | 39 +++++++++++++++++ vendor/libkqueue/src/posix/platform.h | 8 ++++ .../src/solaris/{kqueue.c => platform.c} | 34 +++++++++------ vendor/libkqueue/src/solaris/platform.h | 9 +--- vendor/libkqueue/src/windows/platform.h | 11 ----- 11 files changed, 126 insertions(+), 71 deletions(-) create mode 100644 vendor/libkqueue/src/linux/platform.c create mode 100644 vendor/libkqueue/src/posix/platform.c rename vendor/libkqueue/src/solaris/{kqueue.c => platform.c} (72%) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 81f7a8217..186689962 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -87,6 +87,7 @@ clean: find src -name '*.o' -exec rm {} \; rm -rf pkg cd test && make clean || true + cd www && make clean || true distclean: clean rm -f *.tar.gz config.mk config.h $(PROGRAM).pc $(PROGRAM).la rpm.spec diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index 968e3dd6e..f13a7976d 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -5,7 +5,7 @@ abi_minor="0" abi_version="$abi_major.$abi_minor" cflags="-fpic -Wall -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600" ldflags="" -sources="src/common/filter.c src/common/knote.c +sources="src/common/filter.c src/common/knote.c src/common/kevent.c src/common/kqueue.c" libdepends="" deps="src/common/private.h" @@ -50,8 +50,8 @@ pre_configure_hook() { post_configure_hook() { finalize target "$target" - kqueue="" kevent="src/posix/kevent.c" + platform="src/posix/platform.c" evfilt_signal="src/posix/signal.c" evfilt_proc="src/$target/proc.c" evfilt_socket="src/$target/socket.c" @@ -71,12 +71,13 @@ post_configure_hook() { if [ "$have_sys_eventfd_h" = "yes" ] ; then eventfd="src/linux/eventfd.c" fi + platform="$platform src/linux/platform.c" fi if [ $target = "solaris" ] ; then cflags="$cflags -D__EXTENSIONS__" - kqueue="src/solaris/kqueue.c" kevent="src/solaris/kevent.c" + platform="$platform src/solaris/platform.c" evfilt_timer="src/solaris/timer.c" evfilt_user="src/solaris/user.c" evfilt_proc="" @@ -93,6 +94,7 @@ post_configure_hook() { evfilt_vnode="" fi - sources="$sources $kqueue $kevent $eventfd $evfilt_signal $evfilt_proc + sources="$sources $platform $kevent $eventfd + $evfilt_signal $evfilt_proc $evfilt_socket $evfilt_timer $evfilt_user $evfilt_vnode" } diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index 78faaac61..1573d0b10 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -78,10 +78,9 @@ filter_register(struct kqueue *kq, short filter, const struct filter *src) dbg_printf("filter %d (%s) registered", filter, filter_name(filter)); /* FIXME: should totally remove const from src */ -#if defined(filter_init_hook) - if (filter_init_hook(kq, (struct filter *) src) < 0) + if (kqops.kvt_filter_init != NULL + && kqops.kvt_filter_init(kq, (struct filter *) src) < 0) return (-1); -#endif return (0); } @@ -123,10 +122,8 @@ filter_unregister_all(struct kqueue *kq) knote_free_all(&kq->kq_filt[i]); -#if defined(filter_free_hook) - filter_free_hook(kq, &kq->kq_filt[i]); -#endif - + if (kqops.kvt_filter_free != NULL) + kqops.kvt_filter_free(kq, &kq->kq_filt[i]); } memset(&kq->kq_filt[0], 0, sizeof(kq->kq_filt)); } diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index fbcb91d9f..7d8a8e55d 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -52,15 +52,13 @@ kqueue_free(struct kqueue *kq) { RB_REMOVE(kqt, &kqtree, kq); filter_unregister_all(kq); - -#ifdef kqueue_free_hook - kqueue_free_hook(kq); -#endif - + kqops.kvt_kqueue_free(kq); free(kq); } -static int +/* DEADWOOD: When a file descriptor is closed, it's FD # can be reused by the + next call to open(), socket(), etc. */ +int kqueue_gc(void) { int rv; @@ -73,6 +71,8 @@ kqueue_gc(void) n2 = RB_NEXT(kqt, &kqtree, n1); if (n1->kq_ref == 0) { + dbg_printf("kqueue %d refcount is zero, will be freed", + kqueue_id(n1)); kqueue_free(n1); } else { rv = kqueue_validate(n1); @@ -154,7 +154,14 @@ int VISIBLE kqueue(void) { struct kqueue *kq; - int tmp; + +#if DEADWOOD + /* Free resources associated with closed kqueue descriptors */ + pthread_rwlock_wrlock(&kqtree_mtx); + if (kqueue_gc() < 0) + return (-1); + pthread_rwlock_unlock(&kqtree_mtx); +#endif kq = calloc(1, sizeof(*kq)); if (kq == NULL) @@ -172,18 +179,11 @@ kqueue(void) #endif #ifndef _WIN32 - if (socketpair(AF_UNIX, SOCK_STREAM, 0, kq->kq_sockfd) < 0) - goto errout_unlocked; -#endif - -#ifdef kqueue_init_hook - if (kqueue_init_hook(kq) < 0) + if (kqops.kvt_kqueue_init(kq) < 0) goto errout_unlocked; #endif pthread_rwlock_wrlock(&kqtree_mtx); - if (kqueue_gc() < 0) - goto errout; /* TODO: move outside of the lock if it is safe */ if (filter_register_all(kq) < 0) goto errout; @@ -197,18 +197,7 @@ kqueue(void) pthread_rwlock_unlock(&kqtree_mtx); errout_unlocked: - if (kq->kq_sockfd[0] != kq->kq_sockfd[1]) { - tmp = errno; -#ifndef _WIN32 - (void)close(kq->kq_sockfd[0]); - (void)close(kq->kq_sockfd[1]); -#endif - errno = tmp; - } -#if defined(__sun__) - if (kq->kq_port > 0) - close(kq->kq_port); -#endif + kqops.kvt_kqueue_free(kq); free(kq); return (-1); } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index e69320456..b4dab3d9b 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -158,6 +158,14 @@ struct kqueue { RB_ENTRY(kqueue) entries; }; +struct kqueue_vtable { + int (*kvt_kqueue_init)(struct kqueue *); + void (*kvt_kqueue_free)(struct kqueue *); + int (*kvt_filter_init)(struct kqueue *, struct filter *); + void (*kvt_filter_free)(struct kqueue *, struct filter *); +}; +extern const struct kqueue_vtable const kqops; + struct knote * knote_lookup(struct filter *, short); struct knote * knote_lookup_data(struct filter *filt, intptr_t); struct knote * knote_new(void); diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c new file mode 100644 index 000000000..635f921ac --- /dev/null +++ b/vendor/libkqueue/src/linux/platform.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "../common/private.h" + +const struct kqueue_vtable const kqops = { + posix_kqueue_init, + posix_kqueue_free, +}; + diff --git a/vendor/libkqueue/src/posix/platform.c b/vendor/libkqueue/src/posix/platform.c new file mode 100644 index 000000000..1ad6f1a9a --- /dev/null +++ b/vendor/libkqueue/src/posix/platform.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "../common/private.h" + +int +posix_kqueue_init(struct kqueue *kq) +{ + if (socketpair(AF_UNIX, SOCK_STREAM, 0, kq->kq_sockfd) < 0) { + dbg_perror("socketpair"); + kq->kq_sockfd[0] = -1; + kq->kq_sockfd[1] = -1; + return (-1); + } + + return (0); +} + +void +posix_kqueue_free(struct kqueue *kq) +{ + if (kq->kq_sockfd[0] != -1) + (void) close(kq->kq_sockfd[0]); + if (kq->kq_sockfd[1] != -1) + (void) close(kq->kq_sockfd[1]); +} diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 6847e4c97..47ca33f5d 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -31,10 +31,18 @@ #include #include +#include +#include +#include #include #include #include #include +#include +#include #include +void posix_kqueue_free(struct kqueue *); +int posix_kqueue_init(struct kqueue *); + #endif /* ! _KQUEUE_POSIX_PLATFORM_H */ diff --git a/vendor/libkqueue/src/solaris/kqueue.c b/vendor/libkqueue/src/solaris/platform.c similarity index 72% rename from vendor/libkqueue/src/solaris/kqueue.c rename to vendor/libkqueue/src/solaris/platform.c index df6a1a2da..9ba392df8 100644 --- a/vendor/libkqueue/src/solaris/kqueue.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -14,28 +14,34 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include -#include -#include - -#include "sys/event.h" -#include "private.h" - -void -solaris_kqueue_free(struct kqueue *kq) -{ - if (kq->kq_port > 0) - close(kq->kq_port); -} +#include "../common/private.h" int solaris_kqueue_init(struct kqueue *kq) { + if (posix_kqueue_init(kq) < 0) + return (-1); if ((kq->kq_port = port_create()) < 0) { dbg_perror("port_create(2)"); return (-1); } + dbg_printf("created event port; fd=%d", kq->kq_port); TAILQ_INIT(&kq->kq_events); return (0); } + +void +solaris_kqueue_free(struct kqueue *kq) +{ + posix_kqueue_free(kq); + if (kq->kq_port > 0) { + (void) close(kq->kq_port); + dbg_printf("closed event port; fd=%d", kq->kq_port); + } +} + +const struct kqueue_vtable const kqops = +{ + solaris_kqueue_init, + solaris_kqueue_free, +}; diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index ea43a2b4f..7114c1d84 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -38,16 +38,9 @@ #define X_PORT_SOURCE_SIGNAL 101 #define X_PORT_SOURCE_USER 102 -/* - * Hooks and prototypes - */ -#define kqueue_free_hook solaris_kqueue_free void solaris_kqueue_free(struct kqueue *); - -#define kqueue_init_hook solaris_kqueue_init int solaris_kqueue_init(struct kqueue *); - -void port_event_dequeue(port_event_t *, struct kqueue *); +void port_event_dequeue(port_event_t *, struct kqueue *); /* * Additional members of struct kqueue diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 3c9c54c97..87b56961d 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -63,22 +63,11 @@ /* * Hooks and prototypes */ -#define kqueue_init_hook windows_kqueue_init int windows_kqueue_init(struct kqueue *); - -#define kqueue_free_hook windows_kqueue_free void windows_kqueue_free(struct kqueue *); - -#define kevent_wait windows_kevent_wait int windows_kevent_wait(struct kqueue *, const struct timespec *); - -#define kevent_copyout windows_kevent_copyout int windows_kevent_copyout(struct kqueue *, int, struct kevent *, int); - -#define filter_init_hook windows_filter_init int windows_filter_init(struct kqueue *, struct filter *); - -#define filter_free_hook windows_filter_free void windows_filter_free(struct kqueue *, struct filter *); /* Windows does not support this attribute. From 1e314a8cd2f80386ff3530b60b32190ca9d39468 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 19 Jan 2011 03:03:38 +0000 Subject: [PATCH 0378/1120] win32 kqops changes git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@401 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/filter.c | 8 +- vendor/libkqueue/src/common/kevent.c | 4 +- vendor/libkqueue/src/common/kqueue.c | 4 +- vendor/libkqueue/src/common/private.h | 12 +- vendor/libkqueue/src/linux/platform.c | 4 + vendor/libkqueue/src/posix/kevent.c | 6 +- vendor/libkqueue/src/posix/platform.h | 2 + vendor/libkqueue/src/solaris/platform.c | 4 +- vendor/libkqueue/src/solaris/platform.h | 2 + vendor/libkqueue/src/windows/platform.c | 9 + vendor/libkqueue/src/windows/platform.h | 1 + vendor/libkqueue/src/windows/timer.c | 233 ++++++++++++++++++++++++ 12 files changed, 272 insertions(+), 17 deletions(-) create mode 100644 vendor/libkqueue/src/windows/timer.c diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index 1573d0b10..c978e8563 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -78,8 +78,8 @@ filter_register(struct kqueue *kq, short filter, const struct filter *src) dbg_printf("filter %d (%s) registered", filter, filter_name(filter)); /* FIXME: should totally remove const from src */ - if (kqops.kvt_filter_init != NULL - && kqops.kvt_filter_init(kq, (struct filter *) src) < 0) + if (kqops.filter_init != NULL + && kqops.filter_init(kq, (struct filter *) src) < 0) return (-1); return (0); @@ -122,8 +122,8 @@ filter_unregister_all(struct kqueue *kq) knote_free_all(&kq->kq_filt[i]); - if (kqops.kvt_filter_free != NULL) - kqops.kvt_filter_free(kq, &kq->kq_filt[i]); + if (kqops.filter_free != NULL) + kqops.filter_free(kq, &kq->kq_filt[i]); } memset(&kq->kq_filt[0], 0, sizeof(kq->kq_filt)); } diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index c08156dc2..3990b44c7 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -289,7 +289,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, for (nret = 0; nret == 0;) { /* Wait for one or more events. */ - n = kevent_wait(kq, timeout); + n = kqops.kevent_wait(kq, timeout); if (n < 0) { dbg_printf("(%u) kevent_wait failed", myid); goto errout; @@ -299,7 +299,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, /* Copy the events to the caller */ kqueue_lock(kq); - nret = kevent_copyout(kq, n, eventlist, nevents); + nret = kqops.kevent_copyout(kq, n, eventlist, nevents); kqueue_unlock(kq); } diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 7d8a8e55d..9fec025bb 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -52,7 +52,7 @@ kqueue_free(struct kqueue *kq) { RB_REMOVE(kqt, &kqtree, kq); filter_unregister_all(kq); - kqops.kvt_kqueue_free(kq); + kqops.kqueue_free(kq); free(kq); } @@ -197,7 +197,7 @@ kqueue(void) pthread_rwlock_unlock(&kqtree_mtx); errout_unlocked: - kqops.kvt_kqueue_free(kq); + kqops.kqueue_free(kq); free(kq); return (-1); } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index b4dab3d9b..21255d94d 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -159,12 +159,14 @@ struct kqueue { }; struct kqueue_vtable { - int (*kvt_kqueue_init)(struct kqueue *); - void (*kvt_kqueue_free)(struct kqueue *); - int (*kvt_filter_init)(struct kqueue *, struct filter *); - void (*kvt_filter_free)(struct kqueue *, struct filter *); + int (*kqueue_init)(struct kqueue *); + void (*kqueue_free)(struct kqueue *); + int (*kevent_wait)(struct kqueue *, const struct timespec *); + int (*kevent_copyout)(struct kqueue *, int, struct kevent *, int); + int (*filter_init)(struct kqueue *, struct filter *); + void (*filter_free)(struct kqueue *, struct filter *); }; -extern const struct kqueue_vtable const kqops; +extern const struct kqueue_vtable kqops; struct knote * knote_lookup(struct filter *, short); struct knote * knote_lookup_data(struct filter *filt, intptr_t); diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 635f921ac..8cfd745eb 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -19,5 +19,9 @@ const struct kqueue_vtable const kqops = { posix_kqueue_init, posix_kqueue_free, + posix_kevent_wait, + posix_kevent_copyout, + NULL, + NULL, }; diff --git a/vendor/libkqueue/src/posix/kevent.c b/vendor/libkqueue/src/posix/kevent.c index f72024708..1ee4b5a02 100644 --- a/vendor/libkqueue/src/posix/kevent.c +++ b/vendor/libkqueue/src/posix/kevent.c @@ -22,7 +22,7 @@ const struct filter evfilt_proc = EVFILT_NOTIMPL; int -kevent_wait( +posix_kevent_wait( struct kqueue *kq, const struct timespec *timeout) { @@ -44,7 +44,7 @@ kevent_wait( } int -kevent_copyout(struct kqueue *kq, int nready, +posix_kevent_copyout(struct kqueue *kq, int nready, struct kevent *eventlist, int nevents) { struct filter *filt; @@ -71,4 +71,4 @@ kevent_copyout(struct kqueue *kq, int nready, } return (nret); -} +} \ No newline at end of file diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 47ca33f5d..7884447ed 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -44,5 +44,7 @@ void posix_kqueue_free(struct kqueue *); int posix_kqueue_init(struct kqueue *); +int posix_kevent_wait(struct kqueue *, const struct timespec *); +int posix_kevent_copyout(struct kqueue *, int, struct kevent *, int); #endif /* ! _KQUEUE_POSIX_PLATFORM_H */ diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index 9ba392df8..8675f1eb9 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -40,8 +40,10 @@ solaris_kqueue_free(struct kqueue *kq) } } -const struct kqueue_vtable const kqops = +const struct kqueue_vtable kqops = { solaris_kqueue_init, solaris_kqueue_free, + solaris_kevent_wait, + solaris_kevent_copyout, }; diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index 7114c1d84..de2a5e4d2 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -40,6 +40,8 @@ void solaris_kqueue_free(struct kqueue *); int solaris_kqueue_init(struct kqueue *); +int solaris_kevent_wait(struct kqueue *, const struct timespec *); +int solaris_kevent_copyout(struct kqueue *, int, struct kevent *, int); void port_event_dequeue(port_event_t *, struct kqueue *); /* diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 52203b3f1..df7fb2e8d 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -25,6 +25,15 @@ const struct filter evfilt_read = EVFILT_NOTIMPL; const struct filter evfilt_timer = EVFILT_NOTIMPL; const struct filter evfilt_user = EVFILT_NOTIMPL; +const struct kqueue_vtable kqops = { + windows_kqueue_init, + windows_kqueue_free, + windows_kevent_wait, + windows_kevent_copyout, + windows_filter_init, + windows_filter_free, +}; + BOOL WINAPI DllMain( HINSTANCE self, DWORD reason, diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 87b56961d..597044cbd 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -49,6 +49,7 @@ */ #define KQUEUE_PLATFORM_SPECIFIC \ HANDLE kq_handle; \ + HANDLE kq_apc_dispatcher; \ HANDLE kq_filt_handle[EVFILT_SYSCOUNT]; \ struct filter *kq_filt_ref[EVFILT_SYSCOUNT]; \ size_t kq_filt_count; \ diff --git a/vendor/libkqueue/src/windows/timer.c b/vendor/libkqueue/src/windows/timer.c new file mode 100644 index 000000000..0563cf56d --- /dev/null +++ b/vendor/libkqueue/src/windows/timer.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "../common/private.h" + +#ifndef NDEBUG +static char * +itimerspec_dump(struct itimerspec *ts) +{ + static char __thread buf[1024]; + + snprintf(buf, sizeof(buf), + "itimer: [ interval=%lu s %lu ns, next expire=%lu s %lu ns ]", + ts->it_interval.tv_sec, + ts->it_interval.tv_nsec, + ts->it_value.tv_sec, + ts->it_value.tv_nsec + ); + + return (buf); +} +#endif + +/* Convert milliseconds into seconds+nanoseconds */ +static void +convert_msec_to_itimerspec(struct itimerspec *dst, int src, int oneshot) +{ + time_t sec, nsec; + + sec = src / 1000; + nsec = (src % 1000) * 1000000; + + /* Set the interval */ + if (oneshot) { + dst->it_interval.tv_sec = 0; + dst->it_interval.tv_nsec = 0; + } else { + dst->it_interval.tv_sec = sec; + dst->it_interval.tv_nsec = nsec; + } + + /* Set the initial expiration */ + dst->it_value.tv_sec = sec; + dst->it_value.tv_nsec = nsec; + dbg_printf("%s", itimerspec_dump(dst)); +} + +static int +ktimer_delete(struct filter *filt, struct knote *kn) +{ + int rv = 0; + + if (kn->data.pfd == -1) + return (0); + + dbg_printf("removing timerfd %d from %d", kn->data.pfd, filt->kf_pfd); + if (epoll_ctl(filt->kf_pfd, EPOLL_CTL_DEL, kn->data.pfd, NULL) < 0) { + dbg_printf("epoll_ctl(2): %s", strerror(errno)); + rv = -1; + } + if (close(kn->data.pfd) < 0) { + dbg_printf("close(2): %s", strerror(errno)); + rv = -1; + } + + kn->data.pfd = -1; + return (rv); +} + +int +evfilt_timer_init(struct filter *filt) +{ + filt->kf_pfd = epoll_create(1); + if (filt->kf_pfd < 0) + return (-1); + + dbg_printf("timer epollfd = %d", filt->kf_pfd); + return (0); +} + +void +evfilt_timer_destroy(struct filter *filt) +{ + close (filt->kf_pfd);//LAME +} + +/* TODO: This entire function is copy+pasted from socket.c + with minor changes for timerfds. + Perhaps it could be refactored into a generic epoll_copyout() + that calls custom per-filter actions. + */ +int +evfilt_timer_copyout(struct filter *filt, + struct kevent *dst, + int nevents) +{ + struct epoll_event epevt[MAX_KEVENT]; + struct epoll_event *ev; + struct knote *kn; + uint64_t expired; + int i, nret; + ssize_t n; + + for (;;) { + nret = epoll_wait(filt->kf_pfd, &epevt[0], nevents, 0); + if (nret < 0) { + if (errno == EINTR) + continue; + dbg_perror("epoll_wait"); + return (-1); + } else { + break; + } + } + + for (i = 0, nevents = 0; i < nret; i++) { + ev = &epevt[i]; + /* TODO: put in generic debug.c: epoll_event_dump(ev); */ + kn = ev->data.ptr; + memcpy(dst, &kn->kev, sizeof(*dst)); + if (ev->events & EPOLLERR) + dst->fflags = 1; /* FIXME: Return the actual timer error */ + + /* On return, data contains the number of times the + timer has been trigered. + */ + n = read(kn->data.pfd, &expired, sizeof(expired)); + if (n < 0 || n < sizeof(expired)) { + dbg_puts("invalid read from timerfd"); + expired = 1; /* Fail gracefully */ + } + dst->data = expired; + + if (kn->kev.flags & EV_DISPATCH) { + KNOTE_DISABLE(kn); + ktimer_delete(filt, kn); + } else if (kn->kev.flags & EV_ONESHOT) { + ktimer_delete(filt, kn); + knote_free(filt, kn); + } + + nevents++; + dst++; + } + + return (nevents); +} + +int +evfilt_timer_knote_create(struct filter *filt, struct knote *kn) +{ + struct epoll_event ev; + struct itimerspec ts; + int tfd; + + kn->kev.flags |= EV_CLEAR; + + tfd = timerfd_create(CLOCK_MONOTONIC, 0); + if (tfd < 0) { + dbg_printf("timerfd_create(2): %s", strerror(errno)); + return (-1); + } + dbg_printf("created timerfd %d", tfd); + + convert_msec_to_itimerspec(&ts, kn->kev.data, kn->kev.flags & EV_ONESHOT); + if (timerfd_settime(tfd, 0, &ts, NULL) < 0) { + dbg_printf("timerfd_settime(2): %s", strerror(errno)); + close(tfd); + return (-1); + } + + memset(&ev, 0, sizeof(ev)); + ev.events = EPOLLIN; + ev.data.ptr = kn; + if (epoll_ctl(filt->kf_pfd, EPOLL_CTL_ADD, tfd, &ev) < 0) { + dbg_printf("epoll_ctl(2): %d", errno); + close(tfd); + return (-1); + } + + kn->data.pfd = tfd; + return (0); +} + +int +evfilt_timer_knote_modify(struct filter *filt, struct knote *kn, + const struct kevent *kev) +{ + return (0); /* STUB */ +} + +int +evfilt_timer_knote_delete(struct filter *filt, struct knote *kn) +{ + return (ktimer_delete(filt,kn)); +} + +int +evfilt_timer_knote_enable(struct filter *filt, struct knote *kn) +{ + return evfilt_timer_knote_create(filt, kn); +} + +int +evfilt_timer_knote_disable(struct filter *filt, struct knote *kn) +{ + return evfilt_timer_knote_delete(filt, kn); +} + +const struct filter evfilt_timer = { + EVFILT_TIMER, + evfilt_timer_init, + evfilt_timer_destroy, + evfilt_timer_copyout, + evfilt_timer_knote_create, + evfilt_timer_knote_modify, + evfilt_timer_knote_delete, + evfilt_timer_knote_enable, + evfilt_timer_knote_disable, +}; From f13c79437bd2b54c52741609144253278ab08af2 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 19 Jan 2011 03:06:32 +0000 Subject: [PATCH 0379/1120] linux fixes git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@402 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 2 +- vendor/libkqueue/src/common/kqueue.c | 4 +-- vendor/libkqueue/src/linux/platform.c | 2 +- vendor/libkqueue/src/solaris/kevent.c | 4 +-- vendor/libkqueue/test/common.h | 1 + vendor/libkqueue/test/main.c | 46 +++++++++++++++++++++++++++ 6 files changed, 52 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 186689962..2e0ff1e52 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -87,7 +87,7 @@ clean: find src -name '*.o' -exec rm {} \; rm -rf pkg cd test && make clean || true - cd www && make clean || true + if [ -d www ] ; then cd www && make clean ; fi distclean: clean rm -f *.tar.gz config.mk config.h $(PROGRAM).pc $(PROGRAM).la rpm.spec diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 9fec025bb..c434bdd9c 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -178,10 +178,8 @@ kqueue(void) KQUEUE_DEBUG = (getenv("KQUEUE_DEBUG") == NULL) ? 0 : 1; #endif -#ifndef _WIN32 - if (kqops.kvt_kqueue_init(kq) < 0) + if (kqops.kqueue_init(kq) < 0) goto errout_unlocked; -#endif pthread_rwlock_wrlock(&kqtree_mtx); /* TODO: move outside of the lock if it is safe */ diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 8cfd745eb..d922895b9 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -16,7 +16,7 @@ #include "../common/private.h" -const struct kqueue_vtable const kqops = { +const struct kqueue_vtable kqops = { posix_kqueue_init, posix_kqueue_free, posix_kevent_wait, diff --git a/vendor/libkqueue/src/solaris/kevent.c b/vendor/libkqueue/src/solaris/kevent.c index c84bee76c..061ffe3c3 100644 --- a/vendor/libkqueue/src/solaris/kevent.c +++ b/vendor/libkqueue/src/solaris/kevent.c @@ -122,7 +122,7 @@ port_event_dump(port_event_t *evt) } int -kevent_wait(struct kqueue *kq, const struct timespec *timeout) +solaris_kevent_wait(struct kqueue *kq, const struct timespec *timeout) { port_event_t pe; int rv; @@ -152,7 +152,7 @@ kevent_wait(struct kqueue *kq, const struct timespec *timeout) } int -kevent_copyout(struct kqueue *kq, int nready, +solaris_kevent_copyout(struct kqueue *kq, int nready, struct kevent *eventlist, int nevents) { struct event_buf *ebp; diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 1b91c4817..cc3719dd7 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -41,6 +41,7 @@ #ifndef _WIN32 #include +#include #include #include #include diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index cef0b4d19..6795bae8e 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -25,6 +25,51 @@ struct unit_test { void (*ut_func)(int); }; + +/* + * DEADWOOD: fails on Solaris + * Test if calling fstat() on a socketpair returns unique ino_t and dev_t + * values. This is something that kqueue_gc() relies on. + */ +static void +test_fstat_on_socketpair(void) +{ +#ifdef _WIN32 + return; +#else + struct stat sb[4]; + int a[2], b[2]; + int unique = 1; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, a) < 0) + die("socketpair"); + if (fstat(a[0], &sb[0]) < 0) + die("fstat"); + if (fstat(a[1], &sb[1]) < 0) + die("fstat"); + if (sb[0].st_ino == sb[1].st_ino) { + printf(" inodes=%zu %zu\n", sb[0].st_ino, sb[1].st_ino); + die("NO, inode numbers are not unique"); + } + close(a[0]); + close(a[1]); + if (socketpair(AF_UNIX, SOCK_STREAM, 0, b) < 0) + die("socketpair"); + if (fstat(b[0], &sb[2]) < 0) + die("fstat"); + if (fstat(b[1], &sb[3]) < 0) + die("fstat"); + if (sb[0].st_ino == sb[2].st_ino || sb[0].st_ino == sb[3].st_ino) + unique = 0; + if (sb[1].st_ino == sb[2].st_ino || sb[1].st_ino == sb[3].st_ino) + unique = 0; + printf(" inodes=%zu %zu %zu %zu\n", + sb[0].st_ino, sb[1].st_ino, sb[2].st_ino, sb[3].st_ino); + if (!unique) + die("ERROR - inode numbers are not unique"); +#endif +} + /* * Test the method for detecting when one end of a socketpair * has been closed. This technique is used in kqueue_validate() @@ -147,6 +192,7 @@ main(int argc, char **argv) testing_begin(); test(peer_close_detection); + //DEADWOOD:test(fstat_on_socketpair); test(kqueue); From 2709623734bcb09b338689e1351b5131b6cc2caf Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 19 Jan 2011 03:19:23 +0000 Subject: [PATCH 0380/1120] bugfix git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@403 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 6795bae8e..28e86ad60 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -31,7 +31,7 @@ struct unit_test { * Test if calling fstat() on a socketpair returns unique ino_t and dev_t * values. This is something that kqueue_gc() relies on. */ -static void +void test_fstat_on_socketpair(void) { #ifdef _WIN32 From 309c5f14bc465e6c8e48802c14d7cc5304777cd8 Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 21 Jan 2011 03:30:35 +0000 Subject: [PATCH 0381/1120] win32 timer filter mostly done, improved windows_kevent_wait() git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@404 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/libkqueue.sln | 29 ++++++ vendor/libkqueue/libkqueue.vcxproj | 1 + vendor/libkqueue/src/common/private.h | 1 + vendor/libkqueue/src/windows/platform.c | 19 +++- vendor/libkqueue/src/windows/platform.h | 13 +++ vendor/libkqueue/src/windows/timer.c | 116 +++++++----------------- vendor/libkqueue/test/kqtest.sln | 20 ++++ vendor/libkqueue/test/main.c | 7 +- 8 files changed, 114 insertions(+), 92 deletions(-) create mode 100644 vendor/libkqueue/libkqueue.sln create mode 100644 vendor/libkqueue/test/kqtest.sln diff --git a/vendor/libkqueue/libkqueue.sln b/vendor/libkqueue/libkqueue.sln new file mode 100644 index 000000000..57f8dd011 --- /dev/null +++ b/vendor/libkqueue/libkqueue.sln @@ -0,0 +1,29 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C++ Express 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libkqueue", "libkqueue.vcxproj", "{A29A2A03-DD72-6A48-80FB-43EE0B1A16E7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kqtest", "test\kqtest.vcxproj", "{7578F752-17DD-C6A5-C895-A00098131EEA}" + ProjectSection(ProjectDependencies) = postProject + {A29A2A03-DD72-6A48-80FB-43EE0B1A16E7} = {A29A2A03-DD72-6A48-80FB-43EE0B1A16E7} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A29A2A03-DD72-6A48-80FB-43EE0B1A16E7}.Debug|Win32.ActiveCfg = Debug|Win32 + {A29A2A03-DD72-6A48-80FB-43EE0B1A16E7}.Debug|Win32.Build.0 = Debug|Win32 + {A29A2A03-DD72-6A48-80FB-43EE0B1A16E7}.Release|Win32.ActiveCfg = Release|Win32 + {A29A2A03-DD72-6A48-80FB-43EE0B1A16E7}.Release|Win32.Build.0 = Release|Win32 + {7578F752-17DD-C6A5-C895-A00098131EEA}.Debug|Win32.ActiveCfg = Debug|Win32 + {7578F752-17DD-C6A5-C895-A00098131EEA}.Debug|Win32.Build.0 = Debug|Win32 + {7578F752-17DD-C6A5-C895-A00098131EEA}.Release|Win32.ActiveCfg = Release|Win32 + {7578F752-17DD-C6A5-C895-A00098131EEA}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/vendor/libkqueue/libkqueue.vcxproj b/vendor/libkqueue/libkqueue.vcxproj index 9da03dd9f..752b198c8 100644 --- a/vendor/libkqueue/libkqueue.vcxproj +++ b/vendor/libkqueue/libkqueue.vcxproj @@ -73,6 +73,7 @@ + diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 21255d94d..0b8b5152e 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -98,6 +98,7 @@ struct knote { } vnode; timer_t timerid; pthread_t tid; /* Used by posix/timer.c */ + void *handle; /* Used by win32 filters */ } data; TAILQ_ENTRY(knote) event_ent; /* Used by filter->kf_event */ RB_ENTRY(knote) kntree_ent; /* Used by filter->kntree */ diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index df7fb2e8d..888b50aae 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -22,7 +22,6 @@ const struct filter evfilt_vnode = EVFILT_NOTIMPL; const struct filter evfilt_signal = EVFILT_NOTIMPL; const struct filter evfilt_write = EVFILT_NOTIMPL; const struct filter evfilt_read = EVFILT_NOTIMPL; -const struct filter evfilt_timer = EVFILT_NOTIMPL; const struct filter evfilt_user = EVFILT_NOTIMPL; const struct kqueue_vtable kqops = { @@ -96,8 +95,9 @@ windows_kevent_wait(struct kqueue *kq, const struct timespec *timeout) timeout_ms += timeout->tv_nsec / 1000000; } +#if DEADWOOD /* Wait for an event */ - dbg_printf("waiting for events (timeout=%u ms)", timeout_ms); + dbg_printf("waiting for %u events (timeout=%u ms)", kq->kq_filt_count, timeout_ms); rv = WaitForMultipleObjects(kq->kq_filt_count, kq->kq_filt_handle, FALSE, timeout_ms); switch (rv) { case WAIT_TIMEOUT: @@ -106,15 +106,24 @@ windows_kevent_wait(struct kqueue *kq, const struct timespec *timeout) break; case WAIT_FAILED: - dbg_perror("WaitForMultipleEvents()"); - /* TODO: Use GetLastError() for details */ + dbg_lasterror("WaitForMultipleEvents()"); retval = -1; default: kq->kq_filt_signalled = rv; retval = 1; } +#endif + rv = SleepEx(timeout_ms, TRUE); + if (rv == 0) { + dbg_puts("timeout reached"); + retval = 0; + } else { + dbg_lasterror("SleepEx()"); + retval = -1; + } + return (retval); } @@ -143,6 +152,8 @@ windows_kevent_copyout(struct kqueue *kq, int nready, int windows_filter_init(struct kqueue *kq, struct filter *kf) { + return (0); //XXX-FIXME TESTING + kf->kf_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL); if (kf->kf_event_handle == NULL) { dbg_perror("CreateEvent()"); diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 597044cbd..b6bb51dd5 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -36,6 +36,19 @@ #include "../../include/sys/event.h" + +/* + * Debugging macros + */ +#ifndef NDEBUG +#define dbg_lasterror(str) do { \ + if (KQUEUE_DEBUG) \ + fprintf(stderr, "KQ: [%d] %s(): %s: (LastError=%d)\n", \ + THREAD_ID, __func__, str, GetLastError()); \ +} while (0) + +#endif + /* * Atomic integer operations */ diff --git a/vendor/libkqueue/src/windows/timer.c b/vendor/libkqueue/src/windows/timer.c index 0563cf56d..39a5df9a2 100644 --- a/vendor/libkqueue/src/windows/timer.c +++ b/vendor/libkqueue/src/windows/timer.c @@ -16,97 +16,49 @@ #include "../common/private.h" -#ifndef NDEBUG -static char * -itimerspec_dump(struct itimerspec *ts) -{ - static char __thread buf[1024]; - - snprintf(buf, sizeof(buf), - "itimer: [ interval=%lu s %lu ns, next expire=%lu s %lu ns ]", - ts->it_interval.tv_sec, - ts->it_interval.tv_nsec, - ts->it_value.tv_sec, - ts->it_value.tv_nsec - ); - - return (buf); -} -#endif - -/* Convert milliseconds into seconds+nanoseconds */ +/* Convert milliseconds into negative increments of 100-nanoseconds */ static void -convert_msec_to_itimerspec(struct itimerspec *dst, int src, int oneshot) +convert_msec_to_filetime(LARGE_INTEGER *dst, int src) { - time_t sec, nsec; - - sec = src / 1000; - nsec = (src % 1000) * 1000000; - - /* Set the interval */ - if (oneshot) { - dst->it_interval.tv_sec = 0; - dst->it_interval.tv_nsec = 0; - } else { - dst->it_interval.tv_sec = sec; - dst->it_interval.tv_nsec = nsec; - } - - /* Set the initial expiration */ - dst->it_value.tv_sec = sec; - dst->it_value.tv_nsec = nsec; - dbg_printf("%s", itimerspec_dump(dst)); + dst->QuadPart = -((int64_t) src * 1000 * 10); } static int ktimer_delete(struct filter *filt, struct knote *kn) { - int rv = 0; - - if (kn->data.pfd == -1) + if (kn->data.handle == NULL) return (0); - dbg_printf("removing timerfd %d from %d", kn->data.pfd, filt->kf_pfd); - if (epoll_ctl(filt->kf_pfd, EPOLL_CTL_DEL, kn->data.pfd, NULL) < 0) { - dbg_printf("epoll_ctl(2): %s", strerror(errno)); - rv = -1; - } - if (close(kn->data.pfd) < 0) { - dbg_printf("close(2): %s", strerror(errno)); - rv = -1; - } + if (!CancelWaitableTimer(kn->data.handle)) { + dbg_lasterror("CancelWaitableTimer()"); + return (-1); + } + if (!CloseHandle(kn->data.handle)) { + dbg_lasterror("CloseHandle()"); + return (-1); + } - kn->data.pfd = -1; - return (rv); + kn->data.handle = NULL; + return (0); } int evfilt_timer_init(struct filter *filt) { - filt->kf_pfd = epoll_create(1); - if (filt->kf_pfd < 0) - return (-1); - - dbg_printf("timer epollfd = %d", filt->kf_pfd); return (0); } void evfilt_timer_destroy(struct filter *filt) { - close (filt->kf_pfd);//LAME } -/* TODO: This entire function is copy+pasted from socket.c - with minor changes for timerfds. - Perhaps it could be refactored into a generic epoll_copyout() - that calls custom per-filter actions. - */ int evfilt_timer_copyout(struct filter *filt, struct kevent *dst, int nevents) { +#if FIXME struct epoll_event epevt[MAX_KEVENT]; struct epoll_event *ev; struct knote *kn; @@ -157,41 +109,35 @@ evfilt_timer_copyout(struct filter *filt, } return (nevents); +#endif + return (0); } int evfilt_timer_knote_create(struct filter *filt, struct knote *kn) { - struct epoll_event ev; - struct itimerspec ts; - int tfd; + HANDLE th; + LARGE_INTEGER liDueTime; kn->kev.flags |= EV_CLEAR; - tfd = timerfd_create(CLOCK_MONOTONIC, 0); - if (tfd < 0) { - dbg_printf("timerfd_create(2): %s", strerror(errno)); + th = CreateWaitableTimer(NULL, FALSE, NULL); + if (th == NULL) { + dbg_lasterror("CreateWaitableTimer()"); return (-1); } - dbg_printf("created timerfd %d", tfd); - - convert_msec_to_itimerspec(&ts, kn->kev.data, kn->kev.flags & EV_ONESHOT); - if (timerfd_settime(tfd, 0, &ts, NULL) < 0) { - dbg_printf("timerfd_settime(2): %s", strerror(errno)); - close(tfd); - return (-1); - } - - memset(&ev, 0, sizeof(ev)); - ev.events = EPOLLIN; - ev.data.ptr = kn; - if (epoll_ctl(filt->kf_pfd, EPOLL_CTL_ADD, tfd, &ev) < 0) { - dbg_printf("epoll_ctl(2): %d", errno); - close(tfd); + dbg_printf("created timer handle %p", th); + + convert_msec_to_filetime(&liDueTime, kn->kev.data); + + // XXX-FIXME add completion routine to this call + if (!SetWaitableTimer(th, &liDueTime, (kn->kev.flags & EV_ONESHOT), NULL, NULL, FALSE)) { + dbg_lasterror("SetWaitableTimer()"); + CloseHandle(th); return (-1); } - kn->data.pfd = tfd; + kn->data.handle = th; return (0); } diff --git a/vendor/libkqueue/test/kqtest.sln b/vendor/libkqueue/test/kqtest.sln new file mode 100644 index 000000000..ef1f1695d --- /dev/null +++ b/vendor/libkqueue/test/kqtest.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C++ Express 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kqtest", "kqtest.vcxproj", "{7578F752-17DD-C6A5-C895-A00098131EEA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7578F752-17DD-C6A5-C895-A00098131EEA}.Debug|Win32.ActiveCfg = Debug|Win32 + {7578F752-17DD-C6A5-C895-A00098131EEA}.Debug|Win32.Build.0 = Debug|Win32 + {7578F752-17DD-C6A5-C895-A00098131EEA}.Release|Win32.ActiveCfg = Release|Win32 + {7578F752-17DD-C6A5-C895-A00098131EEA}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 28e86ad60..2794d0fc6 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -144,15 +144,16 @@ int main(int argc, char **argv) { struct unit_test tests[] = { - { "socket", 1, test_evfilt_read }, #ifndef _WIN32 + { "socket", 1, test_evfilt_read }, + { "signal", 1, test_evfilt_signal }, #endif #if FIXME { "proc", 1, test_evfilt_proc }, #endif - { "vnode", 1, test_evfilt_vnode }, - { "timer", 1, test_evfilt_timer }, + { "timer", 1, test_evfilt_timer }, + { "vnode", 1, test_evfilt_vnode }, #if HAVE_EVFILT_USER { "user", 1, test_evfilt_user }, #endif From 89caa7200f7302ad702f06380b48c81be3aa1528 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 22 Jan 2011 03:53:46 +0000 Subject: [PATCH 0382/1120] win32 fixes git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@405 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/filter.c | 2 +- vendor/libkqueue/src/windows/platform.c | 22 ++++++---------------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index c978e8563..a49bea49d 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -79,7 +79,7 @@ filter_register(struct kqueue *kq, short filter, const struct filter *src) /* FIXME: should totally remove const from src */ if (kqops.filter_init != NULL - && kqops.filter_init(kq, (struct filter *) src) < 0) + && kqops.filter_init(kq, dst) < 0) return (-1); return (0); diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 888b50aae..3a95c33b9 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -95,10 +95,9 @@ windows_kevent_wait(struct kqueue *kq, const struct timespec *timeout) timeout_ms += timeout->tv_nsec / 1000000; } -#if DEADWOOD /* Wait for an event */ dbg_printf("waiting for %u events (timeout=%u ms)", kq->kq_filt_count, timeout_ms); - rv = WaitForMultipleObjects(kq->kq_filt_count, kq->kq_filt_handle, FALSE, timeout_ms); + rv = WaitForMultipleObjectsEx(kq->kq_filt_count, kq->kq_filt_handle, FALSE, timeout_ms, TRUE); switch (rv) { case WAIT_TIMEOUT: dbg_puts("no events within the given timeout"); @@ -113,16 +112,6 @@ windows_kevent_wait(struct kqueue *kq, const struct timespec *timeout) kq->kq_filt_signalled = rv; retval = 1; } -#endif - - rv = SleepEx(timeout_ms, TRUE); - if (rv == 0) { - dbg_puts("timeout reached"); - retval = 0; - } else { - dbg_lasterror("SleepEx()"); - retval = -1; - } return (retval); } @@ -152,16 +141,17 @@ windows_kevent_copyout(struct kqueue *kq, int nready, int windows_filter_init(struct kqueue *kq, struct filter *kf) { - return (0); //XXX-FIXME TESTING + HANDLE h; - kf->kf_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL); - if (kf->kf_event_handle == NULL) { + h = CreateEvent(NULL, FALSE, FALSE, NULL); + if (h == NULL) { dbg_perror("CreateEvent()"); return (-1); } + kf->kf_event_handle = h; /* Add the handle to the kqueue filter table */ - kq->kq_filt_handle[kq->kq_filt_count] = kf->kf_event_handle; + kq->kq_filt_handle[kq->kq_filt_count] = h; kq->kq_filt_ref[kq->kq_filt_count] = (struct filter *) kf; kq->kq_filt_count++; From 2a6fb142d7d9675fdfbe3fc76a6bd9df22b9fd57 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 23 Jan 2011 21:03:19 +0000 Subject: [PATCH 0383/1120] Remove kqueue validation code because of the raciness of file descriptor allocation. Make eventfd routines part of kqops. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@406 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/config.inc | 7 +- vendor/libkqueue/src/common/kevent.c | 10 -- vendor/libkqueue/src/common/kqueue.c | 116 ++++------------------ vendor/libkqueue/src/common/private.h | 26 +++-- vendor/libkqueue/src/linux/eventfd.c | 125 ------------------------ vendor/libkqueue/src/linux/platform.c | 89 +++++++++++++++++ vendor/libkqueue/src/linux/platform.h | 7 ++ vendor/libkqueue/src/posix/eventfd.c | 100 ------------------- vendor/libkqueue/src/posix/platform.c | 69 +++++++++++-- vendor/libkqueue/src/posix/platform.h | 14 +++ vendor/libkqueue/src/posix/user.c | 15 ++- vendor/libkqueue/src/solaris/platform.c | 11 ++- 12 files changed, 223 insertions(+), 366 deletions(-) delete mode 100644 vendor/libkqueue/src/linux/eventfd.c delete mode 100644 vendor/libkqueue/src/posix/eventfd.c diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index f13a7976d..2fbaab97e 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -58,7 +58,6 @@ post_configure_hook() { evfilt_timer="src/posix/timer.c" evfilt_user="src/posix/user.c" evfilt_vnode="src/$target/vnode.c" - eventfd="src/posix/eventfd.c" if [ $target = "linux" ] ; then # FIXME: not tested @@ -68,9 +67,6 @@ post_configure_hook() { if [ "$have_sys_timerfd_h" = "yes" ] ; then evfilt_timer="src/linux/timer.c" fi - if [ "$have_sys_eventfd_h" = "yes" ] ; then - eventfd="src/linux/eventfd.c" - fi platform="$platform src/linux/platform.c" fi @@ -82,7 +78,6 @@ post_configure_hook() { evfilt_user="src/solaris/user.c" evfilt_proc="" evfilt_vnode="" - eventfd="" fi # FIXME: This will compile but not actually work @@ -94,7 +89,7 @@ post_configure_hook() { evfilt_vnode="" fi - sources="$sources $platform $kevent $eventfd + sources="$sources $platform $kevent $evfilt_signal $evfilt_proc $evfilt_socket $evfilt_timer $evfilt_user $evfilt_vnode" } diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 3990b44c7..c214d3f1d 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -253,16 +253,6 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, goto out2; } - rv = kqueue_validate(kq); - if (rv < 0) { - nret = -1; - goto out2; - } else if (rv == 0) { - errno = EBADF; - nret = -1; - goto out2; - } - /* * Process each kevent on the changelist. */ diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index c434bdd9c..41ab4393c 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -33,21 +33,31 @@ static pthread_rwlock_t kqtree_mtx; int CONSTRUCTOR _libkqueue_init(void) { - pthread_rwlock_init(&kqtree_mtx, NULL); - dbg_puts("library initialization complete"); - return (0); +#ifdef NDEBUG + KQUEUE_DEBUG = 0; +#elif _WIN32 + /* Experimental port, always debug */ + KQUEUE_DEBUG = 1; +#else + KQUEUE_DEBUG = (getenv("KQUEUE_DEBUG") == NULL) ? 0 : 1; +#endif + + pthread_rwlock_init(&kqtree_mtx, NULL); + + dbg_puts("library initialization complete"); + return (0); } static int kqueue_cmp(struct kqueue *a, struct kqueue *b) { - return memcmp(&a->kq_sockfd[1], &b->kq_sockfd[1], sizeof(int)); + return memcmp(&a->kq_evfd.ef_id, &b->kq_evfd.ef_id, sizeof(int)); } RB_GENERATE(kqt, kqueue, entries, kqueue_cmp) /* Must hold the kqtree_mtx when calling this */ -static void +void kqueue_free(struct kqueue *kq) { RB_REMOVE(kqt, &kqtree, kq); @@ -56,78 +66,11 @@ kqueue_free(struct kqueue *kq) free(kq); } -/* DEADWOOD: When a file descriptor is closed, it's FD # can be reused by the - next call to open(), socket(), etc. */ -int -kqueue_gc(void) -{ - int rv; - struct kqueue *n1, *n2; - - /* Free any kqueue descriptor that is no longer needed */ - /* Sadly O(N), however needed in the case that a descriptor is - closed and kevent(2) will never again be called on it. */ - for (n1 = RB_MIN(kqt, &kqtree); n1 != NULL; n1 = n2) { - n2 = RB_NEXT(kqt, &kqtree, n1); - - if (n1->kq_ref == 0) { - dbg_printf("kqueue %d refcount is zero, will be freed", - kqueue_id(n1)); - kqueue_free(n1); - } else { - rv = kqueue_validate(n1); - if (rv == 0) { - dbg_printf("kqueue %d is no longer valid, will be freed", - kqueue_id(n1)); - kqueue_free(n1); - } - else if (rv < 0) - return (-1); - } - } - - return (0); -} - -int -kqueue_validate(struct kqueue *kq) -{ -#if defined(_WIN32) - return (1); /* FIXME: should scan kqlist to verify fd is valid? */ -#else - int rv; - char buf[1]; - struct pollfd pfd; - - pfd.fd = kq->kq_sockfd[0]; - pfd.events = POLLIN | POLLHUP; - pfd.revents = 0; - - rv = poll(&pfd, 1, 0); - if (rv == 0) - return (1); - if (rv < 0) { - dbg_perror("poll(2)"); - return (-1); - } - if (rv > 0) { - /* NOTE: If the caller accidentally writes to the kqfd, it will - be considered invalid. */ - rv = recv(kq->kq_sockfd[0], buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT); - if (rv == 0) - return (0); - else - return (-1); - } - - return (0); -#endif /* WIN32 */ -} - void kqueue_put(struct kqueue *kq) { atomic_dec(&kq->kq_ref); + /* TODO: free() object when refcount == 0 */ } struct kqueue * @@ -136,15 +79,12 @@ kqueue_get(int kq) struct kqueue query; struct kqueue *ent = NULL; - query.kq_sockfd[1] = kq; + query.kq_evfd.ef_id = kq; pthread_rwlock_rdlock(&kqtree_mtx); ent = RB_FIND(kqt, &kqtree, &query); pthread_rwlock_unlock(&kqtree_mtx); - /* Check for invalid kqueue objects still in the tree */ - if (ent != NULL && (ent->kq_sockfd[0] < 0 || ent->kq_ref == 0)) - ent = NULL; - else + if (ent != NULL) atomic_inc(&ent->kq_ref); return (ent); @@ -155,29 +95,15 @@ kqueue(void) { struct kqueue *kq; -#if DEADWOOD - /* Free resources associated with closed kqueue descriptors */ - pthread_rwlock_wrlock(&kqtree_mtx); - if (kqueue_gc() < 0) - return (-1); - pthread_rwlock_unlock(&kqtree_mtx); -#endif - kq = calloc(1, sizeof(*kq)); if (kq == NULL) return (-1); kq->kq_ref = 1; pthread_mutex_init(&kq->kq_mtx, NULL); -#ifdef NDEBUG - KQUEUE_DEBUG = 0; -#elif _WIN32 - /* Experimental port, always debug */ - KQUEUE_DEBUG = 1; -#else - KQUEUE_DEBUG = (getenv("KQUEUE_DEBUG") == NULL) ? 0 : 1; -#endif + if (kqops.eventfd_init(&kq->kq_evfd) < 0) + goto errout_unlocked; if (kqops.kqueue_init(kq) < 0) goto errout_unlocked; @@ -189,7 +115,7 @@ kqueue(void) pthread_rwlock_unlock(&kqtree_mtx); dbg_printf("created kqueue, fd=%d", kqueue_id(kq)); - return (kq->kq_sockfd[1]); + return (kqops.eventfd_descriptor(&kq->kq_evfd)); errout: pthread_rwlock_unlock(&kqtree_mtx); diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 0b8b5152e..7e988a1ca 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -24,6 +24,7 @@ struct kqueue; struct kevent; +struct eventfd; struct evfilt_data; #if defined(_WIN32) @@ -83,6 +84,13 @@ extern int KQUEUE_DEBUG; */ #define KNFL_PASSIVE_SOCKET (0x01) /* Socket is in listen(2) mode */ +struct eventfd { + int ef_id; +#if defined(EVENTFD_PLATFORM_SPECIFIC) + EVENTFD_PLATFORM_SPECIFIC; +#endif +}; + /* TODO: Make this a variable length structure and allow each filter to add custom fields at the end. */ @@ -130,7 +138,7 @@ struct filter { int (*kn_enable)(struct filter *, struct knote *); int (*kn_disable)(struct filter *, struct knote *); - struct eventfd *kf_efd; /* Used by user.c */ + struct eventfd kf_efd; /* Used by user.c */ int kf_pfd; /* fd to poll(2) for readiness */ int kf_wfd; /* fd to write when an event occurs */ sigset_t kf_sigmask; @@ -147,7 +155,7 @@ struct filter { #define EVFILT_NOTIMPL { 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } struct kqueue { - int kq_sockfd[2]; + struct eventfd kq_evfd; struct filter kq_filt[EVFILT_SYSCOUNT]; fd_set kq_fds, kq_rfds; int kq_nfds; @@ -166,6 +174,11 @@ struct kqueue_vtable { int (*kevent_copyout)(struct kqueue *, int, struct kevent *, int); int (*filter_init)(struct kqueue *, struct filter *); void (*filter_free)(struct kqueue *, struct filter *); + int (*eventfd_init)(struct eventfd *); + void (*eventfd_close)(struct eventfd *); + int (*eventfd_raise)(struct eventfd *); + int (*eventfd_lower)(struct eventfd *); + int (*eventfd_descriptor)(struct eventfd *); }; extern const struct kqueue_vtable kqops; @@ -182,13 +195,6 @@ void knote_enqueue(struct filter *, struct knote *); struct knote * knote_dequeue(struct filter *); int knote_events_pending(struct filter *); -struct eventfd * eventfd_create(void); -void eventfd_free(struct eventfd *); -int eventfd_raise(struct eventfd *); -int eventfd_lower(struct eventfd *); -int eventfd_reader(struct eventfd *); -int eventfd_writer(struct eventfd *); - int filter_lookup(struct filter **, struct kqueue *, short); int filter_socketpair(struct filter *); int filter_register_all(struct kqueue *); @@ -207,7 +213,7 @@ void kqueue_put(struct kqueue *); int kqueue_validate(struct kqueue *); #define kqueue_lock(kq) pthread_mutex_lock(&(kq)->kq_mtx) #define kqueue_unlock(kq) pthread_mutex_unlock(&(kq)->kq_mtx) -#define kqueue_id(kq) ((kq)->kq_sockfd[1]) +#define kqueue_id(kq) ((kq)->kq_evfd.ef_id) int CONSTRUCTOR _libkqueue_init(void); diff --git a/vendor/libkqueue/src/linux/eventfd.c b/vendor/libkqueue/src/linux/eventfd.c deleted file mode 100644 index 208a5d394..000000000 --- a/vendor/libkqueue/src/linux/eventfd.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2010 Mark Heily - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include - -#include "private.h" - -/* A structure is used to allow other targets to emulate this */ -struct eventfd { - int fd; -}; - -struct eventfd * -eventfd_create(void) -{ - struct eventfd *e; - int evfd; - - e = malloc(sizeof(*e)); - if (e == NULL) - return (NULL); - - if ((evfd = eventfd(0, 0)) < 0) { - free(e); - return (NULL); - } - if (fcntl(evfd, F_SETFL, O_NONBLOCK) < 0) { - free(e); - close(evfd); - return (NULL); - } - e->fd = evfd; - - return (e); -} - -void -eventfd_free(struct eventfd *e) -{ - close(e->fd); - free(e); -} - -int -eventfd_raise(struct eventfd *e) -{ - uint64_t counter; - int rv = 0; - - dbg_puts("raising event level"); - counter = 1; - if (write(e->fd, &counter, sizeof(counter)) < 0) { - switch (errno) { - case EAGAIN: - /* Not considered an error */ - break; - - case EINTR: - rv = -EINTR; - break; - - default: - dbg_printf("write(2): %s", strerror(errno)); - rv = -1; - } - } - return (rv); -} - -int -eventfd_lower(struct eventfd *e) -{ - uint64_t cur; - int rv = 0; - - /* Reset the counter */ - dbg_puts("lowering event level"); - if (read(e->fd, &cur, sizeof(cur)) < sizeof(cur)) { - switch (errno) { - case EAGAIN: - /* Not considered an error */ - break; - - case EINTR: - rv = -EINTR; - break; - - default: - dbg_printf("read(2): %s", strerror(errno)); - rv = -1; - } - } - - return (rv); -} - -int -eventfd_reader(struct eventfd *e) -{ - return (e->fd); -} - -int -eventfd_writer(struct eventfd *e) -{ - return (e->fd); -} diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index d922895b9..bebcedc28 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -23,5 +23,94 @@ const struct kqueue_vtable kqops = { posix_kevent_copyout, NULL, NULL, + linux_eventfd_init, + linux_eventfd_close, + linux_eventfd_raise, + linux_eventfd_lower, + linux_eventfd_descriptor }; +int +linux_eventfd_init(struct eventfd *e) +{ + int evfd; + + if ((evfd = eventfd(0, 0)) < 0) { + dbg_perror("eventfd"); + return (-1); + } + if (fcntl(evfd, F_SETFL, O_NONBLOCK) < 0) { + dbg_perror("fcntl"); + close(evfd); + return (-1); + } + e->ef_id = evfd; + + return (0); +} + +void +linux_eventfd_close(struct eventfd *e) +{ + close(e->ef_id); + e->ef_id = -1; +} + +int +linux_eventfd_raise(struct eventfd *e) +{ + uint64_t counter; + int rv = 0; + + dbg_puts("raising event level"); + counter = 1; + if (write(e->ef_id, &counter, sizeof(counter)) < 0) { + switch (errno) { + case EAGAIN: + /* Not considered an error */ + break; + + case EINTR: + rv = -EINTR; + break; + + default: + dbg_printf("write(2): %s", strerror(errno)); + rv = -1; + } + } + return (rv); +} + +int +linux_eventfd_lower(struct eventfd *e) +{ + uint64_t cur; + int rv = 0; + + /* Reset the counter */ + dbg_puts("lowering event level"); + if (read(e->ef_id, &cur, sizeof(cur)) < sizeof(cur)) { + switch (errno) { + case EAGAIN: + /* Not considered an error */ + break; + + case EINTR: + rv = -EINTR; + break; + + default: + dbg_printf("read(2): %s", strerror(errno)); + rv = -1; + } + } + + return (rv); +} + +int +linux_eventfd_descriptor(struct eventfd *e) +{ + return (e->ef_id); +} diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 7ddacd165..ac0f0f2af 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -18,6 +18,7 @@ #define _KQUEUE_LINUX_PLATFORM_H #include +#include /* * Get the current thread ID @@ -28,5 +29,11 @@ # include extern long int syscall (long int __sysno, ...); #define THREAD_ID ((pid_t) syscall(__NR_gettid)) + +int linux_eventfd_init(struct eventfd *); +void linux_eventfd_close(struct eventfd *); +int linux_eventfd_raise(struct eventfd *); +int linux_eventfd_lower(struct eventfd *); +int linux_eventfd_descriptor(struct eventfd *); #endif /* ! _KQUEUE_LINUX_PLATFORM_H */ diff --git a/vendor/libkqueue/src/posix/eventfd.c b/vendor/libkqueue/src/posix/eventfd.c deleted file mode 100644 index 8b84a609a..000000000 --- a/vendor/libkqueue/src/posix/eventfd.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2010 Mark Heily - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include - -#include "private.h" - -struct eventfd { - int fd[2]; -}; - -struct eventfd * -eventfd_create(void) -{ - struct eventfd *e; - - e = malloc(sizeof(*e)); - if (e == NULL) - return (NULL); - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, e->fd) < 0) { - free(e); - return (NULL); - } - if ((fcntl(e->fd[0], F_SETFL, O_NONBLOCK) < 0) || - (fcntl(e->fd[1], F_SETFL, O_NONBLOCK) < 0)) { - free(e); - close(e->fd[0]); - close(e->fd[1]); - return (NULL); - } - - return (e); -} - -void -eventfd_free(struct eventfd *e) -{ - close(e->fd[0]); - close(e->fd[1]); - free(e); -} - -int -eventfd_raise(struct eventfd *e) -{ - dbg_puts("raising event level"); - if (write(e->fd[0], ".", 1) < 0) { - /* FIXME: handle EAGAIN and EINTR */ - dbg_printf("write(2): %s", strerror(errno)); - return (-1); - } - return (0); -} - -int -eventfd_lower(struct eventfd *e) -{ - char buf[1024]; - - /* Reset the counter */ - dbg_puts("lowering event level"); - if (read(e->fd[1], &buf, sizeof(buf)) < 0) { - /* FIXME: handle EAGAIN and EINTR */ - /* FIXME: loop so as to consume all data.. may need mutex */ - dbg_printf("read(2): %s", strerror(errno)); - return (-1); - } - return (0); -} - -int -eventfd_reader(struct eventfd *e) -{ - return (e->fd[1]); -} - -int -eventfd_writer(struct eventfd *e) -{ - return (e->fd[0]); -} diff --git a/vendor/libkqueue/src/posix/platform.c b/vendor/libkqueue/src/posix/platform.c index 1ad6f1a9a..660e9ce5d 100644 --- a/vendor/libkqueue/src/posix/platform.c +++ b/vendor/libkqueue/src/posix/platform.c @@ -19,21 +19,72 @@ int posix_kqueue_init(struct kqueue *kq) { - if (socketpair(AF_UNIX, SOCK_STREAM, 0, kq->kq_sockfd) < 0) { - dbg_perror("socketpair"); - kq->kq_sockfd[0] = -1; - kq->kq_sockfd[1] = -1; + return (0); +} + +void +posix_kqueue_free(struct kqueue *kq) +{ +} + +int +posix_eventfd_init(struct eventfd *e) +{ + int sd[2]; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sd) < 0) { + return (-1); + } + if ((fcntl(sd[0], F_SETFL, O_NONBLOCK) < 0) || + (fcntl(sd[1], F_SETFL, O_NONBLOCK) < 0)) { + close(sd[0]); + close(sd[1]); return (-1); } + e->ef_wfd = sd[0]; + e->ef_id = sd[1]; return (0); } void -posix_kqueue_free(struct kqueue *kq) +posix_eventfd_close(struct eventfd *e) +{ + close(e->ef_id); + close(e->ef_wfd); + e->ef_id = -1; +} + +int +posix_eventfd_raise(struct eventfd *e) +{ + dbg_puts("raising event level"); + if (write(e->ef_wfd, ".", 1) < 0) { + /* FIXME: handle EAGAIN and EINTR */ + dbg_printf("write(2) on fd %d: %s", e->ef_wfd, strerror(errno)); + return (-1); + } + return (0); +} + +int +posix_eventfd_lower(struct eventfd *e) +{ + char buf[1024]; + + /* Reset the counter */ + dbg_puts("lowering event level"); + if (read(e->ef_id, &buf, sizeof(buf)) < 0) { + /* FIXME: handle EAGAIN and EINTR */ + /* FIXME: loop so as to consume all data.. may need mutex */ + dbg_printf("read(2): %s", strerror(errno)); + return (-1); + } + return (0); +} + +int +posix_eventfd_descriptor(struct eventfd *e) { - if (kq->kq_sockfd[0] != -1) - (void) close(kq->kq_sockfd[0]); - if (kq->kq_sockfd[1] != -1) - (void) close(kq->kq_sockfd[1]); + return (e->ef_id); } diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 7884447ed..7424773dd 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -29,6 +29,7 @@ #define VISIBLE __attribute__((visibility("default"))) #define HIDDEN __attribute__((visibility("hidden"))) +#include #include #include #include @@ -42,9 +43,22 @@ #include #include +/* + * Additional members of 'struct eventfd' + */ +#define EVENTFD_PLATFORM_SPECIFIC \ + int ef_wfd + void posix_kqueue_free(struct kqueue *); int posix_kqueue_init(struct kqueue *); + int posix_kevent_wait(struct kqueue *, const struct timespec *); int posix_kevent_copyout(struct kqueue *, int, struct kevent *, int); +int posix_eventfd_init(struct eventfd *); +void posix_eventfd_close(struct eventfd *); +int posix_eventfd_raise(struct eventfd *); +int posix_eventfd_lower(struct eventfd *); +int posix_eventfd_descriptor(struct eventfd *); + #endif /* ! _KQUEUE_POSIX_PLATFORM_H */ diff --git a/vendor/libkqueue/src/posix/user.c b/vendor/libkqueue/src/posix/user.c index c6e198194..89b50eade 100644 --- a/vendor/libkqueue/src/posix/user.c +++ b/vendor/libkqueue/src/posix/user.c @@ -32,13 +32,10 @@ int evfilt_user_init(struct filter *filt) { - filt->kf_efd = eventfd_create(); - if (filt->kf_efd == NULL) + if (kqops.eventfd_init(&filt->kf_efd) < 0) return (-1); - filt->kf_pfd = eventfd_reader(filt->kf_efd); - if (filt->kf_pfd < 0) - return (-1); + filt->kf_pfd = kqops.eventfd_descriptor(&filt->kf_efd); return (0); } @@ -46,7 +43,7 @@ evfilt_user_init(struct filter *filt) void evfilt_user_destroy(struct filter *filt) { - eventfd_free(filt->kf_efd); + kqops.eventfd_close(&filt->kf_efd); return; } @@ -70,7 +67,7 @@ evfilt_user_copyout(struct filter *filt, if (kn->kev.flags & EV_CLEAR) kn->kev.fflags &= ~NOTE_TRIGGER; if (kn->kev.flags & (EV_DISPATCH | EV_CLEAR | EV_ONESHOT)) - eventfd_lower(filt->kf_efd); + kqops.eventfd_lower(&filt->kf_efd); if (kn->kev.flags & EV_DISPATCH) { KNOTE_DISABLE(kn); kn->kev.fflags &= ~NOTE_TRIGGER; @@ -86,7 +83,7 @@ evfilt_user_copyout(struct filter *filt, /* This should normally never happen but is here for debugging */ if (nevents == 0) { dbg_puts("spurious wakeup"); - eventfd_lower(filt->kf_efd); + kqops.eventfd_lower(&filt->kf_efd); } return (nevents); @@ -142,7 +139,7 @@ evfilt_user_knote_modify(struct filter *filt, struct knote *kn, if ((!(kn->kev.flags & EV_DISABLE)) && kev->fflags & NOTE_TRIGGER) { kn->kev.fflags |= NOTE_TRIGGER; knote_enqueue(filt, kn); - eventfd_raise(filt->kf_efd); + kqops.eventfd_raise(&filt->kf_efd); } return (0); diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index 8675f1eb9..2dfd359ad 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -44,6 +44,13 @@ const struct kqueue_vtable kqops = { solaris_kqueue_init, solaris_kqueue_free, - solaris_kevent_wait, - solaris_kevent_copyout, + solaris_kevent_wait, + solaris_kevent_copyout, + NULL, + NULL, + posix_eventfd_init, + posix_eventfd_close, + posix_eventfd_raise, + posix_eventfd_lower, + posix_eventfd_descriptor }; From c2fe04bc82bfdb0bb163458159d2d2d705f67247 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 1 Feb 2011 02:40:59 +0000 Subject: [PATCH 0384/1120] Make the Linux backend completely independent from the POSIX backend. Optimize the Linux backend to remove the use of a per-filter pollfd. Each knote now adds a pollable descriptor to a per-kqueue epollfd. Windows and Solaris backends are not yet refactored and are broken. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@408 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 3 + vendor/libkqueue/config.inc | 16 +- vendor/libkqueue/src/common/filter.c | 71 +------- vendor/libkqueue/src/common/kevent.c | 21 +-- vendor/libkqueue/src/common/knote.c | 57 ++---- vendor/libkqueue/src/common/kqueue.c | 19 +- vendor/libkqueue/src/common/private.h | 39 +++-- vendor/libkqueue/src/linux/platform.c | 158 ++++++++++++++++- vendor/libkqueue/src/linux/platform.h | 36 +++- vendor/libkqueue/src/linux/signal.c | 202 ++++++++++++---------- vendor/libkqueue/src/linux/socket.c | 111 ++++-------- vendor/libkqueue/src/linux/timer.c | 137 ++++----------- vendor/libkqueue/src/linux/user.c | 239 ++++++++++++++++++++++++++ vendor/libkqueue/src/linux/vnode.c | 135 +++++++-------- vendor/libkqueue/src/posix/kevent.c | 2 +- vendor/libkqueue/src/posix/platform.h | 7 + vendor/libkqueue/test/Makefile | 3 + vendor/libkqueue/test/main.c | 34 ++++ vendor/libkqueue/test/signal.c | 2 + 19 files changed, 783 insertions(+), 509 deletions(-) create mode 100644 vendor/libkqueue/src/linux/user.c diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 2e0ff1e52..86f3863e7 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -61,6 +61,9 @@ uninstall: check: clean $(PROGRAM).so.$(ABI_VERSION) cd test && ./configure && make check +debug: clean $(PROGRAM).so.$(ABI_VERSION) + cd test && ./configure && make debug + debug-check: clean cd test && ./configure && KQUEUE_DEBUG=y make check diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index 2fbaab97e..22b171111 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -50,7 +50,6 @@ pre_configure_hook() { post_configure_hook() { finalize target "$target" - kevent="src/posix/kevent.c" platform="src/posix/platform.c" evfilt_signal="src/posix/signal.c" evfilt_proc="src/$target/proc.c" @@ -60,10 +59,14 @@ post_configure_hook() { evfilt_vnode="src/$target/vnode.c" if [ $target = "linux" ] ; then - # FIXME: not tested - #if [ "$have_sys_signalfd_h" = "yes" ] ; then - # evfilt_signal="src/linux/signal.c" - #fi + evfilt_user="src/linux/user.c" + + #XXX-FIXME disabled + evfilt_proc="" + + if [ "$have_sys_signalfd_h" = "yes" ] ; then + evfilt_signal="src/linux/signal.c" + fi if [ "$have_sys_timerfd_h" = "yes" ] ; then evfilt_timer="src/linux/timer.c" fi @@ -72,7 +75,6 @@ post_configure_hook() { if [ $target = "solaris" ] ; then cflags="$cflags -D__EXTENSIONS__" - kevent="src/solaris/kevent.c" platform="$platform src/solaris/platform.c" evfilt_timer="src/solaris/timer.c" evfilt_user="src/solaris/user.c" @@ -89,7 +91,7 @@ post_configure_hook() { evfilt_vnode="" fi - sources="$sources $platform $kevent + sources="$sources $platform $evfilt_signal $evfilt_proc $evfilt_socket $evfilt_timer $evfilt_user $evfilt_vnode" } diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index a49bea49d..8724baf4a 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -46,7 +46,6 @@ filter_register(struct kqueue *kq, short filter, const struct filter *src) memcpy(dst, src, sizeof(*src)); dst->kf_kqueue = kq; RB_INIT(&dst->kf_knote); - TAILQ_INIT(&dst->kf_event); if (src->kf_id == 0) { dbg_puts("filter is not implemented"); return (0); @@ -68,6 +67,7 @@ filter_register(struct kqueue *kq, short filter, const struct filter *src) return (-1); } +#if DEADWOOD /* Add the filter's event descriptor to the main fdset */ if (dst->kf_pfd > 0) { FD_SET(dst->kf_pfd, &kq->kq_fds); @@ -76,6 +76,7 @@ filter_register(struct kqueue *kq, short filter, const struct filter *src) dbg_printf("fds: added %d (nfds=%d)", dst->kf_pfd, kq->kq_nfds); } dbg_printf("filter %d (%s) registered", filter, filter_name(filter)); +#endif /* FIXME: should totally remove const from src */ if (kqops.filter_init != NULL @@ -128,31 +129,6 @@ filter_unregister_all(struct kqueue *kq) memset(&kq->kq_filt[0], 0, sizeof(kq->kq_filt)); } -int -filter_socketpair(struct filter *filt) -{ - int sockfd[2]; - -#ifdef _WIN32 - if (_pipe(sockfd, 512, _O_BINARY) == -1) { - dbg_puts("_pipe failed"); - return (-1); - } - /* FIXME: want nonblocking behavior for writer */ - filt->kf_wfd = sockfd[0]; - filt->kf_pfd = sockfd[1]; -#else - if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) - return (-1); - - fcntl(sockfd[0], F_SETFL, O_NONBLOCK); - filt->kf_wfd = sockfd[0]; - filt->kf_pfd = sockfd[1]; -#endif - - return (0); -} - int filter_lookup(struct filter **filt, struct kqueue *kq, short id) { @@ -196,46 +172,3 @@ filter_name(short filt) else return fname[id]; } - -int -filter_raise(struct filter *filt) -{ - for (;;) { - if (write(filt->kf_wfd, " ", 1) < 0) { - if (errno == EINTR) - continue; - - if (errno != EAGAIN) { - dbg_printf("write(2): %s", strerror(errno)); - /* TODO: set filter error flag */ - return (-1); - } - } - break; - } - - return (0); -} - -int -filter_lower(struct filter *filt) -{ - char buf[1024]; - ssize_t n; - - for (;;) { - n = read(filt->kf_pfd, &buf, sizeof(buf)); - if (n < 0) { - if (errno == EINTR) - continue; - if (errno == EAGAIN) - break; - - dbg_printf("read(2): %s", strerror(errno)); - return (-1); - } - break; - } - - return (0); -} diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index c214d3f1d..a946e259f 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -162,7 +162,6 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) } if (src->flags & EV_DELETE) { - rv = filt->kn_delete(filt, kn); knote_free(filt, kn); return (rv); } else if (src->flags & EV_DISABLE) { @@ -269,9 +268,9 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, } } - /* Determine if we need to wait for events. */ if (nevents > MAX_KEVENT) nevents = MAX_KEVENT; + if (nevents == 0) goto out; @@ -279,18 +278,20 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, for (nret = 0; nret == 0;) { /* Wait for one or more events. */ - n = kqops.kevent_wait(kq, timeout); + n = kqops.kevent_wait(kq, nevents, timeout); + + /* Copy the events to the caller */ + if (fastpath(n > 0)) { + kqueue_lock(kq); + nret = kqops.kevent_copyout(kq, n, eventlist, nevents); + kqueue_unlock(kq); + } if (n < 0) { - dbg_printf("(%u) kevent_wait failed", myid); + dbg_printf("(%u) kevent_wait failed", myid); goto errout; } if (n == 0) - goto out; /* Timeout */ - - /* Copy the events to the caller */ - kqueue_lock(kq); - nret = kqops.kevent_copyout(kq, n, eventlist, nevents); - kqueue_unlock(kq); + goto out; /* Timed out */ } if (KQUEUE_DEBUG) { diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 5625f2189..6a381d035 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -51,8 +51,6 @@ knote_free(struct filter *filt, struct knote *kn) dbg_printf("filter=%s, ident=%u", filter_name(kn->kev.filter), (unsigned int) kn->kev.ident); RB_REMOVE(knt, &filt->kf_knote, kn); - if (kn->event_ent.tqe_prev) //XXX-FIXME what if this is the 1st entry?? - TAILQ_REMOVE(&filt->kf_event, kn, event_ent); filt->kn_delete(filt, kn); free(kn); } @@ -62,13 +60,7 @@ knote_free_all(struct filter *filt) { struct knote *n1, *n2; - /* Destroy all pending events */ - for (n1 = TAILQ_FIRST(&filt->kf_event); n1 != NULL; n1 = n2) { - n2 = TAILQ_NEXT(n1, event_ent); - free(n1); - } - - /* Distroy all knotes */ + /* Destroy all knotes */ for (n1 = RB_MIN(knt, &filt->kf_knote); n1 != NULL; n1 = n2) { n2 = RB_NEXT(knt, filt->kf_knote, n1); RB_REMOVE(knt, &filt->kf_knote, n1); @@ -103,41 +95,6 @@ knote_lookup_data(struct filter *filt, intptr_t data) return (kn); } -void -knote_enqueue(struct filter *filt, struct knote *kn) -{ - /* Prevent a knote from being enqueued() multiple times */ - if (kn->event_ent.tqe_next == NULL && kn->event_ent.tqe_prev == NULL) - TAILQ_INSERT_TAIL(&filt->kf_event, kn, event_ent); -} - -struct knote * -knote_dequeue(struct filter *filt) -{ - struct knote *kn; - - if (TAILQ_EMPTY(&filt->kf_event)) { - kn = NULL; - dbg_puts("no events are pending"); - } else { - kn = TAILQ_FIRST(&filt->kf_event); - TAILQ_REMOVE(&filt->kf_event, kn, event_ent); - memset(&kn->event_ent, 0, sizeof(kn->event_ent)); - } - - return (kn); -} - -int -knote_events_pending(struct filter *filt) -{ - int res; - - res = TAILQ_EMPTY(&filt->kf_event); - - return (res); -} - /* * Test if a socket is active or passive. */ @@ -165,3 +122,15 @@ knote_get_socket_type(struct knote *kn) return (0); } } + +int +knote_disable(struct filter *filt, struct knote *kn) +{ + assert(!(kn->kev.flags & EV_DISABLE)); + + filt->kn_disable(filt, kn); //TODO: Error checking + KNOTE_DISABLE(kn); + return (0); +} + +//TODO: knote_enable() diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 41ab4393c..1352365f9 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -51,7 +51,7 @@ _libkqueue_init(void) static int kqueue_cmp(struct kqueue *a, struct kqueue *b) { - return memcmp(&a->kq_evfd.ef_id, &b->kq_evfd.ef_id, sizeof(int)); + return memcmp(&a->kq_id, &b->kq_id, sizeof(int)); } RB_GENERATE(kqt, kqueue, entries, kqueue_cmp) @@ -79,7 +79,7 @@ kqueue_get(int kq) struct kqueue query; struct kqueue *ent = NULL; - query.kq_evfd.ef_id = kq; + query.kq_id = kq; pthread_rwlock_rdlock(&kqtree_mtx); ent = RB_FIND(kqt, &kqtree, &query); pthread_rwlock_unlock(&kqtree_mtx); @@ -101,26 +101,17 @@ kqueue(void) kq->kq_ref = 1; pthread_mutex_init(&kq->kq_mtx, NULL); - - if (kqops.eventfd_init(&kq->kq_evfd) < 0) - goto errout_unlocked; - if (kqops.kqueue_init(kq) < 0) - goto errout_unlocked; - pthread_rwlock_wrlock(&kqtree_mtx); - /* TODO: move outside of the lock if it is safe */ - if (filter_register_all(kq) < 0) + if (kqops.kqueue_init(kq) < 0) goto errout; RB_INSERT(kqt, &kqtree, kq); pthread_rwlock_unlock(&kqtree_mtx); - dbg_printf("created kqueue, fd=%d", kqueue_id(kq)); - return (kqops.eventfd_descriptor(&kq->kq_evfd)); + dbg_printf("created kqueue, fd=%d", kq->kq_id); + return (kq->kq_id); errout: pthread_rwlock_unlock(&kqtree_mtx); - -errout_unlocked: kqops.kqueue_free(kq); free(kq); return (-1); diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 7e988a1ca..a369befac 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -22,8 +22,12 @@ #include #include "tree.h" +/* Maximum events returnable in a single kevent() call */ +#define MAX_KEVENT 512 + struct kqueue; struct kevent; +struct knote; struct eventfd; struct evfilt_data; @@ -40,10 +44,7 @@ struct evfilt_data; # error Unknown platform #endif - -/* Maximum events returnable in a single kevent() call */ -#define MAX_KEVENT 512 - +#include extern int KQUEUE_DEBUG; @@ -98,6 +99,7 @@ struct knote { struct kevent kev; int flags; union { + /* OLD */ int pfd; /* Used by timerfd */ int events; /* Used by socket */ struct { @@ -108,6 +110,9 @@ struct knote { pthread_t tid; /* Used by posix/timer.c */ void *handle; /* Used by win32 filters */ } data; +#if defined(KNOTE_PLATFORM_SPECIFIC) + KNOTE_PLATFORM_SPECIFIC; +#endif TAILQ_ENTRY(knote) event_ent; /* Used by filter->kf_event */ RB_ENTRY(knote) kntree_ent; /* Used by filter->kntree */ }; @@ -127,7 +132,7 @@ struct filter { int (*kf_init)(struct filter *); void (*kf_destroy)(struct filter *); - int (*kf_copyout)(struct filter *, struct kevent *, int); + int (*kf_copyout)(struct kevent *, const struct kqueue *, struct filter *, struct knote *, void *); /* knote operations */ @@ -139,12 +144,15 @@ struct filter { int (*kn_disable)(struct filter *, struct knote *); struct eventfd kf_efd; /* Used by user.c */ + +#if DEADWOOD + //MOVE TO POSIX? int kf_pfd; /* fd to poll(2) for readiness */ int kf_wfd; /* fd to write when an event occurs */ - sigset_t kf_sigmask; +#endif + struct evfilt_data *kf_data; /* filter-specific data */ RB_HEAD(knt, knote) kf_knote; - TAILQ_HEAD(, knote) kf_event; /* events that have occurred */ struct kqueue *kf_kqueue; #if defined(FILTER_PLATFORM_SPECIFIC) FILTER_PLATFORM_SPECIFIC; @@ -155,7 +163,7 @@ struct filter { #define EVFILT_NOTIMPL { 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } struct kqueue { - struct eventfd kq_evfd; + int kq_id; struct filter kq_filt[EVFILT_SYSCOUNT]; fd_set kq_fds, kq_rfds; int kq_nfds; @@ -170,8 +178,8 @@ struct kqueue { struct kqueue_vtable { int (*kqueue_init)(struct kqueue *); void (*kqueue_free)(struct kqueue *); - int (*kevent_wait)(struct kqueue *, const struct timespec *); - int (*kevent_copyout)(struct kqueue *, int, struct kevent *, int); + int (*kevent_wait)(struct kqueue *, int, const struct timespec *); + int (*kevent_copyout)(struct kqueue *, int, struct kevent *, int); int (*filter_init)(struct kqueue *, struct filter *); void (*filter_free)(struct kqueue *, struct filter *); int (*eventfd_init)(struct eventfd *); @@ -191,17 +199,15 @@ void knote_insert(struct filter *, struct knote *); int knote_get_socket_type(struct knote *); /* TODO: these deal with the eventlist, should use a different prefix */ -void knote_enqueue(struct filter *, struct knote *); -struct knote * knote_dequeue(struct filter *); -int knote_events_pending(struct filter *); +//DEADWOOD:void knote_enqueue(struct filter *, struct knote *); +//DEADWOOD:struct knote * knote_dequeue(struct filter *); +//DEADWOOD:int knote_events_pending(struct filter *); +int knote_disable(struct filter *, struct knote *); int filter_lookup(struct filter **, struct kqueue *, short); -int filter_socketpair(struct filter *); int filter_register_all(struct kqueue *); void filter_unregister_all(struct kqueue *); const char *filter_name(short); -int filter_lower(struct filter *); -int filter_raise(struct filter *); int kevent_wait(struct kqueue *, const struct timespec *); int kevent_copyout(struct kqueue *, int, struct kevent *, int); @@ -213,7 +219,6 @@ void kqueue_put(struct kqueue *); int kqueue_validate(struct kqueue *); #define kqueue_lock(kq) pthread_mutex_lock(&(kq)->kq_mtx) #define kqueue_unlock(kq) pthread_mutex_unlock(&(kq)->kq_mtx) -#define kqueue_id(kq) ((kq)->kq_evfd.ef_id) int CONSTRUCTOR _libkqueue_init(void); diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index bebcedc28..739f7530c 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -16,11 +16,20 @@ #include "../common/private.h" +//XXX-FIXME TEMP +const struct filter evfilt_proc = EVFILT_NOTIMPL; + +/* + * Per-thread epoll event buffer used to ferry data between + * kevent_wait() and kevent_copyout(). + */ +static struct epoll_event __thread epevt[MAX_KEVENT]; + const struct kqueue_vtable kqops = { - posix_kqueue_init, - posix_kqueue_free, - posix_kevent_wait, - posix_kevent_copyout, + linux_kqueue_init, + linux_kqueue_free, + linux_kevent_wait, + linux_kevent_copyout, NULL, NULL, linux_eventfd_init, @@ -30,6 +39,147 @@ const struct kqueue_vtable kqops = { linux_eventfd_descriptor }; +int +linux_kqueue_init(struct kqueue *kq) +{ + kq->kq_id = epoll_create(1); + if (kq->kq_id < 0) { + dbg_perror("epoll_create(2)"); + return (-1); + } + + if (filter_register_all(kq) < 0) { + close(kq->kq_id); + return (-1); + } + + + #if DEADWOOD + //might be useful in posix + + /* Add each filter's pollable descriptor to the epollset */ + for (i = 0; i < EVFILT_SYSCOUNT; i++) { + filt = &kq->kq_filt[i]; + + if (filt->kf_id == 0) + continue; + + memset(&ev, 0, sizeof(ev)); + ev.events = EPOLLIN; + ev.data.ptr = filt; + + if (epoll_ctl(kq->kq_id, EPOLL_CTL_ADD, filt->kf_pfd, &ev) < 0) { + dbg_perror("epoll_ctl(2)"); + close(kq->kq_id); + return (-1); + } + } +#endif + + return (0); +} + +void +linux_kqueue_free(struct kqueue *kq) +{ + abort();//FIXME +} + +static int +linux_kevent_wait_hires( + struct kqueue *kq, + const struct timespec *timeout) +{ + fd_set fds; + int n; + + dbg_puts("waiting for events"); + FD_ZERO(&fds); + FD_SET(kqueue_epfd(kq), &fds); + n = pselect(1, &fds, NULL , NULL, timeout, NULL); + if (n < 0) { + if (errno == EINTR) { + dbg_puts("signal caught"); + return (-1); + } + dbg_perror("pselect(2)"); + return (-1); + } + + return (n); +} + +int +linux_kevent_wait( + struct kqueue *kq, + int nevents, + const struct timespec *ts) +{ + int timeout, nret; + + /* Use pselect() if the timeout value is less than one millisecond. */ + if (ts != NULL && ts->tv_sec == 0 && ts->tv_nsec > 1000000) { + nret = linux_kevent_wait_hires(kq, ts); + if (nret < 1) + return (nret); + + /* Otherwise, use epoll_wait() directly */ + } else { + + /* Convert timeout to the format used by epoll_wait() */ + if (ts == NULL) + timeout = -1; + else + timeout = (1000 * ts->tv_sec) + (ts->tv_nsec / 1000000); + + dbg_puts("waiting for events"); + nret = epoll_wait(kqueue_epfd(kq), &epevt[0], nevents, timeout); + if (nret < 0) { + dbg_perror("epoll_wait"); + return (-1); + } + } + + return (nret); +} + +int +linux_kevent_copyout(struct kqueue *kq, int nready, + struct kevent *eventlist, int nevents) +{ + struct epoll_event *ev; + struct filter *filt; + struct knote *kn; + int i, rv; + + assert(nready >= 1); + + for (i = 0; i < nready; i++) { + ev = &epevt[i]; + kn = (struct knote *) ev->data.ptr; + filt = &kq->kq_filt[~(kn->kev.filter)]; + rv = filt->kf_copyout(eventlist, kq, filt, kn, ev); + if (slowpath(rv < 0)) { + dbg_puts("knote_copyout failed"); + /* XXX-FIXME: hard to handle this without losing events */ + abort(); + } + + /* + * Certain flags cause the associate knote to be deleted + * or disabled. + */ + if (eventlist->flags & EV_DISPATCH) + knote_disable(filt, kn); //TODO: Error checking + if (eventlist->flags & EV_ONESHOT) + knote_free(filt, kn); //TODO: Error checking + + eventlist++; + } + + return (i); +} + int linux_eventfd_init(struct eventfd *e) { diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index ac0f0f2af..585ba4ba0 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -17,8 +17,12 @@ #ifndef _KQUEUE_LINUX_PLATFORM_H #define _KQUEUE_LINUX_PLATFORM_H +#include #include +#include #include +#include +#include /* * Get the current thread ID @@ -28,8 +32,38 @@ # include # include extern long int syscall (long int __sysno, ...); -#define THREAD_ID ((pid_t) syscall(__NR_gettid)) +#define THREAD_ID ((pid_t) syscall(__NR_gettid)) +/* Convenience macros to access the epoll descriptor for the kqueue */ +#define kqueue_epfd(kq) ((kq)->kq_id) +#define filter_epfd(filt) ((filt)->kf_kqueue->kq_id) + +/* + * Additional members of struct knote + */ +#define KNOTE_PLATFORM_SPECIFIC \ + union { \ + int kn_timerfd; \ + int kn_signalfd; \ + int kn_inotifyfd; \ + int kn_eventfd; \ + } kdata + +/* + * Additional members of struct kqueue + */ +#define KQUEUE_PLATFORM_SPECIFIC \ + struct epoll_event kq_plist[MAX_KEVENT]; \ + size_t kq_nplist + +int linux_kqueue_init(struct kqueue *); +void linux_kqueue_free(struct kqueue *); + +int linux_kevent_wait(struct kqueue *, int, const struct timespec *); +int linux_kevent_copyout(struct kqueue *, int, struct kevent *, int); + +int linux_knote_copyout(struct kevent *, struct knote *); + int linux_eventfd_init(struct eventfd *); void linux_eventfd_close(struct eventfd *); int linux_eventfd_raise(struct eventfd *); diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index ae61d3404..cd16f6fba 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -14,154 +14,174 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "sys/event.h" #include "private.h" -/* Highest signal number supported. POSIX standard signals are < 32 */ -#define SIGNAL_MAX 32 +static void +signalfd_reset(int sigfd) +{ + struct signalfd_siginfo sig; + ssize_t n; + + /* Discard any pending signal */ + n = read(sigfd, &sig, sizeof(sig)); + if (n < sizeof(sig)) { + if (errno == EWOULDBLOCK) + return; + //FIXME: eintr? + dbg_perror("read(2) from signalfd"); + abort(); + } +} static int -update_sigmask(const struct filter *filt) +signalfd_add(int epfd, int sigfd, void *ptr) { + struct epoll_event ev; int rv; - rv = signalfd(filt->kf_pfd, &filt->kf_sigmask, 0); - dbg_printf("signalfd = %d", filt->kf_pfd); - if (rv < 0 || rv != filt->kf_pfd) { - dbg_printf("signalfd(2): %s", strerror(errno)); + + /* Add the signalfd to the kqueue's epoll descriptor set */ + memset(&ev, 0, sizeof(ev)); + ev.events = EPOLLIN; + ev.data.ptr = ptr; + rv = epoll_ctl(epfd, EPOLL_CTL_ADD, sigfd, &ev); + if (rv < 0) { + dbg_perror("epoll_ctl(2)"); return (-1); } return (0); } +static int +signalfd_create(int epfd, void *ptr, int signum) +{ + sigset_t sigmask; + int sigfd; + + /* Create a signalfd */ + sigemptyset(&sigmask); + sigaddset(&sigmask, signum); + sigfd = signalfd(-1, &sigmask, SFD_NONBLOCK); + if (sigfd < 0) { + dbg_perror("signalfd(2)"); + goto errout; + } + + /* Block the signal handler from being invoked */ + if (sigprocmask(SIG_BLOCK, &sigmask, NULL) < 0) { + dbg_perror("sigprocmask(2)"); + goto errout; + } + + signalfd_reset(sigfd); + + if (signalfd_add(epfd, sigfd, ptr) < 0) + goto errout; + + dbg_printf("added sigfd %d to epfd %d (signum=%d)", sigfd, epfd, signum); + + return (sigfd); + +errout: + (void) close(sigfd); + return (-1); +} + int evfilt_signal_init(struct filter *filt) { - sigemptyset(&filt->kf_sigmask); - filt->kf_pfd = signalfd(-1, &filt->kf_sigmask, 0); - dbg_printf("signalfd = %d", filt->kf_pfd); - if (filt->kf_pfd < 0) - return (-1); - return (0); } void evfilt_signal_destroy(struct filter *filt) { - close (filt->kf_pfd); } int -evfilt_signal_copyout(struct filter *filt, - struct kevent *dst, - int nevents) +evfilt_signal_copyout(struct kevent *dst, + const struct kqueue *kq, + struct filter *filt, + struct knote *src, + void *unused) { - struct knote *kn; - struct signalfd_siginfo sig[MAX_KEVENT]; - int i; - ssize_t n; + int sigfd; - n = read(filt->kf_pfd, &sig, nevents * sizeof(sig[0])); - if (n < 0 || n < sizeof(sig[0])) { - dbg_puts("invalid read from signalfd"); - return (-1); - } - n /= sizeof(sig[0]); - - for (i = 0, nevents = 0; i < n; i++) { - /* This is not an error because of this race condition: - * 1. Signal arrives and is queued - * 2. The kevent is deleted via kevent(..., EV_DELETE) - * 3. The event is dequeued from the signalfd - */ - kn = knote_lookup(filt, sig[i].ssi_signo); - if (kn == NULL) - continue; - - dbg_printf("got signal %d", sig[i].ssi_signo); - memcpy(dst, &kn->kev, sizeof(*dst)); - /* TODO: dst->data should be the number of times the signal occurred */ - dst->data = 1; - - if (kn->kev.flags & EV_DISPATCH || kn->kev.flags & EV_ONESHOT) { - sigdelset(&filt->kf_sigmask, dst->ident); - update_sigmask(filt); /* TODO: error checking */ - } - if (kn->kev.flags & EV_DISPATCH) - KNOTE_DISABLE(kn); - if (kn->kev.flags & EV_ONESHOT) - knote_free(filt, kn); - - dst++; - nevents++; - } + sigfd = src->kdata.kn_signalfd; + + signalfd_reset(sigfd); - return (nevents); + memcpy(dst, &src->kev, sizeof(*dst)); + /* NOTE: dst->data should be the number of times the signal occurred, + but that information is not available. + */ + dst->data = 1; + + return (0); } int evfilt_signal_knote_create(struct filter *filt, struct knote *kn) { - if (kn->kev.ident >= SIGNAL_MAX) { - dbg_printf("bad signal number %u", (u_int) kn->kev.ident); + int fd; + + fd = signalfd_create(filter_epfd(filt), kn, kn->kev.ident); + if (fd > 0) { + kn->kev.flags |= EV_CLEAR; + kn->kdata.kn_signalfd = fd; + return (0); + } else { + kn->kdata.kn_signalfd = -1; return (-1); } - - kn->kev.flags |= EV_CLEAR; - sigaddset(&filt->kf_sigmask, kn->kev.ident); - - return (update_sigmask(filt)); } int evfilt_signal_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { - if (kev.ident >= SIGNAL_MAX) { - dbg_printf("bad signal number %u", (u_int) kev.ident); - return (-1); - } - - /* Nothing to do since the sigmask does not change. */ + /* Nothing to do since the signal number does not change. */ return (0); } int evfilt_signal_knote_delete(struct filter *filt, struct knote *kn) -{ - sigdelset(&filt->kf_sigmask, kn->kev.ident); +{ + const int sigfd = kn->kdata.kn_signalfd; - return (update_sigmask(filt)); + /* Needed so that delete() can be called after disable() */ + if (kn->kdata.kn_signalfd == -1) + return (0); + + if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_DEL, sigfd, NULL) < 0) { + dbg_perror("epoll_ctl(2)"); + return (-1); + } + + if (close(sigfd) < 0) { + dbg_perror("close(2)"); + return (-1); + } + + /* NOTE: This does not call sigprocmask(3) to unblock the signal. */ + kn->kdata.kn_signalfd = -1; + + return (0); } int evfilt_signal_knote_enable(struct filter *filt, struct knote *kn) { - sigaddset(&filt->kf_sigmask, kn->kev.ident); - - return (update_sigmask(filt)); + dbg_printf("enabling ident %u", (unsigned int) kn->kev.ident); + return evfilt_signal_knote_create(filt, kn); } int evfilt_signal_knote_disable(struct filter *filt, struct knote *kn) { - return (evfilt_signal_knote_delete(filt, kn)); + dbg_printf("disabling ident %u", (unsigned int) kn->kev.ident); + return evfilt_signal_knote_delete(filt, kn); } diff --git a/vendor/libkqueue/src/linux/socket.c b/vendor/libkqueue/src/linux/socket.c index e074230fb..875d939a3 100644 --- a/vendor/libkqueue/src/linux/socket.c +++ b/vendor/libkqueue/src/linux/socket.c @@ -28,9 +28,6 @@ #include #include -#include - -#include "sys/event.h" #include "private.h" @@ -65,7 +62,7 @@ epoll_update(int op, struct filter *filt, struct knote *kn, struct epoll_event * { dbg_printf("op=%d fd=%d events=%s", op, (int)kn->kev.ident, epoll_event_dump(ev)); - if (epoll_ctl(filt->kf_pfd, op, kn->kev.ident, ev) < 0) { + if (epoll_ctl(filter_epfd(filt), op, kn->kev.ident, ev) < 0) { dbg_printf("epoll_ctl(2): %s", strerror(errno)); return (-1); } @@ -73,99 +70,57 @@ epoll_update(int op, struct filter *filt, struct knote *kn, struct epoll_event * return (0); } -static int -socket_knote_delete(int epfd, int fd) -{ - return epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL); -} - int evfilt_socket_init(struct filter *filt) { - filt->kf_pfd = epoll_create(1); - if (filt->kf_pfd < 0) - return (-1); - - dbg_printf("socket epollfd = %d", filt->kf_pfd); return (0); } void evfilt_socket_destroy(struct filter *filt) { - close(filt->kf_pfd); } int -evfilt_socket_copyout(struct filter *filt, - struct kevent *dst, - int nevents) +evfilt_socket_copyout(struct kevent *dst, + const struct kqueue *kq, + struct filter *filt, + struct knote *src, + void *ptr) { - struct epoll_event epevt[MAX_KEVENT]; - struct epoll_event *ev; - struct knote *kn; - int i, nret; + struct epoll_event * const ev = (struct epoll_event *) ptr; - for (;;) { - nret = epoll_wait(filt->kf_pfd, &epevt[0], nevents, 0); - if (nret < 0) { - if (errno == EINTR) - continue; - dbg_perror("epoll_wait"); - return (-1); - } else { - break; - } - } - - for (i = 0, nevents = 0; i < nret; i++) { - ev = &epevt[i]; - epoll_event_dump(ev); - kn = knote_lookup(filt, ev->data.fd); - if (kn != NULL) { - memcpy(dst, &kn->kev, sizeof(*dst)); + epoll_event_dump(ev); + memcpy(dst, &src->kev, sizeof(*dst)); #if defined(HAVE_EPOLLRDHUP) - if (ev->events & EPOLLRDHUP || ev->events & EPOLLHUP) - dst->flags |= EV_EOF; + if (ev->events & EPOLLRDHUP || ev->events & EPOLLHUP) + dst->flags |= EV_EOF; #else - if (ev->events & EPOLLHUP) - dst->flags |= EV_EOF; + if (ev->events & EPOLLHUP) + dst->flags |= EV_EOF; #endif - if (ev->events & EPOLLERR) - dst->fflags = 1; /* FIXME: Return the actual socket error */ + if (ev->events & EPOLLERR) + dst->fflags = 1; /* FIXME: Return the actual socket error */ - if (kn->flags & KNFL_PASSIVE_SOCKET) { - /* On return, data contains the length of the - socket backlog. This is not available under Linux. - */ - dst->data = 1; - } else { - /* On return, data contains the number of bytes of protocol - data available to read. - */ - if (ioctl(dst->ident, - (dst->filter == EVFILT_READ) ? SIOCINQ : SIOCOUTQ, - &dst->data) < 0) { - /* race condition with socket close, so ignore this error */ - dbg_puts("ioctl(2) of socket failed"); - dst->data = 0; - } - } - - if (kn->kev.flags & EV_DISPATCH) { - socket_knote_delete(filt->kf_pfd, kn->kev.ident); - KNOTE_DISABLE(kn); - } else if (kn->kev.flags & EV_ONESHOT) { - socket_knote_delete(filt->kf_pfd, kn->kev.ident); - knote_free(filt, kn); - } - - nevents++; - dst++; + if (src->flags & KNFL_PASSIVE_SOCKET) { + /* On return, data contains the length of the + socket backlog. This is not available under Linux. + */ + dst->data = 1; + } else { + /* On return, data contains the number of bytes of protocol + data available to read. + */ + if (ioctl(dst->ident, + (dst->filter == EVFILT_READ) ? SIOCINQ : SIOCOUTQ, + &dst->data) < 0) { + /* race condition with socket close, so ignore this error */ + dbg_puts("ioctl(2) of socket failed"); + dst->data = 0; } } - return (nevents); + return (0); } int @@ -192,7 +147,7 @@ evfilt_socket_knote_create(struct filter *filt, struct knote *kn) memset(&ev, 0, sizeof(ev)); ev.events = kn->data.events; - ev.data.fd = kn->kev.ident; + ev.data.ptr = kn; return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); } @@ -220,7 +175,7 @@ evfilt_socket_knote_enable(struct filter *filt, struct knote *kn) memset(&ev, 0, sizeof(ev)); ev.events = kn->data.events; - ev.data.fd = kn->kev.ident; + ev.data.ptr = kn; return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); } diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 7fc38a505..239381df1 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -14,24 +14,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Linux equivalents to kqueue(2) */ -#include - -#include "sys/event.h" #include "private.h" #ifndef NDEBUG @@ -76,105 +58,43 @@ convert_msec_to_itimerspec(struct itimerspec *dst, int src, int oneshot) dbg_printf("%s", itimerspec_dump(dst)); } -static int -ktimer_delete(struct filter *filt, struct knote *kn) -{ - int rv = 0; - - if (kn->data.pfd == -1) - return (0); - - dbg_printf("removing timerfd %d from %d", kn->data.pfd, filt->kf_pfd); - if (epoll_ctl(filt->kf_pfd, EPOLL_CTL_DEL, kn->data.pfd, NULL) < 0) { - dbg_printf("epoll_ctl(2): %s", strerror(errno)); - rv = -1; - } - if (close(kn->data.pfd) < 0) { - dbg_printf("close(2): %s", strerror(errno)); - rv = -1; - } - - kn->data.pfd = -1; - return (rv); -} - int evfilt_timer_init(struct filter *filt) { - filt->kf_pfd = epoll_create(1); - if (filt->kf_pfd < 0) - return (-1); - - dbg_printf("timer epollfd = %d", filt->kf_pfd); return (0); } void evfilt_timer_destroy(struct filter *filt) { - close (filt->kf_pfd);//LAME } -/* TODO: This entire function is copy+pasted from socket.c - with minor changes for timerfds. - Perhaps it could be refactored into a generic epoll_copyout() - that calls custom per-filter actions. - */ int -evfilt_timer_copyout(struct filter *filt, - struct kevent *dst, - int nevents) +evfilt_timer_copyout(struct kevent *dst, + const struct kqueue *kq, + struct filter *filt, + struct knote *src, + void *ptr) { - struct epoll_event epevt[MAX_KEVENT]; - struct epoll_event *ev; - struct knote *kn; + struct epoll_event * const ev = (struct epoll_event *) ptr; uint64_t expired; - int i, nret; ssize_t n; - for (;;) { - nret = epoll_wait(filt->kf_pfd, &epevt[0], nevents, 0); - if (nret < 0) { - if (errno == EINTR) - continue; - dbg_perror("epoll_wait"); - return (-1); - } else { - break; - } - } - - for (i = 0, nevents = 0; i < nret; i++) { - ev = &epevt[i]; - /* TODO: put in generic debug.c: epoll_event_dump(ev); */ - kn = ev->data.ptr; - memcpy(dst, &kn->kev, sizeof(*dst)); - if (ev->events & EPOLLERR) - dst->fflags = 1; /* FIXME: Return the actual timer error */ + memcpy(dst, &src->kev, sizeof(*dst)); + if (ev->events & EPOLLERR) + dst->fflags = 1; /* FIXME: Return the actual timer error */ - /* On return, data contains the number of times the - timer has been trigered. - */ - n = read(kn->data.pfd, &expired, sizeof(expired)); - if (n < 0 || n < sizeof(expired)) { - dbg_puts("invalid read from timerfd"); - expired = 1; /* Fail gracefully */ - } - dst->data = expired; - - if (kn->kev.flags & EV_DISPATCH) { - KNOTE_DISABLE(kn); - ktimer_delete(filt, kn); - } else if (kn->kev.flags & EV_ONESHOT) { - ktimer_delete(filt, kn); - knote_free(filt, kn); - } - - nevents++; - dst++; - } + /* On return, data contains the number of times the + timer has been trigered. + */ + n = read(src->data.pfd, &expired, sizeof(expired)); + if (n < 0 || n < sizeof(expired)) { + dbg_puts("invalid read from timerfd"); + expired = 1; /* Fail gracefully */ + } + dst->data = expired; - return (nevents); + return (0); } int @@ -203,7 +123,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) memset(&ev, 0, sizeof(ev)); ev.events = EPOLLIN; ev.data.ptr = kn; - if (epoll_ctl(filt->kf_pfd, EPOLL_CTL_ADD, tfd, &ev) < 0) { + if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_ADD, tfd, &ev) < 0) { dbg_printf("epoll_ctl(2): %d", errno); close(tfd); return (-1); @@ -223,7 +143,22 @@ evfilt_timer_knote_modify(struct filter *filt, struct knote *kn, int evfilt_timer_knote_delete(struct filter *filt, struct knote *kn) { - return (ktimer_delete(filt,kn)); + int rv = 0; + + if (kn->data.pfd == -1) + return (0); + + if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_DEL, kn->data.pfd, NULL) < 0) { + dbg_printf("epoll_ctl(2): %s", strerror(errno)); + rv = -1; + } + if (close(kn->data.pfd) < 0) { + dbg_printf("close(2): %s", strerror(errno)); + rv = -1; + } + + kn->data.pfd = -1; + return (rv); } int diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c new file mode 100644 index 000000000..153550db8 --- /dev/null +++ b/vendor/libkqueue/src/linux/user.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sys/event.h" +#include "private.h" + +/* NOTE: copy+pasted from linux_eventfd_raise() */ +static int +eventfd_raise(int evfd) +{ + uint64_t counter; + int rv = 0; + + dbg_puts("raising event level"); + counter = 1; + if (write(evfd, &counter, sizeof(counter)) < 0) { + switch (errno) { + case EAGAIN: + /* Not considered an error */ + break; + + case EINTR: + rv = -EINTR; + break; + + default: + dbg_printf("write(2): %s", strerror(errno)); + rv = -1; + } + } + return (rv); +} + +/* NOTE: copy+pasted from linux_eventfd_lower() */ +static int +eventfd_lower(int evfd) +{ + uint64_t cur; + int rv = 0; + + /* Reset the counter */ + dbg_puts("lowering event level"); + if (read(evfd, &cur, sizeof(cur)) < sizeof(cur)) { + switch (errno) { + case EAGAIN: + /* Not considered an error */ + break; + + case EINTR: + rv = -EINTR; + break; + + default: + dbg_printf("read(2): %s", strerror(errno)); + rv = -1; + } + } + + return (rv); +} + +int +evfilt_user_init(struct filter *filt) +{ + return (0); +} + +void +evfilt_user_destroy(struct filter *filt) +{ + return; +} + +int +evfilt_user_copyout(struct kevent *dst, + const struct kqueue *kq, + struct filter *filt, + struct knote *src, + void *ptr) +{ + memcpy(dst, &src->kev, sizeof(*dst)); + dst->fflags &= ~NOTE_FFCTRLMASK; //FIXME: Not sure if needed + dst->fflags &= ~NOTE_TRIGGER; + if (src->kev.flags & EV_ADD) { + /* NOTE: True on FreeBSD but not consistent behavior with + other filters. */ + dst->flags &= ~EV_ADD; + } + if (src->kev.flags & EV_CLEAR) + src->kev.fflags &= ~NOTE_TRIGGER; + if (src->kev.flags & (EV_DISPATCH | EV_CLEAR | EV_ONESHOT)) { + if (eventfd_lower(src->kdata.kn_eventfd) < 0) + return (-1); + } + + if (src->kev.flags & EV_DISPATCH) + src->kev.fflags &= ~NOTE_TRIGGER; + + return (0); +} + +int +evfilt_user_knote_create(struct filter *filt, struct knote *kn) +{ + struct epoll_event ev; + int evfd; + + /* Create an eventfd */ + if ((evfd = eventfd(0, 0)) < 0) { + dbg_perror("eventfd"); + goto errout; + } + + /* Add the eventfd to the epoll set */ + memset(&ev, 0, sizeof(ev)); + ev.events = EPOLLIN; + ev.data.ptr = kn; + if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_ADD, evfd, &ev) < 0) { + dbg_perror("epoll_ctl(2)"); + goto errout; + } + + kn->kdata.kn_eventfd = evfd; + + return (0); + +errout: + (void) close(evfd); + kn->kdata.kn_eventfd = -1; + return (-1); +} + +int +evfilt_user_knote_modify(struct filter *filt, struct knote *kn, + const struct kevent *kev) +{ + unsigned int ffctrl; + unsigned int fflags; + + /* Excerpted from sys/kern/kern_event.c in FreeBSD HEAD */ + ffctrl = kev->fflags & NOTE_FFCTRLMASK; + fflags = kev->fflags & NOTE_FFLAGSMASK; + switch (ffctrl) { + case NOTE_FFNOP: + break; + + case NOTE_FFAND: + kn->kev.fflags &= fflags; + break; + + case NOTE_FFOR: + kn->kev.fflags |= fflags; + break; + + case NOTE_FFCOPY: + kn->kev.fflags = fflags; + break; + + default: + /* XXX Return error? */ + break; + } + + if ((!(kn->kev.flags & EV_DISABLE)) && kev->fflags & NOTE_TRIGGER) { + kn->kev.fflags |= NOTE_TRIGGER; + if (eventfd_raise(kn->kdata.kn_eventfd) < 0) + return (-1); + } + + return (0); +} + +int +evfilt_user_knote_delete(struct filter *filt, struct knote *kn) +{ + if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_DEL, + kn->kdata.kn_eventfd, NULL) < 0) { + dbg_perror("epoll_ctl(2)"); + return (-1); + } + if (close(kn->kdata.kn_eventfd) < 0) { + dbg_perror("close(2)"); + return (-1); + } + kn->kdata.kn_eventfd = -1; + + return (0); +} + +int +evfilt_user_knote_enable(struct filter *filt, struct knote *kn) +{ + /* FIXME: what happens if NOTE_TRIGGER is in fflags? + should the event fire? */ + return evfilt_user_knote_create(filt, kn); +} + +int +evfilt_user_knote_disable(struct filter *filt, struct knote *kn) +{ + return evfilt_user_knote_delete(filt, kn); +} + +const struct filter evfilt_user = { + EVFILT_USER, + evfilt_user_init, + evfilt_user_destroy, + evfilt_user_copyout, + evfilt_user_knote_create, + evfilt_user_knote_modify, + evfilt_user_knote_delete, + evfilt_user_knote_enable, + evfilt_user_knote_disable, +}; diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 5bbdaed6e..83d28d914 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -14,25 +14,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "sys/event.h" #include "private.h" static char * @@ -89,13 +70,13 @@ fd_to_path(char *buf, size_t bufsz, int fd) /* TODO: USE this to get events with name field */ int -get_one_event(struct inotify_event *dst, int pfd) +get_one_event(struct inotify_event *dst, int inofd) { ssize_t n; dbg_puts("reading one inotify event"); for (;;) { - n = read(pfd, dst, sizeof(*dst)); + n = read(inofd, dst, sizeof(*dst)); if (n < 0) { if (errno == EINTR) continue; @@ -118,6 +99,8 @@ get_one_event(struct inotify_event *dst, int pfd) static int add_watch(struct filter *filt, struct knote *kn) { + struct epoll_event ev; + int ifd; char path[PATH_MAX]; uint32_t mask; @@ -141,27 +124,54 @@ add_watch(struct filter *filt, struct knote *kn) if (kn->kev.flags & EV_ONESHOT) mask |= IN_ONESHOT; + /* Create an inotify descriptor */ + ifd = inotify_init(); + if (ifd < 0) { + dbg_perror("inotify_init(2)"); + return (-1); + } + + /* Add the watch */ dbg_printf("inotify_add_watch(2); inofd=%d, %s, path=%s", - filt->kf_pfd, inotify_mask_dump(mask), path); - kn->kev.data = inotify_add_watch(filt->kf_pfd, path, mask); + ifd, inotify_mask_dump(mask), path); + kn->kev.data = inotify_add_watch(ifd, path, mask); if (kn->kev.data < 0) { - dbg_printf("inotify_add_watch(2): %s", strerror(errno)); - return (-1); + dbg_perror("inotify_add_watch(2)"); + goto errout; } + + /* Add the inotify fd to the epoll set */ + memset(&ev, 0, sizeof(ev)); + ev.events = EPOLLIN; + ev.data.ptr = kn; + if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_ADD, ifd, &ev) < 0) { + dbg_perror("epoll_ctl(2)"); + goto errout; + } + + kn->kdata.kn_inotifyfd = ifd; + return (0); + +errout: + kn->kdata.kn_inotifyfd = -1; + (void) close(ifd); + return (-1); } static int delete_watch(struct filter *filt, struct knote *kn) { - if (kn->kev.data < 0) + int ifd = kn->kdata.kn_inotifyfd; + + if (ifd < 0) return (0); - if (inotify_rm_watch(filt->kf_pfd, kn->kev.data) < 0) { - dbg_printf("inotify_rm_watch(2): %s", strerror(errno)); + if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_DEL, ifd, NULL) < 0) { + dbg_perror("epoll_ctl(2)"); return (-1); } - dbg_printf("wd %d removed", (int) kn->kev.data); - kn->kev.data = -1; + (void) close(ifd); + kn->kdata.kn_inotifyfd = -1; return (0); } @@ -169,30 +179,25 @@ delete_watch(struct filter *filt, struct knote *kn) int evfilt_vnode_init(struct filter *filt) { - filt->kf_pfd = inotify_init(); - dbg_printf("inotify fd = %d", filt->kf_pfd); - if (filt->kf_pfd < 0) - return (-1); - return (0); } void evfilt_vnode_destroy(struct filter *filt) { - close(filt->kf_pfd); } int -evfilt_vnode_copyout(struct filter *filt, - struct kevent *dst, - int nevents) +evfilt_vnode_copyout(struct kevent *dst, + const struct kqueue *kq, + struct filter *filt, + struct knote *src, + void *ptr) { struct inotify_event evt; struct stat sb; - struct knote *kn; - if (get_one_event(&evt, filt->kf_pfd) < 0) + if (get_one_event(&evt, src->kdata.kn_inotifyfd) < 0) return (-1); dbg_printf("inotify event: %s", inotify_event_dump(&evt)); @@ -201,60 +206,46 @@ evfilt_vnode_copyout(struct filter *filt, return (0); } - kn = knote_lookup_data(filt, evt.wd); - if (kn == NULL) { - dbg_printf("no match for wd # %d", evt.wd); - return (-1); - } - - memcpy(dst, &kn->kev, sizeof(*dst)); + memcpy(dst, &src->kev, sizeof(*dst)); dst->data = 0; /* No error checking because fstat(2) should rarely fail */ //FIXME: EINTR if ((evt.mask & IN_ATTRIB || evt.mask & IN_MODIFY) - && fstat(kn->kev.ident, &sb) == 0) { - if (sb.st_nlink == 0 && kn->kev.fflags & NOTE_DELETE) + && fstat(src->kev.ident, &sb) == 0) { + if (sb.st_nlink == 0 && src->kev.fflags & NOTE_DELETE) dst->fflags |= NOTE_DELETE; - if (sb.st_nlink != kn->data.vnode.nlink && kn->kev.fflags & NOTE_LINK) + if (sb.st_nlink != src->data.vnode.nlink && src->kev.fflags & NOTE_LINK) dst->fflags |= NOTE_LINK; #if HAVE_NOTE_TRUNCATE - if (sb.st_nsize == 0 && kn->kev.fflags & NOTE_TRUNCATE) + if (sb.st_nsize == 0 && src->kev.fflags & NOTE_TRUNCATE) dst->fflags |= NOTE_TRUNCATE; #endif - if (sb.st_size > kn->data.vnode.size && kn->kev.fflags & NOTE_WRITE) + if (sb.st_size > src->data.vnode.size && src->kev.fflags & NOTE_WRITE) dst->fflags |= NOTE_EXTEND; - kn->data.vnode.nlink = sb.st_nlink; - kn->data.vnode.size = sb.st_size; + src->data.vnode.nlink = sb.st_nlink; + src->data.vnode.size = sb.st_size; } - if (evt.mask & IN_MODIFY && kn->kev.fflags & NOTE_WRITE) + if (evt.mask & IN_MODIFY && src->kev.fflags & NOTE_WRITE) dst->fflags |= NOTE_WRITE; - if (evt.mask & IN_ATTRIB && kn->kev.fflags & NOTE_ATTRIB) + if (evt.mask & IN_ATTRIB && src->kev.fflags & NOTE_ATTRIB) dst->fflags |= NOTE_ATTRIB; - if (evt.mask & IN_MOVE_SELF && kn->kev.fflags & NOTE_RENAME) + if (evt.mask & IN_MOVE_SELF && src->kev.fflags & NOTE_RENAME) dst->fflags |= NOTE_RENAME; - if (evt.mask & IN_DELETE_SELF && kn->kev.fflags & NOTE_DELETE) + if (evt.mask & IN_DELETE_SELF && src->kev.fflags & NOTE_DELETE) dst->fflags |= NOTE_DELETE; - if (evt.mask & IN_MODIFY && kn->kev.fflags & NOTE_WRITE) + if (evt.mask & IN_MODIFY && src->kev.fflags & NOTE_WRITE) dst->fflags |= NOTE_WRITE; - if (evt.mask & IN_ATTRIB && kn->kev.fflags & NOTE_ATTRIB) + if (evt.mask & IN_ATTRIB && src->kev.fflags & NOTE_ATTRIB) dst->fflags |= NOTE_ATTRIB; - if (evt.mask & IN_MOVE_SELF && kn->kev.fflags & NOTE_RENAME) + if (evt.mask & IN_MOVE_SELF && src->kev.fflags & NOTE_RENAME) dst->fflags |= NOTE_RENAME; - if (evt.mask & IN_DELETE_SELF && kn->kev.fflags & NOTE_DELETE) + if (evt.mask & IN_DELETE_SELF && src->kev.fflags & NOTE_DELETE) dst->fflags |= NOTE_DELETE; - if (kn->kev.flags & EV_DISPATCH) { - delete_watch(filt, kn); /* TODO: error checking */ - KNOTE_DISABLE(kn); - } else if (kn->kev.flags & EV_ONESHOT) { - delete_watch(filt, kn); /* TODO: error checking */ - knote_free(filt, kn); - } - - return (1); + return (0); } int diff --git a/vendor/libkqueue/src/posix/kevent.c b/vendor/libkqueue/src/posix/kevent.c index 1ee4b5a02..6ebb62e14 100644 --- a/vendor/libkqueue/src/posix/kevent.c +++ b/vendor/libkqueue/src/posix/kevent.c @@ -71,4 +71,4 @@ posix_kevent_copyout(struct kqueue *kq, int nready, } return (nret); -} \ No newline at end of file +} diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 7424773dd..ea792aa9b 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -25,11 +25,18 @@ #define atomic_inc(p) __sync_add_and_fetch((p), 1) #define atomic_dec(p) __sync_sub_and_fetch((p), 1) +/* + * GCC-compatible branch prediction macros + */ +#define fastpath(x) __builtin_expect((x), 1) +#define slowpath(x) __builtin_expect((x), 0) + #define CONSTRUCTOR __attribute__ ((constructor)) #define VISIBLE __attribute__((visibility("default"))) #define HIDDEN __attribute__((visibility("hidden"))) #include +#include #include #include #include diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile index 4db724f7b..6fce32623 100644 --- a/vendor/libkqueue/test/Makefile +++ b/vendor/libkqueue/test/Makefile @@ -24,6 +24,9 @@ kqtest: $(SOURCES) check: kqtest LD_LIBRARY_PATH="..:/usr/sfw/lib/64" ./kqtest +debug: kqtest + LD_LIBRARY_PATH="..:/usr/sfw/lib/64" gdb ./kqtest + valgrind: kqtest valgrind --tool=memcheck --leak-check=full --show-reachable=yes --num-callers=20 --track-fds=yes ./kqtest diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 2794d0fc6..32c80aa58 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -26,6 +26,37 @@ struct unit_test { }; +void +test_kqueue_descriptor_is_pollable(void) +{ + int kq, rv; + struct kevent kev; + fd_set fds; + struct timeval tv; + + if ((kq = kqueue()) < 0) + die("kqueue()"); + + test_no_kevents(kq); + kevent_add(kq, &kev, 2, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 1000, NULL); + test_no_kevents(kq); + + FD_ZERO(&fds); + FD_SET(kq, &fds); + tv.tv_sec = 5; + tv.tv_usec = 0; + rv = select(1, &fds, NULL, NULL, &tv); + if (rv < 0) + die("select() error"); + if (rv == 0) + die("select() no events"); + if (!FD_ISSET(kq, &fds)) { + die("descriptor is not ready for reading"); + } + + close(kq); +} + /* * DEADWOOD: fails on Solaris * Test if calling fstat() on a socketpair returns unique ino_t and dev_t @@ -206,6 +237,9 @@ main(int argc, char **argv) } test(ev_receipt); + /* TODO: this fails now, but would be good later + test(kqueue_descriptor_is_pollable); + */ testing_end(); diff --git a/vendor/libkqueue/test/signal.c b/vendor/libkqueue/test/signal.c index 7b41e93c4..c139e74ce 100644 --- a/vendor/libkqueue/test/signal.c +++ b/vendor/libkqueue/test/signal.c @@ -128,6 +128,8 @@ test_kevent_signal_modify(void) kev.flags |= EV_CLEAR; kev.data = 1; kevent_cmp(&kev, kevent_get(kqfd)); + + test_kevent_signal_del(); } #if HAVE_EV_DISPATCH From 7655c2561cddfdc3616a786a7aab5b79daa2ad9c Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 2 Feb 2011 02:54:50 +0000 Subject: [PATCH 0385/1120] add additional valgrind targets git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@409 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/Makefile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile index 6fce32623..78ce7275b 100644 --- a/vendor/libkqueue/test/Makefile +++ b/vendor/libkqueue/test/Makefile @@ -28,8 +28,17 @@ debug: kqtest LD_LIBRARY_PATH="..:/usr/sfw/lib/64" gdb ./kqtest valgrind: kqtest + LD_LIBRARY_PATH="..:/usr/sfw/lib/64" \ valgrind --tool=memcheck --leak-check=full --show-reachable=yes --num-callers=20 --track-fds=yes ./kqtest +helgrind: kqtest + LD_LIBRARY_PATH="..:/usr/sfw/lib/64" \ + valgrind --tool=helgrind ./kqtest + +cachegrind: kqtest + LD_LIBRARY_PATH="..:/usr/sfw/lib/64" \ + valgrind --tool=cachegrind --branch-sim=yes ./kqtest + check-installed: $(CC) -o kqtest $(CFLAGS) $(SOURCES) $(LDADD) -lkqueue ./kqtest From 843dbbe42929f4a894223cddabd1a82ed52084c1 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 2 Feb 2011 03:13:24 +0000 Subject: [PATCH 0386/1120] Use a lock-free static array for kqueue descriptors < 512 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@410 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kqueue.c | 61 +++++++++++++++------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 1352365f9..fcede1e0d 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -27,6 +27,15 @@ int KQUEUE_DEBUG = 0; +/* + * Fast path (lock-free) for kqueue descriptors < KQLIST_MAX + */ +#define KQLIST_MAX 512 +static struct kqueue *kqlist[KQLIST_MAX]; + +/* + * Slow path for kqueue descriptors > KQLIST_MAX + */ static RB_HEAD(kqt, kqueue) kqtree = RB_INITIALIZER(&kqtree); static pthread_rwlock_t kqtree_mtx; @@ -66,26 +75,23 @@ kqueue_free(struct kqueue *kq) free(kq); } -void -kqueue_put(struct kqueue *kq) -{ - atomic_dec(&kq->kq_ref); - /* TODO: free() object when refcount == 0 */ -} - struct kqueue * -kqueue_get(int kq) +kqueue_lookup(int kq) { struct kqueue query; struct kqueue *ent = NULL; - query.kq_id = kq; - pthread_rwlock_rdlock(&kqtree_mtx); - ent = RB_FIND(kqt, &kqtree, &query); - pthread_rwlock_unlock(&kqtree_mtx); - - if (ent != NULL) - atomic_inc(&ent->kq_ref); + if (slowpath(kq < 0)) { + return (NULL); + } + if (fastpath(kq < KQLIST_MAX)) { + ent = kqlist[kq]; + } else { + query.kq_id = kq; + pthread_rwlock_rdlock(&kqtree_mtx); + ent = RB_FIND(kqt, &kqtree, &query); + pthread_rwlock_unlock(&kqtree_mtx); + } return (ent); } @@ -98,21 +104,20 @@ kqueue(void) kq = calloc(1, sizeof(*kq)); if (kq == NULL) return (-1); - kq->kq_ref = 1; - pthread_mutex_init(&kq->kq_mtx, NULL); - pthread_rwlock_wrlock(&kqtree_mtx); - if (kqops.kqueue_init(kq) < 0) - goto errout; - RB_INSERT(kqt, &kqtree, kq); - pthread_rwlock_unlock(&kqtree_mtx); + if (kqops.kqueue_init(kq) < 0) { + free(kq); + return (-1); + } + + if (kq->kq_id < KQLIST_MAX) { + kqlist[kq->kq_id] = kq; + } else { + pthread_rwlock_wrlock(&kqtree_mtx); + RB_INSERT(kqt, &kqtree, kq); + pthread_rwlock_unlock(&kqtree_mtx); + } dbg_printf("created kqueue, fd=%d", kq->kq_id); return (kq->kq_id); - -errout: - pthread_rwlock_unlock(&kqtree_mtx); - kqops.kqueue_free(kq); - free(kq); - return (-1); } From d101e346ba287ee0220bec7976cbe82cc31f65fb Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 2 Feb 2011 03:39:29 +0000 Subject: [PATCH 0387/1120] Refactor kevent() to make the flow of control more obvious. Add reference counting to the knote structure. This is slightly buggy and probably unnecessary. Eliminate the kqueue_lock() and kqueue_unlock() functions, and create a heirarchy of two locks: the knotelist lock at the filter level, and a per-knote lock. This needs to be looked at more closely. Make note of a race condition when kev.flags contains EV_ADD | EV_DISABLE and a new knote is created. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@411 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/filter.c | 1 + vendor/libkqueue/src/common/kevent.c | 108 +++++++++++--------------- vendor/libkqueue/src/common/knote.c | 47 +++++++++-- vendor/libkqueue/src/common/private.h | 14 ++-- vendor/libkqueue/src/linux/platform.c | 8 +- vendor/libkqueue/src/linux/user.c | 1 + 6 files changed, 100 insertions(+), 79 deletions(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index 8724baf4a..18461a647 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -46,6 +46,7 @@ filter_register(struct kqueue *kq, short filter, const struct filter *src) memcpy(dst, src, sizeof(*src)); dst->kf_kqueue = kq; RB_INIT(&dst->kf_knote); + pthread_rwlock_init(&dst->kf_knote_mtx, NULL); if (src->kf_id == 0) { dbg_puts("filter is not implemented"); return (0); diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index a946e259f..842774599 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -130,7 +130,7 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) if (filter_lookup(&filt, kq, src->filter) < 0) return (-1); - //dbg_printf("src=%s\n", kevent_dump(src)); + dbg_printf("src=%s\n", kevent_dump(src)); kn = knote_lookup(filt, src->ident); if (kn == NULL) { @@ -144,16 +144,23 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) kn->kev.flags |= EV_ADD;//FIXME why? assert(filt->kn_create); if (filt->kn_create(filt, kn) < 0) { - knote_free(filt, kn); + knote_release(filt, kn); errno = EFAULT; return (-1); } knote_insert(filt, kn); dbg_printf("created kevent %s\n", kevent_dump(src)); + + +/* XXX- FIXME Needs to be handled in kn_create() to prevent races */ if (src->flags & EV_DISABLE) { kn->kev.flags |= EV_DISABLE; return (filt->kn_disable(filt, kn)); } + //........................................ + + + return (0); } else { errno = ENOENT; @@ -162,28 +169,22 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) } if (src->flags & EV_DELETE) { - knote_free(filt, kn); - return (rv); + knote_release(filt, kn); + rv = 0; } else if (src->flags & EV_DISABLE) { kn->kev.flags |= EV_DISABLE; - return (filt->kn_disable(filt, kn)); + rv = filt->kn_disable(filt, kn); } else if (src->flags & EV_ENABLE) { kn->kev.flags &= ~EV_DISABLE; - return (filt->kn_enable(filt, kn)); + rv = filt->kn_enable(filt, kn); + } else if (src->flags & EV_ADD || src->flags == 0) { + kn->kev.udata = src->udata; + rv = filt->kn_modify(filt, kn, src); } - /* Implicit EV_ADD */ - kn->kev.udata = src->udata; - return (filt->kn_modify(filt, kn, src)); + knote_unlock(kn); -#if DEADWOOD - /* Special case for EVFILT_USER: - Ignore user-generated events that are not of interest */ - if (src->fflags & NOTE_TRIGGER) { - filter_unlock(filt); - continue; - } -#endif + return (rv); } /** @return number of events added to the eventlist */ @@ -233,9 +234,16 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, { static unsigned int _kevent_counter = 0; struct kqueue *kq; - int rv, n, nret; + int rv = 0; unsigned int myid; + /* Convert the descriptor into an object pointer */ + kq = kqueue_lookup(kqfd); + if (kq == NULL) { + errno = ENOENT; + return (-1); + } + if (KQUEUE_DEBUG) { myid = atomic_inc(&_kevent_counter); dbg_printf("--- kevent %u ---", myid); @@ -243,73 +251,47 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, myid = 0; } - nret = 0; - - kq = kqueue_get(kqfd); - if (kq == NULL) { - errno = ENOENT; - nret = -1; - goto out2; - } - /* * Process each kevent on the changelist. */ - if (nchanges) { - kqueue_lock(kq); + if (nchanges > 0) { rv = kevent_copyin(kq, changelist, nchanges, eventlist, nevents); - kqueue_unlock(kq); dbg_printf("(%u) changelist: rv=%d", myid, rv); if (rv < 0) - goto errout; + goto out; if (rv > 0) { eventlist += rv; nevents -= rv; } } + /* + * Wait for events and copy them to the eventlist + */ if (nevents > MAX_KEVENT) nevents = MAX_KEVENT; - - if (nevents == 0) - goto out; - - /* Handle spurious wakeups where no events are generated. */ - for (nret = 0; nret == 0;) - { - /* Wait for one or more events. */ - n = kqops.kevent_wait(kq, nevents, timeout); - - /* Copy the events to the caller */ - if (fastpath(n > 0)) { - kqueue_lock(kq); - nret = kqops.kevent_copyout(kq, n, eventlist, nevents); - kqueue_unlock(kq); - } - if (n < 0) { + if (nevents > 0) { + rv = kqops.kevent_wait(kq, nevents, timeout); + if (fastpath(rv > 0)) { + rv = kqops.kevent_copyout(kq, rv, eventlist, nevents); + } else if (rv == 0) { + /* Timeout reached */ + } else { dbg_printf("(%u) kevent_wait failed", myid); - goto errout; + goto out; } - if (n == 0) - goto out; /* Timed out */ } if (KQUEUE_DEBUG) { - dbg_printf("(%u) returning %d events", myid, nret); - for (n = 0; n < nret; n++) { + int n; + + dbg_printf("(%u) returning %d events", myid, rv); + for (n = 0; n < rv; n++) { dbg_printf("(%u) eventlist[%d] = %s", myid, n, kevent_dump(&eventlist[n])); } } - goto out; - -errout: - nret = -1; - out: - kqueue_put(kq); - -out2: - dbg_printf("--- END kevent %u ret %d ---", myid, nret); - return (nret); + dbg_printf("--- END kevent %u ret %d ---", myid, rv); + return (rv); } diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 6a381d035..cf951efdd 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -20,6 +20,8 @@ #include "private.h" +static void knote_free(struct filter *, struct knote *); + static int knote_cmp(struct knote *a, struct knote *b) { @@ -39,33 +41,58 @@ knote_new(void) return (dst); } +static inline void +knote_retain(struct knote *kn) +{ + atomic_inc(&kn->kn_ref); +} + +void +knote_release(struct filter *filt, struct knote *kn) +{ + int ref; + + ref = atomic_dec(&kn->kn_ref); + if (ref <= 0) { + dbg_printf("freeing knote at %p, rc=%d", kn, ref); + pthread_rwlock_wrlock(&filt->kf_knote_mtx); + knote_free(filt, kn); + pthread_rwlock_unlock(&filt->kf_knote_mtx); + } else { + dbg_printf("NOT freeing knote %p rc=%d", kn, ref); + } +} + void knote_insert(struct filter *filt, struct knote *kn) { + pthread_rwlock_wrlock(&filt->kf_knote_mtx); RB_INSERT(knt, &filt->kf_knote, kn); + pthread_rwlock_unlock(&filt->kf_knote_mtx); } -void +static void knote_free(struct filter *filt, struct knote *kn) { - dbg_printf("filter=%s, ident=%u", - filter_name(kn->kev.filter), (unsigned int) kn->kev.ident); - RB_REMOVE(knt, &filt->kf_knote, kn); + RB_REMOVE(knt, &filt->kf_knote, kn); filt->kn_delete(filt, kn); - free(kn); + free(kn); } +/* XXX-FIXME this is broken and should be removed */ void knote_free_all(struct filter *filt) { struct knote *n1, *n2; /* Destroy all knotes */ + pthread_rwlock_wrlock(&filt->kf_knote_mtx); for (n1 = RB_MIN(knt, &filt->kf_knote); n1 != NULL; n1 = n2) { n2 = RB_NEXT(knt, filt->kf_knote, n1); RB_REMOVE(knt, &filt->kf_knote, n1); free(n1); } + pthread_rwlock_unlock(&filt->kf_knote_mtx); } /* TODO: rename to knote_lookup_ident */ @@ -76,7 +103,12 @@ knote_lookup(struct filter *filt, short ident) struct knote *ent = NULL; query.kev.ident = ident; + + pthread_rwlock_rdlock(&filt->kf_knote_mtx); ent = RB_FIND(knt, &filt->kf_knote, &query); + if (ent != NULL) + knote_lock(ent); + pthread_rwlock_unlock(&filt->kf_knote_mtx); dbg_printf("id=%d ent=%p", ident, ent); @@ -88,10 +120,15 @@ knote_lookup_data(struct filter *filt, intptr_t data) { struct knote *kn; + pthread_rwlock_rdlock(&filt->kf_knote_mtx); RB_FOREACH(kn, knt, &filt->kf_knote) { if (data == kn->kev.data) break; } + if (kn != NULL) + knote_lock(kn); + pthread_rwlock_unlock(&filt->kf_knote_mtx); + return (kn); } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index a369befac..8244d92ed 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -98,6 +98,7 @@ struct eventfd { struct knote { struct kevent kev; int flags; + pthread_mutex_t mtx; union { /* OLD */ int pfd; /* Used by timerfd */ @@ -110,6 +111,7 @@ struct knote { pthread_t tid; /* Used by posix/timer.c */ void *handle; /* Used by win32 filters */ } data; + volatile uint32_t kn_ref; #if defined(KNOTE_PLATFORM_SPECIFIC) KNOTE_PLATFORM_SPECIFIC; #endif @@ -153,6 +155,7 @@ struct filter { struct evfilt_data *kf_data; /* filter-specific data */ RB_HEAD(knt, knote) kf_knote; + pthread_rwlock_t kf_knote_mtx; struct kqueue *kf_kqueue; #if defined(FILTER_PLATFORM_SPECIFIC) FILTER_PLATFORM_SPECIFIC; @@ -167,8 +170,6 @@ struct kqueue { struct filter kq_filt[EVFILT_SYSCOUNT]; fd_set kq_fds, kq_rfds; int kq_nfds; - pthread_mutex_t kq_mtx; - volatile uint32_t kq_ref; #if defined(KQUEUE_PLATFORM_SPECIFIC) KQUEUE_PLATFORM_SPECIFIC; #endif @@ -193,7 +194,7 @@ extern const struct kqueue_vtable kqops; struct knote * knote_lookup(struct filter *, short); struct knote * knote_lookup_data(struct filter *filt, intptr_t); struct knote * knote_new(void); -void knote_free(struct filter *, struct knote *); +void knote_release(struct filter *, struct knote *); void knote_free_all(struct filter *); void knote_insert(struct filter *, struct knote *); int knote_get_socket_type(struct knote *); @@ -203,6 +204,8 @@ int knote_get_socket_type(struct knote *); //DEADWOOD:struct knote * knote_dequeue(struct filter *); //DEADWOOD:int knote_events_pending(struct filter *); int knote_disable(struct filter *, struct knote *); +#define knote_lock(kn) pthread_mutex_lock(&(kn)->mtx) +#define knote_unlock(kn) pthread_mutex_unlock(&(kn)->mtx) int filter_lookup(struct filter **, struct kqueue *, short); int filter_register_all(struct kqueue *); @@ -214,11 +217,8 @@ int kevent_copyout(struct kqueue *, int, struct kevent *, int); void kevent_free(struct kqueue *); const char *kevent_dump(const struct kevent *); -struct kqueue * kqueue_get(int); -void kqueue_put(struct kqueue *); +struct kqueue * kqueue_lookup(int); int kqueue_validate(struct kqueue *); -#define kqueue_lock(kq) pthread_mutex_lock(&(kq)->kq_mtx) -#define kqueue_unlock(kq) pthread_mutex_unlock(&(kq)->kq_mtx) int CONSTRUCTOR _libkqueue_init(void); diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 739f7530c..961b3d6a6 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -152,13 +152,13 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct knote *kn; int i, rv; - assert(nready >= 1); - for (i = 0; i < nready; i++) { ev = &epevt[i]; kn = (struct knote *) ev->data.ptr; + knote_lock(kn); filt = &kq->kq_filt[~(kn->kev.filter)]; rv = filt->kf_copyout(eventlist, kq, filt, kn, ev); + knote_unlock(kn); if (slowpath(rv < 0)) { dbg_puts("knote_copyout failed"); /* XXX-FIXME: hard to handle this without losing events */ @@ -166,13 +166,13 @@ linux_kevent_copyout(struct kqueue *kq, int nready, } /* - * Certain flags cause the associate knote to be deleted + * Certain flags cause the associated knote to be deleted * or disabled. */ if (eventlist->flags & EV_DISPATCH) knote_disable(filt, kn); //TODO: Error checking if (eventlist->flags & EV_ONESHOT) - knote_free(filt, kn); //TODO: Error checking + knote_release(filt, kn); //TODO: Error checking eventlist++; } diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index 153550db8..7e03ab875 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -207,6 +207,7 @@ evfilt_user_knote_delete(struct filter *filt, struct knote *kn) dbg_perror("close(2)"); return (-1); } + dbg_printf("removed eventfd %d from the epollfd", kn->kdata.kn_eventfd); kn->kdata.kn_eventfd = -1; return (0); From e6a8a104192bfaec4c3eb0d8c0adce24e2f0a126 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 3 Feb 2011 04:45:40 +0000 Subject: [PATCH 0388/1120] New generic lock-free map replaces the kqlist/kqtree. It does not handle overwriting an existing entry; need futher work on this part. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@412 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/config.inc | 2 +- vendor/libkqueue/src/common/kqueue.c | 52 +++++------------ vendor/libkqueue/src/common/map.c | 80 +++++++++++++++++++++++++++ vendor/libkqueue/src/common/private.h | 8 ++- vendor/libkqueue/src/posix/platform.h | 4 ++ 5 files changed, 106 insertions(+), 40 deletions(-) create mode 100644 vendor/libkqueue/src/common/map.c diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index 22b171111..1f67aa605 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -5,7 +5,7 @@ abi_minor="0" abi_version="$abi_major.$abi_minor" cflags="-fpic -Wall -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600" ldflags="" -sources="src/common/filter.c src/common/knote.c +sources="src/common/filter.c src/common/knote.c src/common/map.c src/common/kevent.c src/common/kqueue.c" libdepends="" deps="src/common/private.h" diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index fcede1e0d..f4e87c00d 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -27,17 +27,7 @@ int KQUEUE_DEBUG = 0; -/* - * Fast path (lock-free) for kqueue descriptors < KQLIST_MAX - */ -#define KQLIST_MAX 512 -static struct kqueue *kqlist[KQLIST_MAX]; - -/* - * Slow path for kqueue descriptors > KQLIST_MAX - */ -static RB_HEAD(kqt, kqueue) kqtree = RB_INITIALIZER(&kqtree); -static pthread_rwlock_t kqtree_mtx; +static struct map *kqmap; int CONSTRUCTOR _libkqueue_init(void) @@ -51,20 +41,20 @@ _libkqueue_init(void) KQUEUE_DEBUG = (getenv("KQUEUE_DEBUG") == NULL) ? 0 : 1; #endif - pthread_rwlock_init(&kqtree_mtx, NULL); - + kqmap = map_new(INT_MAX); + if (kqmap == NULL) + abort(); dbg_puts("library initialization complete"); return (0); } +#if DEADWOOD static int kqueue_cmp(struct kqueue *a, struct kqueue *b) { return memcmp(&a->kq_id, &b->kq_id, sizeof(int)); } -RB_GENERATE(kqt, kqueue, entries, kqueue_cmp) - /* Must hold the kqtree_mtx when calling this */ void kqueue_free(struct kqueue *kq) @@ -75,25 +65,12 @@ kqueue_free(struct kqueue *kq) free(kq); } +#endif + struct kqueue * kqueue_lookup(int kq) { - struct kqueue query; - struct kqueue *ent = NULL; - - if (slowpath(kq < 0)) { - return (NULL); - } - if (fastpath(kq < KQLIST_MAX)) { - ent = kqlist[kq]; - } else { - query.kq_id = kq; - pthread_rwlock_rdlock(&kqtree_mtx); - ent = RB_FIND(kqt, &kqtree, &query); - pthread_rwlock_unlock(&kqtree_mtx); - } - - return (ent); + return ((struct kqueue *) map_lookup(kqmap, kq)); } int VISIBLE @@ -110,14 +87,13 @@ kqueue(void) return (-1); } - if (kq->kq_id < KQLIST_MAX) { - kqlist[kq->kq_id] = kq; - } else { - pthread_rwlock_wrlock(&kqtree_mtx); - RB_INSERT(kqt, &kqtree, kq); - pthread_rwlock_unlock(&kqtree_mtx); + dbg_printf("created kqueue, fd=%d", kq->kq_id); + + if (map_insert(kqmap, kq->kq_id, kq) < 0) { + dbg_puts("map insertion failed"); + kqops.kqueue_free(kq); + return (-1); } - dbg_printf("created kqueue, fd=%d", kq->kq_id); return (kq->kq_id); } diff --git a/vendor/libkqueue/src/common/map.c b/vendor/libkqueue/src/common/map.c new file mode 100644 index 000000000..c9c35613c --- /dev/null +++ b/vendor/libkqueue/src/common/map.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "private.h" + +struct map { + volatile size_t len; + void **data; +}; + +struct map * +map_new(size_t len) +{ + struct map *dst; + + dst = calloc(1, sizeof(*dst)); + if (dst == NULL) + return (NULL); + dst->data = mmap(NULL, len * sizeof(void *), PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_NORESERVE | MAP_ANON, -1, 0); + if (dst->data == MAP_FAILED) { + dbg_perror("mmap(2)"); + free(dst); + return (NULL); + } + dst->len = len; + + return (dst); +} + +int +map_insert(struct map *m, int idx, void *ptr) +{ + if (slowpath(idx < 0 || idx > m->len)) + return (-1); + + if (__sync_val_compare_and_swap(&(m->data[idx]), 0, ptr) == NULL) { + dbg_printf("inserted %p in location %d", ptr, idx); + return (0); + } else { + dbg_printf("tried to insert a value into a non-empty location %d (value=%p)", + idx, + m->data[idx]); + return (-1); + } +} + +void * +map_lookup(struct map *m, int idx) +{ + if (slowpath(idx < 0 || idx > m->len)) + return (NULL); + + return m->data[idx]; +} + +int +map_delete(struct map *m, int idx) +{ + if (slowpath(idx < 0 || idx > m->len)) + return (-1); + + //TODO: use CAS and fail if entry is NULL + + m->data[idx] = NULL; + return (0); +} diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 8244d92ed..d163df484 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -28,6 +28,7 @@ struct kqueue; struct kevent; struct knote; +struct map; struct eventfd; struct evfilt_data; @@ -216,10 +217,15 @@ int kevent_wait(struct kqueue *, const struct timespec *); int kevent_copyout(struct kqueue *, int, struct kevent *, int); void kevent_free(struct kqueue *); const char *kevent_dump(const struct kevent *); - struct kqueue * kqueue_lookup(int); int kqueue_validate(struct kqueue *); +struct map *map_new(size_t); +int map_insert(struct map *, int, void *); +void *map_lookup(struct map *, int); +int map_delete(struct map *, int); +void map_free(struct map *); + int CONSTRUCTOR _libkqueue_init(void); #endif /* ! _KQUEUE_PRIVATE_H */ diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index ea792aa9b..5e31e8deb 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -17,6 +17,9 @@ #ifndef _KQUEUE_POSIX_PLATFORM_H #define _KQUEUE_POSIX_PLATFORM_H +/* Required by glibc for MAP_ANON */ +#define __USE_MISC 1 + #include "../../include/sys/event.h" /* @@ -48,6 +51,7 @@ #include #include #include +#include #include /* From cdfaf07f740ae12c462dfe2a207beb0387e9abe9 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 6 Feb 2011 21:03:04 +0000 Subject: [PATCH 0389/1120] improve map functions, fix a crash when reusing a kqueue file descriptor git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@413 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kqueue.c | 6 +++ vendor/libkqueue/src/common/map.c | 53 ++++++++++++++++++++++++--- vendor/libkqueue/src/common/private.h | 4 +- 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index f4e87c00d..d98e59f34 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -77,6 +77,7 @@ int VISIBLE kqueue(void) { struct kqueue *kq; + struct kqueue *tmp; kq = calloc(1, sizeof(*kq)); if (kq == NULL) @@ -89,6 +90,11 @@ kqueue(void) dbg_printf("created kqueue, fd=%d", kq->kq_id); + tmp = map_delete(kqmap, kq->kq_id); + if (tmp != NULL) { + dbg_puts("FIXME -- memory leak here"); + // TODO: kqops.kqueue_free(tmp), or (better yet) decrease it's refcount + } if (map_insert(kqmap, kq->kq_id, kq) < 0) { dbg_puts("map insertion failed"); kqops.kqueue_free(kq); diff --git a/vendor/libkqueue/src/common/map.c b/vendor/libkqueue/src/common/map.c index c9c35613c..2ddd1b0f1 100644 --- a/vendor/libkqueue/src/common/map.c +++ b/vendor/libkqueue/src/common/map.c @@ -17,7 +17,7 @@ #include "private.h" struct map { - volatile size_t len; + size_t len; void **data; }; @@ -58,6 +58,41 @@ map_insert(struct map *m, int idx, void *ptr) } } +int +map_remove(struct map *m, int idx, void *ptr) +{ + if (slowpath(idx < 0 || idx > m->len)) + return (-1); + + if (__sync_val_compare_and_swap(&(m->data[idx]), ptr, 0) == NULL) { + dbg_printf("removed %p from location %d", ptr, idx); + return (0); + } else { + dbg_printf("removal failed: location %d does not contain value %p", idx, m->data[idx]); + return (-1); + } +} + +int +map_replace(struct map *m, int idx, void *oldp, void *newp) +{ + void *tmp; + + if (slowpath(idx < 0 || idx > m->len)) + return (-1); + + tmp = __sync_val_compare_and_swap(&(m->data[idx]), oldp, newp); + if (tmp == oldp) { + dbg_printf("replaced value %p in location %d with value %p", + oldp, idx, newp); + return (0); + } else { + dbg_printf("item in location %d does not match expected value %p", + idx, oldp); + return (-1); + } +} + void * map_lookup(struct map *m, int idx) { @@ -67,14 +102,22 @@ map_lookup(struct map *m, int idx) return m->data[idx]; } -int +void * map_delete(struct map *m, int idx) { + void *oval; + void *nval; + if (slowpath(idx < 0 || idx > m->len)) - return (-1); + return ((void *)-1); - //TODO: use CAS and fail if entry is NULL + /* Hopefully we aren't racing with another thread, but you never know.. */ + do { + oval = m->data[idx]; + nval = __sync_val_compare_and_swap(&(m->data[idx]), oval, NULL); + } while (nval != oval); m->data[idx] = NULL; - return (0); + + return ((void *) oval); } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index d163df484..36c711d68 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -222,8 +222,10 @@ int kqueue_validate(struct kqueue *); struct map *map_new(size_t); int map_insert(struct map *, int, void *); +int map_remove(struct map *, int, void *); +int map_replace(struct map *, int, void *, void *); void *map_lookup(struct map *, int); -int map_delete(struct map *, int); +void *map_delete(struct map *, int); void map_free(struct map *); int CONSTRUCTOR _libkqueue_init(void); From 3a61b33aa87857a3f0849506525254f5ebbeec63 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 9 Feb 2011 03:43:10 +0000 Subject: [PATCH 0390/1120] Implement a simple fixed-size memory allocator. Use a private memory allocator for knote objects. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@414 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/alloc.h | 81 +++++++++++++++++++++++++++ vendor/libkqueue/src/common/knote.c | 18 +++--- vendor/libkqueue/src/common/kqueue.c | 2 + vendor/libkqueue/src/common/private.h | 1 + 4 files changed, 95 insertions(+), 7 deletions(-) create mode 100644 vendor/libkqueue/src/common/alloc.h diff --git a/vendor/libkqueue/src/common/alloc.h b/vendor/libkqueue/src/common/alloc.h new file mode 100644 index 000000000..56c390010 --- /dev/null +++ b/vendor/libkqueue/src/common/alloc.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +/* + * A simple fixed-size memory allocator. + * + * Each translation unit in a program can include this header and + * have access to it's own private memory allocator. This can be useful + * for improving the performance of programs which frequently allocate + * and deallocate objects with a fixed size. + * + * The allocator must be initialized by calling mem_init(). This + * function takes two arguments: the object size, and the maximum + * number of objects in the cache. + * + * The functions mem_alloc() and mem_free() have similar semantics + * to the traditional malloc() and free() calls. The main difference + * is that mem_alloc() does not allow you to specify a specific size. + * + */ + +#include +#include + +static __thread struct { + void **ac_cache; /* An array of reusable memory objects */ + size_t ac_count; /* The number of objects in the cache */ + size_t ac_max; /* The maximum number of cached objects */ + size_t ac_size; /* The size, in bytes, of each object */ +} _ma; + +static inline int +mem_init(size_t objsize, size_t cachesize) +{ + _ma.ac_size = objsize; + _ma.ac_cache = malloc(cachesize * sizeof(void *)); + return (_ma.ac_cache == NULL ? -1 : 0); +} + +static inline void * +mem_alloc(void) +{ + if (_ma.ac_count > 0) + return (_ma.ac_cache[_ma.ac_count--]); + else + return (malloc(_ma.ac_size)); +} + +static inline void * +mem_calloc(void) +{ + void *p; + + p = mem_alloc(); + if (p != NULL) + memset(p, 0, _ma.ac_size); + return (p); +} + +static inline void +mem_free(void *ptr) +{ + if (_ma.ac_count < _ma.ac_max) + _ma.ac_cache[_ma.ac_count++] = ptr; + else + free(ptr); +} diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index cf951efdd..f34fb8917 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -19,9 +19,16 @@ #include #include "private.h" +#include "alloc.h" static void knote_free(struct filter *, struct knote *); +int +knote_init(void) +{ + return (mem_init(sizeof(struct knote), 1024)); +} + static int knote_cmp(struct knote *a, struct knote *b) { @@ -33,12 +40,7 @@ RB_GENERATE(knt, knote, kntree_ent, knote_cmp) struct knote * knote_new(void) { - struct knote *dst; - - if ((dst = calloc(1, sizeof(*dst))) == NULL) - return (NULL); - - return (dst); + return (mem_calloc()); } static inline void @@ -76,7 +78,7 @@ knote_free(struct filter *filt, struct knote *kn) { RB_REMOVE(knt, &filt->kf_knote, kn); filt->kn_delete(filt, kn); - free(kn); + mem_free(kn); } /* XXX-FIXME this is broken and should be removed */ @@ -85,6 +87,8 @@ knote_free_all(struct filter *filt) { struct knote *n1, *n2; + abort(); + /* Destroy all knotes */ pthread_rwlock_wrlock(&filt->kf_knote_mtx); for (n1 = RB_MIN(knt, &filt->kf_knote); n1 != NULL; n1 = n2) { diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index d98e59f34..1dfa62937 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -44,6 +44,8 @@ _libkqueue_init(void) kqmap = map_new(INT_MAX); if (kqmap == NULL) abort(); + if (knote_init() < 0) + abort(); dbg_puts("library initialization complete"); return (0); } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 36c711d68..5df8a3ba5 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -199,6 +199,7 @@ void knote_release(struct filter *, struct knote *); void knote_free_all(struct filter *); void knote_insert(struct filter *, struct knote *); int knote_get_socket_type(struct knote *); +int knote_init(void); /* TODO: these deal with the eventlist, should use a different prefix */ //DEADWOOD:void knote_enqueue(struct filter *, struct knote *); From c34c9b99a0fe83f782913579f20c4e53dc5c13bd Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 12 Feb 2011 22:15:46 +0000 Subject: [PATCH 0391/1120] bump version to 2 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@415 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/config.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index 1f67aa605..06899dc7f 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -1,5 +1,5 @@ program="libkqueue" -version="1.0a" +version="2.0a" abi_major="0" abi_minor="0" abi_version="$abi_major.$abi_minor" From a2baad20690f6c01040bb5f3c58b58262d8fd78b Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 12 Feb 2011 22:16:58 +0000 Subject: [PATCH 0392/1120] fix solaris-test git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@416 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 86f3863e7..319316e52 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -157,4 +157,4 @@ diff: # Used for testing on a Solaris guest VM # solaris-test: - make dist && scp -P 2222 libkqueue-1.0a.tar.gz localhost:/tmp && ssh -p 2222 localhost ". .profile ; cd /tmp ; rm -rf libkqueue-$(VERSION) ; gtar zxvf libkqueue-$(VERSION).tar.gz && cd libkqueue-$(VERSION) && ./configure && make && make check" + make dist && scp -P 2222 libkqueue-$(VERSION).tar.gz localhost:/tmp && ssh -p 2222 localhost ". .profile ; cd /tmp ; rm -rf libkqueue-$(VERSION) ; gtar zxvf libkqueue-$(VERSION).tar.gz && cd libkqueue-$(VERSION) && ./configure && make && make check" From e8879d5366e6f9d0ead2b1dc180460a888e8f3d7 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 13 Feb 2011 04:23:55 +0000 Subject: [PATCH 0393/1120] Add a new atomic_cas() function for Solaris compatibility git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@417 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/map.c | 8 ++++---- vendor/libkqueue/src/posix/platform.h | 3 ++- vendor/libkqueue/src/solaris/platform.h | 4 +++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/src/common/map.c b/vendor/libkqueue/src/common/map.c index 2ddd1b0f1..98e9360f8 100644 --- a/vendor/libkqueue/src/common/map.c +++ b/vendor/libkqueue/src/common/map.c @@ -47,7 +47,7 @@ map_insert(struct map *m, int idx, void *ptr) if (slowpath(idx < 0 || idx > m->len)) return (-1); - if (__sync_val_compare_and_swap(&(m->data[idx]), 0, ptr) == NULL) { + if (atomic_cas(&(m->data[idx]), 0, ptr) == NULL) { dbg_printf("inserted %p in location %d", ptr, idx); return (0); } else { @@ -64,7 +64,7 @@ map_remove(struct map *m, int idx, void *ptr) if (slowpath(idx < 0 || idx > m->len)) return (-1); - if (__sync_val_compare_and_swap(&(m->data[idx]), ptr, 0) == NULL) { + if (atomic_cas(&(m->data[idx]), ptr, 0) == NULL) { dbg_printf("removed %p from location %d", ptr, idx); return (0); } else { @@ -81,7 +81,7 @@ map_replace(struct map *m, int idx, void *oldp, void *newp) if (slowpath(idx < 0 || idx > m->len)) return (-1); - tmp = __sync_val_compare_and_swap(&(m->data[idx]), oldp, newp); + tmp = atomic_cas(&(m->data[idx]), oldp, newp); if (tmp == oldp) { dbg_printf("replaced value %p in location %d with value %p", oldp, idx, newp); @@ -114,7 +114,7 @@ map_delete(struct map *m, int idx) /* Hopefully we aren't racing with another thread, but you never know.. */ do { oval = m->data[idx]; - nval = __sync_val_compare_and_swap(&(m->data[idx]), oval, NULL); + nval = atomic_cas(&(m->data[idx]), oval, NULL); } while (nval != oval); m->data[idx] = NULL; diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 5e31e8deb..17e9ae1d0 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -23,10 +23,11 @@ #include "../../include/sys/event.h" /* - * GCC-compatible atomic integer operations + * GCC-compatible atomic operations */ #define atomic_inc(p) __sync_add_and_fetch((p), 1) #define atomic_dec(p) __sync_sub_and_fetch((p), 1) +#define atomic_cas(p, oval, nval) __sync_val_compare_and_swap(p, oval, nval) /* * GCC-compatible branch prediction macros diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index de2a5e4d2..99b803710 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -22,13 +22,15 @@ #define THREAD_ID (pthread_self()) /* - * Atomic integer operations that override the ones in posix/platform.h + * Atomic operations that override the ones in posix/platform.h */ #include #undef atomic_inc #define atomic_inc atomic_inc_32_nv #undef atomic_dec #define atomic_dec atomic_dec_32_nv +#undef atomic_cas +#define atomic_cas atomic_cas_ptr /* * Event ports From 1aebf877e90fc57ea866daaf213898d5f995b73a Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 13 Feb 2011 04:26:11 +0000 Subject: [PATCH 0394/1120] workaround for a SunOS compiler warning git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@418 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kevent.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 842774599..221643d53 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -120,7 +120,7 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) { struct knote *kn = NULL; struct filter *filt; - int rv; + int rv = 0; if (src->flags & EV_DISPATCH && src->flags & EV_ONESHOT) { errno = EINVAL; @@ -170,7 +170,6 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) if (src->flags & EV_DELETE) { knote_release(filt, kn); - rv = 0; } else if (src->flags & EV_DISABLE) { kn->kev.flags |= EV_DISABLE; rv = filt->kn_disable(filt, kn); From 3b3a251395d7d4739d67c0a90d13107631bc3e36 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 13 Feb 2011 05:46:14 +0000 Subject: [PATCH 0395/1120] Merge solaris/kevent.c into solaris/platform.c, and start refactoring git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@419 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/kevent.c | 206 ------------------------ vendor/libkqueue/src/solaris/platform.c | 153 ++++++++++++++++++ vendor/libkqueue/src/solaris/platform.h | 3 - 3 files changed, 153 insertions(+), 209 deletions(-) delete mode 100644 vendor/libkqueue/src/solaris/kevent.c diff --git a/vendor/libkqueue/src/solaris/kevent.c b/vendor/libkqueue/src/solaris/kevent.c deleted file mode 100644 index 061ffe3c3..000000000 --- a/vendor/libkqueue/src/solaris/kevent.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2009 Mark Heily - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include - -#include "sys/event.h" -#include "private.h" - -const struct filter evfilt_vnode = EVFILT_NOTIMPL; -const struct filter evfilt_proc = EVFILT_NOTIMPL; - -static char * port_event_dump(port_event_t *evt); - - -/* The caller must hold the kq_mtx */ -void -port_event_dequeue(port_event_t *pe, struct kqueue *kq) -{ - struct event_buf *ebp; - - ebp = TAILQ_FIRST(&kq->kq_events); - if (ebp == NULL) - abort(); /* Should never happen */ - memcpy(pe, &ebp->pe, sizeof(*pe)); - TAILQ_REMOVE(&kq->kq_events, ebp, entries); - free(ebp); -} - -/* The caller must not hold the kq_mtx */ -void -port_event_enqueue(struct kqueue *kq, port_event_t *pe) -{ - struct event_buf *ebp; - - ebp = calloc(1, sizeof(*ebp)); - if (ebp == NULL) { - dbg_perror("lost an event! malloc(2)"); - abort(); /* FIXME: use a freelist to prevent this*/ - } - memcpy(&ebp->pe, pe, sizeof(*pe)); - kqueue_lock(kq); - /* XXX-want to insert at the tail but this causes list corruption */ - /* Since multiple threads are consuming events from the list, - there is no guarantee that ordering will be preserved. - */ - TAILQ_INSERT_HEAD(&kq->kq_events, ebp, entries); - kqueue_unlock(kq); -} - -/* Dump a poll(2) events bitmask */ -static char * -poll_events_dump(short events) -{ - static char __thread buf[512]; - -#define _PL_DUMP(attrib) \ - if (events == attrib) \ - strcat(&buf[0], " "#attrib); - - snprintf(&buf[0], 512, "events = %hd 0x%o (", events, events); - _PL_DUMP(POLLIN); - _PL_DUMP(POLLPRI); - _PL_DUMP(POLLOUT); - _PL_DUMP(POLLRDNORM); - _PL_DUMP(POLLRDBAND); - _PL_DUMP(POLLWRBAND); - _PL_DUMP(POLLERR); - _PL_DUMP(POLLHUP); - _PL_DUMP(POLLNVAL); - strcat(&buf[0], ")"); - - return (&buf[0]); - -#undef _PL_DUMP -} - -static char * -port_event_dump(port_event_t *evt) -{ - static char __thread buf[512]; - - if (evt == NULL) { - snprintf(&buf[0], sizeof(buf), "NULL ?!?!\n"); - goto out; - } - -#define PE_DUMP(attrib) \ - if (evt->portev_source == attrib) \ - strcat(&buf[0], #attrib); - - snprintf(&buf[0], 512, - " { object = %u, user = %p, %s, source = %d (", - (unsigned int) evt->portev_object, - evt->portev_user, - poll_events_dump(evt->portev_events), - evt->portev_source); - PE_DUMP(PORT_SOURCE_AIO); - PE_DUMP(PORT_SOURCE_FD); - PE_DUMP(PORT_SOURCE_TIMER); - PE_DUMP(PORT_SOURCE_USER); - PE_DUMP(PORT_SOURCE_ALERT); - strcat(&buf[0], ") }\n"); -#undef PE_DUMP - -out: - return (&buf[0]); -} - -int -solaris_kevent_wait(struct kqueue *kq, const struct timespec *timeout) -{ - port_event_t pe; - int rv; - uint_t nget = 1; - - reset_errno(); - dbg_printf("waiting for events (timeout=%p)", timeout); - rv = port_getn(kq->kq_port, &pe, 1, &nget, (struct timespec *) timeout); - dbg_printf("rv=%d errno=%d (%s) nget=%d", - rv, errno, strerror(errno), nget); - if (rv < 0) { - if (errno == ETIME) { - dbg_puts("no events within the given timeout"); - return (0); - } - if (errno == EINTR) { - dbg_puts("signal caught"); - return (-1); - } - dbg_perror("port_get(2)"); - return (-1); - } - - port_event_enqueue(kq, &pe); - - return (nget); -} - -int -solaris_kevent_copyout(struct kqueue *kq, int nready, - struct kevent *eventlist, int nevents) -{ - struct event_buf *ebp; - struct filter *filt; - int rv; - - ebp = TAILQ_FIRST(&kq->kq_events); - if (ebp == NULL) { - dbg_puts("kq_events was empty"); - return (-1); - } - - dbg_printf("event=%s", port_event_dump(&ebp->pe)); - switch (ebp->pe.portev_source) { - case PORT_SOURCE_FD: - filt = ebp->pe.portev_user; - rv = filt->kf_copyout(filt, eventlist, nevents); - break; - - case PORT_SOURCE_TIMER: - filter_lookup(&filt, kq, EVFILT_TIMER); - rv = filt->kf_copyout(filt, eventlist, nevents); - break; - - case PORT_SOURCE_USER: - switch (ebp->pe.portev_events) { - case X_PORT_SOURCE_SIGNAL: - filter_lookup(&filt, kq, EVFILT_SIGNAL); - rv = filt->kf_copyout(filt, eventlist, nevents); - break; - case X_PORT_SOURCE_USER: - filter_lookup(&filt, kq, EVFILT_USER); - rv = filt->kf_copyout(filt, eventlist, nevents); - break; - default: - dbg_puts("unsupported portev_events"); - abort(); - } - break; - - default: - dbg_puts("unsupported source"); - abort(); - } - if (rv < 0) { - dbg_puts("kevent_copyout failed"); - return (-1); - } - - return (1); -} diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index 2dfd359ad..c722c2746 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -16,6 +16,17 @@ #include "../common/private.h" +const struct filter evfilt_vnode = EVFILT_NOTIMPL; +const struct filter evfilt_proc = EVFILT_NOTIMPL; + +static char * port_event_dump(port_event_t *evt); + +/* + * Per-thread port event buffer used to ferry data between + * kevent_wait() and kevent_copyout(). + */ +static port_event_t __thread evbuf[MAX_KEVENT]; + int solaris_kqueue_init(struct kqueue *kq) { @@ -40,6 +51,148 @@ solaris_kqueue_free(struct kqueue *kq) } } +/* Dump a poll(2) events bitmask */ +static char * +poll_events_dump(short events) +{ + static char __thread buf[512]; + +#define _PL_DUMP(attrib) \ + if (events == attrib) \ + strcat(&buf[0], " "#attrib); + + snprintf(&buf[0], 512, "events = %hd 0x%o (", events, events); + _PL_DUMP(POLLIN); + _PL_DUMP(POLLPRI); + _PL_DUMP(POLLOUT); + _PL_DUMP(POLLRDNORM); + _PL_DUMP(POLLRDBAND); + _PL_DUMP(POLLWRBAND); + _PL_DUMP(POLLERR); + _PL_DUMP(POLLHUP); + _PL_DUMP(POLLNVAL); + strcat(&buf[0], ")"); + + return (&buf[0]); + +#undef _PL_DUMP +} + +static char * +port_event_dump(port_event_t *evt) +{ + static char __thread buf[512]; + + if (evt == NULL) { + snprintf(&buf[0], sizeof(buf), "NULL ?!?!\n"); + goto out; + } + +#define PE_DUMP(attrib) \ + if (evt->portev_source == attrib) \ + strcat(&buf[0], #attrib); + + snprintf(&buf[0], 512, + " { object = %u, user = %p, %s, source = %d (", + (unsigned int) evt->portev_object, + evt->portev_user, + poll_events_dump(evt->portev_events), + evt->portev_source); + PE_DUMP(PORT_SOURCE_AIO); + PE_DUMP(PORT_SOURCE_FD); + PE_DUMP(PORT_SOURCE_TIMER); + PE_DUMP(PORT_SOURCE_USER); + PE_DUMP(PORT_SOURCE_ALERT); + strcat(&buf[0], ") }\n"); +#undef PE_DUMP + +out: + return (&buf[0]); +} + +int +solaris_kevent_wait( + struct kqueue *kq, + int nevents, + const struct timespec *ts) + +{ + port_event_t pe; + int rv; + uint_t nget = 1; + + reset_errno(); + dbg_puts("waiting for events"); + rv = port_getn(kq->kq_port, &evbuf[0], 1, &nget, (struct timespec *) ts); + dbg_printf("rv=%d errno=%d (%s) nget=%d", + rv, errno, strerror(errno), nget); + if (rv < 0) { + if (errno == ETIME) { + dbg_puts("no events within the given timeout"); + return (0); + } + if (errno == EINTR) { + dbg_puts("signal caught"); + return (-1); + } + dbg_perror("port_getn(2)"); + return (-1); + } + + return (nget); +} + +int +solaris_kevent_copyout(struct kqueue *kq, int nready, + struct kevent *eventlist, int nevents) +{ + port_event_t *evt; + struct filter *filt; + int i, rv; + + for (i = 0; i < nready; i++) { + evt = &evbuf[i]; + dbg_printf("event=%s", port_event_dump(evt)); + switch (evt->portev_source) { + case PORT_SOURCE_FD: + filt = evt->portev_user; + rv = filt->kf_copyout(filt, eventlist, nevents); + break; + + case PORT_SOURCE_TIMER: + filter_lookup(&filt, kq, EVFILT_TIMER); + rv = filt->kf_copyout(filt, eventlist, nevents); + break; + + case PORT_SOURCE_USER: + switch (ebp->pe.portev_events) { + case X_PORT_SOURCE_SIGNAL: + filter_lookup(&filt, kq, EVFILT_SIGNAL); + rv = filt->kf_copyout(filt, eventlist, nevents); + break; + case X_PORT_SOURCE_USER: + filter_lookup(&filt, kq, EVFILT_USER); + rv = filt->kf_copyout(filt, eventlist, nevents); + break; + default: + dbg_puts("unsupported portev_events"); + abort(); + } + break; + + default: + dbg_puts("unsupported source"); + abort(); + } + if (rv < 0) { + dbg_puts("kevent_copyout failed"); + return (-1); + } + } + + return (nready); +} + const struct kqueue_vtable kqops = { solaris_kqueue_init, diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index 99b803710..7badc4af3 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -42,9 +42,6 @@ void solaris_kqueue_free(struct kqueue *); int solaris_kqueue_init(struct kqueue *); -int solaris_kevent_wait(struct kqueue *, const struct timespec *); -int solaris_kevent_copyout(struct kqueue *, int, struct kevent *, int); -void port_event_dequeue(port_event_t *, struct kqueue *); /* * Additional members of struct kqueue From 6967c4106683bda4010dd075c67c90bbce4aee45 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 13 Feb 2011 15:35:41 +0000 Subject: [PATCH 0396/1120] remove empty stubs for filter initialization git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@420 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/filter.c | 15 ++++++++------- vendor/libkqueue/src/linux/signal.c | 15 ++------------- vendor/libkqueue/src/linux/socket.c | 19 ++++--------------- vendor/libkqueue/src/linux/timer.c | 15 ++------------- vendor/libkqueue/src/linux/user.c | 16 ++-------------- vendor/libkqueue/src/linux/vnode.c | 15 ++------------- 6 files changed, 20 insertions(+), 75 deletions(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index 18461a647..b96890e1b 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -52,8 +52,6 @@ filter_register(struct kqueue *kq, short filter, const struct filter *src) return (0); } - assert(src->kf_init); - assert(src->kf_destroy); assert(src->kf_copyout); assert(src->kn_create); assert(src->kn_modify); @@ -61,11 +59,14 @@ filter_register(struct kqueue *kq, short filter, const struct filter *src) assert(src->kn_enable); assert(src->kn_disable); - rv = src->kf_init(dst); - if (rv < 0) { - dbg_puts("filter failed to initialize"); - dst->kf_id = 0; - return (-1); + /* Perform (optional) per-filter initialization */ + if (src->kf_init != NULL) { + rv = src->kf_init(dst); + if (rv < 0) { + dbg_puts("filter failed to initialize"); + dst->kf_id = 0; + return (-1); + } } #if DEADWOOD diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index cd16f6fba..6862b146d 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -87,17 +87,6 @@ signalfd_create(int epfd, void *ptr, int signum) return (-1); } -int -evfilt_signal_init(struct filter *filt) -{ - return (0); -} - -void -evfilt_signal_destroy(struct filter *filt) -{ -} - int evfilt_signal_copyout(struct kevent *dst, const struct kqueue *kq, @@ -187,8 +176,8 @@ evfilt_signal_knote_disable(struct filter *filt, struct knote *kn) const struct filter evfilt_signal = { EVFILT_SIGNAL, - evfilt_signal_init, - evfilt_signal_destroy, + NULL, + NULL, evfilt_signal_copyout, evfilt_signal_knote_create, evfilt_signal_knote_modify, diff --git a/vendor/libkqueue/src/linux/socket.c b/vendor/libkqueue/src/linux/socket.c index 875d939a3..3938eb888 100644 --- a/vendor/libkqueue/src/linux/socket.c +++ b/vendor/libkqueue/src/linux/socket.c @@ -70,17 +70,6 @@ epoll_update(int op, struct filter *filt, struct knote *kn, struct epoll_event * return (0); } -int -evfilt_socket_init(struct filter *filt) -{ - return (0); -} - -void -evfilt_socket_destroy(struct filter *filt) -{ -} - int evfilt_socket_copyout(struct kevent *dst, const struct kqueue *kq, @@ -189,8 +178,8 @@ evfilt_socket_knote_disable(struct filter *filt, struct knote *kn) const struct filter evfilt_read = { EVFILT_READ, - evfilt_socket_init, - evfilt_socket_destroy, + NULL, + NULL, evfilt_socket_copyout, evfilt_socket_knote_create, evfilt_socket_knote_modify, @@ -201,8 +190,8 @@ const struct filter evfilt_read = { const struct filter evfilt_write = { EVFILT_WRITE, - evfilt_socket_init, - evfilt_socket_destroy, + NULL, + NULL, evfilt_socket_copyout, evfilt_socket_knote_create, evfilt_socket_knote_modify, diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 239381df1..30d16ade4 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -58,17 +58,6 @@ convert_msec_to_itimerspec(struct itimerspec *dst, int src, int oneshot) dbg_printf("%s", itimerspec_dump(dst)); } -int -evfilt_timer_init(struct filter *filt) -{ - return (0); -} - -void -evfilt_timer_destroy(struct filter *filt) -{ -} - int evfilt_timer_copyout(struct kevent *dst, const struct kqueue *kq, @@ -175,8 +164,8 @@ evfilt_timer_knote_disable(struct filter *filt, struct knote *kn) const struct filter evfilt_timer = { EVFILT_TIMER, - evfilt_timer_init, - evfilt_timer_destroy, + NULL, + NULL, evfilt_timer_copyout, evfilt_timer_knote_create, evfilt_timer_knote_modify, diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index 7e03ab875..e54c30314 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -84,18 +84,6 @@ eventfd_lower(int evfd) return (rv); } -int -evfilt_user_init(struct filter *filt) -{ - return (0); -} - -void -evfilt_user_destroy(struct filter *filt) -{ - return; -} - int evfilt_user_copyout(struct kevent *dst, const struct kqueue *kq, @@ -229,8 +217,8 @@ evfilt_user_knote_disable(struct filter *filt, struct knote *kn) const struct filter evfilt_user = { EVFILT_USER, - evfilt_user_init, - evfilt_user_destroy, + NULL, + NULL, evfilt_user_copyout, evfilt_user_knote_create, evfilt_user_knote_modify, diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 83d28d914..e8630d462 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -176,17 +176,6 @@ delete_watch(struct filter *filt, struct knote *kn) return (0); } -int -evfilt_vnode_init(struct filter *filt) -{ - return (0); -} - -void -evfilt_vnode_destroy(struct filter *filt) -{ -} - int evfilt_vnode_copyout(struct kevent *dst, const struct kqueue *kq, @@ -291,8 +280,8 @@ evfilt_vnode_knote_disable(struct filter *filt, struct knote *kn) const struct filter evfilt_vnode = { EVFILT_VNODE, - evfilt_vnode_init, - evfilt_vnode_destroy, + NULL, + NULL, evfilt_vnode_copyout, evfilt_vnode_knote_create, evfilt_vnode_knote_modify, From ae49cff0332bf7d14d5832927273d975ee3f96d1 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 13 Feb 2011 15:41:26 +0000 Subject: [PATCH 0397/1120] remove unused parameters to kf_copyout() git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@421 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/private.h | 2 +- vendor/libkqueue/src/linux/platform.c | 2 +- vendor/libkqueue/src/linux/signal.c | 6 +----- vendor/libkqueue/src/linux/socket.c | 6 +----- vendor/libkqueue/src/linux/timer.c | 6 +----- vendor/libkqueue/src/linux/user.c | 6 +----- vendor/libkqueue/src/linux/vnode.c | 6 +----- 7 files changed, 7 insertions(+), 27 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 5df8a3ba5..f840db92f 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -135,7 +135,7 @@ struct filter { int (*kf_init)(struct filter *); void (*kf_destroy)(struct filter *); - int (*kf_copyout)(struct kevent *, const struct kqueue *, struct filter *, struct knote *, void *); + int (*kf_copyout)(struct kevent *, struct knote *, void *); /* knote operations */ diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 961b3d6a6..14a07532e 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -157,7 +157,7 @@ linux_kevent_copyout(struct kqueue *kq, int nready, kn = (struct knote *) ev->data.ptr; knote_lock(kn); filt = &kq->kq_filt[~(kn->kev.filter)]; - rv = filt->kf_copyout(eventlist, kq, filt, kn, ev); + rv = filt->kf_copyout(eventlist, kn, ev); knote_unlock(kn); if (slowpath(rv < 0)) { dbg_puts("knote_copyout failed"); diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index 6862b146d..bbe9aaaec 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -88,11 +88,7 @@ signalfd_create(int epfd, void *ptr, int signum) } int -evfilt_signal_copyout(struct kevent *dst, - const struct kqueue *kq, - struct filter *filt, - struct knote *src, - void *unused) +evfilt_signal_copyout(struct kevent *dst, struct knote *src, void *unused) { int sigfd; diff --git a/vendor/libkqueue/src/linux/socket.c b/vendor/libkqueue/src/linux/socket.c index 3938eb888..482bc1f9e 100644 --- a/vendor/libkqueue/src/linux/socket.c +++ b/vendor/libkqueue/src/linux/socket.c @@ -71,11 +71,7 @@ epoll_update(int op, struct filter *filt, struct knote *kn, struct epoll_event * } int -evfilt_socket_copyout(struct kevent *dst, - const struct kqueue *kq, - struct filter *filt, - struct knote *src, - void *ptr) +evfilt_socket_copyout(struct kevent *dst, struct knote *src, void *ptr) { struct epoll_event * const ev = (struct epoll_event *) ptr; diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 30d16ade4..6b4d85e70 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -59,11 +59,7 @@ convert_msec_to_itimerspec(struct itimerspec *dst, int src, int oneshot) } int -evfilt_timer_copyout(struct kevent *dst, - const struct kqueue *kq, - struct filter *filt, - struct knote *src, - void *ptr) +evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr) { struct epoll_event * const ev = (struct epoll_event *) ptr; uint64_t expired; diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index e54c30314..841510369 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -85,11 +85,7 @@ eventfd_lower(int evfd) } int -evfilt_user_copyout(struct kevent *dst, - const struct kqueue *kq, - struct filter *filt, - struct knote *src, - void *ptr) +evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr) { memcpy(dst, &src->kev, sizeof(*dst)); dst->fflags &= ~NOTE_FFCTRLMASK; //FIXME: Not sure if needed diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index e8630d462..ebde155a4 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -177,11 +177,7 @@ delete_watch(struct filter *filt, struct knote *kn) } int -evfilt_vnode_copyout(struct kevent *dst, - const struct kqueue *kq, - struct filter *filt, - struct knote *src, - void *ptr) +evfilt_vnode_copyout(struct kevent *dst, struct knote *src, void *ptr) { struct inotify_event evt; struct stat sb; From 5b85d82aa3fdbba5656120d78a997b60ef0ed847 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 13 Feb 2011 16:33:08 +0000 Subject: [PATCH 0398/1120] solaris fixes git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@422 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/platform.c | 1 - vendor/libkqueue/src/solaris/platform.h | 4 ++++ vendor/libkqueue/src/solaris/socket.c | 24 ++++++++++++++++++++++-- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index c722c2746..97c132cdf 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -117,7 +117,6 @@ solaris_kevent_wait( const struct timespec *ts) { - port_event_t pe; int rv; uint_t nget = 1; diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index 7badc4af3..4085735f7 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -40,6 +40,10 @@ #define X_PORT_SOURCE_SIGNAL 101 #define X_PORT_SOURCE_USER 102 +/* Convenience macros to access the event port descriptor for the kqueue */ +#define kqueue_epfd(kq) ((kq)->kq_id) +#define filter_epfd(filt) ((filt)->kf_kqueue->kq_id) + void solaris_kqueue_free(struct kqueue *); int solaris_kqueue_init(struct kqueue *); diff --git a/vendor/libkqueue/src/solaris/socket.c b/vendor/libkqueue/src/solaris/socket.c index e7b68bfaf..c95b74441 100644 --- a/vendor/libkqueue/src/solaris/socket.c +++ b/vendor/libkqueue/src/solaris/socket.c @@ -82,8 +82,28 @@ evfilt_socket_destroy(struct filter *filt) int evfilt_socket_knote_create(struct filter *filt, struct knote *kn) { - return socket_knote_create(filt->kf_kqueue->kq_port, - kn->kev.filter, kn->kev.ident, filt); + int rv, events; + + switch (kn->kev.filter) { + case EVFILT_READ: + events = POLLIN; + break; + case EVFILT_WRITE: + events = POLLOUT; + break; + default: + dbg_puts("invalid filter"); + return (-1); + } + + rv = port_associate(filter_epfd(filt), PORT_SOURCE_FD, kn->kev.ident, + events, kn); + if (rv < 0) { + dbg_perror("port_associate(2)"); + return (-1); + } + + return (0); } int From 8a7e6ba17915ac1005a495b3d911f0e998eddb37 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 13 Feb 2011 17:33:01 +0000 Subject: [PATCH 0399/1120] add extra debug output git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@423 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/filter.c | 2 ++ vendor/libkqueue/src/common/kevent.c | 1 + 2 files changed, 3 insertions(+) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index b96890e1b..fe5cb3488 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -107,6 +107,7 @@ filter_register_all(struct kqueue *kq) filter_unregister_all(kq); return (-1); } else { + dbg_puts("complete"); return (0); } } @@ -142,6 +143,7 @@ filter_lookup(struct filter **filt, struct kqueue *kq, short id) } *filt = &kq->kq_filt[~id]; if ((*filt)->kf_copyout == NULL) { + dbg_printf("filter %s is not implemented", filter_name(id)); errno = ENOSYS; *filt = NULL; return (-1); diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 221643d53..1131a2567 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -123,6 +123,7 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) int rv = 0; if (src->flags & EV_DISPATCH && src->flags & EV_ONESHOT) { + dbg_puts("Error: EV_DISPATCH and EV_ONESHOT are mutually exclusive"); errno = EINVAL; return (-1); } From 8c8c12f99378bb98ecdf5a68e9fa2b42ecffd317 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 13 Feb 2011 17:33:25 +0000 Subject: [PATCH 0400/1120] Fix compilation issues on Solaris. Unit tests still fail, however git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@424 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/config.inc | 1 + vendor/libkqueue/src/solaris/platform.c | 46 +++---- vendor/libkqueue/src/solaris/platform.h | 7 -- vendor/libkqueue/src/solaris/signal.c | 159 ++++++++++++++++++++++++ vendor/libkqueue/src/solaris/socket.c | 60 +++------ vendor/libkqueue/src/solaris/timer.c | 30 ++--- vendor/libkqueue/src/solaris/user.c | 82 +++++------- 7 files changed, 242 insertions(+), 143 deletions(-) create mode 100644 vendor/libkqueue/src/solaris/signal.c diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index 06899dc7f..14fddb8fc 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -78,6 +78,7 @@ post_configure_hook() { platform="$platform src/solaris/platform.c" evfilt_timer="src/solaris/timer.c" evfilt_user="src/solaris/user.c" + evfilt_signal="src/solaris/signal.c" evfilt_proc="" evfilt_vnode="" fi diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index 97c132cdf..7963ee73b 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -30,25 +30,25 @@ static port_event_t __thread evbuf[MAX_KEVENT]; int solaris_kqueue_init(struct kqueue *kq) { - if (posix_kqueue_init(kq) < 0) - return (-1); - if ((kq->kq_port = port_create()) < 0) { + if ((kq->kq_id = port_create()) < 0) { dbg_perror("port_create(2)"); return (-1); } - dbg_printf("created event port; fd=%d", kq->kq_port); - TAILQ_INIT(&kq->kq_events); + dbg_printf("created event port; fd=%d", kq->kq_id); + + if (filter_register_all(kq) < 0) { + close(kq->kq_id); + return (-1); + } + return (0); } void solaris_kqueue_free(struct kqueue *kq) { - posix_kqueue_free(kq); - if (kq->kq_port > 0) { - (void) close(kq->kq_port); - dbg_printf("closed event port; fd=%d", kq->kq_port); - } + (void) close(kq->kq_id); + dbg_printf("closed event port; fd=%d", kq->kq_id); } /* Dump a poll(2) events bitmask */ @@ -122,7 +122,7 @@ solaris_kevent_wait( reset_errno(); dbg_puts("waiting for events"); - rv = port_getn(kq->kq_port, &evbuf[0], 1, &nget, (struct timespec *) ts); + rv = port_getn(kq->kq_id, &evbuf[0], 1, &nget, (struct timespec *) ts); dbg_printf("rv=%d errno=%d (%s) nget=%d", rv, errno, strerror(errno), nget); if (rv < 0) { @@ -146,32 +146,35 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, struct kevent *eventlist, int nevents) { port_event_t *evt; + struct knote *kn; struct filter *filt; int i, rv; for (i = 0; i < nready; i++) { evt = &evbuf[i]; + kn = evt->portev_user; dbg_printf("event=%s", port_event_dump(evt)); switch (evt->portev_source) { case PORT_SOURCE_FD: - filt = evt->portev_user; - rv = filt->kf_copyout(filt, eventlist, nevents); +//XXX-FIXME WHAT ABOUT WRITE??? + filter_lookup(&filt, kq, EVFILT_READ); + rv = filt->kf_copyout(eventlist, kn, evt); break; case PORT_SOURCE_TIMER: filter_lookup(&filt, kq, EVFILT_TIMER); - rv = filt->kf_copyout(filt, eventlist, nevents); + rv = filt->kf_copyout(eventlist, kn, evt); break; case PORT_SOURCE_USER: - switch (ebp->pe.portev_events) { + switch (evt->portev_events) { case X_PORT_SOURCE_SIGNAL: filter_lookup(&filt, kq, EVFILT_SIGNAL); - rv = filt->kf_copyout(filt, eventlist, nevents); + rv = filt->kf_copyout(eventlist, kn, evt); break; case X_PORT_SOURCE_USER: filter_lookup(&filt, kq, EVFILT_USER); - rv = filt->kf_copyout(filt, eventlist, nevents); + rv = filt->kf_copyout(eventlist, kn, evt); break; default: dbg_puts("unsupported portev_events"); @@ -183,10 +186,11 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, dbg_puts("unsupported source"); abort(); } - if (rv < 0) { - dbg_puts("kevent_copyout failed"); - return (-1); - } + if (rv < 0) { + dbg_puts("kevent_copyout failed"); + return (-1); + } + eventlist++; } return (nready); diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index 4085735f7..1219c0b95 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -47,13 +47,6 @@ void solaris_kqueue_free(struct kqueue *); int solaris_kqueue_init(struct kqueue *); -/* - * Additional members of struct kqueue - */ -#define KQUEUE_PLATFORM_SPECIFIC \ - int kq_port; \ - TAILQ_HEAD(event_buf_listhead,event_buf) kq_events - /* * Data structures */ diff --git a/vendor/libkqueue/src/solaris/signal.c b/vendor/libkqueue/src/solaris/signal.c new file mode 100644 index 000000000..9688dfc66 --- /dev/null +++ b/vendor/libkqueue/src/solaris/signal.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "private.h" + +/* Highest signal number supported. POSIX standard signals are < 32 */ +#define SIGNAL_MAX 32 + +struct sentry { + struct filter *s_filt; + struct knote *s_knote; + volatile uint32_t s_cnt; +}; + +static pthread_mutex_t sigtbl_mtx = PTHREAD_MUTEX_INITIALIZER; +static struct sentry sigtbl[SIGNAL_MAX]; + +static void +signal_handler(int sig) +{ + struct sentry *s; + + if (sig < 0 || sig > SIGNAL_MAX) + abort(); + + s = &sigtbl[sig]; + atomic_inc(&s->s_cnt); + port_send(filter_epfd(s->s_filt), X_PORT_SOURCE_SIGNAL, &sigtbl[sig]); + /* TODO: crash if port_send() fails? */ +} + +static int +catch_signal(struct filter *filt, struct knote *kn) +{ + int sig; + struct sigaction sa; + + sig = kn->kev.ident; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = signal_handler; + sa.sa_flags |= SA_RESTART; + sigfillset(&sa.sa_mask); + + if (sigaction(kn->kev.ident, &sa, NULL) == -1) { + dbg_perror("sigaction"); + return (-1); + } + /* FIXME: will clobber previous entry, if any */ + pthread_mutex_lock(&sigtbl_mtx); + sigtbl[kn->kev.ident].s_filt = filt; + sigtbl[kn->kev.ident].s_knote = kn; + pthread_mutex_unlock(&sigtbl_mtx); + + dbg_printf("installed handler for signal %d", sig); + return (0); +} + +static int +ignore_signal(int sig) +{ + struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_IGN; + sigemptyset(&sa.sa_mask); + + if (sigaction(sig, &sa, NULL) == -1) { + dbg_perror("sigaction"); + return (-1); + } + pthread_mutex_lock(&sigtbl_mtx); + sigtbl[sig].s_filt = NULL; + sigtbl[sig].s_knote = NULL; + pthread_mutex_unlock(&sigtbl_mtx); + + dbg_printf("removed handler for signal %d", sig); + return (0); +} + +int +evfilt_signal_knote_create(struct filter *filt, struct knote *kn) +{ + if (kn->kev.ident >= SIGNAL_MAX) { + dbg_printf("unsupported signal number %u", + (unsigned int) kn->kev.ident); + return (-1); + } + + kn->kev.flags |= EV_CLEAR; + + return catch_signal(filt, kn); +} + +int +evfilt_signal_knote_modify(struct filter *filt, struct knote *kn, + const struct kevent *kev) +{ + kn->kev.flags = kev->flags | EV_CLEAR; + return (0); +} + +int +evfilt_signal_knote_delete(struct filter *filt, struct knote *kn) +{ + return ignore_signal(kn->kev.ident); +} + +int +evfilt_signal_knote_enable(struct filter *filt, struct knote *kn) +{ + return catch_signal(filt, kn); +} + +int +evfilt_signal_knote_disable(struct filter *filt, struct knote *kn) +{ + return ignore_signal(kn->kev.ident); +} + +int +evfilt_signal_copyout(struct kevent *dst, struct knote *src, void *ptr) +{ + dst->ident = src->kev.ident; + dst->filter = EVFILT_SIGNAL; + dst->udata = src->kev.udata; + dst->flags = src->kev.flags; + dst->fflags = 0; + dst->data = 1; + + if (src->kev.flags & EV_DISPATCH || src->kev.flags & EV_ONESHOT) + ignore_signal(src->kev.ident); + + return (1); +} + +const struct filter evfilt_signal = { + EVFILT_SIGNAL, + NULL, + NULL, + evfilt_signal_copyout, + evfilt_signal_knote_create, + evfilt_signal_knote_modify, + evfilt_signal_knote_delete, + evfilt_signal_knote_enable, + evfilt_signal_knote_disable, +}; diff --git a/vendor/libkqueue/src/solaris/socket.c b/vendor/libkqueue/src/solaris/socket.c index c95b74441..1d5d77460 100644 --- a/vendor/libkqueue/src/solaris/socket.c +++ b/vendor/libkqueue/src/solaris/socket.c @@ -67,18 +67,6 @@ socket_knote_delete(int port, int fd) } } -int -evfilt_socket_init(struct filter *filt) -{ - return (0); -} - -void -evfilt_socket_destroy(struct filter *filt) -{ - ; -} - int evfilt_socket_knote_create(struct filter *filt, struct knote *kn) { @@ -119,43 +107,35 @@ evfilt_socket_knote_delete(struct filter *filt, struct knote *kn) if (kn->kev.flags & EV_DISABLE) return (0); else - return (socket_knote_delete(filt->kf_kqueue->kq_port, kn->kev.ident)); + return (socket_knote_delete(filter_epfd(filt), kn->kev.ident)); } int evfilt_socket_knote_enable(struct filter *filt, struct knote *kn) { - return socket_knote_create(filt->kf_kqueue->kq_port, + return socket_knote_create(filter_epfd(filt), kn->kev.filter, kn->kev.ident, filt); } int evfilt_socket_knote_disable(struct filter *filt, struct knote *kn) { - return socket_knote_delete(filt->kf_kqueue->kq_port, kn->kev.ident); + return socket_knote_delete(filter_epfd(filt), kn->kev.ident); } int -evfilt_socket_copyout(struct filter *filt, - struct kevent *dst, - int nevents) +evfilt_socket_copyout(struct kevent *dst, struct knote *src, void *ptr) { - port_event_t pe; - struct knote *kn; + port_event_t *pe = (port_event_t *) ptr; - port_event_dequeue(&pe, filt->kf_kqueue); - kn = knote_lookup(filt, pe.portev_object); - if (kn == NULL) - return (-1); - - memcpy(dst, &kn->kev, sizeof(*dst)); - if (pe.portev_events == 8) //XXX-FIXME Should be POLLHUP) + memcpy(dst, &src->kev, sizeof(*dst)); + if (pe->portev_events == 8) //XXX-FIXME Should be POLLHUP) dst->flags |= EV_EOF; - else if (pe.portev_events & POLLERR) + else if (pe->portev_events & POLLERR) dst->fflags = 1; /* FIXME: Return the actual socket error */ - if (pe.portev_events & POLLIN) { - if (kn->flags & KNFL_PASSIVE_SOCKET) { + if (pe->portev_events & POLLIN) { + if (src->flags & KNFL_PASSIVE_SOCKET) { /* On return, data contains the length of the socket backlog. This is not available under Solaris (?). */ @@ -179,25 +159,19 @@ evfilt_socket_copyout(struct filter *filt, } } - if (kn->kev.flags & EV_DISPATCH) { - socket_knote_delete(filt->kf_kqueue->kq_port, kn->kev.ident); - KNOTE_DISABLE(kn); - } else if (kn->kev.flags & EV_ONESHOT) { + /* FIXME: make sure this is in kqops.copyout() + if (src->kev.flags & EV_DISPATCH || src->kev.flags & EV_ONESHOT) { socket_knote_delete(filt->kf_kqueue->kq_port, kn->kev.ident); - knote_free(filt, kn); - } else { - /* Solaris automatically disassociates a FD event after it - is delivered. This effectively disables the knote. */ - KNOTE_DISABLE(kn); } + */ return (1); } const struct filter evfilt_read = { EVFILT_READ, - evfilt_socket_init, - evfilt_socket_destroy, + NULL, + NULL, evfilt_socket_copyout, evfilt_socket_knote_create, evfilt_socket_knote_modify, @@ -208,8 +182,8 @@ const struct filter evfilt_read = { const struct filter evfilt_write = { EVFILT_WRITE, - evfilt_socket_init, - evfilt_socket_destroy, + NULL, + NULL, evfilt_socket_copyout, evfilt_socket_knote_create, evfilt_socket_knote_modify, diff --git a/vendor/libkqueue/src/solaris/timer.c b/vendor/libkqueue/src/solaris/timer.c index c3a265757..422f3113d 100644 --- a/vendor/libkqueue/src/solaris/timer.c +++ b/vendor/libkqueue/src/solaris/timer.c @@ -82,7 +82,7 @@ ktimer_create(struct filter *filt, struct knote *kn) kn->kev.flags |= EV_CLEAR; - pn.portnfy_port = filt->kf_kqueue->kq_port; + pn.portnfy_port = filter_epfd(filt); pn.portnfy_user = (void *) kn->kev.ident; se.sigev_notify = SIGEV_PORT; @@ -119,25 +119,18 @@ evfilt_timer_destroy(struct filter *filt) } int -evfilt_timer_copyout(struct filter *filt, - struct kevent *dst, - int nevents) +evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr) { - port_event_t pe; + port_event_t *pe = (port_event_t *) ptr; long buf; timer_t timerid; - struct knote *kn; - - port_event_dequeue(&pe, filt->kf_kqueue); /* XXX-FIXME: danger here -- there has to be a better way */ - buf = (long) pe.portev_user; + buf = (long) pe->portev_user; timerid = (timer_t) buf; /* ^^^^^^^^^ */ - kn = knote_lookup(filt, timerid); - dbg_printf("knote=%p", kn); - memcpy(dst, &kn->kev, sizeof(*dst)); + memcpy(dst, &src->kev, sizeof(*dst)); //TODO: //if (ev->events & EPOLLERR) // dst->fflags = 1; /* FIXME: Return the actual timer error */ @@ -147,13 +140,14 @@ evfilt_timer_copyout(struct filter *filt, */ dst->data = 1; //workaround - if (kn->kev.flags & EV_DISPATCH) { - KNOTE_DISABLE(kn); - timer_delete(kn->data.timerid); - } else if (kn->kev.flags & EV_ONESHOT) { - timer_delete(kn->data.timerid); - knote_free(filt, kn); +#if FIXME + //should be done in kqops.copyout() + if (src->kev.flags & EV_DISPATCH) { + timer_delete(src->data.timerid); + } else if (src->kev.flags & EV_ONESHOT) { + timer_delete(src->data.timerid); } +#endif return (1); } diff --git a/vendor/libkqueue/src/solaris/user.c b/vendor/libkqueue/src/solaris/user.c index 499681822..5dc116196 100644 --- a/vendor/libkqueue/src/solaris/user.c +++ b/vendor/libkqueue/src/solaris/user.c @@ -14,63 +14,37 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "sys/event.h" #include "private.h" int -evfilt_user_init(struct filter *filt) +evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr) { - return (0); -} - -void -evfilt_user_destroy(struct filter *filt) -{ - return; -} - -int -evfilt_user_copyout(struct filter *filt, - struct kevent *dst, - int maxevents) -{ - struct knote *kn; - int nevents = 0; + //port_event_t *pe = (port_event_t *) ptr; - for (kn = knote_dequeue(filt); kn != NULL; kn = knote_dequeue(filt)) { - memcpy(dst, &kn->kev, sizeof(*dst)); - dst->fflags &= ~NOTE_FFCTRLMASK; //FIXME: Not sure if needed - dst->fflags &= ~NOTE_TRIGGER; - if (kn->kev.flags & EV_ADD) { - /* NOTE: True on FreeBSD but not consistent behavior with - other filters. */ - dst->flags &= ~EV_ADD; - } - if (kn->kev.flags & EV_CLEAR) - kn->kev.fflags &= ~NOTE_TRIGGER; - /* FIXME: This shouldn't be necessary in Solaris... - if (kn->kev.flags & (EV_DISPATCH | EV_CLEAR | EV_ONESHOT)) - eventfd_lower(filt->kf_efd); - */ - if (kn->kev.flags & EV_DISPATCH) { - KNOTE_DISABLE(kn); - kn->kev.fflags &= ~NOTE_TRIGGER; - } else if (kn->kev.flags & EV_ONESHOT) { - knote_free(filt, kn); - } - - dst++; - if (++nevents == maxevents) - break; - } - - /* This should normally never happen but is here for debugging */ - if (nevents == 0) { - dbg_puts("spurious wakeup"); - /* FIXME: NOT IMPLEMENTED: eventfd_lower(filt->kf_efd); */ + memcpy(dst, &src->kev, sizeof(*dst)); + dst->fflags &= ~NOTE_FFCTRLMASK; //FIXME: Not sure if needed + dst->fflags &= ~NOTE_TRIGGER; + if (src->kev.flags & EV_ADD) { + /* NOTE: True on FreeBSD but not consistent behavior with + other filters. */ + dst->flags &= ~EV_ADD; } + if (src->kev.flags & EV_CLEAR) + src->kev.fflags &= ~NOTE_TRIGGER; + /* FIXME: This shouldn't be necessary in Solaris... + if (src->kev.flags & (EV_DISPATCH | EV_CLEAR | EV_ONESHOT)) + eventfd_lower(filt->kf_efd); + */ + /* FIXME: should move to kqops.copyout() + if (src->kev.flags & EV_DISPATCH) { + KNOTE_DISABLE(src); + src->kev.fflags &= ~NOTE_TRIGGER; + } else if (src->kev.flags & EV_ONESHOT) { + knote_free(filt, src); + } + */ - return (nevents); + return (1); } @@ -123,8 +97,8 @@ evfilt_user_knote_modify(struct filter *filt, struct knote *kn, if ((!(kn->kev.flags & EV_DISABLE)) && kev->fflags & NOTE_TRIGGER) { kn->kev.fflags |= NOTE_TRIGGER; - knote_enqueue(filt, kn); - return (port_send(filt->kf_kqueue->kq_port, X_PORT_SOURCE_USER, NULL)); + //FIXME: how now? knote_enqueue(filt, kn); + return (port_send(filter_epfd(filt), X_PORT_SOURCE_USER, NULL)); } return (0); @@ -152,8 +126,8 @@ evfilt_user_knote_disable(struct filter *filt, struct knote *kn) const struct filter evfilt_user = { EVFILT_USER, - evfilt_user_init, - evfilt_user_destroy, + NULL, + NULL, evfilt_user_copyout, evfilt_user_knote_create, evfilt_user_knote_modify, From d521618638a67641dd7d289abebc718b29ccaf63 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 15 Feb 2011 23:53:04 +0000 Subject: [PATCH 0401/1120] add file and line number to kevent_cmp() git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@425 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/common.h | 3 ++- vendor/libkqueue/test/kevent.c | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index cc3719dd7..43b41b241 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -76,7 +76,8 @@ struct kevent * kevent_get(int); void kevent_update(int kqfd, struct kevent *kev); -void kevent_cmp(struct kevent *, struct kevent *); +#define kevent_cmp(a,b) _kevent_cmp(a,b, __FILE__, __LINE__) +void _kevent_cmp(struct kevent *, struct kevent *, const char *, int); void kevent_add(int kqfd, struct kevent *kev, diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index 83eeefe1d..86b3782d1 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -164,7 +164,7 @@ kevent_add(int kqfd, struct kevent *kev, } void -kevent_cmp(struct kevent *k1, struct kevent *k2) +_kevent_cmp(struct kevent *k1, struct kevent *k2, const char *file, int line) { /* XXX- Workaround for inconsistent implementation of kevent(2) @@ -174,8 +174,8 @@ kevent_cmp(struct kevent *k1, struct kevent *k2) k2->flags |= EV_ADD; #endif if (memcmp(k1, k2, sizeof(*k1)) != 0) { - printf("kevent_cmp: mismatch:\n expected %s\n but got %s\n", - kevent_to_str(k1), kevent_to_str(k2)); + printf("[%s:%d]: kevent_cmp() failed:\n expected %s\n but got %s\n", + file, line, kevent_to_str(k1), kevent_to_str(k2)); abort(); } } From 2a3d09f4711ce1ecfdd56e8c472ed2cf8928980d Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 16 Feb 2011 02:52:41 +0000 Subject: [PATCH 0402/1120] fix Solaris EVFILT_USER git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@426 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/user.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/solaris/user.c b/vendor/libkqueue/src/solaris/user.c index 5dc116196..632ffd821 100644 --- a/vendor/libkqueue/src/solaris/user.c +++ b/vendor/libkqueue/src/solaris/user.c @@ -97,8 +97,7 @@ evfilt_user_knote_modify(struct filter *filt, struct knote *kn, if ((!(kn->kev.flags & EV_DISABLE)) && kev->fflags & NOTE_TRIGGER) { kn->kev.fflags |= NOTE_TRIGGER; - //FIXME: how now? knote_enqueue(filt, kn); - return (port_send(filter_epfd(filt), X_PORT_SOURCE_USER, NULL)); + return (port_send(filter_epfd(filt), X_PORT_SOURCE_USER, kn)); } return (0); From 6a17bac0c04965175538fdabbf0abd1645d0c4bf Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 16 Feb 2011 02:58:56 +0000 Subject: [PATCH 0403/1120] partial fix for Solaris SOCKET filter git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@427 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/socket.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/solaris/socket.c b/vendor/libkqueue/src/solaris/socket.c index 1d5d77460..0633f98d0 100644 --- a/vendor/libkqueue/src/solaris/socket.c +++ b/vendor/libkqueue/src/solaris/socket.c @@ -30,6 +30,7 @@ #include "sys/event.h" #include "private.h" +#if DEADWOOD static int socket_knote_create(int port, int filter, int fd, void *udata) { @@ -66,6 +67,7 @@ socket_knote_delete(int port, int fd) return (0); } } +#endif int evfilt_socket_knote_create(struct filter *filt, struct knote *kn) @@ -106,21 +108,25 @@ evfilt_socket_knote_delete(struct filter *filt, struct knote *kn) { if (kn->kev.flags & EV_DISABLE) return (0); - else - return (socket_knote_delete(filter_epfd(filt), kn->kev.ident)); + + if (port_dissociate(filter_epfd(filt), PORT_SOURCE_FD, kn->kev.ident) < 0) { + dbg_perror("port_dissociate(2)"); + return (-1); + } + + return (0); } int evfilt_socket_knote_enable(struct filter *filt, struct knote *kn) { - return socket_knote_create(filter_epfd(filt), - kn->kev.filter, kn->kev.ident, filt); + return evfilt_socket_knote_create(filt, kn); } int evfilt_socket_knote_disable(struct filter *filt, struct knote *kn) { - return socket_knote_delete(filter_epfd(filt), kn->kev.ident); + return evfilt_socket_knote_delete(filt, kn); } int From 9ac945b7259a1fd0d61735f7cb97ad66b70c1ed7 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 16 Feb 2011 03:11:19 +0000 Subject: [PATCH 0404/1120] More Solaris improvements git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@428 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/socket.c | 4 ++++ vendor/libkqueue/test/common.h | 3 ++- vendor/libkqueue/test/kevent.c | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/solaris/socket.c b/vendor/libkqueue/src/solaris/socket.c index 0633f98d0..39ef9be4c 100644 --- a/vendor/libkqueue/src/solaris/socket.c +++ b/vendor/libkqueue/src/solaris/socket.c @@ -106,8 +106,10 @@ evfilt_socket_knote_modify(struct filter *filt, struct knote *kn, int evfilt_socket_knote_delete(struct filter *filt, struct knote *kn) { + /* FIXME: should be handled at kevent_copyin() if (kn->kev.flags & EV_DISABLE) return (0); + */ if (port_dissociate(filter_epfd(filt), PORT_SOURCE_FD, kn->kev.ident) < 0) { dbg_perror("port_dissociate(2)"); @@ -120,12 +122,14 @@ evfilt_socket_knote_delete(struct filter *filt, struct knote *kn) int evfilt_socket_knote_enable(struct filter *filt, struct knote *kn) { + dbg_printf("enabling knote %p", kn); return evfilt_socket_knote_create(filt, kn); } int evfilt_socket_knote_disable(struct filter *filt, struct knote *kn) { + dbg_printf("disabling knote %p", kn); return evfilt_socket_knote_delete(filt, kn); } diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 43b41b241..ee80949df 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -99,7 +99,8 @@ kevent_add(int kqfd, struct kevent *kev, } while (0); /* Checks if any events are pending, which is an error. */ -void test_no_kevents(int); +#define test_no_kevents(a) _test_no_kevents(a, __FILE__, __LINE__) +void _test_no_kevents(int, const char *, int); /* From test.c */ void test_begin(const char *); diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index 86b3782d1..136db7d29 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -20,7 +20,7 @@ extern int kqfd; /* Checks if any events are pending, which is an error. */ void -test_no_kevents(int kqfd) +_test_no_kevents(int kqfd, const char *file, int line) { int nfds; struct timespec timeo; @@ -31,7 +31,7 @@ test_no_kevents(int kqfd) if (nfds < 0) die("kevent(2)"); if (nfds > 0) { - puts("\nUnexpected event:"); + printf("\n[%s:%d]: Unexpected event:", file, line); die(kevent_to_str(&kev)); } } From 28e1ac4895c28eb37866e298176b6a5d999eb6c5 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 20 Feb 2011 03:24:57 +0000 Subject: [PATCH 0405/1120] Add an additional sanity check git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@429 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/read.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 79f9de65e..db92dcf12 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -98,7 +98,7 @@ test_kevent_socket_clear(void) EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &sockfd[0]); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("kevent"); + die("kevent1"); kevent_socket_fill(); kevent_socket_fill(); @@ -120,7 +120,7 @@ test_kevent_socket_clear(void) kevent_socket_drain(); EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("kevent"); + die("kevent2"); } void @@ -183,10 +183,15 @@ test_kevent_socket_oneshot(void) test_no_kevents(kqfd); - /* Verify that the event has been deleted */ + /* Verify that the kernel watch has been deleted */ kevent_socket_fill(); test_no_kevents(kqfd); kevent_socket_drain(); + + /* Verify that the kevent structure does not exist. */ + kev.flags = EV_DELETE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0) + die("kevent() should have failed"); } /* From ea1048b09a907f23ccb483d234cd4beca978a0a9 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 20 Feb 2011 03:25:22 +0000 Subject: [PATCH 0406/1120] Add extra debug output git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@430 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kevent.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 1131a2567..e8ff06148 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -134,6 +134,7 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) dbg_printf("src=%s\n", kevent_dump(src)); kn = knote_lookup(filt, src->ident); + dbg_printf("knote_lookup: ident %d == %p", (int)src->ident, kn); if (kn == NULL) { if (src->flags & EV_ADD) { if ((kn = knote_new()) == NULL) { @@ -174,12 +175,15 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) } else if (src->flags & EV_DISABLE) { kn->kev.flags |= EV_DISABLE; rv = filt->kn_disable(filt, kn); + dbg_printf("kn_disable returned %d", rv); } else if (src->flags & EV_ENABLE) { kn->kev.flags &= ~EV_DISABLE; rv = filt->kn_enable(filt, kn); + dbg_printf("kn_enable returned %d", rv); } else if (src->flags & EV_ADD || src->flags == 0) { kn->kev.udata = src->udata; rv = filt->kn_modify(filt, kn, src); + dbg_printf("kn_modify returned %d", rv); } knote_unlock(kn); From 6290e99bf4e8ce0cfa7345c9ffd7c9d91352607c Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 20 Feb 2011 03:26:04 +0000 Subject: [PATCH 0407/1120] Bug fixes for Solaris git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@431 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/platform.c | 27 ++++++++++++++--- vendor/libkqueue/src/solaris/socket.c | 40 +------------------------ 2 files changed, 24 insertions(+), 43 deletions(-) diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index 7963ee73b..32cf39871 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -159,6 +159,14 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, //XXX-FIXME WHAT ABOUT WRITE??? filter_lookup(&filt, kq, EVFILT_READ); rv = filt->kf_copyout(eventlist, kn, evt); + + /* For sockets, the event port object must be reassociated + after each event is retrieved. */ + if (rv == 0 && !(kn->kev.flags & EV_DISPATCH + || kn->kev.flags & EV_ONESHOT)) { + rv = filt->kn_create(filt, kn); + } + break; case PORT_SOURCE_TIMER: @@ -186,10 +194,21 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, dbg_puts("unsupported source"); abort(); } - if (rv < 0) { - dbg_puts("kevent_copyout failed"); - return (-1); - } + + if (rv < 0) { + dbg_puts("kevent_copyout failed"); + return (-1); + } + + /* + * Certain flags cause the associated knote to be deleted + * or disabled. + */ + if (eventlist->flags & EV_DISPATCH) + knote_disable(filt, kn); //TODO: Error checking + if (eventlist->flags & EV_ONESHOT) + knote_release(filt, kn); //TODO: Error checking + eventlist++; } diff --git a/vendor/libkqueue/src/solaris/socket.c b/vendor/libkqueue/src/solaris/socket.c index 39ef9be4c..5a20da2a0 100644 --- a/vendor/libkqueue/src/solaris/socket.c +++ b/vendor/libkqueue/src/solaris/socket.c @@ -30,45 +30,6 @@ #include "sys/event.h" #include "private.h" -#if DEADWOOD -static int -socket_knote_create(int port, int filter, int fd, void *udata) -{ - int rv, events; - - switch (filter) { - case EVFILT_READ: - events = POLLIN; - break; - case EVFILT_WRITE: - events = POLLOUT; - break; - default: - dbg_puts("invalid filter"); - return (-1); - } - - rv = port_associate(port, PORT_SOURCE_FD, fd, events, udata); - if (rv < 0) { - dbg_perror("port_associate(2)"); - return (-1); - } - - return (0); -} - -static int -socket_knote_delete(int port, int fd) -{ - if (port_dissociate(port, PORT_SOURCE_FD, fd) < 0) { - dbg_perror("port_dissociate(2)"); - return (-1); - } else { - return (0); - } -} -#endif - int evfilt_socket_knote_create(struct filter *filt, struct knote *kn) { @@ -100,6 +61,7 @@ int evfilt_socket_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { + dbg_puts("XXX-FIXME"); return (-1); /* STUB */ } From 28931ac17f5fea3a82b0959abe0237bbae1faebb Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 20 Feb 2011 04:49:12 +0000 Subject: [PATCH 0408/1120] Fix EVFILT_SIGNAL on Solaris git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@432 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/platform.c | 2 +- vendor/libkqueue/src/solaris/signal.c | 44 ++++++++++++++----------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index 32cf39871..ff3007c27 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -152,7 +152,7 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, for (i = 0; i < nready; i++) { evt = &evbuf[i]; - kn = evt->portev_user; + kn = evt->portev_user; dbg_printf("event=%s", port_event_dump(evt)); switch (evt->portev_source) { case PORT_SOURCE_FD: diff --git a/vendor/libkqueue/src/solaris/signal.c b/vendor/libkqueue/src/solaris/signal.c index 9688dfc66..b708f4d75 100644 --- a/vendor/libkqueue/src/solaris/signal.c +++ b/vendor/libkqueue/src/solaris/signal.c @@ -19,14 +19,14 @@ /* Highest signal number supported. POSIX standard signals are < 32 */ #define SIGNAL_MAX 32 -struct sentry { - struct filter *s_filt; - struct knote *s_knote; - volatile uint32_t s_cnt; -}; +static struct sentry { + int st_signum; + int st_port; + volatile sig_atomic_t st_count; + struct kevent st_kev; +} sigtbl[SIGNAL_MAX]; static pthread_mutex_t sigtbl_mtx = PTHREAD_MUTEX_INITIALIZER; -static struct sentry sigtbl[SIGNAL_MAX]; static void signal_handler(int sig) @@ -34,11 +34,12 @@ signal_handler(int sig) struct sentry *s; if (sig < 0 || sig > SIGNAL_MAX) - abort(); + return; //TODO: DEBUG OUTPUT s = &sigtbl[sig]; - atomic_inc(&s->s_cnt); - port_send(filter_epfd(s->s_filt), X_PORT_SOURCE_SIGNAL, &sigtbl[sig]); + dbg_printf("sig=%d %d", sig, s->st_signum); + atomic_inc(&s->st_count); + port_send(s->st_port, X_PORT_SOURCE_SIGNAL, &sigtbl[sig]); /* TODO: crash if port_send() fails? */ } @@ -58,13 +59,16 @@ catch_signal(struct filter *filt, struct knote *kn) dbg_perror("sigaction"); return (-1); } - /* FIXME: will clobber previous entry, if any */ + pthread_mutex_lock(&sigtbl_mtx); - sigtbl[kn->kev.ident].s_filt = filt; - sigtbl[kn->kev.ident].s_knote = kn; + sigtbl[sig].st_signum = sig; + sigtbl[sig].st_port = filter_epfd(filt); + sigtbl[sig].st_count = 0; + memcpy(&sigtbl[sig].st_kev, &kn->kev, sizeof(struct kevent)); pthread_mutex_unlock(&sigtbl_mtx); dbg_printf("installed handler for signal %d", sig); + dbg_printf("sigtbl ptr = %p", &sigtbl[sig]); return (0); } @@ -81,10 +85,6 @@ ignore_signal(int sig) dbg_perror("sigaction"); return (-1); } - pthread_mutex_lock(&sigtbl_mtx); - sigtbl[sig].s_filt = NULL; - sigtbl[sig].s_knote = NULL; - pthread_mutex_unlock(&sigtbl_mtx); dbg_printf("removed handler for signal %d", sig); return (0); @@ -133,12 +133,18 @@ evfilt_signal_knote_disable(struct filter *filt, struct knote *kn) int evfilt_signal_copyout(struct kevent *dst, struct knote *src, void *ptr) { - dst->ident = src->kev.ident; + port_event_t *pe = (port_event_t *) ptr; + struct sentry *ent = (struct sentry *) pe->portev_user; + + pthread_mutex_lock(&sigtbl_mtx); + dbg_printf("sigtbl ptr = %p sig=%d", ptr, ent->st_signum); + dst->ident = ent->st_kev.ident; dst->filter = EVFILT_SIGNAL; - dst->udata = src->kev.udata; - dst->flags = src->kev.flags; + dst->udata = ent->st_kev.udata; + dst->flags = ent->st_kev.flags; dst->fflags = 0; dst->data = 1; + pthread_mutex_unlock(&sigtbl_mtx); if (src->kev.flags & EV_DISPATCH || src->kev.flags & EV_ONESHOT) ignore_signal(src->kev.ident); From a89a0165a67a4d2088c5e1e4ecb1962800309aea Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 20 Feb 2011 21:17:42 +0000 Subject: [PATCH 0409/1120] effort to fix Solaris timers git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@433 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/timer.c | 64 +++++++++++++--------------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/vendor/libkqueue/src/solaris/timer.c b/vendor/libkqueue/src/solaris/timer.c index 422f3113d..1a73b6162 100644 --- a/vendor/libkqueue/src/solaris/timer.c +++ b/vendor/libkqueue/src/solaris/timer.c @@ -72,40 +72,6 @@ convert_msec_to_itimerspec(struct itimerspec *dst, int src, int oneshot) dbg_printf("%s", itimerspec_dump(dst)); } -static int -ktimer_create(struct filter *filt, struct knote *kn) -{ - port_notify_t pn; - struct sigevent se; - struct itimerspec ts; - timer_t timerid; - - kn->kev.flags |= EV_CLEAR; - - pn.portnfy_port = filter_epfd(filt); - pn.portnfy_user = (void *) kn->kev.ident; - - se.sigev_notify = SIGEV_PORT; - se.sigev_value.sival_ptr = &pn; - - if (timer_create (CLOCK_MONOTONIC, &se, &timerid) < 0) { - dbg_perror("timer_create(2)"); - return (-1); - } - - convert_msec_to_itimerspec(&ts, kn->kev.data, kn->kev.flags & EV_ONESHOT); - if (timer_settime(timerid, 0, &ts, NULL) < 0) { - dbg_perror("timer_settime(2)"); - (void) timer_delete(timerid); - return (-1); - } - - kn->data.timerid = timerid; - dbg_printf("created timer with id #%lu", (unsigned long) timerid); - - return (0); -} - int evfilt_timer_init(struct filter *filt) { @@ -155,7 +121,35 @@ evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr) int evfilt_timer_knote_create(struct filter *filt, struct knote *kn) { - return ktimer_create(filt, kn); + port_notify_t pn; + struct sigevent se; + struct itimerspec ts; + timer_t timerid; + + kn->kev.flags |= EV_CLEAR; + + pn.portnfy_port = filter_epfd(filt); + pn.portnfy_user = (void *) kn; + + se.sigev_notify = SIGEV_PORT; + se.sigev_value.sival_ptr = &pn; + + if (timer_create (CLOCK_MONOTONIC, &se, &timerid) < 0) { + dbg_perror("timer_create(2)"); + return (-1); + } + + convert_msec_to_itimerspec(&ts, kn->kev.data, kn->kev.flags & EV_ONESHOT); + if (timer_settime(timerid, 0, &ts, NULL) < 0) { + dbg_perror("timer_settime(2)"); + (void) timer_delete(timerid); + return (-1); + } + + kn->data.timerid = timerid; + dbg_printf("created timer with id #%lu", (unsigned long) timerid); + + return (0); } int From 806e518279390b5d200630a66a4299996ac33b00 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 20 Feb 2011 21:19:48 +0000 Subject: [PATCH 0410/1120] all Solaris tests work now git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@434 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/timer.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/vendor/libkqueue/src/solaris/timer.c b/vendor/libkqueue/src/solaris/timer.c index 1a73b6162..692c4a15d 100644 --- a/vendor/libkqueue/src/solaris/timer.c +++ b/vendor/libkqueue/src/solaris/timer.c @@ -87,14 +87,7 @@ evfilt_timer_destroy(struct filter *filt) int evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr) { - port_event_t *pe = (port_event_t *) ptr; - long buf; - timer_t timerid; - - /* XXX-FIXME: danger here -- there has to be a better way */ - buf = (long) pe->portev_user; - timerid = (timer_t) buf; - /* ^^^^^^^^^ */ + /* port_event_t *pe = (port_event_t *) ptr; */ memcpy(dst, &src->kev, sizeof(*dst)); //TODO: @@ -107,6 +100,7 @@ evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr) dst->data = 1; //workaround #if FIXME + timerid = src->data.timerid; //should be done in kqops.copyout() if (src->kev.flags & EV_DISPATCH) { timer_delete(src->data.timerid); From 31bbd8a06100375a32488fd260f0f4f73854ec42 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 21 Feb 2011 00:06:42 +0000 Subject: [PATCH 0411/1120] backport "distfile" from pthwq git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@435 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index ee004d8b4..de9f04299 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -18,7 +18,7 @@ c_exports="program version target cflags" -make_exports="program version target \ +make_exports="program version target distfile \ prefix libdir includedir mandir \ cflags ldflags ldadd libdepends \ sources objs deps mans headers extra_dist subdirs \ @@ -198,7 +198,7 @@ check_linker() { # Appears to be a problem with GCC 4.0 and binutils # default_ld="$cc" - ldflags="-shared -o $program.so.$abi_major.$abi_minor $ldflags" + ldflags="-o $program.so.$abi_major.$abi_minor $ldflags" # FIXME: port to solaris if [ "$target" = "linux" ] ; then @@ -312,6 +312,7 @@ finalize ldadd "" finalize ldflags "" finalize deps "" finalize ln "`which ln`" +finalize distfile "$program-$version.tar.gz" pre_configure_hook From d480020a73d4d93dcf8e9e3612462795a1790666 Mon Sep 17 00:00:00 2001 From: jocke Date: Mon, 21 Feb 2011 13:28:44 +0000 Subject: [PATCH 0412/1120] Fix Solaris build - use -shared for Solaris ldflags to build shlib for now, comment out usage of st_count as the 32-bit Solaris atomic ops will bail out on the type sig_atomic_t git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@436 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure | 2 +- vendor/libkqueue/src/solaris/signal.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index de9f04299..5374f592a 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -206,7 +206,7 @@ check_linker() { fi if [ "$target" = "solaris" ] ; then - ldflags="$ldflags" + ldflags="-shared $ldflags" fi finalize ld "$default_ld" diff --git a/vendor/libkqueue/src/solaris/signal.c b/vendor/libkqueue/src/solaris/signal.c index b708f4d75..31ef0d4dd 100644 --- a/vendor/libkqueue/src/solaris/signal.c +++ b/vendor/libkqueue/src/solaris/signal.c @@ -22,7 +22,7 @@ static struct sentry { int st_signum; int st_port; - volatile sig_atomic_t st_count; +// volatile sig_atomic_t st_count; struct kevent st_kev; } sigtbl[SIGNAL_MAX]; @@ -38,7 +38,7 @@ signal_handler(int sig) s = &sigtbl[sig]; dbg_printf("sig=%d %d", sig, s->st_signum); - atomic_inc(&s->st_count); +// atomic_inc(&s->st_count); port_send(s->st_port, X_PORT_SOURCE_SIGNAL, &sigtbl[sig]); /* TODO: crash if port_send() fails? */ } @@ -63,7 +63,7 @@ catch_signal(struct filter *filt, struct knote *kn) pthread_mutex_lock(&sigtbl_mtx); sigtbl[sig].st_signum = sig; sigtbl[sig].st_port = filter_epfd(filt); - sigtbl[sig].st_count = 0; +// sigtbl[sig].st_count = 0; memcpy(&sigtbl[sig].st_kev, &kn->kev, sizeof(struct kevent)); pthread_mutex_unlock(&sigtbl_mtx); From 4b25c91df189a5772c6c92f55f9f5741936b64f9 Mon Sep 17 00:00:00 2001 From: jocke Date: Mon, 21 Feb 2011 17:54:08 +0000 Subject: [PATCH 0413/1120] Typecast instead of comment out s->st_count for the time being git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@437 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/signal.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/solaris/signal.c b/vendor/libkqueue/src/solaris/signal.c index 31ef0d4dd..03d0886e9 100644 --- a/vendor/libkqueue/src/solaris/signal.c +++ b/vendor/libkqueue/src/solaris/signal.c @@ -22,7 +22,7 @@ static struct sentry { int st_signum; int st_port; -// volatile sig_atomic_t st_count; + volatile sig_atomic_t st_count; struct kevent st_kev; } sigtbl[SIGNAL_MAX]; @@ -38,7 +38,7 @@ signal_handler(int sig) s = &sigtbl[sig]; dbg_printf("sig=%d %d", sig, s->st_signum); -// atomic_inc(&s->st_count); + atomic_inc((volatile uint32_t *) &s->st_count); port_send(s->st_port, X_PORT_SOURCE_SIGNAL, &sigtbl[sig]); /* TODO: crash if port_send() fails? */ } @@ -63,7 +63,7 @@ catch_signal(struct filter *filt, struct knote *kn) pthread_mutex_lock(&sigtbl_mtx); sigtbl[sig].st_signum = sig; sigtbl[sig].st_port = filter_epfd(filt); -// sigtbl[sig].st_count = 0; + sigtbl[sig].st_count = 0; memcpy(&sigtbl[sig].st_kev, &kn->kev, sizeof(struct kevent)); pthread_mutex_unlock(&sigtbl_mtx); From 28340c2de709e8b5bb278fe34ab3e065afcccbb8 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 23 Feb 2011 01:33:55 +0000 Subject: [PATCH 0414/1120] Emulate spinlocks on win32 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@438 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/windows/platform.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index b6bb51dd5..f69d1808c 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -114,7 +114,10 @@ typedef int pid_t; #define __thread __declspec(thread) /* Emulation of pthreads mutex functionality */ +#define PTHREAD_PROCESS_SHARED 1 +#define PTHREAD_PROCESS_PRIVATE 2 typedef CRITICAL_SECTION pthread_mutex_t; +typedef CRITICAL_SECTION pthread_spinlock_t; typedef CRITICAL_SECTION pthread_rwlock_t; #define _cs_init(x) InitializeCriticalSection((x)) #define _cs_lock(x) EnterCriticalSection ((x)) @@ -122,6 +125,10 @@ typedef CRITICAL_SECTION pthread_rwlock_t; #define pthread_mutex_lock _cs_lock #define pthread_mutex_unlock _cs_unlock #define pthread_mutex_init(x,y) _cs_init((x)) +#define pthread_spin_lock _cs_lock +#define pthread_spin_unlock _cs_unlock +#define pthread_spin_init(x,y) _cs_init((x)) +#define pthread_mutex_init(x,y) _cs_init((x)) #define pthread_rwlock_rdlock _cs_lock #define pthread_rwlock_wrlock _cs_lock #define pthread_rwlock_unlock _cs_unlock From 2f23edb35e01e166cab3fc988ec1d1d5e13df57e Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 23 Feb 2011 01:41:22 +0000 Subject: [PATCH 0415/1120] Upgrade to makeconf r10. Always use -shared when running the linker (fixes Linux build). git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@439 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 2 +- vendor/libkqueue/configure | 64 +++++++++++++++++++++++++------------- 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 319316e52..9c44b9426 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -31,7 +31,7 @@ $(PROGRAM).a: $(OBJS) $(AR) rcs $(PROGRAM).a $(OBJS) $(PROGRAM).so.$(ABI_VERSION): $(OBJS) - $(LD) $(LDFLAGS) $(OBJS) $(LDADD) + $(LD) -shared $(LDFLAGS) $(OBJS) $(LDADD) $(LN) -sf $(PROGRAM).so.$(ABI_VERSION) $(PROGRAM).so.$(ABI_MAJOR) $(LN) -sf $(PROGRAM).so.$(ABI_VERSION) $(PROGRAM).so diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index 5374f592a..1f7e5c3af 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2009-2010 Mark Heily +# Copyright (c) 2009-2011 Mark Heily # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above @@ -15,11 +15,12 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # +makeconf_version="$Revision: 10 $" -c_exports="program version target cflags" +c_exports="program version target api cflags" -make_exports="program version target distfile \ - prefix libdir includedir mandir \ +make_exports="program version target api distfile \ + prefix bindir sbindir libdir includedir mandir \ cflags ldflags ldadd libdepends \ sources objs deps mans headers extra_dist subdirs \ abi_major abi_minor abi_version \ @@ -42,7 +43,7 @@ export_to_make() { # Prepend $DESTDIR to installation directories case "$id" in - prefix|libdir|includedir|mandir) + prefix) eval "$id=\"\\\$\\\$DESTDIR\$$id\"" esac @@ -67,6 +68,10 @@ finalize() { process_argv() { for arg in $* do + if [ "$arg" = "--makeconf-version" ] ; then + echo $makeconf_version | sed 's/[^0-9.]//g' + exit 0 + fi id=`echo "$arg" | sed 's/=.*//; s/^--//;'` val=`echo "$arg" | sed 's/^.*=//'` if [ "$val" = "" ] ; then val=1 ; fi @@ -173,20 +178,29 @@ check_install() { check_target() { printf "checking operating system type.. " default_target=`uname -s | $tr '[:upper:]' '[:lower:]'` - if [ "$default_target" = "sunos" ] ; then - default_target="solaris" - fi - if [ "$default_target" = "gnu/kfreebsd" ] ; then - default_target="freebsd" - fi + default_api="posix" + case "$default_target" in + sunos) + default_target="solaris" + ;; + "gnu/kfreebsd") + default_target="freebsd" + ;; + "mingw*") + default_target="windows" + default_api="windows" + ;; + esac finalize target "$default_target" - echo "$target" + finalize api "$default_api" + echo "$api-$target" } check_compiler() { printf "checking for a C compiler.. " - check_binary default_cc "/usr/bin/cc" "/usr/bin/gcc" "/usr/sfw/bin/gcc" + check_binary default_cc "/usr/bin/cc" "/usr/bin/gcc" "/usr/sfw/bin/gcc" "`which gcc 2>/dev/null`" finalize cc "$default_cc" + test -x "$cc" || err "Unable to locate a C compiler" echo "$cc" } @@ -206,7 +220,7 @@ check_linker() { fi if [ "$target" = "solaris" ] ; then - ldflags="-shared $ldflags" + ldflags="$ldflags" fi finalize ld "$default_ld" @@ -279,13 +293,15 @@ test -f /usr/xpg4/bin/tr && tr="/usr/xpg4/bin/tr" # Initialize the output files # -for output_file in config.mk $program.pc +for output_file in config.mk do rm -f $output_file echo "# AUTOMATICALLY GENERATED -- DO NOT EDIT" > $output_file done -rm -f config.h -echo "/* AUTOMATICALLY GENERATED -- DO NOT EDIT */" > config.h +if [ "$sources" != "" ] ; then + rm -f config.h + echo "/* AUTOMATICALLY GENERATED -- DO NOT EDIT */" > config.h +fi process_argv "$*" process_env @@ -303,9 +319,11 @@ finalize abi_major "$abi_major" finalize abi_minor "$abi_minor" finalize abi_version "$abi_major.$abi_minor" finalize prefix "/usr/local" -finalize libdir "${prefix}/lib" -finalize includedir "${prefix}/include" -finalize mandir "${prefix}/share/man" +finalize bindir "\\\$(PREFIX)/bin" +finalize sbindir "\\\$(PREFIX)/sbin" +finalize libdir "\\\$(PREFIX)/lib" +finalize includedir "\\\$(PREFIX)/include" +finalize mandir "\\\$(PREFIX)/share/man" finalize cflags "$cflags" finalize libdepends "$libdepends" finalize ldadd "" @@ -330,8 +348,10 @@ subst_vars "$program.pc" subst_vars "$program.la" subst_vars "rpm.spec" -echo "Creating config.h" -export_to_c $c_exports +if [ "$sources" != "" ] ; then + echo "Creating config.h" + export_to_c $c_exports +fi echo "Creating config.mk" export_to_make "$make_exports" From 868b41516743c39701e437c385a9eb1ece58500e Mon Sep 17 00:00:00 2001 From: jocke Date: Wed, 23 Feb 2011 16:48:57 +0000 Subject: [PATCH 0416/1120] Honor CC environment variable as the first pick in the compiler list, temporarily commented out the test for it being executable as it doesn't work properly when CC is set due to how finalize() checks for being empty git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@440 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index 1f7e5c3af..177cad3cf 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -198,9 +198,9 @@ check_target() { check_compiler() { printf "checking for a C compiler.. " - check_binary default_cc "/usr/bin/cc" "/usr/bin/gcc" "/usr/sfw/bin/gcc" "`which gcc 2>/dev/null`" + check_binary default_cc "$cc" "`which $cc 2>/dev/null`" "/usr/bin/cc" "/usr/bin/gcc" "/usr/sfw/bin/gcc" "`which gcc 2>/dev/null`" finalize cc "$default_cc" - test -x "$cc" || err "Unable to locate a C compiler" +# test -x "$cc" || err "Unable to locate a C compiler" echo "$cc" } From 38ea35b33081ad3df266f63bf24829a69e85fcd2 Mon Sep 17 00:00:00 2001 From: jocke Date: Wed, 23 Feb 2011 17:11:47 +0000 Subject: [PATCH 0417/1120] Only map in memory enough to keep the possible set of file descriptors (rlim_max for RLIMIT_NOFILE) rather than MAX_INT, drastically decreases the needed amount of VM backing availble (allowing it to run on also swap-impaired machines). This should be correct, as the kq_id refers to an fd and we can't have more fd:s than this. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@441 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kqueue.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 1dfa62937..b802de125 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -26,6 +26,18 @@ int KQUEUE_DEBUG = 0; +static unsigned int +get_fd_limit(void) +{ + struct rlimit rlim; + + if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { + dbg_perror("getrlimit(2)"); + return (65536); + } else { + return (rlim.rlim_max); + } +} static struct map *kqmap; @@ -41,7 +53,7 @@ _libkqueue_init(void) KQUEUE_DEBUG = (getenv("KQUEUE_DEBUG") == NULL) ? 0 : 1; #endif - kqmap = map_new(INT_MAX); + kqmap = map_new(get_fd_limit()); // INT_MAX if (kqmap == NULL) abort(); if (knote_init() < 0) From e2ab66d6b103e323000f714de8400e10531fe9ba Mon Sep 17 00:00:00 2001 From: jocke Date: Mon, 28 Feb 2011 09:26:14 +0000 Subject: [PATCH 0418/1120] Properly return number of times a timer have been triggered git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@442 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/timer.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/vendor/libkqueue/src/solaris/timer.c b/vendor/libkqueue/src/solaris/timer.c index 692c4a15d..3c854d63b 100644 --- a/vendor/libkqueue/src/solaris/timer.c +++ b/vendor/libkqueue/src/solaris/timer.c @@ -94,10 +94,7 @@ evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr) //if (ev->events & EPOLLERR) // dst->fflags = 1; /* FIXME: Return the actual timer error */ - /* FIXME: On return, data contains the number of times the - timer has been trigered. - */ - dst->data = 1; //workaround + dst->data = timer_getoverrun(src->data.timerid) + 1; #if FIXME timerid = src->data.timerid; From fae58f1b29096eda07e5772b7bd586c40478cabf Mon Sep 17 00:00:00 2001 From: jocke Date: Mon, 28 Feb 2011 14:45:20 +0000 Subject: [PATCH 0419/1120] Make sure we don't 'return' non-initialized events when running with KQUEUE_DEBUG by initializing rv properly (it would generate incorrect debug logs if nevents == 0), tuning debug output slightly. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@443 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kevent.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index e8ff06148..94a0eea00 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -131,7 +131,7 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) if (filter_lookup(&filt, kq, src->filter) < 0) return (-1); - dbg_printf("src=%s\n", kevent_dump(src)); + dbg_printf("src=%s", kevent_dump(src)); kn = knote_lookup(filt, src->ident); dbg_printf("knote_lookup: ident %d == %p", (int)src->ident, kn); @@ -151,7 +151,7 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) return (-1); } knote_insert(filt, kn); - dbg_printf("created kevent %s\n", kevent_dump(src)); + dbg_printf("created kevent %s", kevent_dump(src)); /* XXX- FIXME Needs to be handled in kn_create() to prevent races */ @@ -250,7 +250,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, if (KQUEUE_DEBUG) { myid = atomic_inc(&_kevent_counter); - dbg_printf("--- kevent %u ---", myid); + dbg_printf("--- kevent %u --- (nchanges = %d, nevents = %d)", myid, nchanges, nevents); } else { myid = 0; } @@ -269,6 +269,8 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, } } + rv = 0; + /* * Wait for events and copy them to the eventlist */ @@ -276,6 +278,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, nevents = MAX_KEVENT; if (nevents > 0) { rv = kqops.kevent_wait(kq, nevents, timeout); + dbg_printf("kqops.kevent_wait returned %d", rv); if (fastpath(rv > 0)) { rv = kqops.kevent_copyout(kq, rv, eventlist, nevents); } else if (rv == 0) { From 0ab3e8dc310e9b3e4a0ddf31f84fa10bdeb5987c Mon Sep 17 00:00:00 2001 From: jocke Date: Wed, 2 Mar 2011 08:47:07 +0000 Subject: [PATCH 0420/1120] Added xcode project for convenience for edit/navigation/etc git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@444 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- .../libkqueue.xcodeproj/project.pbxproj | 257 ++ .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | 2831 +++++++++++++++++ .../xcschemes/libkqueue.xcscheme | 58 + .../xcschemes/xcschememanagement.plist | 22 + 5 files changed, 3175 insertions(+) create mode 100644 vendor/libkqueue/libkqueue.xcodeproj/project.pbxproj create mode 100644 vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/xcuserdata/jocke.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 vendor/libkqueue/libkqueue.xcodeproj/xcuserdata/jocke.xcuserdatad/xcschemes/libkqueue.xcscheme create mode 100644 vendor/libkqueue/libkqueue.xcodeproj/xcuserdata/jocke.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/vendor/libkqueue/libkqueue.xcodeproj/project.pbxproj b/vendor/libkqueue/libkqueue.xcodeproj/project.pbxproj new file mode 100644 index 000000000..b463c3d39 --- /dev/null +++ b/vendor/libkqueue/libkqueue.xcodeproj/project.pbxproj @@ -0,0 +1,257 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXFileReference section */ + 85F0626E131E3AB10013C05E /* event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = event.h; path = include/sys/event.h; sourceTree = ""; }; + 85F062A1131E3AE90013C05E /* filter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = filter.c; sourceTree = ""; }; + 85F062A2131E3AE90013C05E /* kevent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kevent.c; sourceTree = ""; }; + 85F062A3131E3AE90013C05E /* queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = queue.h; sourceTree = ""; }; + 85F062A4131E3AE90013C05E /* map.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = map.c; sourceTree = ""; }; + 85F062A5131E3AE90013C05E /* kqueue.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kqueue.c; sourceTree = ""; }; + 85F062A6131E3AE90013C05E /* knote.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = knote.c; sourceTree = ""; }; + 85F062A7131E3AE90013C05E /* private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = private.h; sourceTree = ""; }; + 85F062A8131E3AE90013C05E /* alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = alloc.h; sourceTree = ""; }; + 85F062A9131E3AE90013C05E /* tree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tree.h; sourceTree = ""; }; + 85F062AB131E3AE90013C05E /* socket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = socket.c; sourceTree = ""; }; + 85F062AC131E3AE90013C05E /* platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform.h; sourceTree = ""; }; + 85F062AD131E3AE90013C05E /* signal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = signal.c; sourceTree = ""; }; + 85F062AE131E3AE90013C05E /* vnode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vnode.c; sourceTree = ""; }; + 85F062AF131E3AE90013C05E /* timer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = timer.c; sourceTree = ""; }; + 85F062B0131E3AE90013C05E /* proc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = proc.c; sourceTree = ""; }; + 85F062B1131E3AE90013C05E /* user.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = user.c; sourceTree = ""; }; + 85F062B2131E3AE90013C05E /* platform.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = platform.c; sourceTree = ""; }; + 85F062B4131E3AE90013C05E /* platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform.h; sourceTree = ""; }; + 85F062B5131E3AE90013C05E /* user.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = user.c; sourceTree = ""; }; + 85F062B6131E3AE90013C05E /* signal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = signal.c; sourceTree = ""; }; + 85F062B7131E3AE90013C05E /* proc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = proc.c; sourceTree = ""; }; + 85F062B8131E3AE90013C05E /* kevent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kevent.c; sourceTree = ""; }; + 85F062B9131E3AE90013C05E /* platform.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = platform.c; sourceTree = ""; }; + 85F062BA131E3AE90013C05E /* timer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = timer.c; sourceTree = ""; }; + 85F062BC131E3AE90013C05E /* timer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = timer.c; sourceTree = ""; }; + 85F062BD131E3AE90013C05E /* platform.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = platform.c; sourceTree = ""; }; + 85F062BE131E3AE90013C05E /* socket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = socket.c; sourceTree = ""; }; + 85F062BF131E3AE90013C05E /* user.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = user.c; sourceTree = ""; }; + 85F062C0131E3AE90013C05E /* platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform.h; sourceTree = ""; }; + 85F062C1131E3AE90013C05E /* signal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = signal.c; sourceTree = ""; }; + 85F062C3131E3AE90013C05E /* platform.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = platform.c; sourceTree = ""; }; + 85F062C4131E3AE90013C05E /* timer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = timer.c; sourceTree = ""; }; + 85F062C5131E3AE90013C05E /* platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXGroup section */ + 85F06227131E3A3D0013C05E = { + isa = PBXGroup; + children = ( + 85F0626E131E3AB10013C05E /* event.h */, + 85F062A0131E3AE90013C05E /* common */, + 85F062AA131E3AE90013C05E /* linux */, + 85F062B3131E3AE90013C05E /* posix */, + 85F062BB131E3AE90013C05E /* solaris */, + 85F062C2131E3AE90013C05E /* windows */, + ); + sourceTree = ""; + }; + 85F062A0131E3AE90013C05E /* common */ = { + isa = PBXGroup; + children = ( + 85F062A1131E3AE90013C05E /* filter.c */, + 85F062A2131E3AE90013C05E /* kevent.c */, + 85F062A3131E3AE90013C05E /* queue.h */, + 85F062A4131E3AE90013C05E /* map.c */, + 85F062A5131E3AE90013C05E /* kqueue.c */, + 85F062A6131E3AE90013C05E /* knote.c */, + 85F062A7131E3AE90013C05E /* private.h */, + 85F062A8131E3AE90013C05E /* alloc.h */, + 85F062A9131E3AE90013C05E /* tree.h */, + ); + name = common; + path = src/common; + sourceTree = ""; + }; + 85F062AA131E3AE90013C05E /* linux */ = { + isa = PBXGroup; + children = ( + 85F062AB131E3AE90013C05E /* socket.c */, + 85F062AC131E3AE90013C05E /* platform.h */, + 85F062AD131E3AE90013C05E /* signal.c */, + 85F062AE131E3AE90013C05E /* vnode.c */, + 85F062AF131E3AE90013C05E /* timer.c */, + 85F062B0131E3AE90013C05E /* proc.c */, + 85F062B1131E3AE90013C05E /* user.c */, + 85F062B2131E3AE90013C05E /* platform.c */, + ); + name = linux; + path = src/linux; + sourceTree = ""; + }; + 85F062B3131E3AE90013C05E /* posix */ = { + isa = PBXGroup; + children = ( + 85F062B4131E3AE90013C05E /* platform.h */, + 85F062B5131E3AE90013C05E /* user.c */, + 85F062B6131E3AE90013C05E /* signal.c */, + 85F062B7131E3AE90013C05E /* proc.c */, + 85F062B8131E3AE90013C05E /* kevent.c */, + 85F062B9131E3AE90013C05E /* platform.c */, + 85F062BA131E3AE90013C05E /* timer.c */, + ); + name = posix; + path = src/posix; + sourceTree = ""; + }; + 85F062BB131E3AE90013C05E /* solaris */ = { + isa = PBXGroup; + children = ( + 85F062BC131E3AE90013C05E /* timer.c */, + 85F062BD131E3AE90013C05E /* platform.c */, + 85F062BE131E3AE90013C05E /* socket.c */, + 85F062BF131E3AE90013C05E /* user.c */, + 85F062C0131E3AE90013C05E /* platform.h */, + 85F062C1131E3AE90013C05E /* signal.c */, + ); + name = solaris; + path = src/solaris; + sourceTree = ""; + }; + 85F062C2131E3AE90013C05E /* windows */ = { + isa = PBXGroup; + children = ( + 85F062C3131E3AE90013C05E /* platform.c */, + 85F062C4131E3AE90013C05E /* timer.c */, + 85F062C5131E3AE90013C05E /* platform.h */, + ); + name = windows; + path = src/windows; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXLegacyTarget section */ + 85F0622E131E3A3D0013C05E /* libkqueue */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "$(ACTION)"; + buildConfigurationList = 85F06231131E3A3D0013C05E /* Build configuration list for PBXLegacyTarget "libkqueue" */; + buildPhases = ( + ); + buildToolPath = /usr/bin/make; + dependencies = ( + ); + name = libkqueue; + passBuildSettingsInEnvironment = 1; + productName = libkqueue; + }; +/* End PBXLegacyTarget section */ + +/* Begin PBXProject section */ + 85F06229131E3A3D0013C05E /* Project object */ = { + isa = PBXProject; + attributes = { + ORGANIZATIONNAME = Tbricks; + }; + buildConfigurationList = 85F0622C131E3A3D0013C05E /* Build configuration list for PBXProject "libkqueue" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 85F06227131E3A3D0013C05E; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 85F0622E131E3A3D0013C05E /* libkqueue */, + ); + }; +/* End PBXProject section */ + +/* Begin XCBuildConfiguration section */ + 85F0622F131E3A3D0013C05E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = DEBUG; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.6; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 85F06230131E3A3D0013C05E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.6; + SDKROOT = macosx; + }; + name = Release; + }; + 85F06232131E3A3D0013C05E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + DEBUGGING_SYMBOLS = YES; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 85F06233131E3A3D0013C05E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 85F0622C131E3A3D0013C05E /* Build configuration list for PBXProject "libkqueue" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 85F0622F131E3A3D0013C05E /* Debug */, + 85F06230131E3A3D0013C05E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 85F06231131E3A3D0013C05E /* Build configuration list for PBXLegacyTarget "libkqueue" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 85F06232131E3A3D0013C05E /* Debug */, + 85F06233131E3A3D0013C05E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 85F06229131E3A3D0013C05E /* Project object */; +} diff --git a/vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..ecdfdff53 --- /dev/null +++ b/vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/xcuserdata/jocke.xcuserdatad/UserInterfaceState.xcuserstate b/vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/xcuserdata/jocke.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 000000000..8400fe9ce --- /dev/null +++ b/vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/xcuserdata/jocke.xcuserdatad/UserInterfaceState.xcuserstate @@ -0,0 +1,2831 @@ + + + + + $archiver + NSKeyedArchiver + $objects + + $null + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 2 + + + CF$UID + 3 + + + NS.objects + + + CF$UID + 4 + + + CF$UID + 196 + + + + B8DD28BF-0B77-4F6B-BE84-8CFDEBA37869 + IDEWorkspaceDocument + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 5 + + + CF$UID + 6 + + + CF$UID + 7 + + + CF$UID + 8 + + + CF$UID + 9 + + + CF$UID + 10 + + + NS.objects + + + CF$UID + 11 + + + CF$UID + 194 + + + CF$UID + 21 + + + CF$UID + 5 + + + CF$UID + 2 + + + CF$UID + 195 + + + + IDEWorkspaceTabController_EC0EC534-0E04-4AE1-A499-3DB51327C249 + IDEOrderedWorkspaceTabControllers + IDEWindowToolbarIsVisible + IDEActiveWorkspaceTabController + IDEWorkspaceWindowControllerUniqueIdentifier + IDEWindowFrame + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 12 + + + CF$UID + 13 + + + CF$UID + 14 + + + CF$UID + 15 + + + CF$UID + 16 + + + CF$UID + 17 + + + CF$UID + 18 + + + CF$UID + 19 + + + NS.objects + + + CF$UID + 20 + + + CF$UID + 21 + + + CF$UID + 22 + + + CF$UID + 150 + + + CF$UID + 156 + + + CF$UID + 185 + + + CF$UID + 31 + + + CF$UID + 42 + + + + IDETabLabel + IDEShowNavigator + IDEEditorArea + IDEWorkspaceTabControllerUtilityAreaSplitView + IDENavigatorArea + IDEWorkspaceTabControllerDesignAreaSplitView + IDEShowUtilities + AssistantEditorsLayout + libkqueue.xcodeproj + + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 23 + + + CF$UID + 24 + + + CF$UID + 25 + + + CF$UID + 26 + + + CF$UID + 27 + + + CF$UID + 28 + + + CF$UID + 29 + + + CF$UID + 30 + + + NS.objects + + + CF$UID + 31 + + + CF$UID + 32 + + + CF$UID + 66 + + + CF$UID + 21 + + + CF$UID + 42 + + + CF$UID + 130 + + + CF$UID + 138 + + + CF$UID + 139 + + + + ShowDebuggerArea + IDEEDitorArea_DebugArea + IDEEditorMode_Standard + IDEShowEditor + EditorMode + DebuggerSplitView + DefaultPersistentRepresentations + layoutTree + + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 33 + + + CF$UID + 34 + + + CF$UID + 35 + + + CF$UID + 36 + + + CF$UID + 37 + + + CF$UID + 38 + + + NS.objects + + + CF$UID + 39 + + + CF$UID + 40 + + + CF$UID + 44 + + + CF$UID + 39 + + + CF$UID + 57 + + + CF$UID + 63 + + + + LayoutFocusMode + console + IDEDebuggerAreaSplitView + LayoutMode + IDEDebugArea_SplitView + variables + 1 + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 41 + + + NS.objects + + + CF$UID + 42 + + + + ConsoleFilterMode + 0 + + $classes + + NSMutableDictionary + NSDictionary + NSObject + + $classname + NSMutableDictionary + + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 45 + + + NS.objects + + + CF$UID + 46 + + + + DVTSplitViewItems + + $class + + CF$UID + 56 + + NS.objects + + + CF$UID + 47 + + + CF$UID + 53 + + + + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 48 + + + CF$UID + 49 + + + NS.objects + + + CF$UID + 50 + + + CF$UID + 51 + + + + DVTIdentifier + DVTViewMagnitude + VariablesView + 570 + + $classes + + NSDictionary + NSObject + + $classname + NSDictionary + + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 48 + + + CF$UID + 49 + + + NS.objects + + + CF$UID + 54 + + + CF$UID + 55 + + + + ConsoleArea + 569 + + $classes + + NSMutableArray + NSArray + NSObject + + $classname + NSMutableArray + + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 45 + + + NS.objects + + + CF$UID + 58 + + + + + $class + + CF$UID + 56 + + NS.objects + + + CF$UID + 59 + + + CF$UID + 61 + + + + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 48 + + + CF$UID + 49 + + + NS.objects + + + CF$UID + 50 + + + CF$UID + 60 + + + + 570 + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 48 + + + CF$UID + 49 + + + NS.objects + + + CF$UID + 54 + + + CF$UID + 62 + + + + 569 + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 64 + + + NS.objects + + + CF$UID + 65 + + + + DBGVariablesViewFilterMode + 2 + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 67 + + + NS.objects + + + CF$UID + 68 + + + + EditorLayout_PersistentRepresentation + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 69 + + + NS.objects + + + CF$UID + 70 + + + + Main + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 71 + + + CF$UID + 72 + + + CF$UID + 73 + + + NS.objects + + + CF$UID + 74 + + + CF$UID + 42 + + + CF$UID + 128 + + + + EditorLayout_StateSavingStateDictionaries + EditorLayout_Selected + EditorLayout_Geometry + + $class + + CF$UID + 90 + + NS.objects + + + CF$UID + 75 + + + + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 76 + + + CF$UID + 77 + + + CF$UID + 78 + + + CF$UID + 79 + + + CF$UID + 80 + + + CF$UID + 81 + + + CF$UID + 82 + + + NS.objects + + + CF$UID + 83 + + + CF$UID + 84 + + + CF$UID + 97 + + + CF$UID + 123 + + + CF$UID + 123 + + + CF$UID + 124 + + + CF$UID + 125 + + + + FileDataType + ArchivableRepresentation + EditorState + NavigableItemName + DocumentNavigableItemName + DocumentExtensionIdentifier + DocumentURL + com.apple.xcode.project + + $class + + CF$UID + 96 + + DocumentLocation + + CF$UID + 92 + + DomainIdentifier + + CF$UID + 85 + + IdentifierPath + + CF$UID + 86 + + IndexOfDocumentIdentifier + + CF$UID + 91 + + + Xcode.IDENavigableItemDomain.WorkspaceStructure + + $class + + CF$UID + 90 + + NS.objects + + + CF$UID + 87 + + + + + $class + + CF$UID + 89 + + Identifier + + CF$UID + 88 + + + libkqueue + + $classes + + IDEArchivableStringIndexPair + NSObject + + $classname + IDEArchivableStringIndexPair + + + $classes + + NSArray + NSObject + + $classname + NSArray + + 9223372036854775807 + + $class + + CF$UID + 95 + + documentURL + + CF$UID + 93 + + timestamp + + CF$UID + 0 + + + + $class + + CF$UID + 94 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue.xcodeproj/ + + + $classes + + NSMutableString + NSString + NSObject + + $classname + NSMutableString + + + $classes + + DVTDocumentLocation + NSObject + + $classname + DVTDocumentLocation + + + $classes + + IDENavigableItemArchivableRepresentation + NSObject + + $classname + IDENavigableItemArchivableRepresentation + + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 98 + + + CF$UID + 99 + + + CF$UID + 100 + + + CF$UID + 101 + + + CF$UID + 102 + + + NS.objects + + + CF$UID + 103 + + + CF$UID + 104 + + + CF$UID + 111 + + + CF$UID + 112 + + + CF$UID + 122 + + + + Xcode3ProjectEditorPreviousProjectEditorClass + Xcode3ProjectEditor.sourceList.splitview + Xcode3ProjectEditorPreviousTargetEditorClass + Xcode3ProjectEditorSelectedDocumentLocations + Xcode3ProjectEditor_Xcode3InfoEditor + Xcode3ProjectInfoEditor + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 45 + + + NS.objects + + + CF$UID + 105 + + + + + $class + + CF$UID + 56 + + NS.objects + + + CF$UID + 106 + + + CF$UID + 109 + + + + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 48 + + + CF$UID + 49 + + + NS.objects + + + CF$UID + 107 + + + CF$UID + 108 + + + + + 170 + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 48 + + + CF$UID + 49 + + + NS.objects + + + CF$UID + 107 + + + CF$UID + 110 + + + + 970 + Xcode3InfoEditor + + $class + + CF$UID + 90 + + NS.objects + + + CF$UID + 113 + + + + + $class + + CF$UID + 121 + + documentURL + + CF$UID + 114 + + selection + + CF$UID + 116 + + timestamp + + CF$UID + 115 + + + file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue.xcodeproj/ + 320748289.82216001 + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 117 + + + CF$UID + 118 + + + NS.objects + + + CF$UID + 119 + + + CF$UID + 120 + + + + Editor + Target + Xcode3InfoEditor + libkqueue + + $classes + + Xcode3ProjectDocumentLocation + DVTDocumentLocation + NSObject + + $classname + Xcode3ProjectDocumentLocation + + + $class + + CF$UID + 43 + + NS.keys + + NS.objects + + + libkqueue + Xcode.Xcode3ProjectSupport.EditorDocument.Xcode3Project + + $class + + CF$UID + 127 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 126 + + + file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue.xcodeproj/ + + $classes + + NSURL + NSObject + + $classname + NSURL + + + $class + + CF$UID + 90 + + NS.objects + + + CF$UID + 129 + + + + {{0, 0}, {1140, 876}} + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 45 + + + NS.objects + + + CF$UID + 131 + + + + + $class + + CF$UID + 56 + + NS.objects + + + CF$UID + 132 + + + CF$UID + 135 + + + + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 48 + + + CF$UID + 49 + + + NS.objects + + + CF$UID + 133 + + + CF$UID + 134 + + + + IDEEditor + 203 + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 48 + + + CF$UID + 49 + + + NS.objects + + + CF$UID + 136 + + + CF$UID + 137 + + + + IDEDebuggerArea + 115 + + $class + + CF$UID + 43 + + NS.keys + + NS.objects + + + + $class + + CF$UID + 149 + + geniusEditorContextNode + + CF$UID + 0 + + primaryEditorContextNode + + CF$UID + 140 + + rootLayoutTreeNode + + CF$UID + 146 + + + + $class + + CF$UID + 148 + + children + + CF$UID + 0 + + contentType + 1 + documentArchivableRepresentation + + CF$UID + 141 + + orientation + 0 + parent + + CF$UID + 146 + + + + $class + + CF$UID + 96 + + DocumentLocation + + CF$UID + 92 + + DomainIdentifier + + CF$UID + 85 + + IdentifierPath + + CF$UID + 142 + + IndexOfDocumentIdentifier + + CF$UID + 145 + + + + $class + + CF$UID + 90 + + NS.objects + + + CF$UID + 143 + + + + + $class + + CF$UID + 89 + + Identifier + + CF$UID + 144 + + + libkqueue + 9223372036854775807 + + $class + + CF$UID + 148 + + children + + CF$UID + 147 + + contentType + 0 + documentArchivableRepresentation + + CF$UID + 0 + + orientation + 0 + parent + + CF$UID + 0 + + + + $class + + CF$UID + 90 + + NS.objects + + + CF$UID + 140 + + + + + $classes + + IDEWorkspaceTabControllerLayoutTreeNode + NSObject + + $classname + IDEWorkspaceTabControllerLayoutTreeNode + + + $classes + + IDEWorkspaceTabControllerLayoutTree + NSObject + + $classname + IDEWorkspaceTabControllerLayoutTree + + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 45 + + + NS.objects + + + CF$UID + 151 + + + + + $class + + CF$UID + 56 + + NS.objects + + + CF$UID + 152 + + + CF$UID + 154 + + + + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 48 + + + CF$UID + 49 + + + NS.objects + + + CF$UID + 107 + + + CF$UID + 153 + + + + 652 + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 48 + + + CF$UID + 49 + + + NS.objects + + + CF$UID + 107 + + + CF$UID + 155 + + + + 224 + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 157 + + + CF$UID + 158 + + + NS.objects + + + CF$UID + 158 + + + CF$UID + 159 + + + + SelectedNavigator + Xcode.IDEKit.Navigator.Structure + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 160 + + + CF$UID + 161 + + + CF$UID + 162 + + + CF$UID + 163 + + + CF$UID + 164 + + + CF$UID + 165 + + + CF$UID + 166 + + + NS.objects + + + CF$UID + 167 + + + CF$UID + 31 + + + CF$UID + 168 + + + CF$UID + 31 + + + CF$UID + 31 + + + CF$UID + 170 + + + CF$UID + 173 + + + + IDEVisibleRect + IDEUnsavedDocumentFilteringEnabled + IDENavigatorExpandedItemsBeforeFilteringSet + IDERecentDocumentFilteringEnabled + IDESCMStatusFilteringEnabled + IDESelectedObjects + IDEExpandedItemsSet + {{0, 0}, {259, 832}} + + $class + + CF$UID + 169 + + NS.objects + + + + $classes + + NSSet + NSObject + + $classname + NSSet + + + $class + + CF$UID + 90 + + NS.objects + + + CF$UID + 171 + + + + + $class + + CF$UID + 56 + + NS.objects + + + CF$UID + 172 + + + + libkqueue + + $class + + CF$UID + 169 + + NS.objects + + + CF$UID + 174 + + + CF$UID + 175 + + + CF$UID + 177 + + + CF$UID + 179 + + + CF$UID + 181 + + + CF$UID + 183 + + + + + $class + + CF$UID + 56 + + NS.objects + + + CF$UID + 172 + + + + + $class + + CF$UID + 56 + + NS.objects + + + CF$UID + 172 + + + CF$UID + 176 + + + + windows + + $class + + CF$UID + 56 + + NS.objects + + + CF$UID + 172 + + + CF$UID + 178 + + + + solaris + + $class + + CF$UID + 56 + + NS.objects + + + CF$UID + 172 + + + CF$UID + 180 + + + + common + + $class + + CF$UID + 56 + + NS.objects + + + CF$UID + 172 + + + CF$UID + 182 + + + + posix + + $class + + CF$UID + 56 + + NS.objects + + + CF$UID + 172 + + + CF$UID + 184 + + + + linux + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 45 + + + NS.objects + + + CF$UID + 186 + + + + + $class + + CF$UID + 56 + + NS.objects + + + CF$UID + 187 + + + CF$UID + 189 + + + CF$UID + 191 + + + + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 48 + + + CF$UID + 49 + + + NS.objects + + + CF$UID + 16 + + + CF$UID + 188 + + + + 260 + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 48 + + + CF$UID + 49 + + + NS.objects + + + CF$UID + 14 + + + CF$UID + 190 + + + + 1140 + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 48 + + + CF$UID + 49 + + + NS.objects + + + CF$UID + 192 + + + CF$UID + 193 + + + + IDEUtilitiesArea + 260 + + $class + + CF$UID + 90 + + NS.objects + + + CF$UID + 5 + + + + {{424, 161}, {1400, 952}} + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 197 + + + CF$UID + 198 + + + CF$UID + 199 + + + CF$UID + 200 + + + CF$UID + 201 + + + CF$UID + 202 + + + CF$UID + 203 + + + CF$UID + 204 + + + CF$UID + 205 + + + NS.objects + + + CF$UID + 31 + + + CF$UID + 206 + + + CF$UID + 42 + + + CF$UID + 255 + + + CF$UID + 258 + + + CF$UID + 263 + + + CF$UID + 264 + + + CF$UID + 31 + + + CF$UID + 31 + + + + BreakpointsActivated + DefaultEditorStatesForURLs + DebuggingWindowBehavior + ActiveScheme + ActiveRunDestination + DocumentWindows + RecentEditorDocumentURLs + AppFocusInMiniDebugging + MiniDebuggingConsole + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 207 + + + NS.objects + + + CF$UID + 208 + + + + Xcode.Xcode3ProjectSupport.EditorDocument.Xcode3Project + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 209 + + + CF$UID + 211 + + + NS.objects + + + CF$UID + 213 + + + CF$UID + 240 + + + + + $class + + CF$UID + 127 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 210 + + + + $class + + CF$UID + 94 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue/libkqueue.xcodeproj + + + $class + + CF$UID + 127 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 212 + + + + $class + + CF$UID + 94 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue.xcodeproj/ + + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 214 + + + CF$UID + 215 + + + CF$UID + 216 + + + CF$UID + 217 + + + CF$UID + 218 + + + NS.objects + + + CF$UID + 219 + + + CF$UID + 220 + + + CF$UID + 230 + + + CF$UID + 231 + + + CF$UID + 239 + + + + Xcode3ProjectEditorPreviousProjectEditorClass + Xcode3ProjectEditor.sourceList.splitview + Xcode3ProjectEditorPreviousTargetEditorClass + Xcode3ProjectEditorSelectedDocumentLocations + Xcode3ProjectEditor_Xcode3InfoEditor + Xcode3ProjectInfoEditor + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 221 + + + NS.objects + + + CF$UID + 222 + + + + DVTSplitViewItems + + $class + + CF$UID + 56 + + NS.objects + + + CF$UID + 223 + + + CF$UID + 228 + + + + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 224 + + + CF$UID + 225 + + + NS.objects + + + CF$UID + 226 + + + CF$UID + 227 + + + + DVTIdentifier + DVTViewMagnitude + + 162 + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 224 + + + CF$UID + 225 + + + NS.objects + + + CF$UID + 226 + + + CF$UID + 229 + + + + 978 + Xcode3InfoEditor + + $class + + CF$UID + 90 + + NS.objects + + + CF$UID + 232 + + + + + $class + + CF$UID + 121 + + documentURL + + CF$UID + 233 + + selection + + CF$UID + 235 + + timestamp + + CF$UID + 234 + + + file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue/libkqueue.xcodeproj/ + 320748102.08692503 + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 236 + + + CF$UID + 237 + + + NS.objects + + + CF$UID + 230 + + + CF$UID + 238 + + + + Editor + Target + libkqueue + + $class + + CF$UID + 43 + + NS.keys + + NS.objects + + + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 98 + + + CF$UID + 99 + + + CF$UID + 100 + + + CF$UID + 101 + + + CF$UID + 102 + + + NS.objects + + + CF$UID + 241 + + + CF$UID + 242 + + + CF$UID + 248 + + + CF$UID + 249 + + + CF$UID + 254 + + + + Xcode3ProjectInfoEditor + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 45 + + + NS.objects + + + CF$UID + 243 + + + + + $class + + CF$UID + 56 + + NS.objects + + + CF$UID + 244 + + + CF$UID + 246 + + + + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 48 + + + CF$UID + 49 + + + NS.objects + + + CF$UID + 107 + + + CF$UID + 245 + + + + 170 + + $class + + CF$UID + 52 + + NS.keys + + + CF$UID + 48 + + + CF$UID + 49 + + + NS.objects + + + CF$UID + 107 + + + CF$UID + 247 + + + + 970 + Xcode3InfoEditor + + $class + + CF$UID + 90 + + NS.objects + + + CF$UID + 250 + + + + + $class + + CF$UID + 121 + + documentURL + + CF$UID + 114 + + selection + + CF$UID + 252 + + timestamp + + CF$UID + 251 + + + 320748289.81788599 + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 117 + + + CF$UID + 118 + + + NS.objects + + + CF$UID + 253 + + + CF$UID + 120 + + + + Xcode3InfoEditor + + $class + + CF$UID + 43 + + NS.keys + + NS.objects + + + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 256 + + + NS.objects + + + CF$UID + 257 + + + + IDENameString + libkqueue + + $class + + CF$UID + 43 + + NS.keys + + + CF$UID + 259 + + + CF$UID + 260 + + + NS.objects + + + CF$UID + 261 + + + CF$UID + 262 + + + + IDEDeviceLocation + IDEDeviceArchitecture + dvtdevice-local-computer:localhost + x86_64 + + $class + + CF$UID + 56 + + NS.objects + + + CF$UID + 2 + + + + + $class + + CF$UID + 56 + + NS.objects + + + CF$UID + 265 + + + + + $class + + CF$UID + 127 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 114 + + + + $top + + State + + CF$UID + 1 + + + $version + 100000 + + diff --git a/vendor/libkqueue/libkqueue.xcodeproj/xcuserdata/jocke.xcuserdatad/xcschemes/libkqueue.xcscheme b/vendor/libkqueue/libkqueue.xcodeproj/xcuserdata/jocke.xcuserdatad/xcschemes/libkqueue.xcscheme new file mode 100644 index 000000000..36d8fdcff --- /dev/null +++ b/vendor/libkqueue/libkqueue.xcodeproj/xcuserdata/jocke.xcuserdatad/xcschemes/libkqueue.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/libkqueue/libkqueue.xcodeproj/xcuserdata/jocke.xcuserdatad/xcschemes/xcschememanagement.plist b/vendor/libkqueue/libkqueue.xcodeproj/xcuserdata/jocke.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 000000000..573d47860 --- /dev/null +++ b/vendor/libkqueue/libkqueue.xcodeproj/xcuserdata/jocke.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + libkqueue.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 85F0622E131E3A3D0013C05E + + primary + + + + + From 06a1c0d2d926a9f951a9d5701dcef6d4a35d6fd0 Mon Sep 17 00:00:00 2001 From: jocke Date: Wed, 2 Mar 2011 10:37:08 +0000 Subject: [PATCH 0421/1120] Properly return number of available from fd on Solaris in evfilt_socket_copyout. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@445 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/socket.c | 41 ++++++++++----------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/vendor/libkqueue/src/solaris/socket.c b/vendor/libkqueue/src/solaris/socket.c index 5a20da2a0..3b6095676 100644 --- a/vendor/libkqueue/src/solaris/socket.c +++ b/vendor/libkqueue/src/solaris/socket.c @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -105,39 +106,27 @@ evfilt_socket_copyout(struct kevent *dst, struct knote *src, void *ptr) dst->flags |= EV_EOF; else if (pe->portev_events & POLLERR) dst->fflags = 1; /* FIXME: Return the actual socket error */ - - if (pe->portev_events & POLLIN) { - if (src->flags & KNFL_PASSIVE_SOCKET) { - /* On return, data contains the length of the - socket backlog. This is not available under Solaris (?). - */ - dst->data = 1; - } else { - /* On return, data contains the number of bytes of protocol - data available to read. - */ -#if FIXME - if (ioctl(dst->ident, - (dst->filter == EVFILT_READ) ? SIOCINQ : SIOCOUTQ, - &dst->data) < 0) { - /* race condition with socket close, so ignore this error */ - dbg_puts("ioctl(2) of socket failed"); - dst->data = 0; - } -#else - /* Workaround */ - dst->data = 1; -#endif - } - } + if (pe->portev_events & POLLIN) + { + /* On return, data contains the number of bytes of protocol + data available to read / the length of the socket backlog. */ + + if (ioctl(pe->portev_object, FIONREAD, &dst->data) < 0) + { + /* race condition with socket close, so ignore this error */ + dbg_puts("ioctl(2) of socket failed"); + dst->data = 0; + } + } + /* FIXME: make sure this is in kqops.copyout() if (src->kev.flags & EV_DISPATCH || src->kev.flags & EV_ONESHOT) { socket_knote_delete(filt->kf_kqueue->kq_port, kn->kev.ident); } */ - return (1); + return (0); } const struct filter evfilt_read = { From 1a8b9590e7870a795938aa999847465d23abf632 Mon Sep 17 00:00:00 2001 From: jocke Date: Wed, 2 Mar 2011 13:20:59 +0000 Subject: [PATCH 0422/1120] Use same formatting for dbg_perror as for the other dbg_xxx functions. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@446 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index f840db92f..aa1ed1763 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -62,7 +62,7 @@ extern int KQUEUE_DEBUG; #define dbg_perror(str) do { \ if (KQUEUE_DEBUG) \ - fprintf(stderr, "KQ: [%d] %s(): %s: %s (errno=%d)\n", \ + fprintf(stderr, "KQ [%d]: %s(): %s: %s (errno=%d)\n", \ THREAD_ID, __func__, str, strerror(errno), errno); \ } while (0) From 5743c61a160fe56e072335e8bb1af4c20f5a0cc2 Mon Sep 17 00:00:00 2001 From: jocke Date: Wed, 2 Mar 2011 13:22:39 +0000 Subject: [PATCH 0423/1120] Additional debug for port_associate. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@447 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/socket.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/solaris/socket.c b/vendor/libkqueue/src/solaris/socket.c index 3b6095676..5b6533aee 100644 --- a/vendor/libkqueue/src/solaris/socket.c +++ b/vendor/libkqueue/src/solaris/socket.c @@ -47,6 +47,8 @@ evfilt_socket_knote_create(struct filter *filt, struct knote *kn) dbg_puts("invalid filter"); return (-1); } + + dbg_printf("port_associate kq fd %d with actual fd %ld", filter_epfd(filt), kn->kev.ident); rv = port_associate(filter_epfd(filt), PORT_SOURCE_FD, kn->kev.ident, events, kn); @@ -100,7 +102,8 @@ int evfilt_socket_copyout(struct kevent *dst, struct knote *src, void *ptr) { port_event_t *pe = (port_event_t *) ptr; - + unsigned int pending_data = 0; + memcpy(dst, &src->kev, sizeof(*dst)); if (pe->portev_events == 8) //XXX-FIXME Should be POLLHUP) dst->flags |= EV_EOF; @@ -112,12 +115,14 @@ evfilt_socket_copyout(struct kevent *dst, struct knote *src, void *ptr) /* On return, data contains the number of bytes of protocol data available to read / the length of the socket backlog. */ - if (ioctl(pe->portev_object, FIONREAD, &dst->data) < 0) + if (ioctl(pe->portev_object, FIONREAD, &pending_data) < 0) { /* race condition with socket close, so ignore this error */ dbg_puts("ioctl(2) of socket failed"); dst->data = 0; } + else + dst->data = pending_data; } /* FIXME: make sure this is in kqops.copyout() From b07571965eead96e22f1244b02eda2bb48c816c4 Mon Sep 17 00:00:00 2001 From: jocke Date: Wed, 2 Mar 2011 16:31:21 +0000 Subject: [PATCH 0424/1120] Temporarily disable alloc cache, as it is not threadsafe unless each thread has called mem_init(), which is hard to ensure. The problem is that a different thread may call knote_free() which never before called mem_init(), and then we make libdispatch crash in its internals... Will try to stabilize all libdispatch tests before trying to reenable this... git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@448 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/knote.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index f34fb8917..6420af11e 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -26,7 +26,8 @@ static void knote_free(struct filter *, struct knote *); int knote_init(void) { - return (mem_init(sizeof(struct knote), 1024)); + return 0; +// return (mem_init(sizeof(struct knote), 1024)); } static int @@ -40,7 +41,8 @@ RB_GENERATE(knt, knote, kntree_ent, knote_cmp) struct knote * knote_new(void) { - return (mem_calloc()); + return calloc(1, sizeof(struct knote)); +// return (mem_calloc()); } static inline void @@ -78,7 +80,8 @@ knote_free(struct filter *filt, struct knote *kn) { RB_REMOVE(knt, &filt->kf_knote, kn); filt->kn_delete(filt, kn); - mem_free(kn); + free(kn); +// mem_free(kn); } /* XXX-FIXME this is broken and should be removed */ From 58ab1d9fc3fb54e94532b27b9afd85d866af6199 Mon Sep 17 00:00:00 2001 From: jocke Date: Thu, 3 Mar 2011 07:05:01 +0000 Subject: [PATCH 0425/1120] Make sure that EV_RECEIPT events also calls kn_modify(), as we may get NOTE_TRIGGER updates there that needs to trigger e.g. timers. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@449 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kevent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 94a0eea00..cc7bb36ef 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -180,7 +180,7 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) kn->kev.flags &= ~EV_DISABLE; rv = filt->kn_enable(filt, kn); dbg_printf("kn_enable returned %d", rv); - } else if (src->flags & EV_ADD || src->flags == 0) { + } else if (src->flags & EV_ADD || src->flags == 0 || src->flags & EV_RECEIPT) { kn->kev.udata = src->udata; rv = filt->kn_modify(filt, kn, src); dbg_printf("kn_modify returned %d", rv); From b93fc0dbb0a3aa783f329ca1c696b29ae2db20a3 Mon Sep 17 00:00:00 2001 From: jocke Date: Thu, 3 Mar 2011 13:41:32 +0000 Subject: [PATCH 0426/1120] Remove superfluous newline in debug git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@450 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index ff3007c27..9c20804fe 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -103,7 +103,7 @@ port_event_dump(port_event_t *evt) PE_DUMP(PORT_SOURCE_TIMER); PE_DUMP(PORT_SOURCE_USER); PE_DUMP(PORT_SOURCE_ALERT); - strcat(&buf[0], ") }\n"); + strcat(&buf[0], ") }"); #undef PE_DUMP out: From a712193d313fdfc3e502029dce1cc6b34813c0df Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 7 Mar 2011 04:24:03 +0000 Subject: [PATCH 0427/1120] Fix a build failure on Linux git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@451 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/posix/platform.h | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 17e9ae1d0..c95502c67 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include From b722e1e2d0fc6c0451557dc4e97796fc65e84390 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 7 Mar 2011 04:46:46 +0000 Subject: [PATCH 0428/1120] Move all debugging macros to a single debug.h header to allow them to be reused in other projects git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@452 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/config.inc | 2 +- vendor/libkqueue/src/common/debug.h | 76 +++++++++++++++++++++++++ vendor/libkqueue/src/common/kevent.c | 4 +- vendor/libkqueue/src/common/kqueue.c | 9 +-- vendor/libkqueue/src/common/private.h | 36 +----------- vendor/libkqueue/src/linux/platform.h | 1 - vendor/libkqueue/src/solaris/platform.h | 2 - vendor/libkqueue/src/windows/platform.h | 13 ----- 8 files changed, 85 insertions(+), 58 deletions(-) create mode 100644 vendor/libkqueue/src/common/debug.h diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index 14fddb8fc..860489553 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -8,7 +8,7 @@ ldflags="" sources="src/common/filter.c src/common/knote.c src/common/map.c src/common/kevent.c src/common/kqueue.c" libdepends="" -deps="src/common/private.h" +deps="src/common/private.h src/common/debug.h" mans="kqueue.2" headers="src/common/private.h" extra_dist="*.in" diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h new file mode 100644 index 000000000..00db529af --- /dev/null +++ b/vendor/libkqueue/src/common/debug.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _DEBUG_H +#define _DEBUG_H + +#include + +extern int DEBUG; +extern char *DEBUG_IDENT; + +#if defined(__linux__) +# define THREAD_ID ((pid_t) syscall(__NR_gettid)) +#elif defined(__sun) +# define THREAD_ID (pthread_self()) +#elif defined(_WIN32) +# define THREAD_ID (GetCurrentThreadId()) +#else +# error Unsupported platform +#endif + + +#ifndef NDEBUG +#define dbg_puts(str) do { \ + if (DEBUG) \ + fprintf(stderr, "%s [%d]: %s(): %s\n", \ + DEBUG_IDENT, THREAD_ID, __func__, str); \ +} while (0) + +#define dbg_printf(fmt,...) do { \ + if (DEBUG) \ + fprintf(stderr, "%s [%d]: %s(): "fmt"\n", \ + DEBUG_IDENT, THREAD_ID, __func__, __VA_ARGS__); \ +} while (0) + +#define dbg_perror(str) do { \ + if (DEBUG) \ + fprintf(stderr, "%s [%d]: %s(): %s: %s (errno=%d)\n", \ + DEBUG_IDENT, THREAD_ID, __func__, str, \ + strerror(errno), errno); \ +} while (0) + +# define reset_errno() do { errno = 0; } while (0) + +# if defined(_WIN32) +# define dbg_lasterror(str) do { \ + if (DEBUG) \ + fprintf(stderr, "%s: [%d] %s(): %s: (LastError=%d)\n", \ + THREAD_ID, __func__, str, GetLastError()); \ +} while (0) +# else +# define dbg_lasterror(str) ; +# endif + +#else /* NDEBUG */ +# define dbg_puts(str) ; +# define dbg_printf(fmt,...) ; +# define dbg_perror(str) ; +# define dbg_lasterror(str) ; +# define reset_errno() ; +#endif + +#endif /* ! _DEBUG_H */ diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index cc7bb36ef..2bbe6aac1 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -248,7 +248,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, return (-1); } - if (KQUEUE_DEBUG) { + if (DEBUG) { myid = atomic_inc(&_kevent_counter); dbg_printf("--- kevent %u --- (nchanges = %d, nevents = %d)", myid, nchanges, nevents); } else { @@ -289,7 +289,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, } } - if (KQUEUE_DEBUG) { + if (DEBUG) { int n; dbg_printf("(%u) returning %d events", myid, rv); diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index b802de125..e324b1533 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -24,7 +24,8 @@ #include "private.h" -int KQUEUE_DEBUG = 0; +int DEBUG = 0; +char *DEBUG_IDENT = "KQ"; static unsigned int get_fd_limit(void) @@ -45,12 +46,12 @@ int CONSTRUCTOR _libkqueue_init(void) { #ifdef NDEBUG - KQUEUE_DEBUG = 0; + DEBUG = 0; #elif _WIN32 /* Experimental port, always debug */ - KQUEUE_DEBUG = 1; + DEBUG = 1; #else - KQUEUE_DEBUG = (getenv("KQUEUE_DEBUG") == NULL) ? 0 : 1; + DEBUG = (getenv("KQUEUE_DEBUG") == NULL) ? 0 : 1; #endif kqmap = map_new(get_fd_limit()); // INT_MAX diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index aa1ed1763..49f57bea3 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -45,41 +45,7 @@ struct evfilt_data; # error Unknown platform #endif -#include - -extern int KQUEUE_DEBUG; - -#ifndef NDEBUG -#define dbg_puts(str) do { \ - if (KQUEUE_DEBUG) \ - fprintf(stderr, "KQ [%d]: %s(): %s\n", THREAD_ID, __func__,str); \ -} while (0) - -#define dbg_printf(fmt,...) do { \ - if (KQUEUE_DEBUG) \ - fprintf(stderr, "KQ [%d]: %s(): "fmt"\n", THREAD_ID, __func__,__VA_ARGS__); \ -} while (0) - -#define dbg_perror(str) do { \ - if (KQUEUE_DEBUG) \ - fprintf(stderr, "KQ [%d]: %s(): %s: %s (errno=%d)\n", \ - THREAD_ID, __func__, str, strerror(errno), errno); \ -} while (0) - -# define reset_errno() do { errno = 0; } while (0) - -#else /* NDEBUG */ -# define dbg_puts(str) ; -# define dbg_printf(fmt,...) ; -# define dbg_perror(str) ; -# define reset_errno() ; -#endif - - /* The event_buf structure is only needed by Solaris */ - struct DEADWOOD_event_buf { - int unused; - }; - +#include "debug.h" /* * Flags used by knote->flags diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 585ba4ba0..d68569214 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -32,7 +32,6 @@ # include # include extern long int syscall (long int __sysno, ...); -#define THREAD_ID ((pid_t) syscall(__NR_gettid)) /* Convenience macros to access the epoll descriptor for the kqueue */ #define kqueue_epfd(kq) ((kq)->kq_id) diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index 1219c0b95..2ab7ee66e 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -19,8 +19,6 @@ #include -#define THREAD_ID (pthread_self()) - /* * Atomic operations that override the ones in posix/platform.h */ diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index f69d1808c..7af77394e 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -37,18 +37,6 @@ #include "../../include/sys/event.h" -/* - * Debugging macros - */ -#ifndef NDEBUG -#define dbg_lasterror(str) do { \ - if (KQUEUE_DEBUG) \ - fprintf(stderr, "KQ: [%d] %s(): %s: (LastError=%d)\n", \ - THREAD_ID, __func__, str, GetLastError()); \ -} while (0) - -#endif - /* * Atomic integer operations */ @@ -110,7 +98,6 @@ typedef int pthread_t; typedef int sigset_t; typedef int pid_t; -#define THREAD_ID (GetCurrentThreadId()) #define __thread __declspec(thread) /* Emulation of pthreads mutex functionality */ From 479a42a7a89a2e4bc134602e082f62b583fe969e Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 12 Mar 2011 17:01:51 +0000 Subject: [PATCH 0429/1120] Document a Linux bug git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@454 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/BUGS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vendor/libkqueue/BUGS b/vendor/libkqueue/BUGS index d3144435b..70a2a4e00 100644 --- a/vendor/libkqueue/BUGS +++ b/vendor/libkqueue/BUGS @@ -1 +1,5 @@ * need to uninitialize library after fork() using pthread_atfork() + + * EVFILT_READ and EVFILT_WRITE hang on Linux when used with regular files. + This is because epoll does not work with regular files. + From 8f04eb426092d93b0e8abbaf2d8306c3478b93d0 Mon Sep 17 00:00:00 2001 From: jocke Date: Tue, 15 Mar 2011 08:34:57 +0000 Subject: [PATCH 0430/1120] Try using port_get rather than port_getn as we seem to sometime get lost wakeups for user events, there are a few problems reported for port_getn (http://bugs.opensolaris.org/view_bug.do?bug_id=6268715, http://mail.opensolaris.org/pipermail/networking-discuss/2009-August/011979.html, ...) - will use this for stress testing and see if it fixes the problem. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@455 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/platform.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index 9c20804fe..bde5b0a9c 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -122,9 +122,10 @@ solaris_kevent_wait( reset_errno(); dbg_puts("waiting for events"); - rv = port_getn(kq->kq_id, &evbuf[0], 1, &nget, (struct timespec *) ts); - dbg_printf("rv=%d errno=%d (%s) nget=%d", - rv, errno, strerror(errno), nget); +// rv = port_getn(kq->kq_id, &evbuf[0], 1, &nget, (struct timespec *) ts); + rv = port_get(kq->kq_id, &evbuf[0], (struct timespec *) ts); + + dbg_printf("rv=%d errno=%d (%s) nget=%d", rv, errno, strerror(errno), nget); if (rv < 0) { if (errno == ETIME) { dbg_puts("no events within the given timeout"); From 4e6cd4c505fc6f87ff612286d6e4a3e4f13e7f0d Mon Sep 17 00:00:00 2001 From: jocke Date: Tue, 15 Mar 2011 09:30:39 +0000 Subject: [PATCH 0431/1120] Reverting to using port_getn, but checking nget even in case of error, as events might have been returned. See http://code.google.com/p/gdnsd/source/browse/branches/current/gdnsd/libgdnsd/libev/ev_port.c?spec=svn878&r=878 as well as related links for background... git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@456 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/platform.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index bde5b0a9c..439a88fe8 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -122,11 +122,10 @@ solaris_kevent_wait( reset_errno(); dbg_puts("waiting for events"); -// rv = port_getn(kq->kq_id, &evbuf[0], 1, &nget, (struct timespec *) ts); - rv = port_get(kq->kq_id, &evbuf[0], (struct timespec *) ts); + rv = port_getn(kq->kq_id, &evbuf[0], 1, &nget, (struct timespec *) ts); dbg_printf("rv=%d errno=%d (%s) nget=%d", rv, errno, strerror(errno), nget); - if (rv < 0) { + if ((rv < 0) && (nget < 1)) { if (errno == ETIME) { dbg_puts("no events within the given timeout"); return (0); From 84de70650e52ceafebce13c4e8c509c5c4b9104d Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 19 Mar 2011 14:11:59 +0000 Subject: [PATCH 0432/1120] Fix another 32-bit compilation issue git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@457 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/main.c | 45 ------------------------------------ 1 file changed, 45 deletions(-) diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 32c80aa58..e8078f0fd 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -57,50 +57,6 @@ test_kqueue_descriptor_is_pollable(void) close(kq); } -/* - * DEADWOOD: fails on Solaris - * Test if calling fstat() on a socketpair returns unique ino_t and dev_t - * values. This is something that kqueue_gc() relies on. - */ -void -test_fstat_on_socketpair(void) -{ -#ifdef _WIN32 - return; -#else - struct stat sb[4]; - int a[2], b[2]; - int unique = 1; - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, a) < 0) - die("socketpair"); - if (fstat(a[0], &sb[0]) < 0) - die("fstat"); - if (fstat(a[1], &sb[1]) < 0) - die("fstat"); - if (sb[0].st_ino == sb[1].st_ino) { - printf(" inodes=%zu %zu\n", sb[0].st_ino, sb[1].st_ino); - die("NO, inode numbers are not unique"); - } - close(a[0]); - close(a[1]); - if (socketpair(AF_UNIX, SOCK_STREAM, 0, b) < 0) - die("socketpair"); - if (fstat(b[0], &sb[2]) < 0) - die("fstat"); - if (fstat(b[1], &sb[3]) < 0) - die("fstat"); - if (sb[0].st_ino == sb[2].st_ino || sb[0].st_ino == sb[3].st_ino) - unique = 0; - if (sb[1].st_ino == sb[2].st_ino || sb[1].st_ino == sb[3].st_ino) - unique = 0; - printf(" inodes=%zu %zu %zu %zu\n", - sb[0].st_ino, sb[1].st_ino, sb[2].st_ino, sb[3].st_ino); - if (!unique) - die("ERROR - inode numbers are not unique"); -#endif -} - /* * Test the method for detecting when one end of a socketpair * has been closed. This technique is used in kqueue_validate() @@ -224,7 +180,6 @@ main(int argc, char **argv) testing_begin(); test(peer_close_detection); - //DEADWOOD:test(fstat_on_socketpair); test(kqueue); From 9bcb5ced22133e617135c2d294eb0a242df783c5 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 19 Mar 2011 14:28:29 +0000 Subject: [PATCH 0433/1120] WORKAROUND: signalfd(2) flags are broken on kernels older than Linux 2.6.27 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@458 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/linux/signal.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index bbe9aaaec..067cd96aa 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -55,13 +55,19 @@ signalfd_add(int epfd, int sigfd, void *ptr) static int signalfd_create(int epfd, void *ptr, int signum) { + static int flags = SFD_NONBLOCK; sigset_t sigmask; int sigfd; /* Create a signalfd */ sigemptyset(&sigmask); sigaddset(&sigmask, signum); - sigfd = signalfd(-1, &sigmask, SFD_NONBLOCK); + sigfd = signalfd(-1, &sigmask, flags); + /* WORKAROUND: Flags are broken on kernels older than Linux 2.6.27 */ + if (sigfd < 0 && errno == EINVAL && flags != 0) { + flags = 0; + sigfd = signalfd(-1, &sigmask, flags); + } if (sigfd < 0) { dbg_perror("signalfd(2)"); goto errout; From a16d9fc0d637a30651b06f187ff0fdd499d043ed Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 5 Apr 2011 21:17:21 +0000 Subject: [PATCH 0434/1120] Move knote_get_socket_type() into linux/socket.c. Partial support for EVFILT_READ with regular files. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@463 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/knote.c | 28 --------------- vendor/libkqueue/src/common/private.h | 6 ---- vendor/libkqueue/src/linux/socket.c | 50 ++++++++++++++++++++++++++- vendor/libkqueue/test/read.c | 30 ++++++++++++++++ 4 files changed, 79 insertions(+), 35 deletions(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 6420af11e..9e045ddba 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -139,34 +139,6 @@ knote_lookup_data(struct filter *filt, intptr_t data) return (kn); } -/* - * Test if a socket is active or passive. - */ -int -knote_get_socket_type(struct knote *kn) -{ - socklen_t slen; - int i, lsock; - - slen = sizeof(lsock); - lsock = 0; - i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_ACCEPTCONN, (char *) &lsock, &slen); - if (i < 0) { - switch (errno) { - case ENOTSOCK: /* same as lsock = 0 */ - return (0); - break; - default: - dbg_perror("getsockopt(3)"); - return (-1); - } - } else { - if (lsock) - kn->flags |= KNFL_PASSIVE_SOCKET; - return (0); - } -} - int knote_disable(struct filter *filt, struct knote *kn) { diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 49f57bea3..9de0f6f26 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -47,11 +47,6 @@ struct evfilt_data; #include "debug.h" -/* - * Flags used by knote->flags - */ -#define KNFL_PASSIVE_SOCKET (0x01) /* Socket is in listen(2) mode */ - struct eventfd { int ef_id; #if defined(EVENTFD_PLATFORM_SPECIFIC) @@ -164,7 +159,6 @@ struct knote * knote_new(void); void knote_release(struct filter *, struct knote *); void knote_free_all(struct filter *); void knote_insert(struct filter *, struct knote *); -int knote_get_socket_type(struct knote *); int knote_init(void); /* TODO: these deal with the eventlist, should use a different prefix */ diff --git a/vendor/libkqueue/src/linux/socket.c b/vendor/libkqueue/src/linux/socket.c index 482bc1f9e..1e2c8c6d2 100644 --- a/vendor/libkqueue/src/linux/socket.c +++ b/vendor/libkqueue/src/linux/socket.c @@ -30,6 +30,54 @@ #include "private.h" +/* + * Flags used by knote->flags + */ +#define KNFL_PASSIVE_SOCKET (0x01) /* Socket is in listen(2) mode */ +#define KNFL_REGULAR_FILE (0x02) /* File descriptor is a regular file */ + + +static int +get_descriptor_type(struct knote *kn) +{ + socklen_t slen; + struct stat sb; + int i, lsock; + + /* + * Test if the descriptor is a socket. + */ + if (fstat(kn->kev.ident, &sb) < 0) { + dbg_perror("fstat(2)"); + return (-1); + } + if (! S_ISSOCK(sb.st_mode)) { + //FIXME: could be a pipe, device file, or other non-regular file + kn->flags |= KNFL_REGULAR_FILE; + return (0); + } + + /* + * Test if the socket is active or passive. + */ + slen = sizeof(lsock); + lsock = 0; + i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_ACCEPTCONN, (char *) &lsock, &slen); + if (i < 0) { + switch (errno) { + case ENOTSOCK: /* same as lsock = 0 */ + return (0); + break; + default: + dbg_perror("getsockopt(3)"); + return (-1); + } + } else { + if (lsock) + kn->flags |= KNFL_PASSIVE_SOCKET; + return (0); + } +} static char * epoll_event_dump(struct epoll_event *evt) @@ -113,7 +161,7 @@ evfilt_socket_knote_create(struct filter *filt, struct knote *kn) { struct epoll_event ev; - if (knote_get_socket_type(kn) < 0) + if (get_descriptor_type(kn) < 0) return (-1); /* Convert the kevent into an epoll_event */ diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index db92dcf12..711bb423f 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -318,6 +318,35 @@ test_kevent_socket_eof(void) kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); } +/* Test if EVFILT_READ works with regular files */ +void +test_kevent_regular_file(void) +{ + struct kevent kev; + int fd; + + fd = open("/etc/hosts", O_RDONLY); + if (fd < 0) + abort(); + printf("regfd=%d\n", fd); + + EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, &fd); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + die("kevent"); + + //FIXME:kevent_socket_fill(); + + kev.data = 1; + kevent_cmp(&kev, kevent_get(kqfd)); + + //FIXME:kevent_socket_drain(); + test_no_kevents(kqfd); + + kev.flags = EV_DELETE; + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + die("kevent"); +} + void test_evfilt_read(int _kqfd) { @@ -342,6 +371,7 @@ test_evfilt_read(int _kqfd) #endif test(kevent_socket_listen_backlog); test(kevent_socket_eof); + test(kevent_regular_file); close(sockfd[0]); close(sockfd[1]); } From 5ae6171195881a0e0943e095a09b58eb32a314d2 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 5 Apr 2011 22:22:48 +0000 Subject: [PATCH 0435/1120] Split socket.c into two separate files: read.c and write.c. This means that EVFILT_READ and EVFILT_WRITE are now completely separate filters. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@464 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/config.inc | 1 + vendor/libkqueue/src/linux/platform.c | 82 +++++++++++ vendor/libkqueue/src/linux/platform.h | 15 ++ vendor/libkqueue/src/linux/read.c | 139 ++++++++++++++++++ .../libkqueue/src/linux/{socket.c => write.c} | 131 +---------------- vendor/libkqueue/test/read.c | 2 - 6 files changed, 245 insertions(+), 125 deletions(-) create mode 100644 vendor/libkqueue/src/linux/read.c rename vendor/libkqueue/src/linux/{socket.c => write.c} (51%) diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index 860489553..78e9b1c35 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -60,6 +60,7 @@ post_configure_hook() { if [ $target = "linux" ] ; then evfilt_user="src/linux/user.c" + evfilt_socket="src/linux/read.c src/linux/write.c" #XXX-FIXME disabled evfilt_proc="" diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 14a07532e..358281216 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -264,3 +264,85 @@ linux_eventfd_descriptor(struct eventfd *e) { return (e->ef_id); } + +int +linux_get_descriptor_type(struct knote *kn) +{ + socklen_t slen; + struct stat sb; + int i, lsock; + + /* + * Test if the descriptor is a socket. + */ + if (fstat(kn->kev.ident, &sb) < 0) { + dbg_perror("fstat(2)"); + return (-1); + } + if (! S_ISSOCK(sb.st_mode)) { + //FIXME: could be a pipe, device file, or other non-regular file + kn->flags |= KNFL_REGULAR_FILE; + return (0); + } + + /* + * Test if the socket is active or passive. + */ + slen = sizeof(lsock); + lsock = 0; + i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_ACCEPTCONN, (char *) &lsock, &slen); + if (i < 0) { + switch (errno) { + case ENOTSOCK: /* same as lsock = 0 */ + return (0); + break; + default: + dbg_perror("getsockopt(3)"); + return (-1); + } + } else { + if (lsock) + kn->flags |= KNFL_PASSIVE_SOCKET; + return (0); + } +} + +char * +epoll_event_dump(struct epoll_event *evt) +{ + static char __thread buf[128]; + + if (evt == NULL) + return "(null)"; + +#define EPEVT_DUMP(attrib) \ + if (evt->events & attrib) \ + strcat(&buf[0], #attrib" "); + + snprintf(&buf[0], 128, " { data = %p, events = ", evt->data.ptr); + EPEVT_DUMP(EPOLLIN); + EPEVT_DUMP(EPOLLOUT); +#if defined(HAVE_EPOLLRDHUP) + EPEVT_DUMP(EPOLLRDHUP); +#endif + EPEVT_DUMP(EPOLLONESHOT); + EPEVT_DUMP(EPOLLET); + strcat(&buf[0], "}\n"); + + return (&buf[0]); +#undef EPEVT_DUMP +} + +int +epoll_update(int op, struct filter *filt, struct knote *kn, struct epoll_event *ev) +{ + dbg_printf("op=%d fd=%d events=%s", op, (int)kn->kev.ident, + epoll_event_dump(ev)); + if (epoll_ctl(filter_epfd(filt), op, kn->kev.ident, ev) < 0) { + dbg_printf("epoll_ctl(2): %s", strerror(errno)); + return (-1); + } + + return (0); +} + diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index d68569214..1d0ec91ab 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -17,6 +17,8 @@ #ifndef _KQUEUE_LINUX_PLATFORM_H #define _KQUEUE_LINUX_PLATFORM_H +struct filter; + #include #include #include @@ -37,6 +39,12 @@ extern long int syscall (long int __sysno, ...); #define kqueue_epfd(kq) ((kq)->kq_id) #define filter_epfd(filt) ((filt)->kf_kqueue->kq_id) +/* + * Flags used by knote->flags + */ +#define KNFL_PASSIVE_SOCKET (0x01) /* Socket is in listen(2) mode */ +#define KNFL_REGULAR_FILE (0x02) /* File descriptor is a regular file */ + /* * Additional members of struct knote */ @@ -69,4 +77,11 @@ int linux_eventfd_raise(struct eventfd *); int linux_eventfd_lower(struct eventfd *); int linux_eventfd_descriptor(struct eventfd *); +int linux_get_descriptor_type(struct knote *); + +/* epoll-related functions */ + +int epoll_update(int, struct filter *, struct knote *, struct epoll_event *); +char * epoll_event_dump(struct epoll_event *); + #endif /* ! _KQUEUE_LINUX_PLATFORM_H */ diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c new file mode 100644 index 000000000..1153fb35f --- /dev/null +++ b/vendor/libkqueue/src/linux/read.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "private.h" + +int +evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) +{ + struct epoll_event * const ev = (struct epoll_event *) ptr; + + epoll_event_dump(ev); + memcpy(dst, &src->kev, sizeof(*dst)); +#if defined(HAVE_EPOLLRDHUP) + if (ev->events & EPOLLRDHUP || ev->events & EPOLLHUP) + dst->flags |= EV_EOF; +#else + if (ev->events & EPOLLHUP) + dst->flags |= EV_EOF; +#endif + if (ev->events & EPOLLERR) + dst->fflags = 1; /* FIXME: Return the actual socket error */ + + if (src->flags & KNFL_PASSIVE_SOCKET) { + /* On return, data contains the length of the + socket backlog. This is not available under Linux. + */ + dst->data = 1; + } else { + /* On return, data contains the number of bytes of protocol + data available to read. + */ + if (ioctl(dst->ident, SIOCINQ, &dst->data) < 0) { + /* race condition with socket close, so ignore this error */ + dbg_puts("ioctl(2) of socket failed"); + dst->data = 0; + } + } + + return (0); +} + +int +evfilt_read_knote_create(struct filter *filt, struct knote *kn) +{ + struct epoll_event ev; + + if (linux_get_descriptor_type(kn) < 0) + return (-1); + + /* Convert the kevent into an epoll_event */ +#if defined(HAVE_EPOLLRDHUP) + kn->data.events = EPOLLIN | EPOLLRDHUP; +#else + kn->data.events = EPOLLIN; +#endif + if (kn->kev.flags & EV_ONESHOT || kn->kev.flags & EV_DISPATCH) + kn->data.events |= EPOLLONESHOT; + if (kn->kev.flags & EV_CLEAR) + kn->data.events |= EPOLLET; + + memset(&ev, 0, sizeof(ev)); + ev.events = kn->data.events; + ev.data.ptr = kn; + + return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); +} + +int +evfilt_read_knote_modify(struct filter *filt, struct knote *kn, + const struct kevent *kev) +{ + return (-1); /* STUB */ +} + +int +evfilt_read_knote_delete(struct filter *filt, struct knote *kn) +{ + if (kn->kev.flags & EV_DISABLE) + return (0); + else + return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); +} + +int +evfilt_read_knote_enable(struct filter *filt, struct knote *kn) +{ + struct epoll_event ev; + + memset(&ev, 0, sizeof(ev)); + ev.events = kn->data.events; + ev.data.ptr = kn; + + return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); +} + +int +evfilt_read_knote_disable(struct filter *filt, struct knote *kn) +{ + return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); +} + +const struct filter evfilt_read = { + EVFILT_READ, + NULL, + NULL, + evfilt_read_copyout, + evfilt_read_knote_create, + evfilt_read_knote_modify, + evfilt_read_knote_delete, + evfilt_read_knote_enable, + evfilt_read_knote_disable, +}; diff --git a/vendor/libkqueue/src/linux/socket.c b/vendor/libkqueue/src/linux/write.c similarity index 51% rename from vendor/libkqueue/src/linux/socket.c rename to vendor/libkqueue/src/linux/write.c index 1e2c8c6d2..95d82dd51 100644 --- a/vendor/libkqueue/src/linux/socket.c +++ b/vendor/libkqueue/src/linux/write.c @@ -30,94 +30,6 @@ #include "private.h" -/* - * Flags used by knote->flags - */ -#define KNFL_PASSIVE_SOCKET (0x01) /* Socket is in listen(2) mode */ -#define KNFL_REGULAR_FILE (0x02) /* File descriptor is a regular file */ - - -static int -get_descriptor_type(struct knote *kn) -{ - socklen_t slen; - struct stat sb; - int i, lsock; - - /* - * Test if the descriptor is a socket. - */ - if (fstat(kn->kev.ident, &sb) < 0) { - dbg_perror("fstat(2)"); - return (-1); - } - if (! S_ISSOCK(sb.st_mode)) { - //FIXME: could be a pipe, device file, or other non-regular file - kn->flags |= KNFL_REGULAR_FILE; - return (0); - } - - /* - * Test if the socket is active or passive. - */ - slen = sizeof(lsock); - lsock = 0; - i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_ACCEPTCONN, (char *) &lsock, &slen); - if (i < 0) { - switch (errno) { - case ENOTSOCK: /* same as lsock = 0 */ - return (0); - break; - default: - dbg_perror("getsockopt(3)"); - return (-1); - } - } else { - if (lsock) - kn->flags |= KNFL_PASSIVE_SOCKET; - return (0); - } -} - -static char * -epoll_event_dump(struct epoll_event *evt) -{ - static char __thread buf[128]; - - if (evt == NULL) - return "(null)"; - -#define EPEVT_DUMP(attrib) \ - if (evt->events & attrib) \ - strcat(&buf[0], #attrib" "); - - snprintf(&buf[0], 128, " { data = %p, events = ", evt->data.ptr); - EPEVT_DUMP(EPOLLIN); - EPEVT_DUMP(EPOLLOUT); -#if defined(HAVE_EPOLLRDHUP) - EPEVT_DUMP(EPOLLRDHUP); -#endif - EPEVT_DUMP(EPOLLONESHOT); - EPEVT_DUMP(EPOLLET); - strcat(&buf[0], "}\n"); - - return (&buf[0]); -#undef EPEVT_DUMP -} - -static int -epoll_update(int op, struct filter *filt, struct knote *kn, struct epoll_event *ev) -{ - dbg_printf("op=%d fd=%d events=%s", op, (int)kn->kev.ident, - epoll_event_dump(ev)); - if (epoll_ctl(filter_epfd(filt), op, kn->kev.ident, ev) < 0) { - dbg_printf("epoll_ctl(2): %s", strerror(errno)); - return (-1); - } - - return (0); -} - int evfilt_socket_copyout(struct kevent *dst, struct knote *src, void *ptr) { @@ -135,22 +47,11 @@ evfilt_socket_copyout(struct kevent *dst, struct knote *src, void *ptr) if (ev->events & EPOLLERR) dst->fflags = 1; /* FIXME: Return the actual socket error */ - if (src->flags & KNFL_PASSIVE_SOCKET) { - /* On return, data contains the length of the - socket backlog. This is not available under Linux. - */ - dst->data = 1; - } else { - /* On return, data contains the number of bytes of protocol - data available to read. - */ - if (ioctl(dst->ident, - (dst->filter == EVFILT_READ) ? SIOCINQ : SIOCOUTQ, - &dst->data) < 0) { + /* On return, data contains the the amount of space remaining in the write buffer */ + if (ioctl(dst->ident, SIOCOUTQ, &dst->data) < 0) { /* race condition with socket close, so ignore this error */ dbg_puts("ioctl(2) of socket failed"); dst->data = 0; - } } return (0); @@ -161,18 +62,15 @@ evfilt_socket_knote_create(struct filter *filt, struct knote *kn) { struct epoll_event ev; - if (get_descriptor_type(kn) < 0) + if (linux_get_descriptor_type(kn) < 0) + return (-1); + + /* TODO: return EBADF? */ + if (kn->flags & KNFL_REGULAR_FILE) return (-1); /* Convert the kevent into an epoll_event */ - if (kn->kev.filter == EVFILT_READ) -#if defined(HAVE_EPOLLRDHUP) - kn->data.events = EPOLLIN | EPOLLRDHUP; -#else - kn->data.events = EPOLLIN; -#endif - else - kn->data.events = EPOLLOUT; + kn->data.events = EPOLLOUT; if (kn->kev.flags & EV_ONESHOT || kn->kev.flags & EV_DISPATCH) kn->data.events |= EPOLLONESHOT; if (kn->kev.flags & EV_CLEAR) @@ -219,19 +117,6 @@ evfilt_socket_knote_disable(struct filter *filt, struct knote *kn) return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); } - -const struct filter evfilt_read = { - EVFILT_READ, - NULL, - NULL, - evfilt_socket_copyout, - evfilt_socket_knote_create, - evfilt_socket_knote_modify, - evfilt_socket_knote_delete, - evfilt_socket_knote_enable, - evfilt_socket_knote_disable, -}; - const struct filter evfilt_write = { EVFILT_WRITE, NULL, diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 711bb423f..7680d6452 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -334,8 +334,6 @@ test_kevent_regular_file(void) if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent"); - //FIXME:kevent_socket_fill(); - kev.data = 1; kevent_cmp(&kev, kevent_get(kqfd)); From 7d3f1d336a02a352d9aea4db876e73213ed72522 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 6 Apr 2011 01:51:39 +0000 Subject: [PATCH 0436/1120] Disable debugging if KQUEUE_DEBUG is an empty string git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@465 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kqueue.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index e324b1533..be6b91f4e 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -51,7 +51,9 @@ _libkqueue_init(void) /* Experimental port, always debug */ DEBUG = 1; #else - DEBUG = (getenv("KQUEUE_DEBUG") == NULL) ? 0 : 1; + char *s = getenv("KQUEUE_DEBUG"); + if (s != NULL && strlen(s) > 0) + DEBUG = 1; #endif kqmap = map_new(get_fd_limit()); // INT_MAX From 0b8dfd2d88cfb0e02c1fab4bc7fe856162ea9e27 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 6 Apr 2011 02:49:48 +0000 Subject: [PATCH 0437/1120] Support regular files with EVFILT_READ, fixes the dispatch_read test in libdispatch git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@466 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/BUGS | 4 - vendor/libkqueue/src/linux/platform.c | 30 ++++++- vendor/libkqueue/src/linux/platform.h | 9 ++ vendor/libkqueue/src/linux/read.c | 123 +++++++++++++++++++++++++- vendor/libkqueue/src/linux/vnode.c | 14 +-- vendor/libkqueue/test/read.c | 23 ++++- 6 files changed, 176 insertions(+), 27 deletions(-) diff --git a/vendor/libkqueue/BUGS b/vendor/libkqueue/BUGS index 70a2a4e00..d3144435b 100644 --- a/vendor/libkqueue/BUGS +++ b/vendor/libkqueue/BUGS @@ -1,5 +1 @@ * need to uninitialize library after fork() using pthread_atfork() - - * EVFILT_READ and EVFILT_WRITE hang on Linux when used with regular files. - This is because epoll does not work with regular files. - diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 358281216..b21114d04 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -150,8 +150,9 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct epoll_event *ev; struct filter *filt; struct knote *kn; - int i, rv; + int i, nret, rv; + nret = nready; for (i = 0; i < nready; i++) { ev = &epevt[i]; kn = (struct knote *) ev->data.ptr; @@ -174,10 +175,17 @@ linux_kevent_copyout(struct kqueue *kq, int nready, if (eventlist->flags & EV_ONESHOT) knote_release(filt, kn); //TODO: Error checking - eventlist++; + /* If an empty kevent structure is returned, the event is discarded. */ + /* TODO: add these semantics to windows + solaris platform.c */ + if (fastpath(eventlist->filter != 0)) { + eventlist++; + } else { + dbg_puts("spurious wakeup, discarding event"); + nret--; + } } - return (i); + return (nret); } int @@ -282,6 +290,7 @@ linux_get_descriptor_type(struct knote *kn) if (! S_ISSOCK(sb.st_mode)) { //FIXME: could be a pipe, device file, or other non-regular file kn->flags |= KNFL_REGULAR_FILE; + dbg_printf("fd %d is a regular file\n", (int)kn->kev.ident); return (0); } @@ -346,3 +355,18 @@ epoll_update(int op, struct filter *filt, struct knote *kn, struct epoll_event * return (0); } +/* + * Given a file descriptor, return the path to the file it refers to. + */ +int +linux_fd_to_path(char *buf, size_t bufsz, int fd) +{ + char path[1024]; //TODO: Maxpathlen, etc. + + if (snprintf(&path[0], sizeof(path), "/proc/%d/fd/%d", getpid(), fd) < 0) + return (-1); + + memset(buf, 0, bufsz); + return (readlink(path, buf, bufsz)); +} + diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 1d0ec91ab..c567bd289 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -44,11 +44,17 @@ extern long int syscall (long int __sysno, ...); */ #define KNFL_PASSIVE_SOCKET (0x01) /* Socket is in listen(2) mode */ #define KNFL_REGULAR_FILE (0x02) /* File descriptor is a regular file */ + +/* + * Additional members of struct filter + */ +#undef FILTER_PLATFORM_SPECIFIC /* * Additional members of struct knote */ #define KNOTE_PLATFORM_SPECIFIC \ + int kn_epollfd; /* A copy of filter->epfd */ \ union { \ int kn_timerfd; \ int kn_signalfd; \ @@ -77,7 +83,10 @@ int linux_eventfd_raise(struct eventfd *); int linux_eventfd_lower(struct eventfd *); int linux_eventfd_descriptor(struct eventfd *); +/* utility functions */ + int linux_get_descriptor_type(struct knote *); +int linux_fd_to_path(char *, size_t, int); /* epoll-related functions */ diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index 1153fb35f..4ab12a586 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -30,11 +30,79 @@ #include "private.h" +/* + * Return the offset from the current position to end of file. + */ +static intptr_t +get_eof_offset(int fd) +{ + off_t curpos; + struct stat sb; + + curpos = lseek(fd, 0, SEEK_CUR); + if (curpos == (off_t) -1) { + dbg_perror("lseek(2)"); + curpos = 0; + } + if (fstat(fd, &sb) < 0) { + dbg_perror("fstat(2)"); + sb.st_size = 1; + } + + dbg_printf("curpos=%zu size=%zu\n", curpos, sb.st_size); + return (sb.st_size - curpos); //FIXME: can overflow +} + int evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) { struct epoll_event * const ev = (struct epoll_event *) ptr; + /* Special case: for regular files, return the offset from current position to end of file */ + if (src->flags & KNFL_REGULAR_FILE) { + memcpy(dst, &src->kev, sizeof(*dst)); + dst->data = get_eof_offset(src->kev.ident); + + if (dst->data == 0) { + dst->filter = 0; /* Will cause the kevent to be discarded */ + if (epoll_ctl(src->kn_epollfd, EPOLL_CTL_DEL, src->kdata.kn_eventfd, NULL) < 0) { + dbg_perror("epoll_ctl(2)"); + return (-1); + } + +#if FIXME + /* XXX-FIXME Switch to using kn_inotifyfd to monitor for IN_ATTRIB events + that may signify the file size has changed. + + This code is not tested. + */ + int inofd; + char path[PATH_MAX]; + + inofd = inotify_init(); + if (inofd < 0) { + dbg_perror("inotify_init(2)"); + (void) close(inofd); + return (-1); + } + src->kdata.kn_inotifyfd = inofd; + if (linux_fd_to_path(&path[0], sizeof(path), src->kev.ident) < 0) + return (-1); + if (inotify_add_watch(inofd, path, IN_ATTRIB) < 0) { + dbg_perror("inotify_add_watch"); + return (-1); + } + if (epoll_ctl(src->kn_epollfd, EPOLL_CTL_ADD, src->kdata.kn_inotifyfd, NULL) < 0) { + dbg_perror("epoll_ctl(2)"); + return (-1); + } + /* FIXME: race here, should we check the EOF status again ? */ +#endif + } + + return (0); + } + epoll_event_dump(ev); memcpy(dst, &src->kev, sizeof(*dst)); #if defined(HAVE_EPOLLRDHUP) @@ -89,6 +157,30 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) ev.events = kn->data.events; ev.data.ptr = kn; + /* Special case: for regular files, add a surrogate eventfd that is always readable */ + if (kn->flags & KNFL_REGULAR_FILE) { + int evfd; + + kn->kn_epollfd = filter_epfd(filt); + evfd = eventfd(0, 0); + if (evfd < 0) { + dbg_perror("eventfd(2)"); + return (-1); + } + if (eventfd_write(evfd, 1) < 0) { + dbg_perror("eventfd_write(3)"); + (void) close(evfd); + return (-1); + } + kn->kdata.kn_eventfd = evfd; + + if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_eventfd, &ev) < 0) { + dbg_printf("epoll_ctl(2): %s", strerror(errno)); + return (-1); + } + return (0); + } + return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); } @@ -104,8 +196,17 @@ evfilt_read_knote_delete(struct filter *filt, struct knote *kn) { if (kn->kev.flags & EV_DISABLE) return (0); - else + + if ((kn->flags & KNFL_REGULAR_FILE && kn->kdata.kn_eventfd != -1) < 0) { + if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kdata.kn_eventfd, NULL) < 0) { + dbg_perror("epoll_ctl(2)"); + return (-1); + } + (void) close(kn->kdata.kn_eventfd); + kn->kdata.kn_eventfd = -1; + } else { return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); + } } int @@ -117,13 +218,29 @@ evfilt_read_knote_enable(struct filter *filt, struct knote *kn) ev.events = kn->data.events; ev.data.ptr = kn; - return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); + if (kn->flags & KNFL_REGULAR_FILE) { + if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_eventfd, &ev) < 0) { + dbg_perror("epoll_ctl(2)"); + return (-1); + } + return (0); + } else { + return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); + } } int evfilt_read_knote_disable(struct filter *filt, struct knote *kn) { - return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); + if (kn->flags & KNFL_REGULAR_FILE) { + if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kdata.kn_eventfd, NULL) < 0) { + dbg_perror("epoll_ctl(2)"); + return (-1); + } + return (0); + } else { + return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); + } } const struct filter evfilt_read = { diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index ebde155a4..70f5d0a83 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -55,18 +55,6 @@ inotify_event_dump(struct inotify_event *evt) return (buf); } -static int -fd_to_path(char *buf, size_t bufsz, int fd) -{ - char path[1024]; //TODO: Maxpathlen, etc. - - if (snprintf(&path[0], sizeof(path), "/proc/%d/fd/%d", getpid(), fd) < 0) - return (-1); - - memset(buf, 0, bufsz); - return (readlink(path, buf, bufsz)); -} - /* TODO: USE this to get events with name field */ int @@ -105,7 +93,7 @@ add_watch(struct filter *filt, struct knote *kn) uint32_t mask; /* Convert the fd to a pathname */ - if (fd_to_path(&path[0], sizeof(path), kn->kev.ident) < 0) + if (linux_fd_to_path(&path[0], sizeof(path), kn->kev.ident) < 0) return (-1); /* Convert the fflags to the inotify mask */ diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 7680d6452..0ff3cf1ac 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -323,26 +323,41 @@ void test_kevent_regular_file(void) { struct kevent kev; + struct kevent *kev2; + off_t curpos; int fd; fd = open("/etc/hosts", O_RDONLY); if (fd < 0) abort(); - printf("regfd=%d\n", fd); EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, &fd); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent"); - kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); + kev2 = kevent_get(kqfd); + + /* Set file position to EOF-1 */ + kev2->data--; + if ((curpos = lseek(fd, kev2->data, SEEK_SET)) != kev2->data) { + printf("seek to %zu failed with rv=%zu\n", kev2->data, curpos); + abort(); + } + + /* Set file position to EOF */ + (void) kevent_get(kqfd); + kev2->data = curpos + 1; + if ((curpos = lseek(fd, kev2->data, SEEK_SET)) != kev2->data) { + printf("seek to %zu failed with rv=%zu\n", kev2->data, curpos); + abort(); + } - //FIXME:kevent_socket_drain(); test_no_kevents(kqfd); kev.flags = EV_DELETE; if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent"); + close(fd); } void From 222b8fd155f691ad4afbb9f91a6d43b7e6ab75f9 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 9 Apr 2011 01:24:59 +0000 Subject: [PATCH 0438/1120] Add a test for high-resolution kevent() calls on Linux git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@467 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/common.h | 1 + vendor/libkqueue/test/kevent.c | 20 ++++++++++++++++++++ vendor/libkqueue/test/user.c | 20 ++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index ee80949df..720cc5854 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -72,6 +72,7 @@ void test_evfilt_user(int); extern const char * kevent_to_str(struct kevent *); struct kevent * kevent_get(int); +struct kevent * kevent_get_hires(int); void kevent_update(int kqfd, struct kevent *kev); diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index 136db7d29..616b37be3 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -50,6 +50,26 @@ kevent_get(int kqfd) return (&kev); } +/* In Linux, a kevent() call with less than 1ms resolution + will perform a pselect() call to obtain the higer resolution. + This test exercises that codepath. + */ +struct kevent * +kevent_get_hires(int kqfd) +{ + int nfds; + struct timespec timeo; + static struct kevent __thread kev; + + timeo.tv_sec = 0; + timeo.tv_nsec = 500000; + nfds = kevent(kqfd, NULL, 0, &kev, 1, &timeo); + if (nfds < 1) + die("kevent(2)"); + + return (&kev); +} + char * kevent_fflags_dump(struct kevent *kev) { diff --git a/vendor/libkqueue/test/user.c b/vendor/libkqueue/test/user.c index fc88a7831..d24e9ef6d 100644 --- a/vendor/libkqueue/test/user.c +++ b/vendor/libkqueue/test/user.c @@ -49,6 +49,25 @@ test_kevent_user_get(void) test_no_kevents(kqfd); } +static void +test_kevent_user_get_hires(void) +{ + struct kevent kev; + + test_no_kevents(kqfd); + + /* Add the event, and then trigger it */ + kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, NULL); + kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + + kev.fflags &= ~NOTE_FFCTRLMASK; + kev.fflags &= ~NOTE_TRIGGER; + kev.flags = EV_CLEAR; + kevent_cmp(&kev, kevent_get_hires(kqfd)); + + test_no_kevents(kqfd); +} + static void test_kevent_user_disable_and_enable(void) { @@ -139,6 +158,7 @@ test_evfilt_user(int _kqfd) test(kevent_user_add_and_delete); test(kevent_user_get); + test(kevent_user_get_hires); test(kevent_user_disable_and_enable); test(kevent_user_oneshot); #if HAVE_EV_DISPATCH From 1356beeb1c448022fce2d371b054d160c845696b Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 9 Apr 2011 02:55:07 +0000 Subject: [PATCH 0439/1120] Fix conditional that invokes linux_kevent_wait_hires() git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@468 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/linux/platform.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index b21114d04..e1a4396b5 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -93,7 +93,8 @@ linux_kevent_wait_hires( fd_set fds; int n; - dbg_puts("waiting for events"); + dbg_printf("waiting for events (timeout=%ld sec %ld nsec)", + timeout->tv_sec, timeout->tv_nsec); FD_ZERO(&fds); FD_SET(kqueue_epfd(kq), &fds); n = pselect(1, &fds, NULL , NULL, timeout, NULL); @@ -118,10 +119,8 @@ linux_kevent_wait( int timeout, nret; /* Use pselect() if the timeout value is less than one millisecond. */ - if (ts != NULL && ts->tv_sec == 0 && ts->tv_nsec > 1000000) { + if (ts != NULL && ts->tv_sec == 0 && ts->tv_nsec < 1000000) { nret = linux_kevent_wait_hires(kq, ts); - if (nret < 1) - return (nret); /* Otherwise, use epoll_wait() directly */ } else { From 6928a0a60a9ab99f96106a52734ef6908d397d2f Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 11 Apr 2011 03:17:37 +0000 Subject: [PATCH 0440/1120] Fix incorrect "nfds" argument supplied to pselect(2) git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@469 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/linux/platform.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index e1a4396b5..15fb92838 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -92,12 +92,14 @@ linux_kevent_wait_hires( { fd_set fds; int n; + int epfd; dbg_printf("waiting for events (timeout=%ld sec %ld nsec)", timeout->tv_sec, timeout->tv_nsec); + epfd = kqueue_epfd(kq); FD_ZERO(&fds); - FD_SET(kqueue_epfd(kq), &fds); - n = pselect(1, &fds, NULL , NULL, timeout, NULL); + FD_SET(epfd, &fds); + n = pselect(epfd + 1, &fds, NULL , NULL, timeout, NULL); if (n < 0) { if (errno == EINTR) { dbg_puts("signal caught"); From 517bbc071b4fa36a9167cb695597559d823eefc8 Mon Sep 17 00:00:00 2001 From: marius Date: Wed, 13 Apr 2011 01:14:30 +0000 Subject: [PATCH 0441/1120] Test commit as marius@ git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@470 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/BUGS | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/BUGS b/vendor/libkqueue/BUGS index d3144435b..61d5d2adb 100644 --- a/vendor/libkqueue/BUGS +++ b/vendor/libkqueue/BUGS @@ -1 +1,2 @@ * need to uninitialize library after fork() using pthread_atfork() + From 6ae1e6d5ba395b851f2b83a4a72408460d587304 Mon Sep 17 00:00:00 2001 From: marius Date: Wed, 13 Apr 2011 17:23:13 +0000 Subject: [PATCH 0442/1120] Added clean initialization and destruction to mutex used within a knote. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@471 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/knote.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 9e045ddba..e8f8746b2 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -41,8 +41,17 @@ RB_GENERATE(knt, knote, kntree_ent, knote_cmp) struct knote * knote_new(void) { - return calloc(1, sizeof(struct knote)); -// return (mem_calloc()); + // struct knote* res = return (mem_calloc()); + struct knote* res = malloc(sizeof(struct knote)); + if(!res) return NULL; + + if(pthread_mutex_init(&res->mtx, NULL)){ + dbg_perror("pthread_mutex_init"); + free(res); + return NULL; + } + + return res; } static inline void @@ -80,6 +89,7 @@ knote_free(struct filter *filt, struct knote *kn) { RB_REMOVE(knt, &filt->kf_knote, kn); filt->kn_delete(filt, kn); + pthread_mutex_destroy(&kn->mtx); free(kn); // mem_free(kn); } From e1fcd4efd0eea31359a3f81abf86775f7c0ed82d Mon Sep 17 00:00:00 2001 From: marius Date: Wed, 13 Apr 2011 17:24:19 +0000 Subject: [PATCH 0443/1120] Fixed a bug within kevent_copyin_one() causing a knote mutex to be used after releasing the knote git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@472 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kevent.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 2bbe6aac1..b207697e4 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -171,23 +171,25 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) } if (src->flags & EV_DELETE) { + knote_unlock(kn); knote_release(filt, kn); } else if (src->flags & EV_DISABLE) { kn->kev.flags |= EV_DISABLE; rv = filt->kn_disable(filt, kn); dbg_printf("kn_disable returned %d", rv); + knote_unlock(kn); } else if (src->flags & EV_ENABLE) { kn->kev.flags &= ~EV_DISABLE; rv = filt->kn_enable(filt, kn); dbg_printf("kn_enable returned %d", rv); + knote_unlock(kn); } else if (src->flags & EV_ADD || src->flags == 0 || src->flags & EV_RECEIPT) { kn->kev.udata = src->udata; rv = filt->kn_modify(filt, kn, src); dbg_printf("kn_modify returned %d", rv); + knote_unlock(kn); } - knote_unlock(kn); - return (rv); } From b82779b7160f1159f1304b150a97911b20d0a205 Mon Sep 17 00:00:00 2001 From: marius Date: Wed, 13 Apr 2011 17:35:34 +0000 Subject: [PATCH 0444/1120] Made libkqueue compile on windows again - functionality still broken on this platform git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@473 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/libkqueue.vcxproj | 3 ++ vendor/libkqueue/src/common/alloc.h | 5 +- vendor/libkqueue/src/common/debug.h | 14 +++--- vendor/libkqueue/src/common/kevent.c | 4 +- vendor/libkqueue/src/common/knote.c | 5 ++ vendor/libkqueue/src/common/kqueue.c | 25 ++++++++-- vendor/libkqueue/src/common/map.c | 30 ++++++++---- vendor/libkqueue/src/common/private.h | 11 +++++ vendor/libkqueue/src/windows/platform.c | 19 ++++++-- vendor/libkqueue/src/windows/platform.h | 48 +++++++++++++++---- vendor/libkqueue/src/windows/timer.c | 62 ++++--------------------- vendor/libkqueue/test/common.h | 5 +- vendor/libkqueue/test/kqtest.vcxproj | 6 +++ vendor/libkqueue/test/main.c | 3 -- vendor/libkqueue/test/read.c | 4 +- 15 files changed, 146 insertions(+), 98 deletions(-) diff --git a/vendor/libkqueue/libkqueue.vcxproj b/vendor/libkqueue/libkqueue.vcxproj index 752b198c8..092e51db3 100644 --- a/vendor/libkqueue/libkqueue.vcxproj +++ b/vendor/libkqueue/libkqueue.vcxproj @@ -50,6 +50,7 @@ MachineX86 true Windows + msvcrtd.lib;Libcmtd.lib;%(AdditionalDependencies) @@ -72,12 +73,14 @@ + + diff --git a/vendor/libkqueue/src/common/alloc.h b/vendor/libkqueue/src/common/alloc.h index 56c390010..f82628c93 100644 --- a/vendor/libkqueue/src/common/alloc.h +++ b/vendor/libkqueue/src/common/alloc.h @@ -34,7 +34,10 @@ */ #include -#include + +#ifndef _WIN32 +# include +#endif static __thread struct { void **ac_cache; /* An array of reusable memory objects */ diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index 00db529af..983a9071c 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -19,7 +19,7 @@ #include -extern int DEBUG; +extern int DEBUG_ACTIVE; extern char *DEBUG_IDENT; #if defined(__linux__) @@ -27,7 +27,7 @@ extern char *DEBUG_IDENT; #elif defined(__sun) # define THREAD_ID (pthread_self()) #elif defined(_WIN32) -# define THREAD_ID (GetCurrentThreadId()) +# define THREAD_ID (int)(GetCurrentThreadId()) #else # error Unsupported platform #endif @@ -35,19 +35,19 @@ extern char *DEBUG_IDENT; #ifndef NDEBUG #define dbg_puts(str) do { \ - if (DEBUG) \ + if (DEBUG_ACTIVE) \ fprintf(stderr, "%s [%d]: %s(): %s\n", \ DEBUG_IDENT, THREAD_ID, __func__, str); \ } while (0) #define dbg_printf(fmt,...) do { \ - if (DEBUG) \ + if (DEBUG_ACTIVE) \ fprintf(stderr, "%s [%d]: %s(): "fmt"\n", \ DEBUG_IDENT, THREAD_ID, __func__, __VA_ARGS__); \ } while (0) #define dbg_perror(str) do { \ - if (DEBUG) \ + if (DEBUG_ACTIVE) \ fprintf(stderr, "%s [%d]: %s(): %s: %s (errno=%d)\n", \ DEBUG_IDENT, THREAD_ID, __func__, str, \ strerror(errno), errno); \ @@ -57,9 +57,9 @@ extern char *DEBUG_IDENT; # if defined(_WIN32) # define dbg_lasterror(str) do { \ - if (DEBUG) \ + if (DEBUG_ACTIVE) \ fprintf(stderr, "%s: [%d] %s(): %s: (LastError=%d)\n", \ - THREAD_ID, __func__, str, GetLastError()); \ + DEBUG_IDENT, THREAD_ID, __func__, str, (int)GetLastError()); \ } while (0) # else # define dbg_lasterror(str) ; diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index b207697e4..9e063d25c 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -250,7 +250,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, return (-1); } - if (DEBUG) { + if (DEBUG_ACTIVE) { myid = atomic_inc(&_kevent_counter); dbg_printf("--- kevent %u --- (nchanges = %d, nevents = %d)", myid, nchanges, nevents); } else { @@ -291,7 +291,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, } } - if (DEBUG) { + if (DEBUG_ACTIVE) { int n; dbg_printf("(%u) returning %d events", myid, rv); diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index e8f8746b2..a43d2d48a 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -19,6 +19,7 @@ #include #include "private.h" + #include "alloc.h" static void knote_free(struct filter *, struct knote *); @@ -45,11 +46,15 @@ knote_new(void) struct knote* res = malloc(sizeof(struct knote)); if(!res) return NULL; +#ifdef _WIN32 + pthread_mutex_init(&res->mtx, NULL); +#else if(pthread_mutex_init(&res->mtx, NULL)){ dbg_perror("pthread_mutex_init"); free(res); return NULL; } +#endif return res; } diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index be6b91f4e..9c1c029a5 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -24,12 +24,20 @@ #include "private.h" -int DEBUG = 0; +int DEBUG_ACTIVE = 0; char *DEBUG_IDENT = "KQ"; static unsigned int get_fd_limit(void) { +#ifdef _WIN32 + /* actually windows should be able to hold + way more, as they use HANDLEs for everything. + Still this number should still be sufficient for + the provided number of kqueue fds. + */ + return 65536; +#else struct rlimit rlim; if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { @@ -38,6 +46,7 @@ get_fd_limit(void) } else { return (rlim.rlim_max); } +#endif } static struct map *kqmap; @@ -46,14 +55,22 @@ int CONSTRUCTOR _libkqueue_init(void) { #ifdef NDEBUG - DEBUG = 0; + DEBUG_ACTIVE = 0; #elif _WIN32 /* Experimental port, always debug */ - DEBUG = 1; + DEBUG_ACTIVE = 1; +# ifndef __GNUC__ + /* Enable heap surveillance */ + { + int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ); + tmpFlag |= _CRTDBG_CHECK_ALWAYS_DF; + _CrtSetDbgFlag(tmpFlag); + } +# endif #else char *s = getenv("KQUEUE_DEBUG"); if (s != NULL && strlen(s) > 0) - DEBUG = 1; + DEBUG_ACTIVE = 1; #endif kqmap = map_new(get_fd_limit()); // INT_MAX diff --git a/vendor/libkqueue/src/common/map.c b/vendor/libkqueue/src/common/map.c index 98e9360f8..50ba0cfc7 100644 --- a/vendor/libkqueue/src/common/map.c +++ b/vendor/libkqueue/src/common/map.c @@ -26,9 +26,18 @@ map_new(size_t len) { struct map *dst; - dst = calloc(1, sizeof(*dst)); + dst = calloc(1, sizeof(struct map)); if (dst == NULL) return (NULL); +#ifdef _WIN32 + dst->data = calloc(len, sizeof(void*)); + if(dst->data == NULL) { + dbg_perror("calloc()"); + free(dst); + return NULL; + } + dst->len = len; +#else dst->data = mmap(NULL, len * sizeof(void *), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_NORESERVE | MAP_ANON, -1, 0); if (dst->data == MAP_FAILED) { @@ -37,6 +46,7 @@ map_new(size_t len) return (NULL); } dst->len = len; +#endif return (dst); } @@ -44,10 +54,10 @@ map_new(size_t len) int map_insert(struct map *m, int idx, void *ptr) { - if (slowpath(idx < 0 || idx > m->len)) + if (slowpath(idx < 0 || idx > (int)m->len)) return (-1); - if (atomic_cas(&(m->data[idx]), 0, ptr) == NULL) { + if (atomic_ptr_cas(&(m->data[idx]), 0, ptr) == NULL) { dbg_printf("inserted %p in location %d", ptr, idx); return (0); } else { @@ -61,10 +71,10 @@ map_insert(struct map *m, int idx, void *ptr) int map_remove(struct map *m, int idx, void *ptr) { - if (slowpath(idx < 0 || idx > m->len)) + if (slowpath(idx < 0 || idx > (int)m->len)) return (-1); - if (atomic_cas(&(m->data[idx]), ptr, 0) == NULL) { + if (atomic_ptr_cas(&(m->data[idx]), ptr, 0) == NULL) { dbg_printf("removed %p from location %d", ptr, idx); return (0); } else { @@ -78,10 +88,10 @@ map_replace(struct map *m, int idx, void *oldp, void *newp) { void *tmp; - if (slowpath(idx < 0 || idx > m->len)) + if (slowpath(idx < 0 || idx > (int)m->len)) return (-1); - tmp = atomic_cas(&(m->data[idx]), oldp, newp); + tmp = atomic_ptr_cas(&(m->data[idx]), oldp, newp); if (tmp == oldp) { dbg_printf("replaced value %p in location %d with value %p", oldp, idx, newp); @@ -96,7 +106,7 @@ map_replace(struct map *m, int idx, void *oldp, void *newp) void * map_lookup(struct map *m, int idx) { - if (slowpath(idx < 0 || idx > m->len)) + if (slowpath(idx < 0 || idx > (int)m->len)) return (NULL); return m->data[idx]; @@ -108,13 +118,13 @@ map_delete(struct map *m, int idx) void *oval; void *nval; - if (slowpath(idx < 0 || idx > m->len)) + if (slowpath(idx < 0 || idx > (int)m->len)) return ((void *)-1); /* Hopefully we aren't racing with another thread, but you never know.. */ do { oval = m->data[idx]; - nval = atomic_cas(&(m->data[idx]), oval, NULL); + nval = atomic_ptr_cas(&(m->data[idx]), oval, NULL); } while (nval != oval); m->data[idx] = NULL; diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 9de0f6f26..c35cea6b6 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -35,6 +35,9 @@ struct evfilt_data; #if defined(_WIN32) # include "../windows/platform.h" # include "../common/queue.h" +# if !defined(NDEBUG) && !defined(__GNUC__) +# include +# endif #elif defined(__linux__) # include "../posix/platform.h" # include "../linux/platform.h" @@ -141,7 +144,15 @@ struct kqueue { struct kqueue_vtable { int (*kqueue_init)(struct kqueue *); void (*kqueue_free)(struct kqueue *); + // @param timespec can be given as timeout + // @param int the number of events to wait for + // @param kqueue the queue to wait on int (*kevent_wait)(struct kqueue *, int, const struct timespec *); + // @param kqueue the queue to look at + // @param int The number of events that should be ready + // @param kevent the structure to copy the events into + // @param int The number of events to copy + // @return the actual number of events copied int (*kevent_copyout)(struct kqueue *, int, struct kevent *, int); int (*filter_init)(struct kqueue *, struct filter *); void (*filter_free)(struct kqueue *, struct filter *); diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 3a95c33b9..a775e373e 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -51,7 +51,9 @@ BOOL WINAPI DllMain( break; case DLL_PROCESS_DETACH: +#if XXX WSACleanup(); +#endif break; } @@ -67,6 +69,11 @@ windows_kqueue_init(struct kqueue *kq) return (-1); } + if(filter_register_all(kq) < 0) { + CloseHandle(kq->kq_handle); + return (-1); + } + return (0); } @@ -78,7 +85,7 @@ windows_kqueue_free(struct kqueue *kq) } int -windows_kevent_wait(struct kqueue *kq, const struct timespec *timeout) +windows_kevent_wait(struct kqueue *kq, int no, const struct timespec *timeout) { int retval; DWORD rv, timeout_ms; @@ -96,7 +103,7 @@ windows_kevent_wait(struct kqueue *kq, const struct timespec *timeout) } /* Wait for an event */ - dbg_printf("waiting for %u events (timeout=%u ms)", kq->kq_filt_count, timeout_ms); + dbg_printf("waiting for %u events (timeout=%u ms)", kq->kq_filt_count, (unsigned int)timeout_ms); rv = WaitForMultipleObjectsEx(kq->kq_filt_count, kq->kq_filt_handle, FALSE, timeout_ms, TRUE); switch (rv) { case WAIT_TIMEOUT: @@ -121,6 +128,7 @@ windows_kevent_copyout(struct kqueue *kq, int nready, struct kevent *eventlist, int nevents) { struct filter *filt; + struct knote* kn; int rv; /* KLUDGE: We are abusing the WAIT_FAILED constant to mean @@ -129,8 +137,13 @@ windows_kevent_copyout(struct kqueue *kq, int nready, if (kq->kq_filt_signalled == WAIT_FAILED) return (0); filt = kq->kq_filt_ref[kq->kq_filt_signalled]; + kn = knote_lookup(filt, eventlist->ident); + if(kn == NULL) { + dbg_puts("knote_lookup failed"); + return (-1); + } kq->kq_filt_signalled = WAIT_FAILED; - rv = filt->kf_copyout(filt, eventlist, nevents); + rv = filt->kf_copyout(eventlist, kn, filt); if (rv < 0) { dbg_puts("kevent_copyout failed"); return (-1); diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 7af77394e..18ee425d8 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -27,12 +27,12 @@ #include #include #include - -#pragma comment(lib, "Ws2_32.lib") -/* The #define doesn't seem to work, but the #pragma does.. */ #define _CRT_SECURE_NO_WARNINGS 1 -#pragma warning( disable : 4996 ) +/* The #define doesn't seem to work, but the #pragma does.. */ +#ifdef _MSC_VER +# pragma warning( disable : 4996 ) +#endif #include "../../include/sys/event.h" @@ -40,8 +40,17 @@ /* * Atomic integer operations */ -#define atomic_inc InterlockedIncrement -#define atomic_dec InterlockedDecrement +#ifdef __GNUC__ +# define atomic_inc(p) __sync_add_and_fetch((p), 1) +# define atomic_dec(p) __sync_sub_and_fetch((p), 1) +# define atomic_cas(p, oval, nval) __sync_val_compare_and_swap(p, oval, nval) +# define atomic_ptr_cas(p, oval, nval) __sync_val_compare_and_swap(p, oval, nval) +#else +# define atomic_inc InterlockedIncrement +# define atomic_dec InterlockedDecrement +# define atomic_cas(p, oval, nval) InterlockedCompareExchange(p, nval, oval) +# define atomic_ptr_cas(p, oval, nval) InterlockedCompareExchangePointer(p, nval, oval) +#endif /* * Additional members of struct kqueue @@ -62,12 +71,18 @@ #define FILTER_PLATFORM_SPECIFIC \ HANDLE kf_event_handle +/* + * Some datatype forward declarations + */ +struct filter; +struct kqueue; + /* * Hooks and prototypes */ int windows_kqueue_init(struct kqueue *); void windows_kqueue_free(struct kqueue *); -int windows_kevent_wait(struct kqueue *, const struct timespec *); +int windows_kevent_wait(struct kqueue *, int, const struct timespec *); int windows_kevent_copyout(struct kqueue *, int, struct kevent *, int); int windows_filter_init(struct kqueue *, struct filter *); void windows_filter_free(struct kqueue *, struct filter *); @@ -78,17 +93,29 @@ void windows_filter_free(struct kqueue *, struct filter *); */ #define CONSTRUCTOR +/* + * GCC-compatible branch prediction macros + */ +#ifdef __GNUC__ +# define fastpath(x) __builtin_expect((x), 1) +# define slowpath(x) __builtin_expect((x), 0) +#else +# define fastpath(x) (x) +# define slowpath(x) (x) +#endif + /* Function visibility macros */ #define VISIBLE __declspec(dllexport) #define HIDDEN -#ifndef __func__ +#if !defined(__func__) && !defined(__GNUC__) #define __func__ __FUNCDNAME__ #endif #define snprintf _snprintf #define ssize_t SSIZE_T #define sleep(x) Sleep((x) * 1000) +#define inline __inline /* For POSIX compatibility when compiling, not for actual use */ typedef int socklen_t; @@ -98,7 +125,9 @@ typedef int pthread_t; typedef int sigset_t; typedef int pid_t; -#define __thread __declspec(thread) +#ifndef __GNUC__ +# define __thread __declspec(thread) +#endif /* Emulation of pthreads mutex functionality */ #define PTHREAD_PROCESS_SHARED 1 @@ -116,6 +145,7 @@ typedef CRITICAL_SECTION pthread_rwlock_t; #define pthread_spin_unlock _cs_unlock #define pthread_spin_init(x,y) _cs_init((x)) #define pthread_mutex_init(x,y) _cs_init((x)) +#define pthread_mutex_destroy(x) #define pthread_rwlock_rdlock _cs_lock #define pthread_rwlock_wrlock _cs_lock #define pthread_rwlock_unlock _cs_unlock diff --git a/vendor/libkqueue/src/windows/timer.c b/vendor/libkqueue/src/windows/timer.c index 39a5df9a2..d06266d48 100644 --- a/vendor/libkqueue/src/windows/timer.c +++ b/vendor/libkqueue/src/windows/timer.c @@ -54,62 +54,16 @@ evfilt_timer_destroy(struct filter *filt) } int -evfilt_timer_copyout(struct filter *filt, - struct kevent *dst, - int nevents) +evfilt_timer_copyout(struct kevent* dst, struct knote* src, void* ptr) { -#if FIXME - struct epoll_event epevt[MAX_KEVENT]; - struct epoll_event *ev; - struct knote *kn; - uint64_t expired; - int i, nret; - ssize_t n; - - for (;;) { - nret = epoll_wait(filt->kf_pfd, &epevt[0], nevents, 0); - if (nret < 0) { - if (errno == EINTR) - continue; - dbg_perror("epoll_wait"); - return (-1); - } else { - break; - } - } - - for (i = 0, nevents = 0; i < nret; i++) { - ev = &epevt[i]; - /* TODO: put in generic debug.c: epoll_event_dump(ev); */ - kn = ev->data.ptr; - memcpy(dst, &kn->kev, sizeof(*dst)); - if (ev->events & EPOLLERR) - dst->fflags = 1; /* FIXME: Return the actual timer error */ - - /* On return, data contains the number of times the - timer has been trigered. - */ - n = read(kn->data.pfd, &expired, sizeof(expired)); - if (n < 0 || n < sizeof(expired)) { - dbg_puts("invalid read from timerfd"); - expired = 1; /* Fail gracefully */ - } - dst->data = expired; - - if (kn->kev.flags & EV_DISPATCH) { - KNOTE_DISABLE(kn); - ktimer_delete(filt, kn); - } else if (kn->kev.flags & EV_ONESHOT) { - ktimer_delete(filt, kn); - knote_free(filt, kn); - } - - nevents++; - dst++; - } + memcpy(dst, &src->kev, sizeof(struct kevent*)); + // TODO: Timer error handling + + /* We have no way to determine the number of times + the timer triggered, thus we assume it was only once + */ + dst->data = 1; - return (nevents); -#endif return (0); } diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 720cc5854..640526922 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -49,9 +49,8 @@ #include #include "config.h" #else -#include "../include/sys/event.h" -#include "../src/windows/platform.h" -#pragma comment(lib, "../Debug/libkqueue.lib") +# include "../include/sys/event.h" +# include "../src/windows/platform.h" #endif diff --git a/vendor/libkqueue/test/kqtest.vcxproj b/vendor/libkqueue/test/kqtest.vcxproj index 876aac881..30043fe6a 100644 --- a/vendor/libkqueue/test/kqtest.vcxproj +++ b/vendor/libkqueue/test/kqtest.vcxproj @@ -50,6 +50,7 @@ MachineX86 true Console + wsock32.lib;%(AdditionalDependencies) @@ -82,6 +83,11 @@ + + + {74c1eceb-1d2b-2740-8a0b-9ec65aa06eab} + + diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index e8078f0fd..ac5dc3a55 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -14,9 +14,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include - - #include "common.h" struct unit_test { diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 0ff3cf1ac..2566a17a1 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -340,7 +340,7 @@ test_kevent_regular_file(void) /* Set file position to EOF-1 */ kev2->data--; if ((curpos = lseek(fd, kev2->data, SEEK_SET)) != kev2->data) { - printf("seek to %zu failed with rv=%zu\n", kev2->data, curpos); + printf("seek to %u failed with rv=%lu\n", kev2->data, curpos); abort(); } @@ -348,7 +348,7 @@ test_kevent_regular_file(void) (void) kevent_get(kqfd); kev2->data = curpos + 1; if ((curpos = lseek(fd, kev2->data, SEEK_SET)) != kev2->data) { - printf("seek to %zu failed with rv=%zu\n", kev2->data, curpos); + printf("seek to %u failed with rv=%lu\n", kev2->data, curpos); abort(); } From 98660d80e3b010112c1ee3a1b1c30cd84251b204 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 14 Apr 2011 00:21:11 +0000 Subject: [PATCH 0445/1120] Provide missing atomic_ptr_cas definition on some platforms. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@474 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/posix/platform.h | 1 + vendor/libkqueue/src/solaris/platform.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index c95502c67..58501937f 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -28,6 +28,7 @@ #define atomic_inc(p) __sync_add_and_fetch((p), 1) #define atomic_dec(p) __sync_sub_and_fetch((p), 1) #define atomic_cas(p, oval, nval) __sync_val_compare_and_swap(p, oval, nval) +#define atomic_ptr_cas(p, oval, nval) __sync_val_compare_and_swap(p, oval, nval) /* * GCC-compatible branch prediction macros diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index 2ab7ee66e..81d95af65 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -29,6 +29,8 @@ #define atomic_dec atomic_dec_32_nv #undef atomic_cas #define atomic_cas atomic_cas_ptr +#undef atomic_ptr_cas +#define atomic_ptr_cas atomic_cas_ptr /* * Event ports From b614dfe5f9056602e996e6913c8a4826b08e44f3 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 14 Apr 2011 00:25:27 +0000 Subject: [PATCH 0446/1120] Fix format string type mismatch git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@475 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/read.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 2566a17a1..89d1f2066 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -340,7 +340,8 @@ test_kevent_regular_file(void) /* Set file position to EOF-1 */ kev2->data--; if ((curpos = lseek(fd, kev2->data, SEEK_SET)) != kev2->data) { - printf("seek to %u failed with rv=%lu\n", kev2->data, curpos); + printf("seek to %u failed with rv=%lu\n", + (unsigned int) kev2->data, curpos); abort(); } @@ -348,7 +349,8 @@ test_kevent_regular_file(void) (void) kevent_get(kqfd); kev2->data = curpos + 1; if ((curpos = lseek(fd, kev2->data, SEEK_SET)) != kev2->data) { - printf("seek to %u failed with rv=%lu\n", kev2->data, curpos); + printf("seek to %u failed with rv=%lu\n", + (unsigned int) kev2->data, curpos); abort(); } From 3490d0d76318d52b3d9c0acb252251508b90f44a Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 14 Apr 2011 00:42:11 +0000 Subject: [PATCH 0447/1120] Use calloc() instead of malloc() to avoid the use of uninitialized memory. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@476 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/knote.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index a43d2d48a..67fee8254 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -42,18 +42,21 @@ RB_GENERATE(knt, knote, kntree_ent, knote_cmp) struct knote * knote_new(void) { - // struct knote* res = return (mem_calloc()); - struct knote* res = malloc(sizeof(struct knote)); - if(!res) return NULL; + struct knote *res; + + // return (mem_calloc()); + res = calloc(1, sizeof(struct knote)); + if (res == NULL) + return (NULL); #ifdef _WIN32 pthread_mutex_init(&res->mtx, NULL); #else - if(pthread_mutex_init(&res->mtx, NULL)){ - dbg_perror("pthread_mutex_init"); - free(res); - return NULL; - } + if (pthread_mutex_init(&res->mtx, NULL)){ + dbg_perror("pthread_mutex_init"); + free(res); + return (NULL); + } #endif return res; From 3f84716cfd0b869e27a8f7c03a932e4d03bf7854 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 14 Apr 2011 00:53:06 +0000 Subject: [PATCH 0448/1120] Document test failure on SunOS git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@477 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/BUGS | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/vendor/libkqueue/BUGS b/vendor/libkqueue/BUGS index 61d5d2adb..cc0496d24 100644 --- a/vendor/libkqueue/BUGS +++ b/vendor/libkqueue/BUGS @@ -1,2 +1,15 @@ * need to uninitialize library after fork() using pthread_atfork() + * Solaris unit test failure. + + LD_LIBRARY_PATH="..:/usr/sfw/lib/64" ./kqtest + 1: test_peer_close_detection() + 2: test_kqueue() + 3: test_kevent_socket_add() + 4: test_kevent_socket_del() + 5: test_kevent_socket_add_without_ev_add() + 6: test_kevent_socket_get() + + [read.c:84]: Unexpected event:_test_no_kevents(): [ident=7, filter=-1, flags = 1 (EV_ADD), fflags = 0, data=0, udata=fffffd7fff08c6b4]: Error 0 + + From 56f0ffd197606d5efb97388e24ddb4f3c6712bd4 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 14 Apr 2011 00:56:09 +0000 Subject: [PATCH 0449/1120] Test commit, trying a post-commit email notify hook git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@478 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/BUGS | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/BUGS b/vendor/libkqueue/BUGS index cc0496d24..9ee007922 100644 --- a/vendor/libkqueue/BUGS +++ b/vendor/libkqueue/BUGS @@ -1,3 +1,4 @@ + * need to uninitialize library after fork() using pthread_atfork() * Solaris unit test failure. From 4d131b764c8be3555fa91b5db5ddb0e3fdc38e20 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 14 Apr 2011 00:58:03 +0000 Subject: [PATCH 0450/1120] Test commit, trying a post-commit email notify hook git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@479 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/BUGS | 1 - 1 file changed, 1 deletion(-) diff --git a/vendor/libkqueue/BUGS b/vendor/libkqueue/BUGS index 9ee007922..2ed3f018c 100644 --- a/vendor/libkqueue/BUGS +++ b/vendor/libkqueue/BUGS @@ -13,4 +13,3 @@ [read.c:84]: Unexpected event:_test_no_kevents(): [ident=7, filter=-1, flags = 1 (EV_ADD), fflags = 0, data=0, udata=fffffd7fff08c6b4]: Error 0 - From 8f51d1d81c4186ee24eb90553ce373fe8233a296 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 14 Apr 2011 01:12:48 +0000 Subject: [PATCH 0451/1120] Testing SVN post-commit hook git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@480 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/BUGS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/BUGS b/vendor/libkqueue/BUGS index 2ed3f018c..3a105d5d7 100644 --- a/vendor/libkqueue/BUGS +++ b/vendor/libkqueue/BUGS @@ -4,7 +4,7 @@ * Solaris unit test failure. LD_LIBRARY_PATH="..:/usr/sfw/lib/64" ./kqtest - 1: test_peer_close_detection() + 1: test_peer_close_detection() 2: test_kqueue() 3: test_kevent_socket_add() 4: test_kevent_socket_del() From 5dae17224401c52e544ae366492cb1f955e92b41 Mon Sep 17 00:00:00 2001 From: marius Date: Sat, 16 Apr 2011 08:54:17 +0000 Subject: [PATCH 0452/1120] Add option for static library build activated by defining MAKE_STATIC git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@481 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/include/sys/event.h | 8 ++++++++ vendor/libkqueue/src/common/kqueue.c | 2 +- vendor/libkqueue/src/common/private.h | 2 +- vendor/libkqueue/src/posix/platform.h | 6 +++++- vendor/libkqueue/src/windows/platform.c | 6 +++++- 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index a4362428f..7fd7bf040 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -185,11 +185,19 @@ kevent(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); +#ifdef MAKE_STATIC +__declspec(dllexport) int +libkqueue_init(); +#endif + #else int kqueue(void); int kevent(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); +#ifdef MAKE_STATIC +int libkqueue_init(); +#endif #endif #ifdef __cplusplus diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 9c1c029a5..01f1f0a2a 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -52,7 +52,7 @@ get_fd_limit(void) static struct map *kqmap; int CONSTRUCTOR -_libkqueue_init(void) +libkqueue_init(void) { #ifdef NDEBUG DEBUG_ACTIVE = 0; diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index c35cea6b6..6c09f7366 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -200,6 +200,6 @@ void *map_lookup(struct map *, int); void *map_delete(struct map *, int); void map_free(struct map *); -int CONSTRUCTOR _libkqueue_init(void); +int CONSTRUCTOR libkqueue_init(void); #endif /* ! _KQUEUE_PRIVATE_H */ diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 58501937f..5f8d45909 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -36,7 +36,11 @@ #define fastpath(x) __builtin_expect((x), 1) #define slowpath(x) __builtin_expect((x), 0) -#define CONSTRUCTOR __attribute__ ((constructor)) +#ifdef MAKE_STATIC +# define CONSTRUCTOR +#else +# define CONSTRUCTOR __attribute__ ((constructor)) +#endif #define VISIBLE __attribute__((visibility("default"))) #define HIDDEN __attribute__((visibility("hidden"))) diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index a775e373e..bece13119 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -33,6 +33,8 @@ const struct kqueue_vtable kqops = { windows_filter_free, }; +#ifndef MAKE_STATIC + BOOL WINAPI DllMain( HINSTANCE self, DWORD reason, @@ -46,7 +48,7 @@ BOOL WINAPI DllMain( if (WSAStartup(MAKEWORD(2,2), NULL) != 0) return (FALSE); #endif - if (_libkqueue_init() < 0) + if (libkqueue_init() < 0) return (FALSE); break; @@ -60,6 +62,8 @@ BOOL WINAPI DllMain( return (TRUE); } +#endif + int windows_kqueue_init(struct kqueue *kq) { From 65a20fbf36856e5cd077c0f4e66435b3a7314c2e Mon Sep 17 00:00:00 2001 From: marius Date: Sat, 16 Apr 2011 08:57:12 +0000 Subject: [PATCH 0453/1120] Added CMakeLists.txt for libkqueue and tests git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@482 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/CMakeLists.txt | 108 +++++++++++++++++++++++++++ vendor/libkqueue/test/CMakeLists.txt | 60 +++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 vendor/libkqueue/CMakeLists.txt create mode 100644 vendor/libkqueue/test/CMakeLists.txt diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt new file mode 100644 index 000000000..557d81c7e --- /dev/null +++ b/vendor/libkqueue/CMakeLists.txt @@ -0,0 +1,108 @@ +# +# Copyright (c) 2011 Marius Zwicker +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +cmake_minimum_required(VERSION 2.8) +INCLUDE (CheckIncludeFiles) + +#tests +option(KQUEUE_TESTS "Enable to build tests for libkqueue" OFF) +if(KQUEUE_TESTS) + message("-- Adding tests for libkqueue") + add_subdirectory(test) +endif() + +project(libkqueue) + +#files +file(GLOB_RECURSE INCL include/*.h) +source_group(includes FILES ${INCL}) + +if(WIN32) + file(GLOB SRC + src/windows/*.h + src/windows/*.c + src/common/*.h + src/*.c + src/common/map.c + src/common/filter.c + src/common/knote.c + src/common/kevent.c + src/common/kqueue.c + ) + add_definitions( + -DLIBKQUEUE_EXPORTS + -D_USRDLL + -D_WINDLL + ) + if(MINGW) + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -march=i486") + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -march=i486") + endif() +else() + file(GLOB SRC + src/posix/*.h + src/posix/platform.c + src/linux/*.h + src/linux/platform.c + src/linux/signal.c + src/linux/socket.c + src/linux/timer.c + src/linux/user.c + src/linux/vnode.c + src/common/*.h + src/common/filter.c + src/common/knote.c + src/common/map.c + src/common/kevent.c + src/common/kqueue.c + ) + include_directories( + src/common + ) + add_definitions( + -Wall -Werror + -fpic + -D_XOPEN_SOURCE=600 + -std=c99 + -fvisibility=hidden + ) +endif() +source_group(src FILES ${SRC}) + +#includes +include_directories( + include +) + +#library (static or shared) +option(STATIC_KQUEUE "Enable to build libkqueue as static lib" OFF) +if(STATIC_WORKQUEUE) + add_definitions(-DMAKE_STATIC) + add_library(libkqueue STATIC ${SRC} ${INCL}) +else() + add_library(libkqueue SHARED ${SRC} ${INCL}) +endif() +if(NOT WIN32) + target_link_libraries(libkqueue pthread) +endif() +set_target_properties(libkqueue PROPERTIES DEBUG_POSTFIX "D") + +#tests +option(KQUEUE_TESTS "Enable to build tests for libkqueue" OFF) +if(KQUEUE_TESTS) + message("-- Adding tests for libkqueue") + add_subdirectory(test) +endif() diff --git a/vendor/libkqueue/test/CMakeLists.txt b/vendor/libkqueue/test/CMakeLists.txt new file mode 100644 index 000000000..770650335 --- /dev/null +++ b/vendor/libkqueue/test/CMakeLists.txt @@ -0,0 +1,60 @@ +# +# Copyright (c) 2011 Marius Zwicker +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +#files +if(UNIX) + set(SRC + main.c + kevent.c + test.c + proc.c + read.c + signal.c + timer.c + vnode.c + user.c + ) +else() + set(SRC + common.h + kevent.c + main.c + read.c + test.c + timer.c + user.c + vnode.c + ) +endif() + + +#includes +include_directories( + ../include +) + +if(UNIX) + add_definitions( + -rdynamic + ) + set(LIBS pthread rt) +else() + set(LIBS wsock32) +endif() + +add_executable(libkqueue-test ${SRC}) +target_link_libraries(libkqueue-test libkqueue ${LIBS}) +set_target_properties(libkqueue-test PROPERTIES DEBUG_POSTFIX "D") From 9692350bd6c306a71fa98f488cc21d99a6edebd7 Mon Sep 17 00:00:00 2001 From: marius Date: Sun, 17 Apr 2011 19:34:34 +0000 Subject: [PATCH 0454/1120] EVTFILT_TIMER working on windows Added binary files on windows to svn:ignore git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@483 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/libkqueue.vcxproj | 2 + vendor/libkqueue/src/common/kevent.c | 1 + vendor/libkqueue/src/common/private.h | 1 + vendor/libkqueue/src/windows/event_loop.c | 270 ++++++++++++++++++++++ vendor/libkqueue/src/windows/event_loop.h | 119 ++++++++++ vendor/libkqueue/src/windows/platform.c | 96 ++++---- vendor/libkqueue/src/windows/platform.h | 19 +- vendor/libkqueue/src/windows/timer.c | 40 +++- vendor/libkqueue/test/main.c | 2 + 9 files changed, 498 insertions(+), 52 deletions(-) create mode 100644 vendor/libkqueue/src/windows/event_loop.c create mode 100644 vendor/libkqueue/src/windows/event_loop.h diff --git a/vendor/libkqueue/libkqueue.vcxproj b/vendor/libkqueue/libkqueue.vcxproj index 092e51db3..2577e6a3d 100644 --- a/vendor/libkqueue/libkqueue.vcxproj +++ b/vendor/libkqueue/libkqueue.vcxproj @@ -74,6 +74,7 @@ + @@ -84,6 +85,7 @@ + diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 9e063d25c..36ed99fd4 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -144,6 +144,7 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) memcpy(&kn->kev, src, sizeof(kn->kev)); kn->kev.flags &= ~EV_ENABLE; kn->kev.flags |= EV_ADD;//FIXME why? + kn->kn_kq = kq; assert(filt->kn_create); if (filt->kn_create(filt, kn) < 0) { knote_release(filt, kn); diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 6c09f7366..5708a332c 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -77,6 +77,7 @@ struct knote { void *handle; /* Used by win32 filters */ } data; volatile uint32_t kn_ref; + struct kqueue* kn_kq; #if defined(KNOTE_PLATFORM_SPECIFIC) KNOTE_PLATFORM_SPECIFIC; #endif diff --git a/vendor/libkqueue/src/windows/event_loop.c b/vendor/libkqueue/src/windows/event_loop.c new file mode 100644 index 000000000..6ed332bc5 --- /dev/null +++ b/vendor/libkqueue/src/windows/event_loop.c @@ -0,0 +1,270 @@ +/* +* Copyright (c) 2011 Marius Zwicker +* +* Permission to use, copy, modify, and distribute this software for any +* purpose with or without fee is hereby granted, provided that the above +* copyright notice and this permission notice appear in all copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + + + +#include "../common/private.h" + +/* +* Conditionals on windows +*/ +#if TARGET_WIN_VISTA +// These conditions are supported using Windows Vista and up only. We need a XP compatible workaround here + +# define pthread_cond_init(c,x) InitializeConditionVariable((c)) +# define pthread_cond_destroy(c) +# define pthread_cond_wait(c,m) SleepConditionVariableCS((c),(m), INFINITE) +# define pthread_cond_broadcast(c) WakeAllConditionVariable((c)); +# define pthread_cond_signal(c) WakeConditionVariable((c)); + +#else + +typedef struct { + int unused; +} pthread_condattr_t; + +/* Credits for this pthread_cond_t implementation on windows go to +the authors of http://www.cs.wustl.edu/~schmidt/win32-cv-1.html: +Douglas C. Schmidt and Irfan Pyarali +Department of Computer Science +Washington University, St. Louis, Missouri + +Please note that this implementation is not a fully featured posix condition implementation +but only usable for our purposes as it allows only one thread calling cond_wait at a time. +*/ + +int + pthread_cond_init (pthread_cond_t *cv, + const pthread_condattr_t * attr) +{ + cv->waiters_count_ = 0; + + // Init the second mutex + InitializeCriticalSection(&cv->waiters_count_lock_); + + // Create an auto-reset event. + cv->events_[SIGNAL] = CreateEvent (NULL, // no security + FALSE, // auto-reset event + FALSE, // non-signaled initially + NULL); // unnamed + + // Create a manual-reset event. + cv->events_[BROADCAST] = CreateEvent (NULL, // no security + TRUE, // manual-reset + FALSE, // non-signaled initially + NULL); // unnamed + + return cv->events_[SIGNAL] == 0 || cv->events_[BROADCAST] == 0 ; +} + +int pthread_cond_timedwait(pthread_cond_t *cv, + pthread_mutex_t *external_mutex, const struct timespec* timeout) +{ + DWORD timeout_ms, rv; + int last_waiter = 0; + + /* Convert timeout to milliseconds */ + /* NOTE: loss of precision for timeout values less than 1ms */ + if (timeout == NULL) { + timeout_ms = INFINITE; + } else { + timeout_ms = 0; + if (timeout->tv_sec > 0) + timeout_ms += ((DWORD)timeout->tv_sec) / 1000; + if (timeout->tv_sec > 0) + timeout_ms += timeout->tv_nsec / 1000000; + } + + + + // Avoid race conditions. + EnterCriticalSection (&cv->waiters_count_lock_); + cv->waiters_count_++; + LeaveCriticalSection (&cv->waiters_count_lock_); + + // It's ok to release the here since Win32 + // manual-reset events maintain state when used with + // . This avoids the "lost wakeup" bug... + LeaveCriticalSection (external_mutex); + + // Wait for either event to become signaled due to + // being called or being called. + rv = WaitForMultipleObjects (2, cv->events_, FALSE, timeout_ms); + if( rv == WAIT_TIMEOUT) { + int r = 0; + return EVT_TIMEDOUT; + } else if(rv == WAIT_FAILED) { + dbg_lasterror("cond_timedwait failed"); + return EVT_ERR; + } + + EnterCriticalSection (&cv->waiters_count_lock_); + cv->waiters_count_--; + last_waiter = + rv == WAIT_OBJECT_0 + BROADCAST + && cv->waiters_count_ == 0; + LeaveCriticalSection (&cv->waiters_count_lock_); + + // Some thread called . + if (last_waiter) + // We're the last waiter to be notified or to stop waiting, so + // reset the manual event. + ResetEvent (cv->events_[BROADCAST]); + + // Reacquire the . + EnterCriticalSection (external_mutex); + + return 0; +} + +int + pthread_cond_wait (pthread_cond_t *cv, + pthread_mutex_t *external_mutex) +{ + return pthread_cond_timedwait(cv, external_mutex, NULL); +} + +int + pthread_cond_signal (pthread_cond_t *cv) +{ + int have_waiters = 0; + + // Avoid race conditions. + EnterCriticalSection (&cv->waiters_count_lock_); + have_waiters = cv->waiters_count_ > 0; + LeaveCriticalSection (&cv->waiters_count_lock_); + + if (have_waiters) + SetEvent (cv->events_[SIGNAL]); + + return 0; +} + +int + pthread_cond_destroy(pthread_cond_t *cv) +{ + CloseHandle(cv->events_[SIGNAL]); + CloseHandle(cv->events_[BROADCAST]); + + return 0; +} +#endif + +/* +* Event loop implementation +*/ + +void evt_init(evt_loop_t t){ + assert(t); + pthread_mutex_init(&t->access, NULL); + pthread_cond_init(&t->cond, NULL); + t->used = TRUE; +} + +evt_loop_t evt_create(){ + evt_loop_t neu = (evt_loop_t)malloc(sizeof(struct evt_loop_s)); + assert(neu); + memset(neu,0,sizeof(struct evt_loop_s)); + + evt_init(neu); + + return neu; +} + +int evt_signal(evt_loop_t l, int type, void* data){ + // create new item + evt_event_t i = (evt_event_t)malloc(sizeof(struct evt_event_s)); + + assert(l); + + if (i == NULL) + return -1; // creation failed + i->type = type; // link with the given event type + i->data = data; + i->next = NULL; + + pthread_mutex_lock(&l->access); + if (l->last != NULL) + l->last->next = i; + l->last = i; + if (l->first == NULL) { // if this item is first one, signal waiting getitem call + l->first = i; + pthread_cond_signal(&l->cond); + } + pthread_mutex_unlock(&l->access); + return 0; +} + +int evt_run(evt_loop_t l, evt_event_t evt, int max_ct, const struct timespec* timeout){ + evt_event_t curr = NULL; + + assert(l); + assert(evt); + assert(max_ct > 0); + + pthread_mutex_lock(&l->access); + while(1){ + // get item from list, if available + if (l->first == NULL) { + if( pthread_cond_timedwait(&l->cond, &l->access, timeout) == EVT_TIMEDOUT ) // no item available, wait for it + return EVT_TIMEDOUT; + + // in this case we can be sure to hold the mutex again + continue; + } + curr = l->first; + l->first = curr->next; // remove item + if (l->first == NULL) + l->last = NULL; // this was the last item + pthread_mutex_unlock(&l->access); + + assert(curr); + // TODO: Real event array support + // return the current event + memcpy(&(evt[0]), curr, sizeof(struct evt_event_s)); + free(curr); + return 1; + + pthread_mutex_lock(&l->access); + } + +} + +void evt_destroy(evt_loop_t l){ + evt_event_t i = NULL, curr = NULL; + + assert(l); + + if (l->used == FALSE) + return; + + // delete all waiting items + i = l->first; + while (i != NULL) { + curr = i; + i = i->next; + free(curr); + } + + // reset list + l->first = NULL; + l->last = NULL; + + pthread_mutex_destroy(&l->access); + pthread_cond_destroy(&l->cond); + + free(l); +} diff --git a/vendor/libkqueue/src/windows/event_loop.h b/vendor/libkqueue/src/windows/event_loop.h new file mode 100644 index 000000000..83aa322bf --- /dev/null +++ b/vendor/libkqueue/src/windows/event_loop.h @@ -0,0 +1,119 @@ +/* +* Copyright (c) 2011 Marius Zwicker +* +* Permission to use, copy, modify, and distribute this software for any +* purpose with or without fee is hereby granted, provided that the above +* copyright notice and this permission notice appear in all copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + + +#ifndef KQUEUE_WINDOWS_EVENTLOOP_H +#define KQUEUE_WINDOWS_EVENTLOOP_H + +// some condition variable typedefs +#if TARGET_WIN_VISTA +// These conditions are supported using Windows Vista and up only. We need a XP compatible workaround here + +typedef CONDITION_VARIABLE pthread_cond_t; + +#else + +typedef struct { + u_int waiters_count_; + // Count of the number of waiters. + + CRITICAL_SECTION waiters_count_lock_; + // Serialize access to . + +#define SIGNAL 0 +#define BROADCAST 1 +#define MAX_EVENTS 2 + + HANDLE events_[MAX_EVENTS]; + // Signal and broadcast event HANDLEs. +} pthread_cond_t; + +#endif + +// +// A single event item +// +typedef struct evt_event_s { + int type; + void* data; + struct evt_event_s* next; +}* evt_event_t; + +#define EVT_EVENT_INITIALIZER { 0, NULL, NULL } + +// +// An event loop, normally you have one loop per thread +// +typedef struct evt_loop_s { + int id; + void* data; + evt_event_t first; + evt_event_t last; + pthread_mutex_t access; + pthread_cond_t cond; + unsigned char used; +}* evt_loop_t; + +// +// The different event types +// +enum evt_type { + EVT_WAKEUP =0, /* Simply wake the thread, the callback will know what to do */ + EVT_EXIT =1, /* Immediately exit the event loop */ + EVT_CUSTOM =2 /* Some custom event */ +}; + +// +// Flags describing the return values of evt_run +// +enum evt_flags { + EVT_ERR = -3, /* An error occured */ + EVT_TIMEDOUT = -5, /* Timeout elapsed before receiving an event */ +}; + +// +// Creates a new event loop +// +evt_loop_t evt_create(); + +// +// Initializes an existing eventloop (as if it was new) +// +void evt_init(evt_loop_t t); + +// +// Destroys the given event loop, make sure +// that evt-run returned before. This will +// erase all pending events as well +// +void evt_destroy(evt_loop_t l); + +// +// Sends an event of type type with the given data +// to the given event loop +// +int evt_signal(evt_loop_t l, int type, void* data); + +// +// Executes the given event loop. +// Will return in two casees only: +// - The timeout expired (return value EVT_TIMEDOUT) +// - An event was returned (return value corresponds to the number of events returned) +// evt will contain the returned events as an array, with max_ct events maximum +// +int evt_run(evt_loop_t l, evt_event_t evt, int max_ct, const struct timespec* timeout); + +#endif /* KQUEUE_WINDOWS_EVENTLOOP_H */ diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index bece13119..f16b37983 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -16,6 +16,12 @@ #include "../common/private.h" +/* + * Per-thread evt event buffer used to ferry data between + * kevent_wait() and kevent_copyout(). + */ +static struct evt_event_s __thread pending_events[MAX_KEVENT]; + /* FIXME: remove these as filters are implemented */ const struct filter evfilt_proc = EVFILT_NOTIMPL; const struct filter evfilt_vnode = EVFILT_NOTIMPL; @@ -67,14 +73,14 @@ BOOL WINAPI DllMain( int windows_kqueue_init(struct kqueue *kq) { - kq->kq_handle = CreateEvent(NULL, FALSE, FALSE, NULL); - if (kq->kq_handle == NULL) { - dbg_perror("CreatEvent()"); + kq->kq_loop = evt_create(); + if (kq->kq_loop == NULL) { + dbg_perror("evt_create()"); return (-1); } if(filter_register_all(kq) < 0) { - CloseHandle(kq->kq_handle); + evt_destroy(kq->kq_loop); return (-1); } @@ -84,7 +90,7 @@ windows_kqueue_init(struct kqueue *kq) void windows_kqueue_free(struct kqueue *kq) { - CloseHandle(kq->kq_handle); + evt_destroy(kq->kq_loop); free(kq); } @@ -108,20 +114,19 @@ windows_kevent_wait(struct kqueue *kq, int no, const struct timespec *timeout) /* Wait for an event */ dbg_printf("waiting for %u events (timeout=%u ms)", kq->kq_filt_count, (unsigned int)timeout_ms); - rv = WaitForMultipleObjectsEx(kq->kq_filt_count, kq->kq_filt_handle, FALSE, timeout_ms, TRUE); + rv = evt_run(kq->kq_loop, pending_events, MAX_KEVENT, timeout); switch (rv) { - case WAIT_TIMEOUT: + case EVT_TIMEDOUT: dbg_puts("no events within the given timeout"); retval = 0; break; - case WAIT_FAILED: - dbg_lasterror("WaitForMultipleEvents()"); + case EVT_ERR: + dbg_lasterror("WaitForSingleEvent()"); retval = -1; default: - kq->kq_filt_signalled = rv; - retval = 1; + retval = rv; } return (retval); @@ -133,42 +138,50 @@ windows_kevent_copyout(struct kqueue *kq, int nready, { struct filter *filt; struct knote* kn; - int rv; - - /* KLUDGE: We are abusing the WAIT_FAILED constant to mean - that there are no filters with pending events. - */ - if (kq->kq_filt_signalled == WAIT_FAILED) - return (0); - filt = kq->kq_filt_ref[kq->kq_filt_signalled]; - kn = knote_lookup(filt, eventlist->ident); - if(kn == NULL) { - dbg_puts("knote_lookup failed"); - return (-1); + evt_event_t evt; + int i, rv, nret; + + assert(nready < MAX_KEVENT); + + nret = nready; + for(i = 0; i < nready; i++) { + evt = &(pending_events[i]); + kn = (struct knote*)evt->data; + knote_lock(kn); + filt = &kq->kq_filt[~(kn->kev.filter)]; + rv = filt->kf_copyout(eventlist, kn, evt); + knote_unlock(kn); + if (slowpath(rv < 0)) { + dbg_puts("knote_copyout failed"); + /* XXX-FIXME: hard to handle this without losing events */ + abort(); + } + + /* + * Certain flags cause the associated knote to be deleted + * or disabled. + */ + if (eventlist->flags & EV_DISPATCH) + knote_disable(filt, kn); //TODO: Error checking + if (eventlist->flags & EV_ONESHOT) + knote_release(filt, kn); //TODO: Error checking + + /* If an empty kevent structure is returned, the event is discarded. */ + if (fastpath(eventlist->filter != 0)) { + eventlist++; + } else { + dbg_puts("spurious wakeup, discarding event"); + nret--; + } } - kq->kq_filt_signalled = WAIT_FAILED; - rv = filt->kf_copyout(eventlist, kn, filt); - if (rv < 0) { - dbg_puts("kevent_copyout failed"); - return (-1); - } - return (1); + + return nret; } int windows_filter_init(struct kqueue *kq, struct filter *kf) { - HANDLE h; - h = CreateEvent(NULL, FALSE, FALSE, NULL); - if (h == NULL) { - dbg_perror("CreateEvent()"); - return (-1); - } - kf->kf_event_handle = h; - - /* Add the handle to the kqueue filter table */ - kq->kq_filt_handle[kq->kq_filt_count] = h; kq->kq_filt_ref[kq->kq_filt_count] = (struct filter *) kf; kq->kq_filt_count++; @@ -178,6 +191,5 @@ windows_filter_init(struct kqueue *kq, struct filter *kf) void windows_filter_free(struct kqueue *kq, struct filter *kf) { - CloseHandle(kf->kf_event_handle); - /* FIXME: Remove the handle from the kqueue filter table */ + } \ No newline at end of file diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 18ee425d8..12fa4979a 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -58,18 +58,21 @@ * Would be better to */ #define KQUEUE_PLATFORM_SPECIFIC \ - HANDLE kq_handle; \ - HANDLE kq_apc_dispatcher; \ - HANDLE kq_filt_handle[EVFILT_SYSCOUNT]; \ + evt_loop_t kq_loop; \ struct filter *kq_filt_ref[EVFILT_SYSCOUNT]; \ - size_t kq_filt_count; \ - DWORD kq_filt_signalled + size_t kq_filt_count /* * Additional members of struct filter */ -#define FILTER_PLATFORM_SPECIFIC \ - HANDLE kf_event_handle +//#define FILTER_PLATFORM_SPECIFIC \ +// HANDLE kf_event_handle + +/* + * Additional members for struct knote + */ +#define KNOTE_PLATFORM_SPECIFIC \ + HANDLE kn_event_whandle /* * Some datatype forward declarations @@ -151,4 +154,6 @@ typedef CRITICAL_SECTION pthread_rwlock_t; #define pthread_rwlock_unlock _cs_unlock #define pthread_rwlock_init(x,y) _cs_init((x)) +#include "event_loop.h" + #endif /* ! _KQUEUE_WINDOWS_PLATFORM_H */ diff --git a/vendor/libkqueue/src/windows/timer.c b/vendor/libkqueue/src/windows/timer.c index d06266d48..52a04487d 100644 --- a/vendor/libkqueue/src/windows/timer.c +++ b/vendor/libkqueue/src/windows/timer.c @@ -16,6 +16,9 @@ #include "../common/private.h" +/* Needed for safe termination of a pending timer */ +static struct knote __thread *about_to_delete = NULL; + /* Convert milliseconds into negative increments of 100-nanoseconds */ static void convert_msec_to_filetime(LARGE_INTEGER *dst, int src) @@ -26,9 +29,16 @@ convert_msec_to_filetime(LARGE_INTEGER *dst, int src) static int ktimer_delete(struct filter *filt, struct knote *kn) { - if (kn->data.handle == NULL) + + if (kn->data.handle == NULL || kn->kn_event_whandle == NULL) return (0); + about_to_delete = kn; + if(!UnregisterWaitEx(kn->kn_event_whandle, INVALID_HANDLE_VALUE)) { + dbg_lasterror("UnregisterWait()"); + return (-1); + } + if (!CancelWaitableTimer(kn->data.handle)) { dbg_lasterror("CancelWaitableTimer()"); return (-1); @@ -38,10 +48,32 @@ ktimer_delete(struct filter *filt, struct knote *kn) return (-1); } + about_to_delete = NULL; kn->data.handle = NULL; return (0); } +static VOID CALLBACK evfilt_timer_callback(void* param, BOOLEAN fired){ + struct knote* kn; + struct kqueue* kq; + + if(fired){ + dbg_printf("called, but timer did not fire - this case should never be reached"); + return; + } + + assert(param); + kn = (struct knote*)param; + dbg_printf("called for knote at %p, rc=%d", kn, kn->kn_ref); + if(about_to_delete == kn) { + dbg_printf("knote marked for deletion, skipping event"); + return; + } + kq = kn->kn_kq; + assert(kq); + evt_signal(kq->kq_loop, EVT_WAKEUP, kn); +} + int evfilt_timer_init(struct filter *filt) { @@ -56,7 +88,7 @@ evfilt_timer_destroy(struct filter *filt) int evfilt_timer_copyout(struct kevent* dst, struct knote* src, void* ptr) { - memcpy(dst, &src->kev, sizeof(struct kevent*)); + memcpy(dst, &src->kev, sizeof(struct kevent)); // TODO: Timer error handling /* We have no way to determine the number of times @@ -85,13 +117,15 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) convert_msec_to_filetime(&liDueTime, kn->kev.data); // XXX-FIXME add completion routine to this call - if (!SetWaitableTimer(th, &liDueTime, (kn->kev.flags & EV_ONESHOT), NULL, NULL, FALSE)) { + if (!SetWaitableTimer(th, &liDueTime, (kn->kev.flags & EV_ONESHOT) ? 0 : kn->kev.data, NULL, NULL, FALSE)) { dbg_lasterror("SetWaitableTimer()"); CloseHandle(th); return (-1); } kn->data.handle = th; + RegisterWaitForSingleObject(&kn->kn_event_whandle, th, evfilt_timer_callback, kn, INFINITE, 0); + return (0); } diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index ac5dc3a55..fd97863d0 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -137,7 +137,9 @@ main(int argc, char **argv) { "proc", 1, test_evfilt_proc }, #endif { "timer", 1, test_evfilt_timer }, +#ifndef _WIN32 { "vnode", 1, test_evfilt_vnode }, +#endif #if HAVE_EVFILT_USER { "user", 1, test_evfilt_user }, #endif From cfc671443c77e33b696c478172fb44e9003e144a Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 18 Apr 2011 01:41:26 +0000 Subject: [PATCH 0455/1120] By default, kevent() will serialize the copyout() and copyin() functions so that only one thread can operate on a kevent structure. This is controlled by the SERIALIZE_KEVENT macro. This temporarily restores the behavior from libkqueue 1.0 to give us time to implement fine-grained locking properly. New functions: kqueue_lock() and kqueue_unlock(). git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@484 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kevent.c | 12 ++++++ vendor/libkqueue/src/common/knote.c | 32 ++++++++++++++-- vendor/libkqueue/src/common/kqueue.c | 2 + vendor/libkqueue/src/common/private.h | 54 ++++++++++++++++++--------- 4 files changed, 79 insertions(+), 21 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 36ed99fd4..534199b82 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -262,7 +262,13 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, * Process each kevent on the changelist. */ if (nchanges > 0) { +#if SERIALIZE_KEVENT + kqueue_lock(kq); +#endif rv = kevent_copyin(kq, changelist, nchanges, eventlist, nevents); +#if SERIALIZE_KEVENT + kqueue_unlock(kq); +#endif dbg_printf("(%u) changelist: rv=%d", myid, rv); if (rv < 0) goto out; @@ -283,7 +289,13 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, rv = kqops.kevent_wait(kq, nevents, timeout); dbg_printf("kqops.kevent_wait returned %d", rv); if (fastpath(rv > 0)) { +#if SERIALIZE_KEVENT + kqueue_lock(kq); +#endif rv = kqops.kevent_copyout(kq, rv, eventlist, nevents); +#if SERIALIZE_KEVENT + kqueue_unlock(kq); +#endif } else if (rv == 0) { /* Timeout reached */ } else { diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 67fee8254..8d235d92d 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -49,6 +49,7 @@ knote_new(void) if (res == NULL) return (NULL); +#if ! SERIALIZE_KEVENT #ifdef _WIN32 pthread_mutex_init(&res->mtx, NULL); #else @@ -57,31 +58,48 @@ knote_new(void) free(res); return (NULL); } +#endif #endif return res; } -static inline void +void knote_retain(struct knote *kn) { +#if ! SERIALIZE_KEVENT atomic_inc(&kn->kn_ref); +#endif } void knote_release(struct filter *filt, struct knote *kn) { +#if SERIALIZE_KEVENT + knote_free(filt, kn); +#else int ref; - ref = atomic_dec(&kn->kn_ref); - if (ref <= 0) { + assert (kn->kn_ref >= 0); + + /* + * Optimize for the case where only a single thread is accessing + * the knote structure. + */ + if (fastpath(kn->kn_ref == 0)) + ref = 0; + else + ref = atomic_dec(&kn->kn_ref); + + if (ref == 0) { dbg_printf("freeing knote at %p, rc=%d", kn, ref); pthread_rwlock_wrlock(&filt->kf_knote_mtx); knote_free(filt, kn); pthread_rwlock_unlock(&filt->kf_knote_mtx); } else { - dbg_printf("NOT freeing knote %p rc=%d", kn, ref); + dbg_printf("decrementing refcount of knote %p rc=%d", kn, ref); } +#endif } void @@ -97,7 +115,9 @@ knote_free(struct filter *filt, struct knote *kn) { RB_REMOVE(knt, &filt->kf_knote, kn); filt->kn_delete(filt, kn); +#if ! SERIALIZE_KEVENT pthread_mutex_destroy(&kn->mtx); +#endif free(kn); // mem_free(kn); } @@ -131,8 +151,10 @@ knote_lookup(struct filter *filt, short ident) pthread_rwlock_rdlock(&filt->kf_knote_mtx); ent = RB_FIND(knt, &filt->kf_knote, &query); +#if ! SERIALIZE_KEVENT if (ent != NULL) knote_lock(ent); +#endif pthread_rwlock_unlock(&filt->kf_knote_mtx); dbg_printf("id=%d ent=%p", ident, ent); @@ -150,8 +172,10 @@ knote_lookup_data(struct filter *filt, intptr_t data) if (data == kn->kev.data) break; } +#if ! SERIALIZE_KEVENT if (kn != NULL) knote_lock(kn); +#endif pthread_rwlock_unlock(&filt->kf_knote_mtx); return (kn); diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 01f1f0a2a..5ec835f29 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -117,6 +117,8 @@ kqueue(void) if (kq == NULL) return (-1); + pthread_mutex_init(&kq->kq_mtx, NULL); + if (kqops.kqueue_init(kq) < 0) { free(kq); return (-1); diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 5708a332c..c4548068c 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -22,6 +22,12 @@ #include #include "tree.h" +/* If true, calls to kevent() will be serialized so that only a + single thread can copyin/copyout. This should go away once + fine-grained locking is fixed. +*/ +#define SERIALIZE_KEVENT 1 + /* Maximum events returnable in a single kevent() call */ #define MAX_KEVENT 512 @@ -63,7 +69,6 @@ struct eventfd { struct knote { struct kevent kev; int flags; - pthread_mutex_t mtx; union { /* OLD */ int pfd; /* Used by timerfd */ @@ -76,8 +81,11 @@ struct knote { pthread_t tid; /* Used by posix/timer.c */ void *handle; /* Used by win32 filters */ } data; - volatile uint32_t kn_ref; struct kqueue* kn_kq; +#if ! SERIALIZE_KEVENT + pthread_mutex_t mtx; + volatile uint32_t kn_ref; +#endif #if defined(KNOTE_PLATFORM_SPECIFIC) KNOTE_PLATFORM_SPECIFIC; #endif @@ -136,6 +144,8 @@ struct kqueue { struct filter kq_filt[EVFILT_SYSCOUNT]; fd_set kq_fds, kq_rfds; int kq_nfds; + pthread_mutex_t kq_mtx; + volatile uint32_t kq_ref; #if defined(KQUEUE_PLATFORM_SPECIFIC) KQUEUE_PLATFORM_SPECIFIC; #endif @@ -165,21 +175,31 @@ struct kqueue_vtable { }; extern const struct kqueue_vtable kqops; -struct knote * knote_lookup(struct filter *, short); -struct knote * knote_lookup_data(struct filter *filt, intptr_t); -struct knote * knote_new(void); -void knote_release(struct filter *, struct knote *); -void knote_free_all(struct filter *); -void knote_insert(struct filter *, struct knote *); -int knote_init(void); - -/* TODO: these deal with the eventlist, should use a different prefix */ -//DEADWOOD:void knote_enqueue(struct filter *, struct knote *); -//DEADWOOD:struct knote * knote_dequeue(struct filter *); -//DEADWOOD:int knote_events_pending(struct filter *); -int knote_disable(struct filter *, struct knote *); -#define knote_lock(kn) pthread_mutex_lock(&(kn)->mtx) -#define knote_unlock(kn) pthread_mutex_unlock(&(kn)->mtx) +/* + * kqueue internal API + */ +#define kqueue_lock(kq) pthread_mutex_lock(&(kq)->kq_mtx) +#define kqueue_unlock(kq) pthread_mutex_unlock(&(kq)->kq_mtx) + +/* + * knote internal API + */ +struct knote * knote_lookup(struct filter *, short); +struct knote * knote_lookup_data(struct filter *filt, intptr_t); +struct knote * knote_new(void); +void knote_release(struct filter *, struct knote *); +void knote_retain(struct knote *); +void knote_free_all(struct filter *); +void knote_insert(struct filter *, struct knote *); +int knote_init(void); +int knote_disable(struct filter *, struct knote *); +#if ! SERIALIZE_KEVENT +#define knote_lock(kn) pthread_mutex_lock(&(kn)->mtx) +#define knote_unlock(kn) pthread_mutex_unlock(&(kn)->mtx) +#else +#define knote_lock(kn) do {} while (0) +#define knote_unlock(kn) do {} while (0) +#endif int filter_lookup(struct filter **, struct kqueue *, short); int filter_register_all(struct kqueue *); From 388c7c42b394fc07b1e4004f6459805590ea8bb9 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 23 Apr 2011 18:27:10 +0000 Subject: [PATCH 0456/1120] Fix various build issues on MinGW. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@485 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 15 +++++++++------ vendor/libkqueue/config.inc | 20 ++++++++++++++++++-- vendor/libkqueue/configure | 2 +- vendor/libkqueue/src/common/kqueue.c | 16 +++++++--------- vendor/libkqueue/src/windows/event_loop.c | 1 - vendor/libkqueue/src/windows/platform.h | 14 ++++++++++---- vendor/libkqueue/src/windows/timer.c | 7 ++++--- vendor/libkqueue/test/Makefile | 2 +- vendor/libkqueue/test/config.inc | 16 +++++++++++++++- vendor/libkqueue/test/test.c | 2 ++ 10 files changed, 67 insertions(+), 28 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 9c44b9426..0e9945ecd 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -58,14 +58,17 @@ uninstall: rm -f $(MANDIR)/man2/kevent.2 rmdir $(INCLUDEDIR)/kqueue/sys $(INCLUDEDIR)/kqueue -check: clean $(PROGRAM).so.$(ABI_VERSION) - cd test && ./configure && make check +test/config.mk: + cd test && ../configure -debug: clean $(PROGRAM).so.$(ABI_VERSION) - cd test && ./configure && make debug +check: clean $(PROGRAM).so.$(ABI_VERSION) test/config.mk + cd test && make check -debug-check: clean - cd test && ./configure && KQUEUE_DEBUG=y make check +debug: clean $(PROGRAM).so.$(ABI_VERSION) test/config.mk + cd test && make debug + +debug-check: clean test/config.mk + cd test && KQUEUE_DEBUG=y make check $(DISTFILE): $(SOURCES) $(HEADERS) mkdir $(PROGRAM)-$(VERSION) diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index 78e9b1c35..c08fc8f59 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -3,7 +3,7 @@ version="2.0a" abi_major="0" abi_minor="0" abi_version="$abi_major.$abi_minor" -cflags="-fpic -Wall -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600" +cflags="-Wall -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600" ldflags="" sources="src/common/filter.c src/common/knote.c src/common/map.c src/common/kevent.c src/common/kqueue.c" @@ -25,6 +25,10 @@ pre_configure_hook() { cflags="$cflags -g3 -O0 -rdynamic" fi + if [ "$target" != "windows" ] ; then + cflags="$cflags -fpic" + fi + optional_headers="err.h" libdepends=" -L$libdir" @@ -32,7 +36,7 @@ pre_configure_hook() { check_symbol sys/epoll.h EPOLLRDHUP - # Actually a GCC 4.X dependency + # TODO - note this as a GCC 4.X dependency cflags="$cflags -fvisibility=hidden" libdepends="$libdepends -lpthread -lrt" @@ -93,6 +97,18 @@ post_configure_hook() { evfilt_vnode="" fi + if [ $target = "windows" ] ; then + platform="src/windows/platform.c src/windows/event_loop.c" + cflags="$cflags -march=i686" + ldflags="$ldflags -march=i686" + evfilt_proc="" + evfilt_signal="" + evfilt_socket="" + evfilt_timer="src/windows/timer.c" + evfilt_user="" + evfilt_vnode="" + fi + sources="$sources $platform $evfilt_signal $evfilt_proc $evfilt_socket $evfilt_timer $evfilt_user $evfilt_vnode" diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index 177cad3cf..7db442928 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -186,7 +186,7 @@ check_target() { "gnu/kfreebsd") default_target="freebsd" ;; - "mingw*") + mingw*) default_target="windows" default_api="windows" ;; diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 5ec835f29..cab472fa5 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -56,21 +56,19 @@ libkqueue_init(void) { #ifdef NDEBUG DEBUG_ACTIVE = 0; -#elif _WIN32 - /* Experimental port, always debug */ - DEBUG_ACTIVE = 1; -# ifndef __GNUC__ +#else + char *s = getenv("KQUEUE_DEBUG"); + if (s != NULL && strlen(s) > 0) { + DEBUG_ACTIVE = 1; +# if defined(_WIN32) && !defined(__GNUC__) /* Enable heap surveillance */ { int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ); tmpFlag |= _CRTDBG_CHECK_ALWAYS_DF; _CrtSetDbgFlag(tmpFlag); } -# endif -#else - char *s = getenv("KQUEUE_DEBUG"); - if (s != NULL && strlen(s) > 0) - DEBUG_ACTIVE = 1; +# endif /* _WIN32 */ + } #endif kqmap = map_new(get_fd_limit()); // INT_MAX diff --git a/vendor/libkqueue/src/windows/event_loop.c b/vendor/libkqueue/src/windows/event_loop.c index 6ed332bc5..64c2b088a 100644 --- a/vendor/libkqueue/src/windows/event_loop.c +++ b/vendor/libkqueue/src/windows/event_loop.c @@ -104,7 +104,6 @@ int pthread_cond_timedwait(pthread_cond_t *cv, // being called or being called. rv = WaitForMultipleObjects (2, cv->events_, FALSE, timeout_ms); if( rv == WAIT_TIMEOUT) { - int r = 0; return EVT_TIMEDOUT; } else if(rv == WAIT_FAILED) { dbg_lasterror("cond_timedwait failed"); diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 12fa4979a..2cb6a5618 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -17,6 +17,10 @@ #ifndef _KQUEUE_WINDOWS_PLATFORM_H #define _KQUEUE_WINDOWS_PLATFORM_H +/* Require Windows XP or later */ +#define WINVER 0x0501 +#define _WIN32_WINNT 0x0501 + /* Reduces build time by omitting extra system headers */ #define WIN32_LEAN_AND_MEAN @@ -43,8 +47,8 @@ #ifdef __GNUC__ # define atomic_inc(p) __sync_add_and_fetch((p), 1) # define atomic_dec(p) __sync_sub_and_fetch((p), 1) -# define atomic_cas(p, oval, nval) __sync_val_compare_and_swap(p, oval, nval) -# define atomic_ptr_cas(p, oval, nval) __sync_val_compare_and_swap(p, oval, nval) +# define atomic_cas(p, v0, v1) __sync_val_compare_and_swap((p), (v0), (v1)) +# define atomic_ptr_cas(p, v0, v1) __sync_val_compare_and_swap((p), (v0), (v1)) #else # define atomic_inc InterlockedIncrement # define atomic_dec InterlockedDecrement @@ -65,8 +69,10 @@ /* * Additional members of struct filter */ -//#define FILTER_PLATFORM_SPECIFIC \ -// HANDLE kf_event_handle +/* +#define FILTER_PLATFORM_SPECIFIC \ + HANDLE kf_event_handle +*/ /* * Additional members for struct knote diff --git a/vendor/libkqueue/src/windows/timer.c b/vendor/libkqueue/src/windows/timer.c index 52a04487d..07feb9105 100644 --- a/vendor/libkqueue/src/windows/timer.c +++ b/vendor/libkqueue/src/windows/timer.c @@ -58,15 +58,16 @@ static VOID CALLBACK evfilt_timer_callback(void* param, BOOLEAN fired){ struct kqueue* kq; if(fired){ - dbg_printf("called, but timer did not fire - this case should never be reached"); + dbg_puts("called, but timer did not fire - this case should never be reached"); return; } assert(param); kn = (struct knote*)param; - dbg_printf("called for knote at %p, rc=%d", kn, kn->kn_ref); +// FIXME: depends on ! SERIALIZE_KEVENT +// dbg_printf("called for knote at %p, rc=%d", kn, kn->kn_ref); if(about_to_delete == kn) { - dbg_printf("knote marked for deletion, skipping event"); + dbg_puts("knote marked for deletion, skipping event"); return; } kq = kn->kn_kq; diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile index 78ce7275b..e129b6d50 100644 --- a/vendor/libkqueue/test/Makefile +++ b/vendor/libkqueue/test/Makefile @@ -22,7 +22,7 @@ kqtest: $(SOURCES) $(CC) -o kqtest $(CFLAGS) $(SOURCES) $(LDADD) check: kqtest - LD_LIBRARY_PATH="..:/usr/sfw/lib/64" ./kqtest + LD_LIBRARY_PATH="..:/usr/sfw/lib/64" PATH="$$PATH:.." ./kqtest debug: kqtest LD_LIBRARY_PATH="..:/usr/sfw/lib/64" gdb ./kqtest diff --git a/vendor/libkqueue/test/config.inc b/vendor/libkqueue/test/config.inc index 885933a22..b80227e63 100755 --- a/vendor/libkqueue/test/config.inc +++ b/vendor/libkqueue/test/config.inc @@ -13,7 +13,12 @@ pre_configure_hook() { || { sys_event_h="../include/sys/event.h" cflags="$cflags -I../include -L.." - ldadd="$ldadd -lkqueue -lpthread -lrt" + if [ "$target" = "windows" ] + then + ldadd="$ldadd ../libkqueue.so" + else + ldadd="$ldadd -lkqueue -lpthread -lrt" + fi } check_symbol $sys_event_h EV_DISPATCH @@ -35,4 +40,13 @@ pre_configure_hook() { cflags="$cflags -rdynamic" fi + if [ "$target" = "windows" ] + then + cflags="$cflags -march=i686" + ldflags="$ldflags -march=i686" + ldadd="$ldadd -lws2_32" + # KLUDGE: to remove signal.c, proc.c + sources="main.c kevent.c test.c read.c timer.c vnode.c" + fi + } diff --git a/vendor/libkqueue/test/test.c b/vendor/libkqueue/test/test.c index 9dc9482d2..f935b1d9e 100644 --- a/vendor/libkqueue/test/test.c +++ b/vendor/libkqueue/test/test.c @@ -27,6 +27,7 @@ static int error_flag = 1; static char * cur_test_id = NULL; /* FIXME: not portable beyond linux */ +#ifndef _WIN32 static void error_handler(int signum) { @@ -41,6 +42,7 @@ error_handler(int signum) #endif exit(1); } +#endif /* ! _WIN32 */ static void testing_atexit(void) From 9e1c2363c1f0aab260156c7b907d176d0275adc9 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 24 Apr 2011 02:56:17 +0000 Subject: [PATCH 0457/1120] Change the EVFILT_READ test to use TCP sockets instead of UNIX domain sockets, so the tests can be run on Windows. Fix a bug on Linux where epoll() will not return EPOLLHUP when a TCP socket is closed. Instead, it will return POLLIN with zero bytes in the protocol buffer. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@486 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/linux/read.c | 5 +- vendor/libkqueue/test/read.c | 103 ++++++++++++++++++++---------- 2 files changed, 74 insertions(+), 34 deletions(-) diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index 4ab12a586..3d72e3948 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -103,7 +103,7 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) return (0); } - epoll_event_dump(ev); + dbg_printf("epoll: %s", epoll_event_dump(ev)); memcpy(dst, &src->kev, sizeof(*dst)); #if defined(HAVE_EPOLLRDHUP) if (ev->events & EPOLLRDHUP || ev->events & EPOLLHUP) @@ -128,6 +128,9 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) /* race condition with socket close, so ignore this error */ dbg_puts("ioctl(2) of socket failed"); dst->data = 0; + } else { + if (dst->data == 0) + dst->flags |= EV_EOF; } } diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 89d1f2066..71b05017b 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -18,7 +18,48 @@ #include "common.h" static int __thread kqfd; -static int __thread sockfd[2]; +static int __thread client_fd; +static int __thread server_fd; + +/* + * Create a connected TCP socket. + */ +static void +create_socket_connection(int *client, int *server, const short port) +{ + struct sockaddr_in sain; + socklen_t sa_len = sizeof(sain); + int one = 1; + int clnt, srvr, accepted; + + /* Create a passive socket */ + memset(&sain, 0, sizeof(sain)); + sain.sin_family = AF_INET; + sain.sin_port = htons(port); + if ((srvr = socket(PF_INET, SOCK_STREAM, 0)) < 0) + err(1, "socket"); + if (setsockopt(srvr, SOL_SOCKET, SO_REUSEADDR, + (char *) &one, sizeof(one)) != 0) + err(1, "setsockopt"); + if (bind(srvr, (struct sockaddr *) &sain, sa_len) < 0) + err(1, "bind"); + if (listen(srvr, 100) < 0) + err(1, "listen"); + + /* Simulate a client connecting to the server */ + sain.sin_family = AF_INET; + sain.sin_port = htons(port); + sain.sin_addr.s_addr = inet_addr("127.0.0.1"); + if ((clnt = socket(AF_INET, SOCK_STREAM, 0)) < 0) + err(1, "clnt: socket"); + if (connect(clnt, (struct sockaddr *) &sain, sa_len) < 0) + err(1, "clnt: connect"); + if ((accepted = accept(srvr, NULL, 0)) < 0) + err(1, "srvr: accept"); + + *client = clnt; + *server = accepted; +} static void kevent_socket_drain(void) @@ -26,15 +67,15 @@ kevent_socket_drain(void) char buf[1]; /* Drain the read buffer, then make sure there are no more events. */ - if (read(sockfd[0], &buf[0], 1) < 1) - die("read(2)"); + if (recv(client_fd, &buf[0], 1, 0) < 1) + die("recv(2)"); } static void kevent_socket_fill(void) { - if (write(sockfd[1], ".", 1) < 1) - die("write(2)"); + if (send(server_fd, ".", 1, 0) < 1) + die("send(2)"); } @@ -43,7 +84,7 @@ test_kevent_socket_add(void) { struct kevent kev; - kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); + kevent_add(kqfd, &kev, client_fd, EVFILT_READ, EV_ADD, 0, 0, &client_fd); } void @@ -52,7 +93,7 @@ test_kevent_socket_add_without_ev_add(void) struct kevent kev; /* Try to add a kevent without specifying EV_ADD */ - EV_SET(&kev, sockfd[0], EVFILT_READ, 0, 0, 0, &sockfd[0]); + EV_SET(&kev, client_fd, EVFILT_READ, 0, 0, 0, &client_fd); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0) die("kevent should have failed"); @@ -71,9 +112,9 @@ test_kevent_socket_get(void) { struct kevent kev; - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); + EV_SET(&kev, client_fd, EVFILT_READ, EV_ADD, 0, 0, &client_fd); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("kevent"); + die("kevent:1"); kevent_socket_fill(); @@ -85,7 +126,7 @@ test_kevent_socket_get(void) kev.flags = EV_DELETE; if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("kevent"); + die("kevent:2"); } void @@ -96,7 +137,7 @@ test_kevent_socket_clear(void) test_no_kevents(kqfd); kevent_socket_drain(); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &sockfd[0]); + EV_SET(&kev, client_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &client_fd); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent1"); @@ -118,7 +159,7 @@ test_kevent_socket_clear(void) test_no_kevents(kqfd); kevent_socket_drain(); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); + EV_SET(&kev, client_fd, EVFILT_READ, EV_DELETE, 0, 0, &client_fd); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent2"); } @@ -129,10 +170,10 @@ test_kevent_socket_disable_and_enable(void) struct kevent kev; /* Add an event, then disable it. */ - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); + EV_SET(&kev, client_fd, EVFILT_READ, EV_ADD, 0, 0, &client_fd); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent"); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DISABLE, 0, 0, &sockfd[0]); + EV_SET(&kev, client_fd, EVFILT_READ, EV_DISABLE, 0, 0, &client_fd); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent"); @@ -159,7 +200,7 @@ test_kevent_socket_del(void) { struct kevent kev; - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); + EV_SET(&kev, client_fd, EVFILT_READ, EV_DELETE, 0, 0, &client_fd); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent"); @@ -174,7 +215,7 @@ test_kevent_socket_oneshot(void) struct kevent kev; /* Re-add the watch and make sure no events are pending */ - kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]); + kevent_add(kqfd, &kev, client_fd, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &client_fd); test_no_kevents(kqfd); kevent_socket_fill(); @@ -243,7 +284,7 @@ test_kevent_socket_dispatch(void) struct kevent kev; /* Re-add the watch and make sure no events are pending */ - kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &sockfd[0]); + kevent_add(kqfd, &kev, client_fd, EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &client_fd); test_no_kevents(kqfd); /* The event will occur only once, even though EV_CLEAR is not @@ -255,14 +296,14 @@ test_kevent_socket_dispatch(void) /* Re-enable the kevent */ /* FIXME- is EV_DISPATCH needed when rearming ? */ - kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_ENABLE | EV_DISPATCH, 0, 0, &sockfd[0]); + kevent_add(kqfd, &kev, client_fd, EVFILT_READ, EV_ENABLE | EV_DISPATCH, 0, 0, &client_fd); kev.data = 1; kev.flags = EV_ADD | EV_DISPATCH; /* FIXME: may not be portable */ kevent_cmp(&kev, kevent_get(kqfd)); test_no_kevents(kqfd); /* Since the knote is disabled, the EV_DELETE operation succeeds. */ - kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); + kevent_add(kqfd, &kev, client_fd, EVFILT_READ, EV_DELETE, 0, 0, &client_fd); kevent_socket_drain(); } @@ -278,7 +319,7 @@ test_kevent_socket_lowat(void) /* Re-add the watch and make sure no events are pending */ puts("-- re-adding knote, setting low watermark to 2 bytes"); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &sockfd[0]); + EV_SET(&kev, client_fd, EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &client_fd); if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) die("%s", test_id); test_no_kevents(); @@ -291,7 +332,7 @@ test_kevent_socket_lowat(void) kevent_socket_fill(); if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) die("%s", test_id); - KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); + KEV_CMP(kev, client_fd, EVFILT_READ, 0); test_no_kevents(); kevent_socket_drain(); @@ -305,17 +346,19 @@ test_kevent_socket_eof(void) struct kevent kev; /* Re-add the watch and make sure no events are pending */ - kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); + kevent_add(kqfd, &kev, client_fd, EVFILT_READ, EV_ADD, 0, 0, &client_fd); test_no_kevents(kqfd); - if (close(sockfd[1]) < 0) + //if (shutdown(server_fd, SHUT_RDWR) < 0) + // die("close(2)"); + if (close(server_fd) < 0) die("close(2)"); kev.flags |= EV_EOF; kevent_cmp(&kev, kevent_get(kqfd)); /* Delete the watch */ - kevent_add(kqfd, &kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); + kevent_add(kqfd, &kev, client_fd, EVFILT_READ, EV_DELETE, 0, 0, &client_fd); } /* Test if EVFILT_READ works with regular files */ @@ -365,13 +408,7 @@ test_kevent_regular_file(void) void test_evfilt_read(int _kqfd) { -#ifdef _WIN32 - die("XXX-FIXME"); -#else - /* Create a connected pair of full-duplex sockets for testing socket events */ - if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) - die("socketpair"); -#endif + create_socket_connection(&client_fd, &server_fd, 23456); kqfd = _kqfd; test(kevent_socket_add); @@ -387,6 +424,6 @@ test_evfilt_read(int _kqfd) test(kevent_socket_listen_backlog); test(kevent_socket_eof); test(kevent_regular_file); - close(sockfd[0]); - close(sockfd[1]); + close(client_fd); + close(server_fd); } From 9e8ba821257e3da6ff7de30d65218f9141be00b9 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 25 Apr 2011 02:50:54 +0000 Subject: [PATCH 0458/1120] Partial implementation of EVFILT_READ on Windows. Switch to using IOCP as the synchronization mechanism on Windows instead of emulating pthread condition variables. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@487 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/config.inc | 6 +- vendor/libkqueue/src/common/debug.h | 18 +++- vendor/libkqueue/src/windows/platform.c | 128 ++++++++++++++++-------- vendor/libkqueue/src/windows/platform.h | 4 +- vendor/libkqueue/src/windows/timer.c | 8 ++ vendor/libkqueue/test/main.c | 10 +- 6 files changed, 120 insertions(+), 54 deletions(-) diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index c08fc8f59..a9c18b3a0 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -99,11 +99,13 @@ post_configure_hook() { if [ $target = "windows" ] ; then platform="src/windows/platform.c src/windows/event_loop.c" - cflags="$cflags -march=i686" + cflags="$cflags -march=i686 -lws2_32" ldflags="$ldflags -march=i686" + ldadd="-lws2_32" evfilt_proc="" evfilt_signal="" - evfilt_socket="" + #evfilt_socket="src/windows/read.c src/linux/write.c" + evfilt_socket="src/windows/read.c" evfilt_timer="src/windows/timer.c" evfilt_user="" evfilt_vnode="" diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index 983a9071c..c95435d30 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -61,16 +61,24 @@ extern char *DEBUG_IDENT; fprintf(stderr, "%s: [%d] %s(): %s: (LastError=%d)\n", \ DEBUG_IDENT, THREAD_ID, __func__, str, (int)GetLastError()); \ } while (0) + +# define dbg_wsalasterror(str) do { \ + if (DEBUG_ACTIVE) \ + fprintf(stderr, "%s: [%d] %s(): %s: (WSALastError=%d)\n", \ + DEBUG_IDENT, THREAD_ID, __func__, str, (int)WSAGetLastError()); \ +} while (0) # else # define dbg_lasterror(str) ; +# define dbg_wsalasterror(str) ; # endif #else /* NDEBUG */ -# define dbg_puts(str) ; -# define dbg_printf(fmt,...) ; -# define dbg_perror(str) ; -# define dbg_lasterror(str) ; -# define reset_errno() ; +# define dbg_puts(str) do {} while (0) +# define dbg_printf(fmt,...) do {} while (0) +# define dbg_perror(str) do {} while (0) +# define dbg_lasterror(str) do {} while (0) +# define dbg_wsalasterror(str) do {} while (0) +# define reset_errno() do {} while (0) #endif #endif /* ! _DEBUG_H */ diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index f16b37983..94af24fc6 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -16,27 +16,32 @@ #include "../common/private.h" +struct event_buf { + DWORD bytes; + ULONG_PTR key; + OVERLAPPED *overlap; +}; + /* * Per-thread evt event buffer used to ferry data between * kevent_wait() and kevent_copyout(). */ -static struct evt_event_s __thread pending_events[MAX_KEVENT]; +static __thread struct event_buf iocp_buf; /* FIXME: remove these as filters are implemented */ const struct filter evfilt_proc = EVFILT_NOTIMPL; const struct filter evfilt_vnode = EVFILT_NOTIMPL; const struct filter evfilt_signal = EVFILT_NOTIMPL; const struct filter evfilt_write = EVFILT_NOTIMPL; -const struct filter evfilt_read = EVFILT_NOTIMPL; const struct filter evfilt_user = EVFILT_NOTIMPL; const struct kqueue_vtable kqops = { windows_kqueue_init, windows_kqueue_free, - windows_kevent_wait, - windows_kevent_copyout, - windows_filter_init, - windows_filter_free, + windows_kevent_wait, + windows_kevent_copyout, + windows_filter_init, + windows_filter_free, }; #ifndef MAKE_STATIC @@ -73,11 +78,29 @@ BOOL WINAPI DllMain( int windows_kqueue_init(struct kqueue *kq) { + kq->kq_iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, + (ULONG_PTR) 0, 0); + if (kq->kq_iocp == NULL) { + dbg_lasterror("CreateIoCompletionPort"); + return (-1); + } + + /* Create a handle whose sole purpose is to indicate a synthetic + * IO event. */ + kq->kq_synthetic_event = CreateSemaphore(NULL, 0, 1, NULL); + if (kq->kq_synthetic_event == NULL) { + /* FIXME: close kq_iocp */ + dbg_lasterror("CreateSemaphore"); + return (-1); + } + +#if DEADWOOD kq->kq_loop = evt_create(); if (kq->kq_loop == NULL) { dbg_perror("evt_create()"); return (-1); } +#endif if(filter_register_all(kq) < 0) { evt_destroy(kq->kq_loop); @@ -98,7 +121,8 @@ int windows_kevent_wait(struct kqueue *kq, int no, const struct timespec *timeout) { int retval; - DWORD rv, timeout_ms; + DWORD timeout_ms; + BOOL success; /* Convert timeout to milliseconds */ /* NOTE: loss of precision for timeout values less than 1ms */ @@ -112,6 +136,25 @@ windows_kevent_wait(struct kqueue *kq, int no, const struct timespec *timeout) timeout_ms += timeout->tv_nsec / 1000000; } + dbg_printf("waiting for events (timeout=%u ms)", (unsigned int) timeout_ms); + memset(&iocp_buf, 0, sizeof(iocp_buf)); + success = GetQueuedCompletionStatus(kq->kq_iocp, + &iocp_buf.bytes, &iocp_buf.key, &iocp_buf.overlap, + timeout_ms); + if (success) { + return (1); + } else { + if (GetLastError() == WAIT_TIMEOUT) { + dbg_puts("no events within the given timeout"); + return (0); + } + dbg_lasterror("GetQueuedCompletionStatus"); + return (-1); + } + +#if DEADWOOD + DWORD rv; + /* Wait for an event */ dbg_printf("waiting for %u events (timeout=%u ms)", kq->kq_filt_count, (unsigned int)timeout_ms); rv = evt_run(kq->kq_loop, pending_events, MAX_KEVENT, timeout); @@ -128,7 +171,8 @@ windows_kevent_wait(struct kqueue *kq, int no, const struct timespec *timeout) default: retval = rv; } - +#endif + return (retval); } @@ -138,42 +182,38 @@ windows_kevent_copyout(struct kqueue *kq, int nready, { struct filter *filt; struct knote* kn; - evt_event_t evt; - int i, rv, nret; - - assert(nready < MAX_KEVENT); - - nret = nready; - for(i = 0; i < nready; i++) { - evt = &(pending_events[i]); - kn = (struct knote*)evt->data; - knote_lock(kn); - filt = &kq->kq_filt[~(kn->kev.filter)]; - rv = filt->kf_copyout(eventlist, kn, evt); - knote_unlock(kn); - if (slowpath(rv < 0)) { - dbg_puts("knote_copyout failed"); - /* XXX-FIXME: hard to handle this without losing events */ - abort(); - } + int rv, nret; + + //FIXME: not true for EVFILT_IOCP + kn = (struct knote *) iocp_buf.overlap; + knote_lock(kn); + filt = &kq->kq_filt[~(kn->kev.filter)]; + rv = filt->kf_copyout(eventlist, kn, &iocp_buf); + knote_unlock(kn); + if (slowpath(rv < 0)) { + dbg_puts("knote_copyout failed"); + /* XXX-FIXME: hard to handle this without losing events */ + abort(); + } else { + nret = 1; + } - /* - * Certain flags cause the associated knote to be deleted - * or disabled. - */ - if (eventlist->flags & EV_DISPATCH) - knote_disable(filt, kn); //TODO: Error checking - if (eventlist->flags & EV_ONESHOT) - knote_release(filt, kn); //TODO: Error checking - - /* If an empty kevent structure is returned, the event is discarded. */ - if (fastpath(eventlist->filter != 0)) { - eventlist++; - } else { - dbg_puts("spurious wakeup, discarding event"); - nret--; - } - } + /* + * Certain flags cause the associated knote to be deleted + * or disabled. + */ + if (eventlist->flags & EV_DISPATCH) + knote_disable(filt, kn); //TODO: Error checking + if (eventlist->flags & EV_ONESHOT) + knote_release(filt, kn); //TODO: Error checking + + /* If an empty kevent structure is returned, the event is discarded. */ + if (fastpath(eventlist->filter != 0)) { + eventlist++; + } else { + dbg_puts("spurious wakeup, discarding event"); + nret--; + } return nret; } @@ -192,4 +232,4 @@ void windows_filter_free(struct kqueue *kq, struct filter *kf) { -} \ No newline at end of file +} diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 2cb6a5618..d56078aef 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -58,10 +58,10 @@ /* * Additional members of struct kqueue - * FIXME: This forces a thread-per-filter model - * Would be better to */ #define KQUEUE_PLATFORM_SPECIFIC \ + HANDLE kq_iocp; \ + HANDLE kq_synthetic_event; \ evt_loop_t kq_loop; \ struct filter *kq_filt_ref[EVFILT_SYSCOUNT]; \ size_t kq_filt_count diff --git a/vendor/libkqueue/src/windows/timer.c b/vendor/libkqueue/src/windows/timer.c index 07feb9105..ca39a9c40 100644 --- a/vendor/libkqueue/src/windows/timer.c +++ b/vendor/libkqueue/src/windows/timer.c @@ -72,7 +72,15 @@ static VOID CALLBACK evfilt_timer_callback(void* param, BOOLEAN fired){ } kq = kn->kn_kq; assert(kq); + + if (!PostQueuedCompletionStatus(kq->kq_iocp, 1, (ULONG_PTR) 0, (LPOVERLAPPED) kn)) { + dbg_lasterror("PostQueuedCompletionStatus()"); + return; + /* FIXME: need more extreme action */ + } +#if DEADWOOD evt_signal(kq->kq_loop, EVT_WAKEUP, kn); +#endif } int diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index fd97863d0..1f1c7b7d1 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -128,8 +128,8 @@ int main(int argc, char **argv) { struct unit_test tests[] = { + { "socket", 1, test_evfilt_read }, #ifndef _WIN32 - { "socket", 1, test_evfilt_read }, { "signal", 1, test_evfilt_signal }, #endif @@ -149,6 +149,14 @@ main(int argc, char **argv) char *arg; int match, kqfd; + +#ifdef _WIN32 + /* Initialize the Winsock library */ + WSADATA wsaData; + if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) + err(1, "WSAStartup failed"); +#endif + /* If specific tests are requested, disable all tests by default */ if (argc > 1) { for (test = &tests[0]; test->ut_name != NULL; test++) { From 0977fdf30de657e07413ca06caedd3fe62de9e79 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 25 Apr 2011 23:21:07 +0000 Subject: [PATCH 0459/1120] Commit a missing file that was accidentally ommited. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@488 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/windows/read.c | 208 ++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 vendor/libkqueue/src/windows/read.c diff --git a/vendor/libkqueue/src/windows/read.c b/vendor/libkqueue/src/windows/read.c new file mode 100644 index 000000000..ce085eeef --- /dev/null +++ b/vendor/libkqueue/src/windows/read.c @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "../common/private.h" + +static VOID CALLBACK +evfilt_read_callback(void *param, BOOLEAN fired) +{ + struct kqueue *kq; + struct knote *kn; + + assert(param); + + if (fired) { + dbg_puts("called, but event was not triggered(?)"); + return; + } + + assert(param); + kn = (struct knote*)param; + // FIXME: check if knote is pending destroyed + kq = kn->kn_kq; + assert(kq); + + if (!PostQueuedCompletionStatus(kq->kq_iocp, 1, (ULONG_PTR) 0, (LPOVERLAPPED) param)) { + dbg_lasterror("PostQueuedCompletionStatus()"); + return; + /* FIXME: need more extreme action */ + } + + /* DEADWOOD + kn = (struct knote *) param; + evt_signal(kn->kn_kq->kq_loop, EVT_WAKEUP, kn); + */ +} + +#if FIXME +static intptr_t +get_eof_offset(int fd) +{ + off_t curpos; + struct stat sb; + + curpos = lseek(fd, 0, SEEK_CUR); + if (curpos == (off_t) -1) { + dbg_perror("lseek(2)"); + curpos = 0; + } + if (fstat(fd, &sb) < 0) { + dbg_perror("fstat(2)"); + sb.st_size = 1; + } + + dbg_printf("curpos=%zu size=%zu\n", curpos, sb.st_size); + return (sb.st_size - curpos); //FIXME: can overflow +} +#endif + +int +evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) +{ +#if FIXME + struct event_buf * const ev = (struct event_buf *) ptr; + + /* FIXME: for regular files, return the offset from current position to end of file */ + //if (src->flags & KNFL_REGULAR_FILE) { ... } + + epoll_event_dump(ev); + memcpy(dst, &src->kev, sizeof(*dst)); +#if defined(HAVE_EPOLLRDHUP) + if (ev->events & EPOLLRDHUP || ev->events & EPOLLHUP) + dst->flags |= EV_EOF; +#else + if (ev->events & EPOLLHUP) + dst->flags |= EV_EOF; +#endif + if (ev->events & EPOLLERR) + dst->fflags = 1; /* FIXME: Return the actual socket error */ + + if (src->flags & KNFL_PASSIVE_SOCKET) { + /* On return, data contains the length of the + socket backlog. This is not available under Linux. + */ + dst->data = 1; + } else { + /* On return, data contains the number of bytes of protocol + data available to read. + */ + if (ioctl(dst->ident, SIOCINQ, &dst->data) < 0) { + /* race condition with socket close, so ignore this error */ + dbg_puts("ioctl(2) of socket failed"); + dst->data = 0; + } + } +#endif + + return (0); +} + +int +evfilt_read_knote_create(struct filter *filt, struct knote *kn) +{ + HANDLE evt; + int rv; + + /* Create an auto-reset event object */ + evt = CreateEvent(NULL, FALSE, FALSE, NULL); + if (evt == NULL) { + dbg_lasterror("CreateEvent()"); + return (-1); + } + + rv = WSAEventSelect( + (SOCKET) kn->kev.ident, + evt, + FD_READ | FD_ACCEPT | FD_CLOSE); + if (rv != 0) { + dbg_wsalasterror("WSAEventSelect()"); + CloseHandle(evt); + return (-1); + } + + /* TODO: handle regular files in addition to sockets */ + + /* TODO: handle in copyout + if (kn->kev.flags & EV_ONESHOT || kn->kev.flags & EV_DISPATCH) + kn->data.events |= EPOLLONESHOT; + if (kn->kev.flags & EV_CLEAR) + kn->data.events |= EPOLLET; + */ + + if (RegisterWaitForSingleObject(&kn->kn_event_whandle, evt, + evfilt_read_callback, kn, INFINITE, 0) == 0) { + dbg_puts("RegisterWaitForSingleObject failed"); + CloseHandle(evt); + return (-1); + } + + kn->data.handle = evt; + + return (0); +} + +int +evfilt_read_knote_modify(struct filter *filt, struct knote *kn, + const struct kevent *kev) +{ + return (-1); /* STUB */ +} + +int +evfilt_read_knote_delete(struct filter *filt, struct knote *kn) +{ + if (kn->kev.flags & EV_DISABLE) + return (0); + + if (kn->data.handle == NULL || kn->kn_event_whandle == NULL) + return (0); + + if(!UnregisterWaitEx(kn->kn_event_whandle, INVALID_HANDLE_VALUE)) { + dbg_lasterror("UnregisterWait()"); + return (-1); + } + if (!WSACloseEvent(kn->data.handle)) { + dbg_wsalasterror("WSACloseEvent()"); + return (-1); + } + + kn->data.handle = NULL; + return (0); +} + +int +evfilt_read_knote_enable(struct filter *filt, struct knote *kn) +{ + return evfilt_read_knote_create(filt, kn); +} + +int +evfilt_read_knote_disable(struct filter *filt, struct knote *kn) +{ + return evfilt_read_knote_delete(filt, kn); +} + +const struct filter evfilt_read = { + EVFILT_READ, + NULL, + NULL, + evfilt_read_copyout, + evfilt_read_knote_create, + evfilt_read_knote_modify, + evfilt_read_knote_delete, + evfilt_read_knote_enable, + evfilt_read_knote_disable, +}; From 46baf837ad51f22e8ed72f42579878624c09222a Mon Sep 17 00:00:00 2001 From: marius Date: Tue, 26 Apr 2011 19:26:38 +0000 Subject: [PATCH 0460/1120] Updated VS Solution and CMakeLists.txt to reflect latest changes Added annotation to timer bug on windows Fixed a wrong visibility in the static build of libkqueue git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@489 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/CMakeLists.txt | 17 ++++++++++++----- vendor/libkqueue/libkqueue.vcxproj | 3 ++- vendor/libkqueue/src/common/kqueue.c | 3 +++ vendor/libkqueue/src/linux/read.c | 2 +- vendor/libkqueue/src/windows/timer.c | 1 + 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 557d81c7e..d81531306 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -24,7 +24,7 @@ if(KQUEUE_TESTS) add_subdirectory(test) endif() -project(libkqueue) +project(kqueue) #files file(GLOB_RECURSE INCL include/*.h) @@ -62,6 +62,8 @@ else() src/linux/timer.c src/linux/user.c src/linux/vnode.c + src/linux/write.c + src/linux/read.c src/common/*.h src/common/filter.c src/common/knote.c @@ -91,14 +93,19 @@ include_directories( option(STATIC_KQUEUE "Enable to build libkqueue as static lib" OFF) if(STATIC_WORKQUEUE) add_definitions(-DMAKE_STATIC) - add_library(libkqueue STATIC ${SRC} ${INCL}) + add_library(kqueue STATIC ${SRC} ${INCL}) else() - add_library(libkqueue SHARED ${SRC} ${INCL}) + add_library(kqueue SHARED ${SRC} ${INCL}) +endif() + +if(WIN32) + set(LIB ${LIB} Ws2_32) endif() if(NOT WIN32) - target_link_libraries(libkqueue pthread) + set(LIB ${LIB} pthread) endif() -set_target_properties(libkqueue PROPERTIES DEBUG_POSTFIX "D") +target_link_libraries(kqueue ${LIB}) +set_target_properties(kqueue PROPERTIES DEBUG_POSTFIX "D") #tests option(KQUEUE_TESTS "Enable to build tests for libkqueue" OFF) diff --git a/vendor/libkqueue/libkqueue.vcxproj b/vendor/libkqueue/libkqueue.vcxproj index 2577e6a3d..09a7912de 100644 --- a/vendor/libkqueue/libkqueue.vcxproj +++ b/vendor/libkqueue/libkqueue.vcxproj @@ -50,7 +50,7 @@ MachineX86 true Windows - msvcrtd.lib;Libcmtd.lib;%(AdditionalDependencies) + msvcrtd.lib;Libcmtd.lib;Ws2_32.lib;%(AdditionalDependencies) @@ -76,6 +76,7 @@ + diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index cab472fa5..3a71677e8 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -52,6 +52,9 @@ get_fd_limit(void) static struct map *kqmap; int CONSTRUCTOR +#ifdef MAKE_STATIC + VISIBLE +#endif libkqueue_init(void) { #ifdef NDEBUG diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index 3d72e3948..bb648e4a3 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -49,7 +49,7 @@ get_eof_offset(int fd) sb.st_size = 1; } - dbg_printf("curpos=%zu size=%zu\n", curpos, sb.st_size); + dbg_printf("curpos=%zu size=%zu\n", (size_t)curpos, (size_t)sb.st_size); return (sb.st_size - curpos); //FIXME: can overflow } diff --git a/vendor/libkqueue/src/windows/timer.c b/vendor/libkqueue/src/windows/timer.c index ca39a9c40..e82b3cb23 100644 --- a/vendor/libkqueue/src/windows/timer.c +++ b/vendor/libkqueue/src/windows/timer.c @@ -17,6 +17,7 @@ #include "../common/private.h" /* Needed for safe termination of a pending timer */ +// FIXME: This is not a threadsafe solution but can be fixed by using ref count and the upcoming KNOTE_DELETED static struct knote __thread *about_to_delete = NULL; /* Convert milliseconds into negative increments of 100-nanoseconds */ From 6b0fbf14a3a4fb64accaa8c1aaef90f25db8e42c Mon Sep 17 00:00:00 2001 From: marius Date: Tue, 26 Apr 2011 20:12:28 +0000 Subject: [PATCH 0461/1120] EVFILT_USER implementation on windows Change VS Solution structure to be more well-arranged git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@490 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/libkqueue.vcxproj | 1 + vendor/libkqueue/libkqueue.vcxproj.filters | 67 +++++++++++ vendor/libkqueue/src/windows/platform.c | 1 - vendor/libkqueue/src/windows/user.c | 127 +++++++++++++++++++++ vendor/libkqueue/test/common.h | 1 + 5 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 vendor/libkqueue/libkqueue.vcxproj.filters create mode 100644 vendor/libkqueue/src/windows/user.c diff --git a/vendor/libkqueue/libkqueue.vcxproj b/vendor/libkqueue/libkqueue.vcxproj index 09a7912de..361b08368 100644 --- a/vendor/libkqueue/libkqueue.vcxproj +++ b/vendor/libkqueue/libkqueue.vcxproj @@ -78,6 +78,7 @@ + diff --git a/vendor/libkqueue/libkqueue.vcxproj.filters b/vendor/libkqueue/libkqueue.vcxproj.filters new file mode 100644 index 000000000..986e4f4fe --- /dev/null +++ b/vendor/libkqueue/libkqueue.vcxproj.filters @@ -0,0 +1,67 @@ + + + + + common + + + common + + + common + + + common + + + common + + + windows + + + windows + + + windows + + + windows + + + windows + + + + + common + + + common + + + common + + + common + + + windows + + + windows + + + windows + + + + + + {d00529d5-005e-4a55-950f-987dc27e5101} + + + {11f5eddb-b2fe-4fc5-9733-f52ee80e8a4c} + + + \ No newline at end of file diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 94af24fc6..55271120a 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -33,7 +33,6 @@ const struct filter evfilt_proc = EVFILT_NOTIMPL; const struct filter evfilt_vnode = EVFILT_NOTIMPL; const struct filter evfilt_signal = EVFILT_NOTIMPL; const struct filter evfilt_write = EVFILT_NOTIMPL; -const struct filter evfilt_user = EVFILT_NOTIMPL; const struct kqueue_vtable kqops = { windows_kqueue_init, diff --git a/vendor/libkqueue/src/windows/user.c b/vendor/libkqueue/src/windows/user.c new file mode 100644 index 000000000..bdbc1bf34 --- /dev/null +++ b/vendor/libkqueue/src/windows/user.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "../common/private.h" + +int +evfilt_user_init(struct filter *filt) +{ + return (0); +} + +void +evfilt_user_destroy(struct filter *filt) +{ +} + +int +evfilt_user_copyout(struct kevent* dst, struct knote* src, void* ptr) +{ + memcpy(dst, &src->kev, sizeof(struct kevent)); + + dst->fflags &= ~NOTE_FFCTRLMASK; //FIXME: Not sure if needed + dst->fflags &= ~NOTE_TRIGGER; + if (src->kev.flags & EV_ADD) { + /* NOTE: True on FreeBSD but not consistent behavior with + other filters. */ + dst->flags &= ~EV_ADD; + } + if (src->kev.flags & EV_CLEAR) + src->kev.fflags &= ~NOTE_TRIGGER; + + if (src->kev.flags & EV_DISPATCH) + src->kev.fflags &= ~NOTE_TRIGGER; + + return (0); +} + +int +evfilt_user_knote_create(struct filter *filt, struct knote *kn) +{ + return (0); +} + +int +evfilt_user_knote_modify(struct filter *filt, struct knote *kn, + const struct kevent *kev) +{ + unsigned int ffctrl; + unsigned int fflags; + + /* Excerpted from sys/kern/kern_event.c in FreeBSD HEAD */ + ffctrl = kev->fflags & NOTE_FFCTRLMASK; + fflags = kev->fflags & NOTE_FFLAGSMASK; + switch (ffctrl) { + case NOTE_FFNOP: + break; + + case NOTE_FFAND: + kn->kev.fflags &= fflags; + break; + + case NOTE_FFOR: + kn->kev.fflags |= fflags; + break; + + case NOTE_FFCOPY: + kn->kev.fflags = fflags; + break; + + default: + /* XXX Return error? */ + break; + } + + if ((!(kn->kev.flags & EV_DISABLE)) && kev->fflags & NOTE_TRIGGER) { + kn->kev.fflags |= NOTE_TRIGGER; + if (!PostQueuedCompletionStatus(kn->kn_kq->kq_iocp, 1, (ULONG_PTR) 0, (LPOVERLAPPED) kn)) { + dbg_lasterror("PostQueuedCompletionStatus()"); + return (-1); + } + } + + return (0); +} + +int +evfilt_user_knote_delete(struct filter *filt, struct knote *kn) +{ + return (0); +} + +int +evfilt_user_knote_enable(struct filter *filt, struct knote *kn) +{ + return evfilt_user_knote_create(filt, kn); +} + +int +evfilt_user_knote_disable(struct filter *filt, struct knote *kn) +{ + return evfilt_user_knote_delete(filt, kn); +} + +const struct filter evfilt_user = { + EVFILT_USER, + evfilt_user_init, + evfilt_user_destroy, + evfilt_user_copyout, + evfilt_user_knote_create, + evfilt_user_knote_modify, + evfilt_user_knote_delete, + evfilt_user_knote_enable, + evfilt_user_knote_disable, +}; \ No newline at end of file diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 640526922..081d1d632 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -51,6 +51,7 @@ #else # include "../include/sys/event.h" # include "../src/windows/platform.h" +# define HAVE_EVFILT_USER 1 #endif From 5781979a85d9a403e805ba327dd33826f3a6549a Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 27 Apr 2011 03:30:31 +0000 Subject: [PATCH 0462/1120] Re-enable the knote mutex and reference counter. Improve the knote reference counting mechanism. New function knote_delete(). Rename 'flags' to 'kn_flags' in struct knote. Rename 'mtx' to 'kn_mtx' in struct knote. Rename 'kntree_ent' to 'kn_entries' in struct knote. Add a knote flag named 'KNFL_KNOTE_DELETED' to indicate that a knote has been deleted. With reference counting, this becomes necessary. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@491 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/BUGS | 10 ++ vendor/libkqueue/Makefile | 2 +- vendor/libkqueue/TODO | 27 ++++++ vendor/libkqueue/src/common/filter.c | 3 +- vendor/libkqueue/src/common/kevent.c | 15 ++- vendor/libkqueue/src/common/knote.c | 120 ++++++++++-------------- vendor/libkqueue/src/common/private.h | 22 ++--- vendor/libkqueue/src/linux/platform.c | 7 +- vendor/libkqueue/src/linux/platform.h | 6 -- vendor/libkqueue/src/linux/read.c | 12 +-- vendor/libkqueue/src/linux/write.c | 2 +- vendor/libkqueue/src/solaris/platform.c | 2 +- vendor/libkqueue/src/windows/platform.c | 2 +- 13 files changed, 123 insertions(+), 107 deletions(-) diff --git a/vendor/libkqueue/BUGS b/vendor/libkqueue/BUGS index 3a105d5d7..cb25a87f4 100644 --- a/vendor/libkqueue/BUGS +++ b/vendor/libkqueue/BUGS @@ -1,3 +1,13 @@ + * When passing a knote pointer to the kernel, the reference count of + the knote structure should be incremented. Conversely, when the pointer + has been returned from the kernel and the event unregistered from the + kernel, the reference count should be decremented. + + * Some functions should crash instead of silently printing a debug + message.. for example, knote_release(). + + * knote_get_by_ident uses 'short' for the ident, but the actual datatype + is 'uintptr_t'. * need to uninitialize library after fork() using pthread_atfork() diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 0e9945ecd..fecd27377 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -68,7 +68,7 @@ debug: clean $(PROGRAM).so.$(ABI_VERSION) test/config.mk cd test && make debug debug-check: clean test/config.mk - cd test && KQUEUE_DEBUG=y make check + cd test && KQUEUE_DEBUG=yes make check $(DISTFILE): $(SOURCES) $(HEADERS) mkdir $(PROGRAM)-$(VERSION) diff --git a/vendor/libkqueue/TODO b/vendor/libkqueue/TODO index 1a3ecaea2..5bf88de0f 100644 --- a/vendor/libkqueue/TODO +++ b/vendor/libkqueue/TODO @@ -1,3 +1,30 @@ + * There are very likely to be lock-related bugs stemming from when the + kevent_copyin() and kevent_copyout() functions stopped holding the + kqueue lock. It would be nice to have a lock testing mechanism to + check that the correct locks are held.. something like: + + #define MTX_LOCKED 1 + #define MTX_UNLOCKED 0 + #if NDEBUG + #define LOCK_MONITOR(x) int x + #define lock_assert(x,y) assert((x) == (y)) + #define lock_acquire(x,y) do { pthread_mutex_lock((x)); y = MTX_LOCKED } while (0) + #define lock_release(x,y) do { pthread_mutex_unlock((x)); y = MTX_UNLOCKED } while (0) + #else + #define LOCK_MONITOR(x) /**/ + #define lock_assert(x,y) do {} while (0) + #define lock_acquire(x,y) do { pthread_mutex_lock((x)); } while (0) + #define lock_release(x,y) do { pthread_mutex_unlock((x)); } while (0) + #endif + + struct foo { + LOCK_MONITOR(foo_lockstat); + } + ... + + lock_assert(&kn->kn_lockmon, MTX_LOCKED); + lock_assert(&kn->kn_lockmon, MTX_UNLOCKED); + * Add a counter that increments on each each kevent() call. When printing debug information within kevent(), display the value of the counter. This will be helpful when debugging a multithreaded program that may have diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index fe5cb3488..1b4708e22 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -124,7 +124,8 @@ filter_unregister_all(struct kqueue *kq) if (kq->kq_filt[i].kf_destroy != NULL) kq->kq_filt[i].kf_destroy(&kq->kq_filt[i]); - knote_free_all(&kq->kq_filt[i]); + //XXX-FIXME + //knote_free_all(&kq->kq_filt[i]); if (kqops.filter_free != NULL) kqops.filter_free(kq, &kq->kq_filt[i]); diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 534199b82..429f64610 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -154,7 +154,6 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) knote_insert(filt, kn); dbg_printf("created kevent %s", kevent_dump(src)); - /* XXX- FIXME Needs to be handled in kn_create() to prevent races */ if (src->flags & EV_DISABLE) { kn->kev.flags |= EV_DISABLE; @@ -162,33 +161,33 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) } //........................................ - - return (0); } else { + dbg_printf("no entry found for ident=%u", (unsigned int)src->ident); errno = ENOENT; return (-1); } } if (src->flags & EV_DELETE) { - knote_unlock(kn); - knote_release(filt, kn); + rv = knote_delete(filt, kn); + dbg_printf("knote_delete returned %d", rv); + /* NOTE: the knote lock was dropped by knote_delete() */ } else if (src->flags & EV_DISABLE) { kn->kev.flags |= EV_DISABLE; rv = filt->kn_disable(filt, kn); dbg_printf("kn_disable returned %d", rv); - knote_unlock(kn); + knote_unlock(kn); } else if (src->flags & EV_ENABLE) { kn->kev.flags &= ~EV_DISABLE; rv = filt->kn_enable(filt, kn); dbg_printf("kn_enable returned %d", rv); - knote_unlock(kn); + knote_unlock(kn); } else if (src->flags & EV_ADD || src->flags == 0 || src->flags & EV_RECEIPT) { kn->kev.udata = src->udata; rv = filt->kn_modify(filt, kn, src); dbg_printf("kn_modify returned %d", rv); - knote_unlock(kn); + knote_unlock(kn); } return (rv); diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 8d235d92d..05842a5c5 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -22,8 +22,6 @@ #include "alloc.h" -static void knote_free(struct filter *, struct knote *); - int knote_init(void) { @@ -37,7 +35,7 @@ knote_cmp(struct knote *a, struct knote *b) return memcmp(&a->kev.ident, &b->kev.ident, sizeof(a->kev.ident)); } -RB_GENERATE(knt, knote, kntree_ent, knote_cmp) +RB_GENERATE(knt, knote, kn_entries, knote_cmp) struct knote * knote_new(void) @@ -49,57 +47,39 @@ knote_new(void) if (res == NULL) return (NULL); -#if ! SERIALIZE_KEVENT #ifdef _WIN32 - pthread_mutex_init(&res->mtx, NULL); + pthread_mutex_init(&res->kn_mtx, NULL); #else - if (pthread_mutex_init(&res->mtx, NULL)){ + if (pthread_mutex_init(&res->kn_mtx, NULL)){ dbg_perror("pthread_mutex_init"); free(res); return (NULL); } #endif -#endif - - return res; -} + res->kn_ref = 1; -void -knote_retain(struct knote *kn) -{ -#if ! SERIALIZE_KEVENT - atomic_inc(&kn->kn_ref); -#endif + return (res); } +/* Must be called while holding the knote lock */ void knote_release(struct filter *filt, struct knote *kn) { -#if SERIALIZE_KEVENT - knote_free(filt, kn); -#else - int ref; - - assert (kn->kn_ref >= 0); - - /* - * Optimize for the case where only a single thread is accessing - * the knote structure. - */ - if (fastpath(kn->kn_ref == 0)) - ref = 0; - else - ref = atomic_dec(&kn->kn_ref); - - if (ref == 0) { - dbg_printf("freeing knote at %p, rc=%d", kn, ref); - pthread_rwlock_wrlock(&filt->kf_knote_mtx); - knote_free(filt, kn); - pthread_rwlock_unlock(&filt->kf_knote_mtx); + assert (kn->kn_ref > 0); + + if (--kn->kn_ref == 0) { + if (kn->kn_flags & KNFL_KNOTE_DELETED) { + dbg_printf("freeing knote at %p", kn); + knote_unlock(kn); + pthread_mutex_destroy(&kn->kn_mtx); + free(kn); + } else { + dbg_puts("this should never happen"); + } } else { - dbg_printf("decrementing refcount of knote %p rc=%d", kn, ref); + dbg_printf("decrementing refcount of knote %p rc=%d", kn, kn->kn_ref); + knote_unlock(kn); } -#endif } void @@ -110,37 +90,41 @@ knote_insert(struct filter *filt, struct knote *kn) pthread_rwlock_unlock(&filt->kf_knote_mtx); } -static void -knote_free(struct filter *filt, struct knote *kn) -{ - RB_REMOVE(knt, &filt->kf_knote, kn); - filt->kn_delete(filt, kn); -#if ! SERIALIZE_KEVENT - pthread_mutex_destroy(&kn->mtx); -#endif - free(kn); -// mem_free(kn); -} - -/* XXX-FIXME this is broken and should be removed */ -void -knote_free_all(struct filter *filt) +/* Must be called while holding the knote lock */ +int +knote_delete(struct filter *filt, struct knote *kn) { - struct knote *n1, *n2; + struct knote query; + struct knote *tmp; - abort(); + if (kn->kn_flags & KNFL_KNOTE_DELETED) { + dbg_puts("ERROR: double deletion detected"); + return (-1); + } - /* Destroy all knotes */ + /* + * Drop the knote lock, and acquire both the knotelist write lock + * and the knote lock. Verify that the knote wasn't removed by another + * thread before we acquired the knotelist lock. + */ + query.kev.ident = kn->kev.ident; + knote_unlock(kn); pthread_rwlock_wrlock(&filt->kf_knote_mtx); - for (n1 = RB_MIN(knt, &filt->kf_knote); n1 != NULL; n1 = n2) { - n2 = RB_NEXT(knt, filt->kf_knote, n1); - RB_REMOVE(knt, &filt->kf_knote, n1); - free(n1); + tmp = RB_FIND(knt, &filt->kf_knote, &query); + if (tmp == kn) { + RB_REMOVE(knt, &filt->kf_knote, kn); } pthread_rwlock_unlock(&filt->kf_knote_mtx); + + filt->kn_delete(filt, kn); //XXX-FIXME check return value + + kn->kn_flags |= KNFL_KNOTE_DELETED; + + knote_release(filt, kn); + + return (0); } -/* TODO: rename to knote_lookup_ident */ struct knote * knote_lookup(struct filter *filt, short ident) { @@ -151,10 +135,8 @@ knote_lookup(struct filter *filt, short ident) pthread_rwlock_rdlock(&filt->kf_knote_mtx); ent = RB_FIND(knt, &filt->kf_knote, &query); -#if ! SERIALIZE_KEVENT if (ent != NULL) knote_lock(ent); -#endif pthread_rwlock_unlock(&filt->kf_knote_mtx); dbg_printf("id=%d ent=%p", ident, ent); @@ -162,8 +144,9 @@ knote_lookup(struct filter *filt, short ident) return (ent); } +#if DEADWOOD struct knote * -knote_lookup_data(struct filter *filt, intptr_t data) +knote_get_by_data(struct filter *filt, intptr_t data) { struct knote *kn; @@ -172,14 +155,15 @@ knote_lookup_data(struct filter *filt, intptr_t data) if (data == kn->kev.data) break; } -#if ! SERIALIZE_KEVENT - if (kn != NULL) + if (kn != NULL) { knote_lock(kn); -#endif + knote_retain(kn); + } pthread_rwlock_unlock(&filt->kf_knote_mtx); return (kn); } +#endif int knote_disable(struct filter *filt, struct knote *kn) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index c4548068c..077a420de 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -63,12 +63,16 @@ struct eventfd { #endif }; -/* TODO: Make this a variable length structure and allow - each filter to add custom fields at the end. +/* + * Flags used by knote->kn_flags */ +#define KNFL_PASSIVE_SOCKET (0x01) /* Socket is in listen(2) mode */ +#define KNFL_REGULAR_FILE (0x02) /* File descriptor is a regular file */ +#define KNFL_KNOTE_DELETED (0x10) /* The knote object is no longer valid */ + struct knote { struct kevent kev; - int flags; + int kn_flags; union { /* OLD */ int pfd; /* Used by timerfd */ @@ -82,15 +86,12 @@ struct knote { void *handle; /* Used by win32 filters */ } data; struct kqueue* kn_kq; -#if ! SERIALIZE_KEVENT - pthread_mutex_t mtx; + pthread_mutex_t kn_mtx; volatile uint32_t kn_ref; -#endif #if defined(KNOTE_PLATFORM_SPECIFIC) KNOTE_PLATFORM_SPECIFIC; #endif - TAILQ_ENTRY(knote) event_ent; /* Used by filter->kf_event */ - RB_ENTRY(knote) kntree_ent; /* Used by filter->kntree */ + RB_ENTRY(knote) kn_entries; }; #define KNOTE_ENABLE(ent) do { \ @@ -185,12 +186,11 @@ extern const struct kqueue_vtable kqops; * knote internal API */ struct knote * knote_lookup(struct filter *, short); -struct knote * knote_lookup_data(struct filter *filt, intptr_t); +//DEADWOOD: struct knote * knote_get_by_data(struct filter *filt, intptr_t); struct knote * knote_new(void); void knote_release(struct filter *, struct knote *); -void knote_retain(struct knote *); -void knote_free_all(struct filter *); void knote_insert(struct filter *, struct knote *); +int knote_delete(struct filter *, struct knote *); int knote_init(void); int knote_disable(struct filter *, struct knote *); #if ! SERIALIZE_KEVENT diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 15fb92838..8181ae9ae 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -173,8 +173,9 @@ linux_kevent_copyout(struct kqueue *kq, int nready, */ if (eventlist->flags & EV_DISPATCH) knote_disable(filt, kn); //TODO: Error checking + //^^^^^^^^ FIXME, shouldn't this need the lock held? if (eventlist->flags & EV_ONESHOT) - knote_release(filt, kn); //TODO: Error checking + knote_delete(filt, kn); //TODO: Error checking /* If an empty kevent structure is returned, the event is discarded. */ /* TODO: add these semantics to windows + solaris platform.c */ @@ -290,7 +291,7 @@ linux_get_descriptor_type(struct knote *kn) } if (! S_ISSOCK(sb.st_mode)) { //FIXME: could be a pipe, device file, or other non-regular file - kn->flags |= KNFL_REGULAR_FILE; + kn->kn_flags |= KNFL_REGULAR_FILE; dbg_printf("fd %d is a regular file\n", (int)kn->kev.ident); return (0); } @@ -312,7 +313,7 @@ linux_get_descriptor_type(struct knote *kn) } } else { if (lsock) - kn->flags |= KNFL_PASSIVE_SOCKET; + kn->kn_flags |= KNFL_PASSIVE_SOCKET; return (0); } } diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index c567bd289..732de4ccb 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -39,12 +39,6 @@ extern long int syscall (long int __sysno, ...); #define kqueue_epfd(kq) ((kq)->kq_id) #define filter_epfd(filt) ((filt)->kf_kqueue->kq_id) -/* - * Flags used by knote->flags - */ -#define KNFL_PASSIVE_SOCKET (0x01) /* Socket is in listen(2) mode */ -#define KNFL_REGULAR_FILE (0x02) /* File descriptor is a regular file */ - /* * Additional members of struct filter */ diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index bb648e4a3..e8a3fb486 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -59,7 +59,7 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) struct epoll_event * const ev = (struct epoll_event *) ptr; /* Special case: for regular files, return the offset from current position to end of file */ - if (src->flags & KNFL_REGULAR_FILE) { + if (src->kn_flags & KNFL_REGULAR_FILE) { memcpy(dst, &src->kev, sizeof(*dst)); dst->data = get_eof_offset(src->kev.ident); @@ -115,7 +115,7 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) if (ev->events & EPOLLERR) dst->fflags = 1; /* FIXME: Return the actual socket error */ - if (src->flags & KNFL_PASSIVE_SOCKET) { + if (src->kn_flags & KNFL_PASSIVE_SOCKET) { /* On return, data contains the length of the socket backlog. This is not available under Linux. */ @@ -161,7 +161,7 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) ev.data.ptr = kn; /* Special case: for regular files, add a surrogate eventfd that is always readable */ - if (kn->flags & KNFL_REGULAR_FILE) { + if (kn->kn_flags & KNFL_REGULAR_FILE) { int evfd; kn->kn_epollfd = filter_epfd(filt); @@ -200,7 +200,7 @@ evfilt_read_knote_delete(struct filter *filt, struct knote *kn) if (kn->kev.flags & EV_DISABLE) return (0); - if ((kn->flags & KNFL_REGULAR_FILE && kn->kdata.kn_eventfd != -1) < 0) { + if ((kn->kn_flags & KNFL_REGULAR_FILE && kn->kdata.kn_eventfd != -1) < 0) { if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kdata.kn_eventfd, NULL) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); @@ -221,7 +221,7 @@ evfilt_read_knote_enable(struct filter *filt, struct knote *kn) ev.events = kn->data.events; ev.data.ptr = kn; - if (kn->flags & KNFL_REGULAR_FILE) { + if (kn->kn_flags & KNFL_REGULAR_FILE) { if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_eventfd, &ev) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); @@ -235,7 +235,7 @@ evfilt_read_knote_enable(struct filter *filt, struct knote *kn) int evfilt_read_knote_disable(struct filter *filt, struct knote *kn) { - if (kn->flags & KNFL_REGULAR_FILE) { + if (kn->kn_flags & KNFL_REGULAR_FILE) { if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kdata.kn_eventfd, NULL) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); diff --git a/vendor/libkqueue/src/linux/write.c b/vendor/libkqueue/src/linux/write.c index 95d82dd51..76bb7488f 100644 --- a/vendor/libkqueue/src/linux/write.c +++ b/vendor/libkqueue/src/linux/write.c @@ -66,7 +66,7 @@ evfilt_socket_knote_create(struct filter *filt, struct knote *kn) return (-1); /* TODO: return EBADF? */ - if (kn->flags & KNFL_REGULAR_FILE) + if (kn->kn_flags & KNFL_REGULAR_FILE) return (-1); /* Convert the kevent into an epoll_event */ diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index 439a88fe8..0d58549c9 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -207,7 +207,7 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, if (eventlist->flags & EV_DISPATCH) knote_disable(filt, kn); //TODO: Error checking if (eventlist->flags & EV_ONESHOT) - knote_release(filt, kn); //TODO: Error checking + knote_delete(filt, kn); //TODO: Error checking eventlist++; } diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 55271120a..f881bb2bc 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -204,7 +204,7 @@ windows_kevent_copyout(struct kqueue *kq, int nready, if (eventlist->flags & EV_DISPATCH) knote_disable(filt, kn); //TODO: Error checking if (eventlist->flags & EV_ONESHOT) - knote_release(filt, kn); //TODO: Error checking + knote_delete(filt, kn); //TODO: Error checking /* If an empty kevent structure is returned, the event is discarded. */ if (fastpath(eventlist->filter != 0)) { From c982f7eaba3e6814cacda6ee20e0abf62506cac1 Mon Sep 17 00:00:00 2001 From: marius Date: Thu, 28 Apr 2011 12:01:04 +0000 Subject: [PATCH 0463/1120] Some changes to the 'new' ref-count mechanism of knote - please elaborate Fixed a race condition within windows timers using the ref count mechanism git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@492 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/knote.c | 2 +- vendor/libkqueue/src/common/private.h | 1 + vendor/libkqueue/src/windows/timer.c | 46 +++++++++++++++------------ 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 05842a5c5..09b30070d 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -67,7 +67,7 @@ knote_release(struct filter *filt, struct knote *kn) { assert (kn->kn_ref > 0); - if (--kn->kn_ref == 0) { + if (atomic_dec(&kn->kn_ref) == 0) { if (kn->kn_flags & KNFL_KNOTE_DELETED) { dbg_printf("freeing knote at %p", kn); knote_unlock(kn); diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 077a420de..0685034d1 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -188,6 +188,7 @@ extern const struct kqueue_vtable kqops; struct knote * knote_lookup(struct filter *, short); //DEADWOOD: struct knote * knote_get_by_data(struct filter *filt, intptr_t); struct knote * knote_new(void); +#define knote_retain(kn) atomic_inc(&kn->kn_ref) void knote_release(struct filter *, struct knote *); void knote_insert(struct filter *, struct knote *); int knote_delete(struct filter *, struct knote *); diff --git a/vendor/libkqueue/src/windows/timer.c b/vendor/libkqueue/src/windows/timer.c index e82b3cb23..e4105a4b2 100644 --- a/vendor/libkqueue/src/windows/timer.c +++ b/vendor/libkqueue/src/windows/timer.c @@ -16,10 +16,6 @@ #include "../common/private.h" -/* Needed for safe termination of a pending timer */ -// FIXME: This is not a threadsafe solution but can be fixed by using ref count and the upcoming KNOTE_DELETED -static struct knote __thread *about_to_delete = NULL; - /* Convert milliseconds into negative increments of 100-nanoseconds */ static void convert_msec_to_filetime(LARGE_INTEGER *dst, int src) @@ -34,7 +30,6 @@ ktimer_delete(struct filter *filt, struct knote *kn) if (kn->data.handle == NULL || kn->kn_event_whandle == NULL) return (0); - about_to_delete = kn; if(!UnregisterWaitEx(kn->kn_event_whandle, INVALID_HANDLE_VALUE)) { dbg_lasterror("UnregisterWait()"); return (-1); @@ -49,9 +44,11 @@ ktimer_delete(struct filter *filt, struct knote *kn) return (-1); } - about_to_delete = NULL; - kn->data.handle = NULL; - return (0); + if( !(kn->kev.flags & EV_ONESHOT) ) + knote_release(filt, kn); + + kn->data.handle = NULL; + return (0); } static VOID CALLBACK evfilt_timer_callback(void* param, BOOLEAN fired){ @@ -65,23 +62,29 @@ static VOID CALLBACK evfilt_timer_callback(void* param, BOOLEAN fired){ assert(param); kn = (struct knote*)param; -// FIXME: depends on ! SERIALIZE_KEVENT -// dbg_printf("called for knote at %p, rc=%d", kn, kn->kn_ref); - if(about_to_delete == kn) { + + if(kn->kn_flags & KNFL_KNOTE_DELETED) { dbg_puts("knote marked for deletion, skipping event"); return; - } - kq = kn->kn_kq; - assert(kq); - - if (!PostQueuedCompletionStatus(kq->kq_iocp, 1, (ULONG_PTR) 0, (LPOVERLAPPED) kn)) { - dbg_lasterror("PostQueuedCompletionStatus()"); - return; - /* FIXME: need more extreme action */ - } + } else { + kq = kn->kn_kq; + assert(kq); + + if (!PostQueuedCompletionStatus(kq->kq_iocp, 1, (ULONG_PTR) 0, (LPOVERLAPPED) kn)) { + dbg_lasterror("PostQueuedCompletionStatus()"); + return; + /* FIXME: need more extreme action */ + } #if DEADWOOD - evt_signal(kq->kq_loop, EVT_WAKEUP, kn); + evt_signal(kq->kq_loop, EVT_WAKEUP, kn); #endif + } + if(kn->kev.flags & EV_ONESHOT) { + struct filter* filt; + if( filter_lookup(&filt, kq, kn->kev.filter) ) + dbg_perror("filter_lookup()"); + knote_release(filt, kn); + } } int @@ -135,6 +138,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) kn->data.handle = th; RegisterWaitForSingleObject(&kn->kn_event_whandle, th, evfilt_timer_callback, kn, INFINITE, 0); + knote_retain(kn); return (0); } From 5d61b95033c408b3388c72a328e0c9b3e8941526 Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 29 Apr 2011 03:28:07 +0000 Subject: [PATCH 0464/1120] Add tracing mutexes to debug.h. /* * Tracing mutexes are a thin wrapper around the pthread_mutex_t * datatype that tracks and reports when a mutex is locked or unlocked. * It also allows you to assert that a mutex has (or has not) been locked * by calling tracing_mutex_assert(). */ git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@493 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/debug.h | 46 ++++++++++++++++++++++++++++- vendor/libkqueue/test/Makefile | 7 +++-- vendor/libkqueue/test/lockstat.c | 40 +++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 vendor/libkqueue/test/lockstat.c diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index c95435d30..49a6eff57 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -18,11 +18,14 @@ #define _DEBUG_H #include +#include +#include extern int DEBUG_ACTIVE; extern char *DEBUG_IDENT; #if defined(__linux__) +# include # define THREAD_ID ((pid_t) syscall(__NR_gettid)) #elif defined(__sun) # define THREAD_ID (pthread_self()) @@ -32,7 +35,6 @@ extern char *DEBUG_IDENT; # error Unsupported platform #endif - #ifndef NDEBUG #define dbg_puts(str) do { \ if (DEBUG_ACTIVE) \ @@ -67,11 +69,46 @@ extern char *DEBUG_IDENT; fprintf(stderr, "%s: [%d] %s(): %s: (WSALastError=%d)\n", \ DEBUG_IDENT, THREAD_ID, __func__, str, (int)WSAGetLastError()); \ } while (0) + # else # define dbg_lasterror(str) ; # define dbg_wsalasterror(str) ; # endif +/* + * Tracing mutexes are a thin wrapper around the pthread_mutex_t + * datatype that tracks and reports when a mutex is locked or unlocked. + * It also allows you to assert that a mutex has (or has not) been locked + * by calling tracing_mutex_assert(). + */ + +# define MTX_UNLOCKED 0 +# define MTX_LOCKED 1 + +typedef struct { + pthread_mutex_t mtx_lock; + int mtx_status; +} tracing_mutex_t; + +# define tracing_mutex_init(mtx, attr) do { \ + pthread_mutex_init(&(mtx)->mtx_lock, (attr)); \ + (mtx)->mtx_status = MTX_UNLOCKED; \ +} while (0) + +# define tracing_mutex_assert(x,y) assert((x)->mtx_status == (y)) + +# define tracing_mutex_lock(x) do { \ + dbg_printf("waiting for %s", #x); \ + pthread_mutex_lock(&((x)->mtx_lock)); \ + dbg_printf("locked %s", #x); \ + (x)->mtx_status = MTX_LOCKED; \ +} while (0) + +# define tracing_mutex_unlock(x) do { \ + (x)->mtx_status = MTX_UNLOCKED; \ + pthread_mutex_unlock(&((x)->mtx_lock)); \ + dbg_printf("unlocked %s", # x); \ +} while (0) #else /* NDEBUG */ # define dbg_puts(str) do {} while (0) # define dbg_printf(fmt,...) do {} while (0) @@ -79,6 +116,13 @@ extern char *DEBUG_IDENT; # define dbg_lasterror(str) do {} while (0) # define dbg_wsalasterror(str) do {} while (0) # define reset_errno() do {} while (0) +# define MTX_UNLOCKED +# define MTX_LOCKED +# define tracing_mutex_t pthread_mutex_t +# define tracing_mutex_init pthread_mutex_init +# define tracing_mutex_assert(x,y) do {} while (0) +# define tracing_mutex_lock pthread_mutex_lock +# define tracing_mutex_unlock pthread_mutex_unlock #endif #endif /* ! _DEBUG_H */ diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile index e129b6d50..875927a08 100644 --- a/vendor/libkqueue/test/Makefile +++ b/vendor/libkqueue/test/Makefile @@ -16,7 +16,10 @@ include config.mk -all: kqtest +all: kqtest lockstat + +lockstat: lockstat.c + $(CC) -o lockstat $(CFLAGS) lockstat.c $(LDADD) kqtest: $(SOURCES) $(CC) -o kqtest $(CFLAGS) $(SOURCES) $(LDADD) @@ -56,5 +59,5 @@ edit: $(EDITOR) *.[ch] clean: - rm -f *.o *.a kqtest + rm -f *.o *.a kqtest lockstat for x in libdispatch stress; do cd $$x && make clean && cd ..; done diff --git a/vendor/libkqueue/test/lockstat.c b/vendor/libkqueue/test/lockstat.c new file mode 100644 index 000000000..079a113b7 --- /dev/null +++ b/vendor/libkqueue/test/lockstat.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include "../src/common/debug.h" + +int DEBUG_ACTIVE = 1; +char * DEBUG_IDENT = "lockstat"; + +struct foo { + tracing_mutex_t foo_lock; +}; + +/* + * Test the lockstat.h API + */ +int main() { + struct foo x; + + tracing_mutex_init(&x.foo_lock, NULL); + tracing_mutex_lock(&x.foo_lock); + tracing_mutex_assert(&x.foo_lock, MTX_LOCKED); + tracing_mutex_unlock(&x.foo_lock); + tracing_mutex_assert(&x.foo_lock, MTX_UNLOCKED); + + return (0); +} From 50347a4f9bfe236844872ea8ad8b591a8db3e90b Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 29 Apr 2011 03:59:59 +0000 Subject: [PATCH 0465/1120] Use tracing_mutex_t instead of pthread_mutex_t for knote and kqueue locks. Fix a locking bug in Linux kevent_copyout(). Fix and enable the knote_lock() and knote_unlock() macros. Implement tracing_mutex_destroy(). git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@494 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/debug.h | 4 ++++ vendor/libkqueue/src/common/knote.c | 22 +++++++++------------- vendor/libkqueue/src/common/kqueue.c | 2 +- vendor/libkqueue/src/common/private.h | 17 ++++++----------- vendor/libkqueue/src/linux/platform.c | 8 ++++---- 5 files changed, 24 insertions(+), 29 deletions(-) diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index 49a6eff57..9fbd1653c 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -95,6 +95,8 @@ typedef struct { (mtx)->mtx_status = MTX_UNLOCKED; \ } while (0) +# define tracing_mutex_destroy(mtx) pthread_mutex_destroy(&(mtx)->mtx_lock) + # define tracing_mutex_assert(x,y) assert((x)->mtx_status == (y)) # define tracing_mutex_lock(x) do { \ @@ -109,6 +111,7 @@ typedef struct { pthread_mutex_unlock(&((x)->mtx_lock)); \ dbg_printf("unlocked %s", # x); \ } while (0) + #else /* NDEBUG */ # define dbg_puts(str) do {} while (0) # define dbg_printf(fmt,...) do {} while (0) @@ -120,6 +123,7 @@ typedef struct { # define MTX_LOCKED # define tracing_mutex_t pthread_mutex_t # define tracing_mutex_init pthread_mutex_init +# define tracing_mutex_destroy pthread_mutex_destroy # define tracing_mutex_assert(x,y) do {} while (0) # define tracing_mutex_lock pthread_mutex_lock # define tracing_mutex_unlock pthread_mutex_unlock diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 09b30070d..ccdb72559 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -42,36 +42,28 @@ knote_new(void) { struct knote *res; - // return (mem_calloc()); res = calloc(1, sizeof(struct knote)); if (res == NULL) return (NULL); -#ifdef _WIN32 - pthread_mutex_init(&res->kn_mtx, NULL); -#else - if (pthread_mutex_init(&res->kn_mtx, NULL)){ - dbg_perror("pthread_mutex_init"); - free(res); - return (NULL); - } -#endif + tracing_mutex_init(&res->kn_mtx, NULL); //TODO: error checking res->kn_ref = 1; return (res); } -/* Must be called while holding the knote lock */ void knote_release(struct filter *filt, struct knote *kn) { assert (kn->kn_ref > 0); + tracing_mutex_assert(&kn->kn_mtx, MTX_LOCKED); + if (atomic_dec(&kn->kn_ref) == 0) { if (kn->kn_flags & KNFL_KNOTE_DELETED) { dbg_printf("freeing knote at %p", kn); knote_unlock(kn); - pthread_mutex_destroy(&kn->kn_mtx); + tracing_mutex_destroy(&kn->kn_mtx); free(kn); } else { dbg_puts("this should never happen"); @@ -90,13 +82,14 @@ knote_insert(struct filter *filt, struct knote *kn) pthread_rwlock_unlock(&filt->kf_knote_mtx); } -/* Must be called while holding the knote lock */ int knote_delete(struct filter *filt, struct knote *kn) { struct knote query; struct knote *tmp; + tracing_mutex_assert(&kn->kn_mtx, MTX_LOCKED); + if (kn->kn_flags & KNFL_KNOTE_DELETED) { dbg_puts("ERROR: double deletion detected"); return (-1); @@ -112,6 +105,7 @@ knote_delete(struct filter *filt, struct knote *kn) pthread_rwlock_wrlock(&filt->kf_knote_mtx); tmp = RB_FIND(knt, &filt->kf_knote, &query); if (tmp == kn) { + knote_lock(kn); RB_REMOVE(knt, &filt->kf_knote, kn); } pthread_rwlock_unlock(&filt->kf_knote_mtx); @@ -170,6 +164,8 @@ knote_disable(struct filter *filt, struct knote *kn) { assert(!(kn->kev.flags & EV_DISABLE)); + tracing_mutex_assert(&kn->kn_mtx, MTX_LOCKED); + filt->kn_disable(filt, kn); //TODO: Error checking KNOTE_DISABLE(kn); return (0); diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 3a71677e8..f82461c9c 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -118,7 +118,7 @@ kqueue(void) if (kq == NULL) return (-1); - pthread_mutex_init(&kq->kq_mtx, NULL); + tracing_mutex_init(&kq->kq_mtx, NULL); if (kqops.kqueue_init(kq) < 0) { free(kq); diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 0685034d1..e4d21ed1f 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -86,7 +86,7 @@ struct knote { void *handle; /* Used by win32 filters */ } data; struct kqueue* kn_kq; - pthread_mutex_t kn_mtx; + tracing_mutex_t kn_mtx; volatile uint32_t kn_ref; #if defined(KNOTE_PLATFORM_SPECIFIC) KNOTE_PLATFORM_SPECIFIC; @@ -145,7 +145,7 @@ struct kqueue { struct filter kq_filt[EVFILT_SYSCOUNT]; fd_set kq_fds, kq_rfds; int kq_nfds; - pthread_mutex_t kq_mtx; + tracing_mutex_t kq_mtx; volatile uint32_t kq_ref; #if defined(KQUEUE_PLATFORM_SPECIFIC) KQUEUE_PLATFORM_SPECIFIC; @@ -179,8 +179,8 @@ extern const struct kqueue_vtable kqops; /* * kqueue internal API */ -#define kqueue_lock(kq) pthread_mutex_lock(&(kq)->kq_mtx) -#define kqueue_unlock(kq) pthread_mutex_unlock(&(kq)->kq_mtx) +#define kqueue_lock(kq) tracing_mutex_lock(&(kq)->kq_mtx) +#define kqueue_unlock(kq) tracing_mutex_unlock(&(kq)->kq_mtx) /* * knote internal API @@ -194,13 +194,8 @@ void knote_insert(struct filter *, struct knote *); int knote_delete(struct filter *, struct knote *); int knote_init(void); int knote_disable(struct filter *, struct knote *); -#if ! SERIALIZE_KEVENT -#define knote_lock(kn) pthread_mutex_lock(&(kn)->mtx) -#define knote_unlock(kn) pthread_mutex_unlock(&(kn)->mtx) -#else -#define knote_lock(kn) do {} while (0) -#define knote_unlock(kn) do {} while (0) -#endif +#define knote_lock(kn) tracing_mutex_lock(&(kn)->kn_mtx) +#define knote_unlock(kn) tracing_mutex_unlock(&(kn)->kn_mtx) int filter_lookup(struct filter **, struct kqueue *, short); int filter_register_all(struct kqueue *); diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 8181ae9ae..d06e3f972 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -160,7 +160,6 @@ linux_kevent_copyout(struct kqueue *kq, int nready, knote_lock(kn); filt = &kq->kq_filt[~(kn->kev.filter)]; rv = filt->kf_copyout(eventlist, kn, ev); - knote_unlock(kn); if (slowpath(rv < 0)) { dbg_puts("knote_copyout failed"); /* XXX-FIXME: hard to handle this without losing events */ @@ -172,10 +171,11 @@ linux_kevent_copyout(struct kqueue *kq, int nready, * or disabled. */ if (eventlist->flags & EV_DISPATCH) - knote_disable(filt, kn); //TODO: Error checking - //^^^^^^^^ FIXME, shouldn't this need the lock held? + knote_disable(filt, kn); //FIXME: Error checking if (eventlist->flags & EV_ONESHOT) - knote_delete(filt, kn); //TODO: Error checking + knote_delete(filt, kn); //FIXME: Error checking + + knote_unlock(kn); /* If an empty kevent structure is returned, the event is discarded. */ /* TODO: add these semantics to windows + solaris platform.c */ From e037af5e9e216c48af4247efc93ccf063afe688f Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 29 Apr 2011 23:47:51 +0000 Subject: [PATCH 0466/1120] Improvements to EVFILT_READ on Windows. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@495 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/config.inc | 2 +- vendor/libkqueue/src/windows/read.c | 71 ++++++++++++++--------------- 2 files changed, 36 insertions(+), 37 deletions(-) diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index a9c18b3a0..e99423ed8 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -107,7 +107,7 @@ post_configure_hook() { #evfilt_socket="src/windows/read.c src/linux/write.c" evfilt_socket="src/windows/read.c" evfilt_timer="src/windows/timer.c" - evfilt_user="" + evfilt_user="src/windows/user.c" evfilt_vnode="" fi diff --git a/vendor/libkqueue/src/windows/read.c b/vendor/libkqueue/src/windows/read.c index ce085eeef..6eb77de87 100644 --- a/vendor/libkqueue/src/windows/read.c +++ b/vendor/libkqueue/src/windows/read.c @@ -19,8 +19,10 @@ static VOID CALLBACK evfilt_read_callback(void *param, BOOLEAN fired) { + WSANETWORKEVENTS events; struct kqueue *kq; struct knote *kn; + int rv; assert(param); @@ -29,11 +31,26 @@ evfilt_read_callback(void *param, BOOLEAN fired) return; } - assert(param); - kn = (struct knote*)param; + assert(param); + kn = (struct knote*)param; // FIXME: check if knote is pending destroyed - kq = kn->kn_kq; - assert(kq); + kq = kn->kn_kq; + assert(kq); + + /* Retrieve the socket events and update the knote */ + rv = WSAEnumNetworkEvents( + (SOCKET) kn->kev.ident, + kn->data.handle, + &events); + if (rv != 0) { + dbg_wsalasterror("WSAEnumNetworkEvents"); + return; //fIXME: should crash or invalidate the knote + } + /* FIXME: check for errors somehow.. + if (events.lNetworkEvents & FD_ACCEPT) + kn->kev.flags |= EV + */ + if (!PostQueuedCompletionStatus(kq->kq_iocp, 1, (ULONG_PTR) 0, (LPOVERLAPPED) param)) { dbg_lasterror("PostQueuedCompletionStatus()"); @@ -72,40 +89,22 @@ get_eof_offset(int fd) int evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) { -#if FIXME - struct event_buf * const ev = (struct event_buf *) ptr; - - /* FIXME: for regular files, return the offset from current position to end of file */ - //if (src->flags & KNFL_REGULAR_FILE) { ... } - - epoll_event_dump(ev); - memcpy(dst, &src->kev, sizeof(*dst)); -#if defined(HAVE_EPOLLRDHUP) - if (ev->events & EPOLLRDHUP || ev->events & EPOLLHUP) - dst->flags |= EV_EOF; -#else - if (ev->events & EPOLLHUP) - dst->flags |= EV_EOF; -#endif - if (ev->events & EPOLLERR) - dst->fflags = 1; /* FIXME: Return the actual socket error */ - - if (src->flags & KNFL_PASSIVE_SOCKET) { - /* On return, data contains the length of the - socket backlog. This is not available under Linux. - */ + //struct event_buf * const ev = (struct event_buf *) ptr; + + /* TODO: handle regular files + if (src->flags & KNFL_REGULAR_FILE) { ... } */ + + memcpy(dst, &src->kev, sizeof(*dst)); + if (src->kn_flags & KNFL_PASSIVE_SOCKET) { + /* TODO: should contains the length of the socket backlog */ dst->data = 1; } else { /* On return, data contains the number of bytes of protocol data available to read. */ - if (ioctl(dst->ident, SIOCINQ, &dst->data) < 0) { - /* race condition with socket close, so ignore this error */ - dbg_puts("ioctl(2) of socket failed"); - dst->data = 0; - } + /* FIXME: use WSAIoctl and FIONREAD to get the actual value */ + dst->data = 1; } -#endif return (0); } @@ -142,15 +141,15 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) kn->data.events |= EPOLLET; */ - if (RegisterWaitForSingleObject(&kn->kn_event_whandle, evt, - evfilt_read_callback, kn, INFINITE, 0) == 0) { + kn->data.handle = evt; + + if (RegisterWaitForSingleObject(&kn->kn_event_whandle, evt, + evfilt_read_callback, kn, INFINITE, 0) == 0) { dbg_puts("RegisterWaitForSingleObject failed"); CloseHandle(evt); return (-1); } - kn->data.handle = evt; - return (0); } From 1fa43813e8a191c9df5d5a21ad3c577e875bd6a1 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 30 Apr 2011 04:19:08 +0000 Subject: [PATCH 0467/1120] Various fixes for Windows. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@496 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/windows/platform.c | 35 +++++++++++++++++++++++-- vendor/libkqueue/src/windows/platform.h | 3 +++ vendor/libkqueue/src/windows/read.c | 15 +++++++---- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index f881bb2bc..0bd0a4477 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -84,6 +84,7 @@ windows_kqueue_init(struct kqueue *kq) return (-1); } +#if DEADWOOD /* Create a handle whose sole purpose is to indicate a synthetic * IO event. */ kq->kq_synthetic_event = CreateSemaphore(NULL, 0, 1, NULL); @@ -93,7 +94,6 @@ windows_kqueue_init(struct kqueue *kq) return (-1); } -#if DEADWOOD kq->kq_loop = evt_create(); if (kq->kq_loop == NULL) { dbg_perror("evt_create()"); @@ -188,7 +188,6 @@ windows_kevent_copyout(struct kqueue *kq, int nready, knote_lock(kn); filt = &kq->kq_filt[~(kn->kev.filter)]; rv = filt->kf_copyout(eventlist, kn, &iocp_buf); - knote_unlock(kn); if (slowpath(rv < 0)) { dbg_puts("knote_copyout failed"); /* XXX-FIXME: hard to handle this without losing events */ @@ -206,6 +205,8 @@ windows_kevent_copyout(struct kqueue *kq, int nready, if (eventlist->flags & EV_ONESHOT) knote_delete(filt, kn); //TODO: Error checking + knote_unlock(kn); + /* If an empty kevent structure is returned, the event is discarded. */ if (fastpath(eventlist->filter != 0)) { eventlist++; @@ -232,3 +233,33 @@ windows_filter_free(struct kqueue *kq, struct filter *kf) { } + +int +windows_get_descriptor_type(struct knote *kn) +{ + socklen_t slen; + struct stat sb; + int i, lsock; + + /* + * Test if the descriptor is a socket. + */ + if (fstat(kn->kev.ident, &sb) == 0) { + dbg_printf("HANDLE %d appears to a be regular file", kn->kev.ident); + kn->kn_flags |= KNFL_REGULAR_FILE; + } else { + /* Assume that the HANDLE is a socket. */ + /* TODO: we could do a WSAIoctl and check for WSAENOTSOCK */ + + /* + * Test if the socket is active or passive. + */ + slen = sizeof(lsock); + lsock = 0; + i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_ACCEPTCONN, (char *) &lsock, &slen); + if (i == 0 && lsock) + kn->kn_flags |= KNFL_PASSIVE_SOCKET; + } + + return (0); +} diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index d56078aef..f6e799460 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -31,6 +31,8 @@ #include #include #include +#include +#include #define _CRT_SECURE_NO_WARNINGS 1 /* The #define doesn't seem to work, but the #pragma does.. */ @@ -95,6 +97,7 @@ int windows_kevent_wait(struct kqueue *, int, const struct timespec *); int windows_kevent_copyout(struct kqueue *, int, struct kevent *, int); int windows_filter_init(struct kqueue *, struct filter *); void windows_filter_free(struct kqueue *, struct filter *); +int windows_get_descriptor_type(struct knote *); /* Windows does not support this attribute. DllMain() is the only available constructor function. diff --git a/vendor/libkqueue/src/windows/read.c b/vendor/libkqueue/src/windows/read.c index 6eb77de87..2b32e5978 100644 --- a/vendor/libkqueue/src/windows/read.c +++ b/vendor/libkqueue/src/windows/read.c @@ -89,6 +89,8 @@ get_eof_offset(int fd) int evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) { + unsigned long bufsize; + //struct event_buf * const ev = (struct event_buf *) ptr; /* TODO: handle regular files @@ -102,8 +104,11 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) /* On return, data contains the number of bytes of protocol data available to read. */ - /* FIXME: use WSAIoctl and FIONREAD to get the actual value */ - dst->data = 1; + if (ioctlsocket(src->kev.ident, FIONREAD, &bufsize) != 0) { + dbg_wsalasterror("ioctlsocket"); + return (-1); + } + dst->data = bufsize; } return (0); @@ -115,6 +120,9 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) HANDLE evt; int rv; + if (windows_get_descriptor_type(kn) < 0) + return (-1); + /* Create an auto-reset event object */ evt = CreateEvent(NULL, FALSE, FALSE, NULL); if (evt == NULL) { @@ -163,9 +171,6 @@ evfilt_read_knote_modify(struct filter *filt, struct knote *kn, int evfilt_read_knote_delete(struct filter *filt, struct knote *kn) { - if (kn->kev.flags & EV_DISABLE) - return (0); - if (kn->data.handle == NULL || kn->kn_event_whandle == NULL) return (0); From c479f6972ee393920af39c203dcb7581d1054d36 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 30 Apr 2011 17:59:30 +0000 Subject: [PATCH 0468/1120] Remove TODO items git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@497 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/TODO | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/vendor/libkqueue/TODO b/vendor/libkqueue/TODO index 5bf88de0f..e8cb162cb 100644 --- a/vendor/libkqueue/TODO +++ b/vendor/libkqueue/TODO @@ -1,34 +1,3 @@ - * There are very likely to be lock-related bugs stemming from when the - kevent_copyin() and kevent_copyout() functions stopped holding the - kqueue lock. It would be nice to have a lock testing mechanism to - check that the correct locks are held.. something like: - - #define MTX_LOCKED 1 - #define MTX_UNLOCKED 0 - #if NDEBUG - #define LOCK_MONITOR(x) int x - #define lock_assert(x,y) assert((x) == (y)) - #define lock_acquire(x,y) do { pthread_mutex_lock((x)); y = MTX_LOCKED } while (0) - #define lock_release(x,y) do { pthread_mutex_unlock((x)); y = MTX_UNLOCKED } while (0) - #else - #define LOCK_MONITOR(x) /**/ - #define lock_assert(x,y) do {} while (0) - #define lock_acquire(x,y) do { pthread_mutex_lock((x)); } while (0) - #define lock_release(x,y) do { pthread_mutex_unlock((x)); } while (0) - #endif - - struct foo { - LOCK_MONITOR(foo_lockstat); - } - ... - - lock_assert(&kn->kn_lockmon, MTX_LOCKED); - lock_assert(&kn->kn_lockmon, MTX_UNLOCKED); - - * Add a counter that increments on each each kevent() call. When printing - debug information within kevent(), display the value of the counter. - This will be helpful when debugging a multithreaded program that may have - multiple kevent() calls executing in parallel. * Add a dbg_printf() statement within kevent_wait() to report the value of the timeout. From 413449fe8d5479301764ffcb1ba54a2dcb27c4f7 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 30 Apr 2011 18:21:51 +0000 Subject: [PATCH 0469/1120] Test commit using new hook git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@498 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/TODO | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/TODO b/vendor/libkqueue/TODO index e8cb162cb..37e87b573 100644 --- a/vendor/libkqueue/TODO +++ b/vendor/libkqueue/TODO @@ -10,3 +10,4 @@ that 64-bit values can be used in the 'udata' field on 32-bit platforms. * Check other filters for the EV_DISPATCH bug that was fixed in r252. + From f195787b336b4c2b408ebb775af36318a33c7510 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 1 May 2011 20:25:07 +0000 Subject: [PATCH 0470/1120] Remove www/ directory, since the website is now managed by Trac git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@499 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 3 +- vendor/libkqueue/www/Makefile | 25 ---- vendor/libkqueue/www/default.css | 34 ----- vendor/libkqueue/www/download.html.in | 22 ---- vendor/libkqueue/www/footer.m4 | 9 -- vendor/libkqueue/www/header.m4 | 29 ----- vendor/libkqueue/www/index.html.in | 27 ---- vendor/libkqueue/www/install.html.in | 33 ----- vendor/libkqueue/www/links.html.in | 49 -------- vendor/libkqueue/www/linux_impl.png | Bin 27556 -> 0 bytes vendor/libkqueue/www/scalability.png | Bin 25589 -> 0 bytes vendor/libkqueue/www/slides.odg | Bin 11262 -> 0 bytes vendor/libkqueue/www/solaris_impl.png | Bin 12401 -> 0 bytes vendor/libkqueue/www/status.html | 123 ------------------ vendor/libkqueue/www/support.html.in | 23 ---- vendor/libkqueue/www/usage.html.in | 174 -------------------------- 16 files changed, 1 insertion(+), 550 deletions(-) delete mode 100644 vendor/libkqueue/www/Makefile delete mode 100644 vendor/libkqueue/www/default.css delete mode 100644 vendor/libkqueue/www/download.html.in delete mode 100644 vendor/libkqueue/www/footer.m4 delete mode 100644 vendor/libkqueue/www/header.m4 delete mode 100644 vendor/libkqueue/www/index.html.in delete mode 100644 vendor/libkqueue/www/install.html.in delete mode 100644 vendor/libkqueue/www/links.html.in delete mode 100644 vendor/libkqueue/www/linux_impl.png delete mode 100644 vendor/libkqueue/www/scalability.png delete mode 100644 vendor/libkqueue/www/slides.odg delete mode 100644 vendor/libkqueue/www/solaris_impl.png delete mode 100644 vendor/libkqueue/www/status.html delete mode 100644 vendor/libkqueue/www/support.html.in delete mode 100644 vendor/libkqueue/www/usage.html.in diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index fecd27377..920325342 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -20,7 +20,7 @@ DISTFILE=$(PROGRAM)-$(VERSION).tar.gz include config.mk -.PHONY :: install uninstall check dist dist-upload publish-www clean merge distclean fresh-build rpm edit cscope +.PHONY :: install uninstall check dist dist-upload clean merge distclean fresh-build rpm edit cscope all: $(PROGRAM).so.$(ABI_VERSION) @@ -93,7 +93,6 @@ clean: find src -name '*.o' -exec rm {} \; rm -rf pkg cd test && make clean || true - if [ -d www ] ; then cd www && make clean ; fi distclean: clean rm -f *.tar.gz config.mk config.h $(PROGRAM).pc $(PROGRAM).la rpm.spec diff --git a/vendor/libkqueue/www/Makefile b/vendor/libkqueue/www/Makefile deleted file mode 100644 index 79bffa304..000000000 --- a/vendor/libkqueue/www/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# For information about using M4 to generate HTML, see: -# -# http://tldp.org/LDP/LG/issue22/using_m4.html -# - -OBJS=download.html index.html links.html usage.html support.html install.html -DESTDIR=~/public_html/libkqueue - -all: clean $(OBJS) - -%.html: - m4 -P < $@.in > $@ - tidy -q -m $@ - chmod 444 $@ - -clean: - rm -f $(OBJS) - -edit: - $(EDITOR) *.in - -install: - cd $(DESTDIR) && rm -f $(OBJS) - cp *.html *.css *.png ~/public_html/libkqueue/ - diff --git a/vendor/libkqueue/www/default.css b/vendor/libkqueue/www/default.css deleted file mode 100644 index 2878aa768..000000000 --- a/vendor/libkqueue/www/default.css +++ /dev/null @@ -1,34 +0,0 @@ - body { - background: #DCDCDC; - margin: 0; - } - div.content { - background: white; - margin: 0 3em; - padding: 0 3em; - } - .blockquote { margin-right: 2em } - code.block { - padding: 10px; - border: 1px solid black; - background: beige; - margin: 2em; - } - h1 { - font-size: 3em; - color: maroon; - text-align: center; - } - h2 { - //margin-left: -1em; - padding-top: 0.5em; - } - ol { - margin: 2em; - } - li { - padding-bottom: 10px; - } - p { - padding-bottom: 10px; - } diff --git a/vendor/libkqueue/www/download.html.in b/vendor/libkqueue/www/download.html.in deleted file mode 100644 index 8a361cc29..000000000 --- a/vendor/libkqueue/www/download.html.in +++ /dev/null @@ -1,22 +0,0 @@ -m4_include(header.m4) - -

          Binary Packages

          - -

          Debian

          - -Debian users can install the libkqueue0 and libkqueue-dev packages. - -

          Source Releases

          - -The source code for each release can be downloaded from here. - -

          Unreleased Development Version

          - -To checkout the Subversion repository, run the following command: -
          - -
          -svn checkout svn://mark.heily.com/libkqueue/trunk libkqueue
          -
          - -m4_include(footer.m4) diff --git a/vendor/libkqueue/www/footer.m4 b/vendor/libkqueue/www/footer.m4 deleted file mode 100644 index b38ac43be..000000000 --- a/vendor/libkqueue/www/footer.m4 +++ /dev/null @@ -1,9 +0,0 @@ -
          -
          -
          -
          -© 2009-2010 Mark Heily. All rights reserved. -
          -
      - - diff --git a/vendor/libkqueue/www/header.m4 b/vendor/libkqueue/www/header.m4 deleted file mode 100644 index c3196fa71..000000000 --- a/vendor/libkqueue/www/header.m4 +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - libkqueue - - - - - -
      - -

      libkqueue

      - -
      -
      -Overview | -Download | -Installation | -Usage | -Support | -Links -
      - -
      - diff --git a/vendor/libkqueue/www/index.html.in b/vendor/libkqueue/www/index.html.in deleted file mode 100644 index 72d7d1646..000000000 --- a/vendor/libkqueue/www/index.html.in +++ /dev/null @@ -1,27 +0,0 @@ -m4_include(header.m4) - -

      Overview

      -libkqueue is a userspace implementation of the kqueue(2) kernel event notification mechanism. Initial efforts are focused on porting to the Linux 2.6 kernel. There is also an experimental Solaris port. - -

      -libkqueue acts as a translator between the kevent structure and the native kernel facilities of the host machine. The following diagram illustrates how this works under Linux: -

      - -

      -Linux implementation -

      - -Solaris has an event ports facility that is very similar to kqueue. On this platform, the kevent() function is mapped directly to the port_get() system call: - -

      -Solaris implementation -

      - -

      Benchmarks

      -On Linux, libkqueue provides O(1) scalability relative to the number of concurrent client connections. This is an improvement over the traditional poll(2) system call which has O(N) scalability. For testing, two versions of the thttpd web server were compiled: one using libkqueue, and one using poll(2). The ApacheBench benchmarking utility was used to compare the performance of both versions. A custom script was used to create thousands of idle connections to the server, to simulate the use of HTTP Keepalives on a busy real-world server. -

      -Scalability -

      - -m4_include(footer.m4) - diff --git a/vendor/libkqueue/www/install.html.in b/vendor/libkqueue/www/install.html.in deleted file mode 100644 index 4911b5918..000000000 --- a/vendor/libkqueue/www/install.html.in +++ /dev/null @@ -1,33 +0,0 @@ -m4_include(header.m4) - -

      Installation

      - -Here are the instructions for building the source code on a variety of operating systems. - -

      Linux

      - -libkqueue currently requires the following: - -
        -
      • GCC -
      • Linux 2.6.22 or higher -
      • glibc 2.8 or higher -
      - -

      Solaris

      - -The Solaris port requires Solaris 10 or higher, and uses the GNU compiler and toolchain. - -

      Nexenta

      - -To build on Nexenta, the gcc-multilib package is required. - -

      RHEL 5

      - -
      -Required packages: glibc-headers, gcc
      -
      -Recommended packages: rpm-build
      -
      - -m4_include(footer.m4) diff --git a/vendor/libkqueue/www/links.html.in b/vendor/libkqueue/www/links.html.in deleted file mode 100644 index 0a73cbc2b..000000000 --- a/vendor/libkqueue/www/links.html.in +++ /dev/null @@ -1,49 +0,0 @@ - -m4_include(header.m4) - -

      Links

      - - - -

      Linux kernel event mechanisms

      - - - -

      Solaris kernel event mechanisms

      - - - -m4_include(footer.m4) diff --git a/vendor/libkqueue/www/linux_impl.png b/vendor/libkqueue/www/linux_impl.png deleted file mode 100644 index 313275f2b6acf6e9c65eed92da74d10016c1c517..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27556 zcmc$_bySsY*FB0Th=72Cgc1VM-67=`1nKUOmXhu=0Hp<_8>FSX6$GSFK)PE%y6dd% z`@Q3Q=Xd@;hi5!E*lg~7-`BNbt~uuws322O|NOT zs}GW_?z@dboqP(BD|30nmdN|wwxIWee^5Tce zuEFi1cuBO;QJ)6I>|g9Wu|HuJjZO4$+Ksuzl_EWJnaFw6pL%f`q<+3D`K{aUY5dOq z?4%8T;@ROnmNlIj-}wRRn|+I2!!*C5_9vREWKMZUcgz{f2v9x~peR~M6(?a%rzRJB zNtQ)aZf(buJ6vpe%CG83INpey3fGzx;dJse+I0-WLzqZ(t`xt&J;Uy*=J2!m@99mDQ6kKua(TX zI5e4?*1;$2smeptbgUo!tzqzWugITnULmH__PI0}y$TvoMs6SqBUhH&dZ!GUU-Cd> z)R?Fwg}c|r&P~4|=iOUtLw!y8Z(iRW%01|sgs)TN)&p!p|bCVo`kG2g}k|`TV3tL+_A@&ZRMiIE@)HdXQ#nbGKiL7QMqy~ALW;@%jGlfFf`BcJ#A_vwcFX6B1&5EDeiC8zxG-k z6NR2k-h=JM*#=D@+JR18zwN$)NIGNF(gQ)Cp*1cIeFBDCl;VfXo4eT;Ds|*_Nqu(^ ziMK6{<)r3zn5y-24f^FDxwiZzx@#m{=N~VYDA6eAVXO9?xp>{alM{gvdvyLg41dof z^#hZl??bw-ijRlFG)aB5ekC^fx1@dKA5@W#h=uY78yJalDdnN%F671xl~3@cA1*Q9^-wcnpLSYl=xRq|H`Vg)z7D!t#^!! z&wVYUJ=^c&C##7tqCd_Loavo^+8V}Oam#;Z75r4UIxro8uKTl4uamKbo6Oqm_;MMo zQu%P+rzL$%sryj+!w>tO?LWoUS-aR|I^1{e4$ttt64fvs`B%@zm6@=Nmi7%WX3+n>qXV zROwj{OV~$kn*^+xSS7o>5i`vq;$c(CA4N`TnY<#B9#!1lj`}Ga>qBvPYNrM}4jbgi z)fRian^dk+%{p`WR@I7oDZFWOOoK-~I?_%;R%*f4qr&Y1+s5R#YuDa8{C+zbZa za0)M3a8OqE{E2Tks>$?9krW^9DU=JrnEPv>#k)G&>AA~CB=umZoR3QUa{rl#J}ue+ zjhhg@Sgf8XiI<*Z7w;Fn%}TCPAs(J!Jcq5%^-G~Z)x~-a6Abt|)Cf#RihB%Fa-^*&1JJ6p(^;(4 zDE&-y4Vrl+l;^z)W28jS$+ODD@@W0=#^-Z>A7FG&du|$1Qi|`Gbo840X@=O95X87B z(I{LZzOB1Ha=SV>^slSYl*ZuT9?H4$EO7T2*6tGO&Aq6o0eJ4gB6E`3>Q}Rs*KDRM ziU(8IjpoC3*DQ~E%QJ6cVkiuCw0&|PZb{qB=z4v)<*ghbclw()CvvcOxzoTl^q9{3 z8`Ec$msuz%Hp6!ULvHY@pof*^V7QmMo*F1zl5xGuQAg zG)li>g~k*iyS6b-#0Pz6%1F$AP2+xxwl|-vE#srbZ?y;MT9^n7N-rjz4sAbzHc1JS zCYK3Bysz131A~a-qrP)r1JWfmiCYIFot9;gs4@WieI=5r!Od|`r&10RL`h7CVZr0Y9(ZCau(HM?Cxzkm>7HQ^W>Uu zS73CMj_-oT!GzS1r=41)ukQ%Qt-Rqc3J)4bine4b=~=iig@q|87v~xugqt!}YG7oo&npVWLkg^E%L7{H?r#1H9(R62?rvZ2f zH?@2ohqZ?7p8ksmjqVDsOD(5!?uCCGZwwgn>bQ9Oi&?s$MY}4YJl$D^tJl>%yYfV+ zD{W0tCc)0tRk+vlLIkrv&E<*=KbFPW`sdfzkat~QTfR&Y#D3j-=gGU+eEHQ+aBDZT zUb=<9+S)8gk^#jDQ=zckN)yG@Y;5-)5yeui?Cw+g=_kptCG8d+C#XM8dA2LsQp{R0~;<3>HWoB1DC?)=P&k{11#%ek`ut2q_lupVtDZb9Hb zfuDyfkbV2vndVM(XGHMdrCjL)HP)5Y&L0J&&3Yq0lW*Itq9Va@^hKJAm0j}=*-7MT zt4J_)-+i9A)@$LG+ z5*GUZ_mErB5*vYnLP5*I=;pN0(4-W7+B>1ljdLG~^Jn)KcBGcy#Z8=PsDHYxEE-bp zynHN@g?NI&!T#k}<&|QD=>_JVXV#Q}`CvQw8H?B$Dax=VPX>yj`uzNSmFeh z*WPHU@z~fHWAvY;_uO(i+S)Gbzk5eVYmBUyx93_Dd2NF9h>&3SQ{&|13bTCDGF9Gt&1&7$+@|NbmGE-r4a^*tR8O`a-ax+1^r zv=DiCwcCzSPzJn9VX&gGuuwYdzJSA{)P7tnEEUFR?AD4`Q-VT54Nu;oV?2a$2rzWC zo`=UNd;~6q$QM<{6EB~UBE5I--rc@^TPr47>QPZq(cIje-^Y`^m15o6$n3Spu7ByH zyCSG1r<=TW_M&$dI<9uR*`7UnhCz#*uW~~c9Ztq8tzudA7^6C0Ch+p{g@5?)a;8a` z(xfj*z-pw(l=vAlA$&+8p0cj4^{ZDYiHQ?Mdi8rN{rCuyy}9Yjb-2(QgJ zxAiDHdHDOUsH%w7KbUE|L1AH4RaN>mcImRTgM)*6M@PQL+v&8aKYDs5OAN15ejglE ziBiBrU}IyyefyR;pw?lj>u09qEy{Q3x22yykLNH(Pwi);r?+!-EU&H(4-J*DzJ_eG z(Jg~H3LT*jT<2QQ{1M;SdlW=3D$IHl?(tXMH{P+=><6ElP;C<#o9=@`w?g~)ABc9*u+JG*9P z3=|X;Xrts3xYt5OZ{0w(wcYyu{kzY_=^aFhko&JJ86qO0*!_K{b4+CGf9(L*be(Q+ zPft%z$RQ;qBWrDKg_}QaI)V7|x;#JmGhC39oz2&@dio#T-7W+v3-o>o>XCKDey?GVP9GAtWTcI%!kMkw5r5rBkR*A>>vf8BRX_rNF#D z<>$|z0RaJ>ot;+#ycX8h8>>Gvx2EcI*6bXAeSY55)I{utjVwy5q*=v)4!#))p#&lZv2ZW zWGp_d?7(C&2QM!UCgy!1H+G-LuQ5^hL{Jz%K5gSHsI-jMWzDe|A0HQ_ zqRNm<54TboslsS!>Ixczo9_MKQc4tq|ciY>@;ry5x6AO!o zS+m5no3Ixv1A;y{D5$Kw{A?9%d1a-XnJGd_S5HrLpwW-FJ@f$)At5au#@)Mj#i@RF zuq^pptUV=|s=}#?ozgGosQc_Y% z7IbbAK}lP%TezM^`XMy5vbx&U(UFOs9v&8ItHSf=C;MJhTwIQ@rG9t{3jGQ_bQqM` z+1X6$U(zg2p;2>ia8NXo1{h|`CDIZG!>Y(CscLI$AN`&3++U6O^vO^78nUWxN5JDl ze!=a__of+;2|8im;1of=#xr~UAKl<$A1z;%QAcM2GRVhm7I#yx-lcbVn1_<`NtW`? z$$72giif*&h#zpG&DAL zKT3V*H^5DH=MFR@c(kVogoyW>LhZ^rh)zh-(2x*VpWUVI!Y^Mgj~8%ZxJJ%Yg}QZ4 z7K=Y3*xsWZ?d-%0IGT;&V2RkxeuZGXPePKFlM}n?>|3ngD4)b{`0{03WaMt@b>Ek3 zp_Jn~m6rDi2@l^;j{jQ$BrvE84wivV4i&s*VdwNO|bj>l`qEo6t1e zLHD@`0@7RTAw4VW;o%``foVcqob_~r055M9bW6XF(Ci3Vv}IF-YD-G+&anTbHIGB> z$cV<^LX^M1gsQ44^e54dI>GOgv`@jbSimoEpidzZRnyS+~C2AZt>%6jwWjYDmcVO+rN2hctR`T1W+B5|>z zJI$jQKCVR=;3sGqAutt4;P{0K@>VTJNNeXni88q-DY55 zfOI=U#U+N{@i8z2X0N5CrLmP{LFsaKc3$Ft1t=jeFE7d1GTI-PXJLY6XDy79DDHa#mLKHKyvEk;x4Gz~kVLJ*n&ds*;t}I`q-bC5H`9 zWQZ_gge@Qt2tYj0+WEr@lrr0=8$IEPUl<$jwRPd$zn>5tEul07C8B9mT25A$+cqkN z-+o>N{c<1$07&b5+>t_^oad&5Z2Hy~7Vh)kZ*BM?FWl7_7f1Z~@nfhv^Ycb;#Mo`8 z8x|KA;o`oXoKjiJY;0^{3m#C0D=Y@tYX1PzO-xK=ik9w``^aXmo0$s`>k$o2C^5&| z?6sbr9zajdeSSbwY8pJ0o;>e)gq(?y+Z%k2&?-VJjZy<8f-I`qT1_C zrG$W2Ja9xqcBdX3jRy?@Bz=`4ToL>(RI0orn+&~o(t&leFh*r5cy#8X{ov))4+MO4 z<*Ja;PD;Hkp;rCo+aM-tYU3XtDajtYcsPi0%igaPULpp}gt48_^6~*lLsH4g%0hzQqFm`qwi>TkgBT173Mw&2^-6JU zI^31VHqnY9bE8t|CaF1JXKLazo=LCmxKwRxHc$}}ZT=j5GQlMvCmNaU*0HN|`|ol8 zq`D}Dd!I#hjBnEf(+e%OV7?VA;U%d$GZD4EthQwFEp2uDaO3zc4T%WhFo#M{&mx>) zwv~M8Mm@zl3BZvDk{JBYce3S~yUY4is8~h1m_ISy zYtzE*zZATD5M!!U-?_r$$S`;mT4Jd6JAXYX7wgtoTVxWQF9k-@Xf1hn8Q}$WO4p3G zNH;GDzVnK^l782M`CWO~!Bf_5ZKwG13u)z)FZ^7WaaRMh@F52Q=P~(;1vGp_)n-~T z7iLDsSsi0-nEu==YctL6-nQS$m?ta-7ks;^6fpj@moYP)x=0^q(FsJ(uY}9nI+UAh z#n_bZ$9%4sK)cs>b$KMp#l;n12xA;OI|eqkDt(jLeF4uy>x687#2mCoScu4|D1QW{ z+~7h-_!T1>Jw1J#hh6ZT#bPN*HdFh1A-G`$o*~|j5+NCyi7hJ}gSHIBuZTRhWrw)U}7Fk|#OzyC@^k;&;VB=ls zFVADPt!y3P-5TG!gKXU<%9+gv@U4cdX6LT{p*h^yo+9 zIE?9oIN8~M^!8rV(LmDkSPrGpcXf8It;Z|^&Z)E<{>4oV&t)@Jr2~=;d(`&DvDGtAoRC zgZtjGmyf-DX--Z~a`IHHd&fN#Td$XQF`LNcFqAr@x8xaz$`B-!e!my4qExrnL&F4{ zrW+kEd=(l`0y*ASpUST;tS&Y!1Sa7j_@AdNzGI3e`Z4YGO%PT7afuYg??!I5jn8 zT2>sdj&;wsS=;Q zDvEumX#2A+88Cb@%BOwh$Wq*n8@c?vmhUcunxV@b%I|3bl!dYvQ;j40Ty1^>&N>Hw zM=C4ToQ($s4@MUy8XI3VSf`xi^!z%nCRC$RV+!6xol;j+oLySFcmIAq$$o+J`fo!+ zLx3E0DlI@Nz_76G*02;)Hs|?YFF~Qn3*YS2FjZC&eY9Bkci^J>w-_n#OiNiF0AB@Qf8w=v!b_dpf6357! z2)Wl39THc)A!3xUwLBv~B~?Stn@dZXKaoRDh)1AcZ?qabY zpZ;?VB9WSHKRl!1@wcv`lUK4FKd)TYQjdzrCmZbMSMP}4-Z;?XifTb1Fq8_oH!L>AFKpYcUg4VXX^lq^)2eD*9MG4bZjn+2-*mc#ilG|CL7M$1P#&VLVNjP4p5 z8k(BYbCo`Dn8g(pZSEHY7}j+5w;sm&le06d8>qFqBEFaB0AP|uyzkcwel?e2Sk;!- zE5wLM0q%m$eO;U(FnoMFHu9s#RI-(oHrgY;1~PFfV8Ux6bM$?Bmka;gMbHN<-=Qiw zZE|Em1ceo0G#`y8qneI4MO0Bmw7pKY$j6P5PONN*^nJAbT2pEM`dBNOl|12{UmG1; zf9O-&%<&NSasNyVY%f*UoIg;SAismrTf)Sl@mF$bla-Qz8FT=QlzQXQI z0t(sl1a1AP?J393>aJE$EGLw1>Njd?d9`*#m}*rG*Yx^Mchi3=An@;>4=W;l*dJL7^|?FwjQr_rykE}TU3I{6BC=9%An? z>Hhqw3tJjK+^t%_gzsb*eN4AQsxJ0{bu0YMdACjPM0(aJD?MFVS=qA?;+@^(u&w5+ zOCXE|b+jR160%{S;}0ABHg7Xl=HI`9<=+C-=(_e8aHMAD=102{gFxcI$Y6YRlYTH( zYS^+;JKo#nxdztZ)R(hUgHDzc+L%8l@wM_>3FSKPE*a}?>hTNRZE+So&+9swcydkHmF$X)p%-uB74aYxvi*)26jH6Sh- zf-DEp-rzKS?X=f@`7*b(v^2Z57v>(|D{=2#OS4wNtkf=yG1ndYyFT};N#eq{FXAAf zdP~%2tY}?pYt`aOyr<*H{Ld+!i6G4w)86|P8@yd~oV0tP0%~YSxW$JXE0aIonrf+= ztPhzR&E`E?d(iFS+d+KQ7^5+>gt@hu^t&*RgvoNCtYCtz-qs{`RS*&F>UlOvF=1JT zHeq`zi+!%byhQN)G5UzPR`8`#XYq1$jsbQGM~Tf-E(j{C4)O(ca(CVD-aRgFUOfif z)97(<>?IgFDq?bwfh!nz3fY0G`>@` zEUiwNNnlD!irGLh`tAGY2O|bc8H)igIZ2L?WOXJ}SsEc_3p1`Ofh){KFE7ibHY z^KHSu3w2_HSxeiDcHquo$V*$Bw}xQ_l!!v5O!R!**S`x1Y*VlF_1$BG`}gEmJp|?o z7@3)qfI5kym1EU!kixL|nb8J(K2R`SN=Tj!0|Rg_FizL5U0cfP0SW<_sEaz7%{zbn z+J$2F9+#p>r<%3H9?0y9iVEFkpGM_8abeU7<=IK}=mhP;=}N1S&(EWF_x5g4!mu#~ zcn0`{?x}#q|6$vJQiSHI-GsTdxaf57M@>a#aBqAm>NbY^-Z?mkmd=6^yuZJA@}3A4)my_j(5is@ zh>hjkJMm&;EA9xVz$IpX{ckj{fF<%iJCu`=dD;uNj-pBhlR1}J&uFb<&T?2ydAXyM z6g;?`z*JICkF1Q0j6Z?{2709M(IE%YDQHd$dndPU-J*)f^|~iQOKbN1!yThi%`D|x zH{QBKh$KJOc!-ylaZMTXbx_Dc4eVcE0*?$;1fT=pYu~?re*|o{uI&(PITaPv{=vcE zuV26kbX!E4zj~#wt2+rv0kl@k`bAI%J**IBiNUo`n6JFVmhR%?4+6CBjG_bC0oo}* z3E)Y0eI|*5+a9}Y%68ew7Yu1^f_amao(JOr(41h|S4W}R!iHeX*~gIDvFv!r2~ zaCfiT@g_P2(n?xZ7Qz5f3(QGNPETQnge`}1;qDour2`CU6;c{NwFC7<^(jccVkfk* z-5Oss4Q*^1fk&#;wlOumM@Hrixf>Lr@V%phLfGR|$3mfIX@>3!egf7-NeO#Gc2rap zGCa2exNWD;fvE$zs=d9PG1?MFotT)IdY4Uv=?&P#PsX4a0Da_sxIxlk4|fT549W#| zt7_csjiJ0je=H))-(TXBl5{z$3V`mE3?t=WXP1(fXEnHZ+fZ0iV)rvc;sM{QA#M$j zDIRfhmVx+^8>dM56Ugw(ZBh`Y;J5Io=^!E=4gxK20e1i&0v-QwkTc#I78|4lM+b*r zKBpiH&G?+LP?`WMpOt`vjV-;`K(6= z1_l(*ESQ*>jExtNU|7^g_iPOcspaV$2M^D%8It3@i9^cH!&9hLo_#n7>ImS^(6F%S zde`E^K_D0=8a?@1+0D$%#uW-w8G(oedJ?YmQq&s|rhcOb3?WM^D=GxT84_5&zP@~X z)lgU@BqZ(;5$WjYbhNiOaU=r^1n~u678ZXqheFh+0X_skItauTqAY~LiF~#xk&$-^ z2tHppb^dYLU3}illu1cRiB#TN8MVeObK@^Rz&BQ{HnYB@TAKl213G&^i-ou-% zgIR?E32XoB3g*w?TKyrZ#nP5tDgg{_z6OK2s`*Jtr0I&9`4(~uH#_XJ64VQZ1q1{V z+I2Q_3Q$Z?4NM~gwfVl04m#3P)1xD?Jz;VSs}AE6mE;_w(nD zw^|u;MfH&D&uYUnBx{u)7ZLFjgwpkq;;n^+sOV^C!0MniKrsq4jC0VSsVokl$(hlZ z5)t~p|0=fXzGb$Ir`eEf>|xLGN&e?-p_-j*+xjq@IJ&y_cXtnxc0s7J!w%_7kbY(n z6s!Yc!LsrcG*b`<3Z)WhqdI|pOcnM0ySjROG~=rgxA{xx_rl5wU2L~SLXk$XzKMy6 zJ4po2tmxd1Y%c%&!a{OV5-`#+iHY6pJ$|?Fp^pN5RHEFwRjIwXwgx(80^(L~WJ*fdDb_t8z-G?mgv311Uv#RhN!VYAwM|=QDO-T(A00j1 zMIT|?$zblmQrzgQcEZ< zeFs3{-=Cl31I^mff`AdDH<6Aon8^#-n*W19EIdH8yywRCfX5O!XR8;$g2MXg?(hN& z$)J)AEbDDDL8zixSy>>e)Dabh7*a@dIvDyUJR?e*XLUxfkh8q?DE_&KP}qasr}(^x)%y_JZz9&Ue#1v+Y$hwd&Z!mA*rFMDPiy){F8Y=GlSxYIo6N)5Y}@8hg@j& z?_a=oSkNF}yeM(m)aK*k3(EgoXa(I3OcVnnBMLGyT)ezRsuL**36{pjnTqt!!pR$< zPDLVc445(XH8Bs6t(b%BuO-~i4qnhRAquL8;yfduTPdLKrTpmSGGPe}jD zAUASV!0qFYc$0svF4LOzSaod0hh)IkG{o#hP;nH@M-|&8XZl;^1HX{yXCK?d@&6Px{u@U*5fI z1%$_w%qp8K$U{S83PR`yY)X@V97#SDAlS*g9($07iZe5z>+ElD4}?_ejRA$Wv=sgE z<2I0hyKX|Inv+niMZ8ZxXJ=<5h`B2;3`M@5nDh*piIT;bGCA*Sz4Y!q#$f#P3qT(* zESnn}UMqcM2&o+TWZ19si;JJmY3=`|CWb%`WB;P6sY#sL50xAeP%G;;0x%4$y*H>a z4<0_LI;7m|0jdGoS^kL8C%?2Ub#j!Fxf?&n6eg4uW%hVj}K+Zj7HV zhjM=ca0bU&bF(iE1y(CC!vG(U&VcOb{co|(X4K=OiFSaCnmkLB3B+{5z_3BKltR6cq%LawNH6klpi8h~~)jh?X?xoK$+outy{R#wbkym%PfO(z?tI2Jxju=MvYz$vI{^g$WG zn?ME#x@^RK{P_CfM$_AH4`W1%*Gp}ro)Y7n;LI&|**6xwcJ^$vgxPA?S$@dhZ^P($ zUsN;h4fze-a8nrd?X`r}wHe|Vscvv;w%8ydObF>6o=y`mR>S}<1X5;Y4}5=YdUbv!4gIjXJal~^N{VMbg4DLMl2K9x4g+8p z>h7<;a#l{+v+uDH#`G4*pR56Doi!hqr z!r1Ey%0J9IAeazHfC7tPCR9k`Fa71>pBD;!bYlZFFFu=bzn2ZYot=4r=77bWm^cHU z9>$M?ZU$;Q&U@O(T;g-An()Lkr%4p1Laz+Lwau(VUbuo z!Ja=l5P4ed9$vdz=DVemcjc6aCbk&tn9ZQUEpQ4jGj9^DO$jU~$1L5Cs* z*qWT*E)B35n3Nb9yTBO0&mXs7Cw7BOnjxuSbI;Tt?l{<#i=Bk7se}D8 z8+k}&0K=m6)WhM=W16isZQ51>uhM%@);7n=J9>JU|G5i5vyl)Ne|cJtFu7C_6MLQA zUHtkriui&zj3osm$JC6B`O3G?(;LZ!Jpgl^93O+I1~nJ@1ri_A(xOLPBYV!EpE>fw zc)cz~?G|Ocr;z!@&Yx(xC&}%VwC*7!5O(Q`iGG{ z#<|Z;FDy*Z>RVr$wseC(W@Iw8Y&E(VBjT%U zKNm`waJ(>2$d}FUj@7>Nl8%pWq_s5@G7u$A3CBCtE+k#3rrnY{wrNujzz0(TxL@fbgR z|A3+fBRH%Y3>l2zN*iAvNN)w21^VQ{{=Nxke0aD5kh==Wg8n~V_kAYt!!x{IJuBxe zcZ(7iwd2A;Ae`E7o5dGr{5*<=Qevc9etl(VH2Zl+su}u5a4+>~pGZ0v8FrWDgQn4- z+3UdNZES1^2@3}Y2cw~W10WR{83~Qy-H%T()z#IytRo{M1~qn+8R=Q@6e2Kyre1Zk zH9x#h(azrUi9zMN(N4eURnNlCuV265&-PkzML)C|-MHyQo%PVKXxLG0^u_~(l;!95 zBRjJ9DE$noNB*o1ej7ZiuHrVsp!730nOo(g+wH*#e`YF3K18H*r{U?dXYC&;pF)E< zUj0c;9zFsI1hW8}R+%_G0Tq81&3{c=0Pt3KO{EPDDZ@Je z0df_O}L+ZtdV>*CINwXL*g5sEBM2#K(Iw1-U5Y#K%mMkeB1a{ z3y2te-v{d>FgpU13$!8_$$-uX`hgrsH=aMbOF=;ap1Rf5mtao?t_A6}94)YvGjLG?#~KUuK{*eG;i{4n3@ohH zXgV04x<6iS%q-=#o_MZ1q2Zau#arv^XFy(2_#D3h z{?%e@jYE#j9grU)6 z+>Uj1Kc{}h8;e|MW0R8&;I_Q(>qQHb z3)t|$MECCqh%DeSz&c=U{D2Lq<`B`n1TE_K@82*QE%6tD=?uw{mYd`52C}vOcld{s z=i&=o-(c5t0EvJPmYjsd!pJB?Iq!F|f$ghTO<x}t;=f)1A-Cj$2in z<6>ZB)UJ5>6N)L%W->5^z-t46@$b&521AI(!D%_Qk~o*e#&QOJUS{pH%^$3zI0Y(s-m5 z%3^4cX*F&;^I%PX`PYLNcy91v10VgNhX_2wU=mkjj0SF}x|$Dl7wyGtINRFyKztaK z`}+ERbH6RpZycYRA|qmvVn~|@v1H}HN)IqZFn*E38I6`*HEd$`S>PSvHGu8F!(;p) z+6GJjN!Goz3u!1RF8=UgYN9SH*ujSZ^#T_rHwd8y=oiE`gb5?>=g@mI{~0d?{+HMj z1G2f-yj5U$xTwcIy@V1NpT$IW+Mq6XbacG$SOELDEuZbQxR?kZ9G-ab?Jd9{XcbBX z2jD9OJOp0iaJVB39Ec6wF5m?r|6o$!!Ic$w{1}39baeC~r-2g8&V8w(22imUpY=2^}5gKnAYb;X{9VWk*UxN(%ZM`MrB^ zJPHH{_t~#+pwCjJ9@oJc4TqCm(}ZmBSibj~M`}nwVf~$M41Ocp^ceuQsMqlToHv0l z+9(#?ni7auI)xN*6FA1RBql4{12oHbqtfMsuM-nU7ibOb02+{KP&i8~DrBXkK>We@ z5jz5dFSHb++3;d2;QN5I0Eq;6HZPH8(7YhCD$B|c$V=7%I`ke$djbjpm=r(L=L67& zUW!G;DlU?am64gbu&}@ogo%lX5ZS5p^Ya4@9KL{cet6$N6M7;jSO38{LzV|1@*^3^ z%}tgFDP*9%#!;dtu!7I7bIOyY&9oQ?SPhW|)$Bt^7nHKlB-Qp=rp`i3*E%ue~IYOy+pyIwaklkHuLfB?GW_fC3X%IyN^qL0{x} z#HNgSYzb)Ve?-*0C^$d>Yi5IN`y|Q0M}QDnURDO8b$A4=(-Swhn)mN-hIc%+pBIN% z!TVUe3O43fuU>)pGwAe<&#Wg7dU#@7+(S+&hS_f5vY-fo;5hsUAD(&?(9OGd*Qqk! zy?ytNPA)-QN!8k#nYG2~8dz|7e9w149F&xo57RE><>uA}Mm;g{0l5I9>$aO&EwW>C zag~Ey!VulXsFrUH(-;Ks4?3r)|1~SYk4xG?9dOLSh?o|37|JQe4~>=ic`CwS;G#(a z7?_#&_xG)TeeMJT8jl2;hB*NR#n$pN;e!VS?pRhmaU8(Oa&vMbOq^m;Q)eLDci7W# zTE0>U(lao0wze)n!%cWP38)N8WO!mNbZ|~!?~w~~^X7YCr0*ieD=ZvgbHOG}nL0oQ zs+A&RG>vHIzfp#SauJxFXCmoV{~IaH9OHM`j}#k7erOVcbc0$8-ftiZ!WIrU#*8g2 zNZ|0tvtCrPEcE0KdtKo3OG`PB@;=Dyjx$Z(7{Nslab6-b?d@i;5zrd<=76exnecmX zu=~dku@6oILHC%51MXn@!zjZh3c6$l=y=&%H;#kuSwcfZM@Q$D1F0B38@T(2%z`)! z{zdfwhrkAahI&mx3BV>4T`=)s1mgsShx^9oO-xLHV#!TS{Zv6AJbMk~LQ0Xk=d7`i z-az<3wXh?N1#Smi@x3Z<2qZvyqZT*N01yt<5uBy}s87f_qf%nSC(_rlVxpsY;CNlE za~{|wa%Ji^K#uUuyj23tn?Qo({{7{pB}x&&bqG_`H)0R*ut_)34|kba2L>9B7J`eRo^hsgJYoZ_x0|3X4kJ@uhsnvM3$kU z{qeS;IC{9bx+Sm+R|4T?4FiyaGFi%SG6#Sf6fdX0lO#WxTp9e^!8Q#UCmBK<5f}G? zer>k+H)xwj7cNo^POG{SN&p$;Afz}9z8c(5~Ni+W@X-a-L=!>8UD)ZtVL&*K2Fm@@FHTS7<@?}} zoycTow7)+ZYSue=j0tEvu?lhU=EAhJS#K`esk%z|0p^eo4^pyn`5hb`fsJ^EVFA(* zBHeAFSUGQ~qeBw5IfGs#bq1zxC`edOm?XK2JzqwB2S`jYclrm;c)GIG3rZ;{NY*$Z z`M-Z8lo@e0_~eka$LgY}xqT-5l_F&{73_%Ag|Vd!^g??i094%*?X23z3Q$v;^)gCk%gttE;OV(b1Ld zR^N5Yt{KtSqOQ%G+7*+(j2M&{A9dX|HVH0!5E8LPY{t|6q9?@0hrpPmT~IawP3wLc z9~CA;;3I$aTY-lMMa`nxlZVl3`dcFgN%BW7qWx!HeUAMCN4kpNT^mFHCV6>zu`6y$ zs;jGCU0ysW9EW6NSKpijXaU5px-S1J92#0^Z)62fjhMB9AgFg@qW(~b z2UHcZK6Hx2p-D78BF^+X1Bw2NCmI z8RS_3c$qr1YM~nGxT6= zrL#wb!As$xBiWgm@064Yz%c=JoJAB@dB(pwKR=)E)#O*rM#^KnwFgdXzi8kLgw};Y z&*89!fiN740ilhUNdjCN8Y>Ps?;QaK2skdk_%IHFUM1`-gd0b^vqAvGdZ>@=o$*_& zvGrajyKtxiV2RYDNWl?MnO$66CFN#@%)L2o*h;|}NFXl!5Qf)NW2(TWs-*NylR>al z^Bkgoyc+~iF)^|0H`&vYH7j05G&hT;_80Hv)I9b#0-dd_y4rTOQCD64H$(^!j_m3$ z83>-LtH;#WduB%HffV55BN8CCL@;4=Obl$0Jb`uskOt~Pw&insdyZ2de?@imDyZ;g z7f{^$L5F2`ddV=JnVl2WYxbC*zXud;h}zyeF0WKAXb1g2z1D= z96)-2p>C!gDB^&RNKH-c(Oozoa{?x><>h5!{H!@Rn|7JZ3?~l3*+zjbUTR`y_6*cU zn03U(CmY<$->ffHR#ZT}-Zn$-2#_wwquM}7-sf<3a$?@11fKz%C1O|Xq7xBmf`JIe zB3M-z8?R@WfaJ&zel|Ev1h%dh+yt?zjNU-hxFauP57xc=BOO5d{9na=S5#9`x2_dL z1PL7k(NLr#y@NvN0s^6h0MeTf3B3fA8ba?Kq$*u$p<|(iBE1Mg=v8`e$&LScxMz&} ze9w8=4|A+B*W7cjGWYuC{8mVKI3cQeQ$D17)lEo4%FfOvL`73?JqaaurM~wFALe2w z_qO^HVSggTSJHvF76K1|vLaV#NXV;nA$C4KO?`cuf;=X|`8Of9EQ_%qfLfIC6&21# zMrkQ2v|TDUA*i(G(_30OI&FX?RkpmRboyX$lyo{H1Id);W!Tn9Eas!yQa2$?uf-G) z&hiBI#uy^N43BzM9!6_QabX>Jy-o$mTi-%nuLs^5L?-Vb)F&ceiDgz)6qNbjJYkyr zp}->Rs_d`{1skR9v&k;0Nu~CAFo=X~p3~k974x~GH!;Z+zvlgmKJmSEOPfW4ajN2! zVudF;qmdOLOEpqct5D>lv*9YQ@b|1R*CZuiyhmYtoks5VN@q7dy9pacUB! zAM3T!&RoSDAJ@^>7sApjJR+$`PH7d4nZEkpXv5!)(qibsA>x=jp8Cb-S?+z%X8Q$zIEO zqc{FTv9me;DK(u6*R+6x!MBpx)KKo9DgyL|@q7+0(=1kjrmd?J+aW)y57<`L*s|`= zT;XCgyWt(l?HHlzb9Ynm0N2HxPOq8{dJKAsOZm?3`I=2Yuob^n`Ef<7HDF=Y%_lJTf)#X;62mlDQg0aBX;|S5JGKz5W?fx@hPc z@lwt%){O7orPR05*hz`V112F4S>-|5T7-&y+-|1}wy7kKhWFE|*rjz>;8o#|G0B*@mTR zpOzO`oYPHTr8wgiMs#jg3tcSkeNllYttbiDy7i(rX$dm zuc>Tph%Y(kK_r5A-LzljZa7#@eHd6gI3_TOU9X5v=DZw<(o?AhRb{r5{|tcBzTT)4 z1vuEy4|;+)QdE(jBa^cwV+Sl<&-*!GSBpu#;0A+Yg_LCacljY{U3h6hM9QZK3u3X% zzDchy=X-=b+>b~tH%IP3_ehG8{}y*^{i-rIFwc7&=5ZtL=0EG^)G0uN!7!$2k7ox4 zp7CkkVL@_Km)e&8BQ*vfKTyv8=WX#6hRK$Y>2Z zp*nZxZYizHiLZ7lwx%|%j}XtQK+4=490(4ww6pd1&f6a7 zZ?&`KL2g(n>{_Qkq~5O38Y@57s{Sn*#v}gs%F-!j^USzSTDpu915b?oJNPuFvo==B zpu!;KjMMm)_2f)Z4EUb^u5}B+N`vAcrxgk3`MLo^R%$s)A&ZOOdpFt}OmvKW6o6vb zp~{**-c%B*JB;N`PNq8FsVs<3IzU(+>T0l5>)P2u#!Io&hhs(+n3A~UA~~rVRv?>% z>~<&;X*As=`^Q)NqBuABV@yPK14Mzm?-?i>S!lEIGQRudPYepfMFBs$IHEtDz1$to zpoK8p=o}zSjVi`R#~)f9^R{qg5;?f)kdo~;r{9Ut09o&ZsBjfSGa0u9rM9$+$w|)x zZC2%zMd8w2@|?Taz0?`zqnxS0i#4&;j3~%xPa)svV`nqkME>Dg_c)m-P6gLtT?#dn z)da2)u5CNc-eEJCYlht)Jl4bX;at7MO560fFb~o^+2%bvoAT+>-AGrZLY>h2`DP5vPPmZF z7Sx;@2wZe@Eww=wt)97x)luK%M&)`bI}I8wqC}T&DQy z=SyEg0l>id!&Im#1IOOC!As_)wIz}S^K!tdeR|&$B0;&ms>=_yiV8l)#}WGd5{Ris z`2qkD8oAgemUmkLdjt;3`kBpfNli7B3;*dgfv%+&pHhf_)O6Byh)1wG=x|%#ofPmF zXTSRTYKH-C)_Gx$B=fy6?FqTboGIL}_+!teZ7v*M>WDuuh}tbA)G|mM2sD%3`Y6I+ z4}Lk#@^}HyVQ`cniH7Z_v4Q2sjt_`G0BGE5&TPiEO{wmCTa1S54;&^eN;~19`Uo$I zwx!%XJ&Xq4)vM&Iv}$vmkB)j%2ojZ+?Osw^^uiUpkfLzGz1J}!sx>E&s%o*W`AAILrBF*f`f$Brc-c~X4d|MgHFy;1zEw}Gh+Kf{9--f@B0Tb!d? zA7>&92k|mZ=SKYTj=M@$c7vOi`5gX~jK|#xJi{2Yzntjw3by;>uwW8xCzEd7wG3Z0r-&b5d8;a3^p_*~>4LchF*6Q7TB8UIR+O@4De!9+Dx zEmmeYfVWIOfq!;BKNwp&>k%=GbfM7;S$42A0s{K1zueA!2^z_74j*Cb*qL1h|B*fq zLfUK;3#8r;^JS5KWTpUK-Zl!24v}DYysUr4;PB97P0peAYaY2tLLvfxw!&PtXqF{) zx)$XUNi^QpW0v8zGuG8!69Hywdn|6}X=jx@GDa$X!bgThHz}2HB0SwK&a4 z$c02sZPLK2*!Isbf4=9gf8p^W-a4^XZwzyBQuYR8ncrT4hgOgUdH#>~MA*H?(#*w< zggCi4N5_YM_r7q=)W$#{78AdtW7XAW4yRN|ZH?)-;0?^~<=qc2INpVss3d^GvRe!f zr;UHc${+1-j22ME7Ua9g^&W@65a*$d_@OW;pFjafmXmM1jtEIJC~IlMcTFqg_UY)M z=~phUN&YqZS(Vi=84~FlDFo|KjX28o-Oq@-XN*hM2$*Dx$_ZX=D4G2HP*HCPo1uEZ zd(}pft=I~W^xe&DKOpvdk)qW2G=*QViadZBg{-&)1Fm2dRBG(i_0~&nU!t0twBVZ+MPHQ7@S!^pKVPGI#fC}l#0aNEoS(2xC7|wvkKvT|UJ9nPG^#whuyFM{ zjDf~9*@_PWoU|U)#nrRX*z9{%T2nAc^8KE-pD|AEwuMXEn`kpPdgqY?WMg}sm7jzN z48qiCDf=e6oi^xZUmZ&@kqx*!-mQ`o98)l`g4hS&;8Y=E?A|&UH@8xj+_L}t&V%XF zXJF$6h)pQ%dh%>oiy7=A6a4+xq1*&V{+c*XBzwP~g7;M%X z^BdB}1xuBUT?lH7|1ir|O=HZC)h3_loBB1Y)K&_mvSS8v56~pDP|rI#85A3=3tqwVgfYo#0FJRuk;}Ia# zBa)cP7!E*Z)@6H@Vz7WLLg)1y^%rS@%T4R9-gfcy2|4AbJ}K_UfcU0k;?bjJo}L=d zEWw1)An+cOGCuz6f%TZG#<*i}nRCfYP`-le=x!(5FV&WKr>PF(|ERv$&@(X{U1(Jo}8o*4i4N<3A)*^HIvso5Ao2@Oo09sjR5TGrBm= zNlZ0WOMU=_p-SMF9rRZM(VF%<&cQ>Sfdp0a$KUX6EJbqag)@ql*;rVDP@2!qL?^53qXu zEu^fxIM{vtsOInG-RP7$3nYCPaW z^AmN<$dOUuh|g{n_l3M^72P+k4rvSX7s(2~ocSo&I{q0A>FM4_3ne6=kg5||nbIgB zAv22j(8dVI==NxspiwHnweBP07Ysr}5@eeCjdWeh&m)lTQuZy6Wr;Eefxz_gQVQ)F zBq#1lrsnYYFZn^)K)!DigE%i4T826rL0wyG>+C<~@J3EU&gg^Elj`kJR#5!_0b}$ks`mGzqnBT5aF^WGH zsa_K*6m)T-1N9sz2p`8iSL%6bsu#=S>ONgxJzlHd8CUJI zdzvhT6Qj9pHjp|*bn`XpfyiS@vE~!<)bEyJU}Qp=7h#fb66a1aiQVp0(s;`9oIh2Q zt=0`2*o1b``?ZmjlB8C0ahG&tG1UgtF}Wm!M0PJxB-7BPs;g$}cRNBgJ@o|A9PDKs zw5DisCG+;#nLjbPZsbqT|9sAf5V60L*u6ygueq9Pfv>TK+5HIQCydK6*US2d@MzpG zC)doMiCqu)ANcbEN9f3!pF(jnN=~Rs7`Qj@`H^map!4RNIP+sM36Fh9| zp^bp0ZoZ$vlomf@uZ(6vm>6a!P)z0g`DaaWmHWw_KyS@|(Vm2&X0$elkdW&kmY$G5r5VVdM$0H5oDTOsAr>R^@=0cn<$tKD z)Q8;zCy5r}svX}!u6h5s)CX%ui~t`(d3pJ$sa&1A8NeRYn)%k)S2{ljXre ztlXCck)y5>ASE;SeU4&ZUfazWl2ed zE8B51)BHDjlRwmBnc0e|>wiBrr9Pc?J_&PEu?uKRkMOB<)B=s6CUctD2%&GdHb0y&Q1p%x0!F&yaO{Q{Xk7vdl(J8DC$- zNbIH@xyD#iNlpX`-LLEQosm~nEwmLcJecNDK7Vw_L1UGza_7xMXW)KC?yc)e^@vf2 zFSA>U1%HWjpZ2ylt)ol9{f=xj$?@yOl^?sA`tk?+#mr43QLtw?d}bA~m1FAzw1KQjQq zG1D;f(FN2=LX7WCsH!;Im&NN9!JgbeWqp`bcWyeL<3qBAZ45t1AH*L%Wm4m$?2*KOcL8z|I6e4MZzi*8fVKm!Dfz z%EL8TWsjB1L7PRcKS>SLA+w#CIC3f7X zI55k-kR)GRFJv%~MIE{D{GERls#@sW|1m%|Dprd-vB#P+zTD?<(Az{2=$n88D?IR< z*!^IVff3VSIo3AV*C5Nh%t}+1EDljxn_`*%YzvF%E04hF=A4T|F^7+=G)Y0vbid*-)%t- z5^f{tuK{v6NfJM8-rqc@R5Wf?SkvZl37c`N9{;uQ%Lx_~Q~1;H5LEo&W9j!B(yQZ6>5~N-%DuB^po=S9TZI5p)qQJZ zaVK^2tdkKNt;N=dxu^Zal9b5EZJ56HR-gUEa;FzUoN1s;-(UuIB5|MFjyNVg{rzI1 zd8Z2#Q*%5wjQ-Ej`6oAR!^78jFc28IZ#!Oj@3TBjyJ69frX6q(mQFS0kWJJhvH6Q91OlP1OtGr~m8D0^CA)NB7#rHQTQn4iF9pk2U+xu}A zGc^s_HzPgUa5Jm?T-OL2-x;D8dBQ`z+hxN8f8KQ!c76@mx^|;H$uWXBd%ambZZ0cw z)QBnj*swdIb028wB!$1ioX9E?Njs(nW(4Qu&Ca?_#Xc35X_}PE|7f$^v{}ISXuEm+ zIr95>-G-b+A3osFYl9oV!u)pNL*^Q6MsDc0S)w+mLswjwxyicsMB{OA=9%cpEB(w3 zTi%2&X7z!@En|(PCCZG`msZAe$LkV;Ux|3;?LKrqfNq-IXr~ zuHU9K#w(vcRw!#;8=|owWU*DUJh0X?9@*DBACS2EzI+N@tXumybI;CHlONzpMtoxK zZhPRDZRE^+qx07bCv+9Z+f{y1PvTAHCO`6PL2Fy)f8&|2-X{GoAA;VsQ(I0v@lZzo z)P=69dDH2qBNLIgqP0&%<^{_=zUMhCJEBc`8fZq>9phN%X4oP0VZiY*1@6%=!}XiF zS}iiL-TIPLLiRA!ckYP*%(ojkIn^HXIxycIiF*n zYS!uDu+8fB?B;Bc0#<9lZ+8h_K9q1|?uj@#_MSZ~YsZTskNoC=!Nn0*@bfM8T zjL;6R5L-a6hbGTOOZb{7n`Uv4&o9v{`SE!jujIFwthphLJk41$ddeE*6#H6aXu2U8 zsF7yzm|2d^MG>_H*5MYyIwJzx^Yh?MrQzSZ^1TU=HEm3;$!n#iffx(>@!@@(AXsnnqPK(yC1cI8jW7?D;)@hSD^6#vp)`Yh6r3fE?ipmZ2U8}<9 zOe4D7HzcBqy@*Eo&t^4Pl0Lg%!)sdQ*NLSwD$j)HaQ0r_`1ym=OuXN#;2bRb5r``9 z#o4c%0EQe*Nb+a`_z7jlo2`c%?Qc}^cTqS6i8R`zNohkUlOizzl&YmBJl?1LyRc~J zKX?3mBoKZ6e-*#S-?^-irHXvHaS97zhE`d#_N?rO+7$JsMunp*-Qo4HpTtq^2u1jt z)&sI6RH?F>>xYEa&&$$=N0;?qE@F4)<{yK9C>-jKYebSJ|5YlQYqT7x3Jnb?k2;hD z2paR2fb#uAcUCR&v^neBb<|X{T`AP7lq;OZC1c<*RH0HY+LYnpmrOw`WfR$H0#@qg zmP|ko3kxtkv^+CgLLOf;CEbYb^J#17XFTiGs~=zrt!&k^uIaQCygw`SfKYw@&p{Qz yPX8C$`)@w`?}*?3n)v_09{=9_O$!ju%G(2xm`0RRBnH|eh`0068J003iw2n&_OI<$R* z4lvFtQeuEA5YZ9z4ZN|e)K|dUzeg^xH~}g_a*)<&wzh5P!p|u2Kw-+{%tC zrMPC_DO|q*zy%yheo26`sG|?6ELIzn0>Sp_fqLU7@(nqbBq3+!zxM z?t?nO&(zEi@L|*`oA_hFc73X^Fo+aq+WvLQ$0R~qXYc4p?^(gXk7w{=cSAPkX{J1( zQ_!&u6`*8Qn^bdjA}P%-?%y!sfnB?~xw^D+2CD#f;P_gt-<7U2y6z#Hy6Woc+vzOIW}>$HQw?jBA!w&6V|PwTheHP?Pov~23$Gb8uuhu03ps3)3nPxBDbkk!C*S9|cXU)LZFGCc|b zGU$!RTQfFP_iS6(0+g)N^85kzq!;YiO`W3YLM|o zVv9zm_DBvpGaAAVM~CB|eb=Zsx&1$_nT+*}o2x{i0Z`vxKC4HcbNiY{e*i>!hOVDr zzg)fKU>LNOS4i{hWzn~3$df#E(@Ip*E(K_@`R8EWURGt80lwoO`1$%z{x;J{jAGCJ zeZYCFCQNn^!$}iCmtrx-+xCV_hEB3cUSh)KyG*L;g`QpaDs9|B0&sZ@lbY}3|6;t{ z$l$wU_a~&Hjof_WS=?YLwFfP$<|WI4o*IyfGlde0n$!6xmW<4@KWO7cZ?#@3b!5-A zf9B0yd#b4j;3hxp9Rx&LMpwO^@V|TO8$@qjKQ1Z&3$4% zi`B8<4LjaAO^=O^_1MRSww&y_fHkA-V+iZFVaLz~g$v_6i-UG%W?C5M;U#;nHCPY5 zA9ezMoV<(_;2&c@?P(fJVBUMbl{7RplGm9MMLQEe&#lXHR}tyoYfCZ3Ud*iu&k(jt zB}v+a8IZyP$WM0aYHJ(6%D^;U$1ZqX<*we}R#jY4rH3GSl&B5AZC5c)7K-(K;aNt`;E+_jF~CAtF>DMCaU$0 zEFy20nO}dZhSs^9@1luz{DDMJmow~tjrJEcs}4N9MYS924UH7aO^vJ=Evn)*2+T-cgBU#ZnRSl9iN{OED{(oPU2pM6&72x8 z-+B4|rW#9Gc=b|60GK(p8ApkP{veudJ`IIi8hCT#4SLbAAcBF> zR5^cD#k0M-r)igYS#6qLeu)qJtowXHohm@4v8>lw)pY$>G5|L zDtC0ogAyd$UK;ppd)*HVbe5tLnz^-+n(t9+%;xm<6Wo|^0`5^Ddc10?ymoL>Ud-CD z4$r#jKk~|(YZ}LUE1t8!?4hRu@oikf7w$n)b zV61wT>)sw!_L&n9mQ?^^jx61sZkj1(;&VCJ+5rDCk6Zj!zMewWhyyp7Y(-Ex-hEAQ zTeflhsPU%dYhg!o-b;f52>nf>kl8BKRHlh0vhVTsKE|dr5H+CayR}uH{1wYdcH=c- zaS~@O%B+--z9ac|T~+*uTfsMtviD?-A2jv^2YZ&b4L0U&DjX>jsw>+5mWf#U^o;%s zp)U&~3UbIEo-xbT>qijPHLG{9Gqon97&iPlu2iyc_Q_phfW)M|6nrCPos*I89v+}n ziO`Rjt)cg5x3?BM^8@)=s>|)&qLS91o=v(APq5!L=gAu4@wk|`G|Q&!VlK{Cz|stPPCgEqr*;7~_~Bz8cJ2>kNrqVGz_R!NQzv|cOWd%Q0>FK~pKR7FDH~f@utzYw}f^|4L z9kcF>x?wpvn`vZsbKrbEZ>i2t>i+N- z=Hn_|a}!rlUMd{-xsF-W<~*PZ(s<&Qwc|!;{U5hY{d14y0vy-am1Q7#hyV6yFI8=Z zQ-13ewGE2e>16uEe;nEtFgi2^eh<)DcbAibzbRh#hK%+$$<&v%6Y>lDpOmiz=)K|j zyaNRG8^I0nd9rZn6fS%$%+wUN?tAErfXU^ku4oixKueWyHodbhk1nJgajJ$urszra zIexCW+5|!J>%}#Ra05=uOA9%pktwriqTFDRs}5jMJG)`xThAH$+zy{*5DA-W9A-0w zGZj=1UBc^UPKsil7)T5eqE1d0Q-SOloo52)-wYJ2(JW&8Yj0e>J+i`&R^9hy3#2mn zJ&e3`R`1av$D=c3aXk0=a!2nidpE(x*6#P(D;Ck#kDM-c;>l;ae)Zm<Y-GH9H)T6W?JBjV%g#(#|nM)w);Y@=4`%+A6IOFW=y; zZygwozlib6+@k>i8b@Ufd>$qO6en`@SebnKfmnCU44(W-??eu{y>iDv!dEd&pO!5} zqxwxV6_pj;d^dOX;eK5D{F%9BmJIcCWJVJc(!FZm$^S|@I5JK^)MagmSN;@DvUF9lCyS2m= zN@L^g2gwo^e({_B>Arjklf0JOpYt~3KHvRdP$coH(lMvUzf`Cpte z-Q7+R!%I=b4iz}}bJKCUbs)Ul!;=baZ=mzlD4`c!1^`@csq!vsLto>;~yt zql1k*hAbBV5xgR$pw+nZ(5h^=IoUzV)HX`?)r7)OSMS!b;JhogQui0 zGYWN=b6D!*$^fnHc}B#^<_@PKTwWnsvhO+9c|H5%Y7D@M1YcA5U>+Yn6Nkwhhz2Gr?pHno0 zOT*Ngw49$eqchTJ8eg>OA3vmBxkoxBG?6s0Z`{lZ7w7GVxLu(~dD&k_u{o<&3W~kD z+KZ$I*0S5Xkvzy2{TVRT8%h5eCkr~TM187_#Ey9OxPLoKKKoFlp;~JnbpP9z>W!;r z-WWq`u|zcqcjMuQ;bfxk;{dhR8r5^2&#`7((LgFh<9k=Y0{pwLkR)517q1d$df~60 z`3hRGZk{L4z*f1Xl~lskKRMyCgCgLe{i#R>895^l53Sm>9GfxWrq1RaXJQ)%n^|vSd#|;gP#jQpYlC@6$zr4*Y>O1n#1D?Y!RFA|nHV?osmP z3E>p=PDea810SDfGE9sh0 zK#qKFHRW(q#yxTg$LXDxM!t1}oEC)Wv0MVk?}xTierb>HfnEdmZRCLqZ>6J)K(eyB z3@9?XzMU(F_mTo@2uz}AKo*u$@+Ve>82{!O{IyLXuk&juW1+p1dX(cS=i%=zZdYt; zWV^k8RfA{`w%;Rvxs&q5&}{kf!{31BA6i9FSjpC!f>cfjT@3$@W^(d8iFHH~_5_vB zuS7lem1p-?d1i)w$P>QoE$;lD<1rcwZk`twy}5yX z`Xg1|RbF&|pj(4EGGtzl?^$XJY+&0Gcbd%WN9lnF$O#IvPgU!1H6j zjL_r+945?In@OE+RbXLqj@^(t|hhi!H09AgXR;we*n3P&$f5> zFKOObb~GfVt_N8kX$aB6L?hS%;}2R%ezJyB2VE_8Pd?y~ftr~`9Q9$}RAm{Qao|rpxXkw!5g`M3(jnYGcT2xL*jqWG#q%dh2bzv> zhqYeqQQG~sdtQ$|X*z%NaJ5Mxh|-le8VNf;cr#|TEbGi&Z#garg7>3?f{~o1AEvk~ zC&A1yROSU#XKzEcC-qb*Nq{l<%AegvY7JwbP~opX6fLaQrEvc#yG(PqW4#xhOF7!b zWig!R>b}Xr3zEjiNZf6LY*_p170y=*RxGwAR{DQ@7u=NOsKt=2cR|m5eg7Jl3*$1p z(rEbv#M~v@m0k<=Y4!+`fP6DpaMFa8{i$p_i9d$g_*ZT7A;&~v;<|E5+dq}f)ic%8 z(@qr^h`&W`#?GSv4E1)bhX*{>`};9R`_z;N#!|R}xy^?y2o-EUcv?T>-Uc`l_XGNV zzMWJr*Fx0Iq-#wnl6^SF#7B~v@6s=v%KJ>3H~|vK-!hD&J9hNe*T^i`ZI3F1&Tuo2Nvo@#Dr)}dEkC*Wdv2|- zXj7xyPN-Q^aonhWxOz9qzK{W@Jfz`>gd^;H%8yRmN6@;peA;CQpD`$^W?#DW4n6`Y z_s@)VY)D1SIuvX}=MonSArll9txxCsDY?@89< z!wDMfZ2$18X_HX=SX(>vZzSnROwIJ!83_)WW>N)M)K#sD@{{B@jvJlZPIxXpwfl=_ zM77rbnvKXf=(t=9=}XynotzWYs7#uiRFr^L>R`HdM|sS6k>R@HhN&hG#{qBwTE$#{ zn;GD{>^5(Tf|YOM#(pGFT8v-XidUY$B^IJm*FB+PWG+;st{GPO^BOLpX*ybLj85S( z>+v-|4#kc2_6z&6j_BO5m>rikd7nQkjhfHiZH*Tl9|+(#0Mn>nCn~wIYbjQfH8K{D zV;<5-5deTXFJ`{LZc{)2*JJS;@S@VPEAf(oB9B4h8)@XK_NALEhKjM!!@lcWao#}4 zuFPq>S2X_4BZPEG+eJjsc}^J#?df}vKp2EkO_V)XfW1<+lXQmuDIs#i2WZ=-E)Z}q zt6VifU!H2Gv`@RFB2>3Elfj^0?$&tBACAB`{lJt(Jd59t0|{TQN3m?kBAYd***`qd zLkEO(bvF(Ey{r?0?8g8J;q}wrwo0cFR7#`STuZ$+LMC)teu1)xINfFGg#PZkxjexI z8h>}pxDP8LZcb9$oBwIqlyDhT`+lQN?j5reI-hLXlLDOn8`817uEk`o=06kF1y*f!-KC6Y3Nuzz| zN|BDWP#4yUL!Dv{uyC@p*2M44@Jhq-{+MRus^_S{IBU3IyzOfALE*zFmJ8Yj6X%Yy zP9{m6Z-2}&dG!MlsaMtU`E>3-quyl?Cr5)Ew&B_PPXeRrWS@=bldzLx?0aDV(blsW zFf{9j%kxVuwnK?PCidh=>v7MZBYE6~lLj>tlw|ZPM^{G--xJf&VC%PqbhrS z*pl_W)62d<%kgqSb7KLXe=Vokrnp;mrT@iC*(hYu+Bhc2{nv8q6Y3L#>!iDNK9OcX zm;ZeHhsPX=hx$9jtQQ*ZQyT-v{uNI-%}EM7{eqM_=L`^b<5K4vgoF8v!Y1W;@RX+s z>C+WRVbtB81lwkQcl(5J~bi;mPh`%T# z?ESO&=5A{{Hf=qaXvF+@`SC=ig$)K9pkvIeM8q%;H+ObRgpHlQpdlC^J^th5)(bu` zTT21aGEb91y;vcugyahaX%_3-P%Wt`X+>nc5fO~TIc^=sUEQ%u>oLBTuC5JRTAy(% zF$Z};*z}PL5)#t-`ucaA#JHHQiea9cIdcSvkltc%I8wvdw>(-U0;6s=I+S{2gd>PG zCJ~V?Wa048BCs117gtgz9dnw4iiU;|6}~LAs5H#r*=T6#{`Gh1AS^C}S9cN$K%j{w zrGoew3x`jlXB~_mO@z6&znpyL0K&_C0jv!2B!nzMTpcPL!4U`s~B0bPk_n z*A>zWKuH_{e8!i@xPRMkxjpi%edJ?0^R<%Ye*`oC8@eZUfB*8l&SZWS=;X0b1xLfA z+mf7`tW$*0g*#-U=fmfQgpBTA<$o^H5|G^{ib%ezH6mTdb#i)ct?pAtwZulr# zuKzf+R+&_oIx(AsgSTHmr5n}a;nk}%x;_ofSw?hb2Ho8ERlh??D@!4g9etO=LG$+3 z@tryD!CSYK*%>qIFW-1Bt`|=1ffqAn+3{~)w}<*JL9x`)XA%oy?6thPP}T}cF-S?8 zxIxW4mL@gs$6kXg_LG889>9<;N=LXRADX^HIgpt~^W)O!e|l-dw;Wo&>pqT8`4K8@ z$i&BEyZFLCqgY_N8m&+4;&YdYja+65)zgHHq?Jl^VH=QRNUtk^&+%MB{$$9G$%lHd z^xlCvdS1j;4!Y>2ap{DjucL8SX#wQt$8*Nzxk|hU0pIirwtly`01=?SX+Lc33(D3J z_M1@VzIDr9L_Ssg-G?*St_p?aN2&DD*hbiYrz@4L?ge{L8c4_x#qZcu?ztPJ$~R0q zv8ycm4%d>17X`b)teh0~ui)M^83V%WMw^yF+Lw9k8FXowS2n6i$%Eu7+p!-bRxVk- zqnUr?@l-qtD5)b1wzixW90TPS*oM5P`hjT zDpQ(`M9%oT43$=c{z)OB`ZFgoU4hijyx#pfAkEgsD_;3Lp>Aj%6P zIA?wi_YxU*4)?)8dbQoUrDzTU5B***RS_&P?eJAO%Kp!^xWgK8A0uA)|Na$q^vl|F z)o%9sIU3qVy8P6$hG)ws^3~TOF%IBSxvYiTw>EW~;8ZGxL_Quf9K_$`Z~~9Tq#l%) z_cytyAeb@yx~%B8nZ*f;yKwV!cki422JN57inus1b;l6_=e24~q5Yk$IgP1uC6-uv z;}!kKgetN}y7(Q36M|V82TztyhHUe^8af6JJUC&8XQAq|?lSm~N}mJ>d4=sDgphgR z3#_Om=)S=0X?!Wt6*opzsrt-V^Mn(Q8Ee(y<>XEHUFR$j&(?G4jWI;)7UrM?5UlW~P(EW!Y*~l>8VyqF$$uHEo)o^Yt(V z;5N@t-2M6fNE1*{xVD6ipeGoBx9Dtxd}hsU(y$tC`vWs53ITHc=0b$*p0;uyf|!h| z8J_lmh$qwOsy3z0DVV=r_?xws+|ym&x1=@T)g@?{Q7Q&-fv4v2NM0>YBDlca`5ET% zk`vO|;s_@_gzm25l^!t-M0M1VLvH7Feb>*zhy7QyMK9t8b}67mZ0=<$NGPkxd}i7* z#jZsZEign|btWm+T*(eM-WY1V85+=+o)P+bVx0y2SS(o&_%30hvyKbYfCT`YB>&F*HMl-fFT3XurLL|#O@A4P^_8SjFrtfB1b`|!a2bcCYApH}## zGe>3S1;eIvInp}mu|GmHa{4Evcg-m;X0RWQkQmhZu~#@1vR&U7tWWDR-ZR+Zl{wx` z^LP>z%-;i7Dc#@iwbB0b6a+0)^e4l2FhKcOx*p8aZg zYbcX49k%cTE<=8;2)$eE6=|y2!YS6Yk6H1~KF(^p?uV$tew-QK)>)ib2b-wIj>BmL z=wzq?eeqUt9K(?efL0ayt;@^6@b2Q#O=#Pul1gX$`P_lJWW#@~0 z!+Hn!%ud&`w;pQCPk++>i+CKQo?6YG@3~E4vwor=D61%Wv)b(eMBw4B8ZRzFL;WSZ zl^OE2DaXkv`t{5e6(RehDg2!#IP;zUUz99Tm+i{EXyG``bt2ZTFeX z*91al`xSMZD?D5z$R^&x z2UJI2AbQM;)x7u=G&OPix@)WR*Vb0jIG_@7@H$MImdS}_fAb=?(-ZHZf^O#)*0jC4 z0QX3zP8Q74$or~w#3O_W5swGeds@qGXiJFaKJuXJ?apGIrCo8_{c zO5#mo%_U9Lps{qTxPNUU+Tq&*eFk593d8;P0u>-_y+ZZB?xKc@9&SPIWEI3E z$Vkv$lY+v@GN`Yu_s|vk85GfQpKkSCP5Am9)O_5@+F`eF5IqUY#QwFTSklT-7tpA4 zVDB)0zJ-s3e+VVNa{=#Z**Luabb|~%bPcI${U*pr3}1_||FvY(H6hP>-C4okT7Gx) z`WggTjgYj%p61xw5S>=j6%KufXvT+A(;A1R3ciO}9lXl{T^ymFD_kG~45Zbhq1oGI z?)UO9bL_kfUSAN%4@ATOniKzYv zkfU&M_U>H4;R=v&HX{l>HH2{xu->L&}F(39( zpvuevS&+&JmIMiGMFwekfHBY9%6 zCD4o2RJ@~k71g^>8XFG?X8elv;3C>a_TVD9g3bY-6#GU;fu^-0q^Wl`Z9tBd8iB4r z$R&K=i%t9HJp6Vr{#tjC`TL=P`?ecv`pb>>YWuHdb{zSE?U(SQJ5a+r${36Zk$McV zXTy4oUt=N1F|oyQap{RBM|R9;PIxT2GOOOoGhQm(ctQy~v);{k=EQ=$iLrw!Dgh@` z(!igGaLt~D`@b`sc=2PGaw$pG?=0|w(7O*YVKMywmSTs-7H7v%%ZDXX?6Jd$ug{hD ztBd||LI)(YO80(nK3c{QBRD>@?aS)Fb#C^;#pgES>K!2o=50tct({y(Aa3npCenv- zaL6B_C%~=A&>bVLtyz~{(vIn0Q++nH}Lp~$c7687T-nK<~ z(qRSkFYW2rnpb*ErAfkLs?g`de5+~pBG8y1J3|e^+Wj%FwFp953+<^v<8zU)CS}q3 z?jQ7mK=Ot^Do-G2lE%U4#fZhcbBwPm7-fBstG<3;7EB!OO#jA_=5QTikI3f|Z2#pn zv*b#f&TGI))?Nxr?D&t`)__D`b`RJiQy5TL1d0cpIasNF2nPp}*W^OiZDv{^biO*U zXJETbnw46Pq33@WMU36qkk0b9R^o=$8iV5rZ~4914P8T#;_f3BlZL>r)b4<>q92l1 z!4?be{fsWo;m;LZVhF{w^(6_M-6uY=&^TZG>R%C_$ey!@qckFA9yPd|AKj5@gz%O! zq6yPXylcSX2JKw2>Iw$-jj{+itR*a=B4~U(5dHGg9??g9ixhq$+9epCoRN>B0ZG`$ zuVb(&^uRrV?c*~(psVIG>S_0+;DGuSlY9SKgkV`lo34_8n~7|n$5@ek3k%@Dqf~B1 zOPl;h9I^GT|7OqOzEG4qNPr!`bTo|FG2Du#)RBsE;ZIi7RrTlAFo31e4Iibx*ceh@ zrpSxL;n_LA?Fvj7D~_-%!xkR$o885E2p59~{;}Om6~iP=0+gC?2;FkrcL*<(*5Q4!_smkK_|Rl1_pH6KJF? zwzI1k2a0D!oV^wF3K8oN$Y4(2oo>TWplp&{dgYj@u2A%-l;hq|l9@h=H{A!%e{$gNXyYg(@OT1nD+~GR+Chv;(N|9z) zjg1-|ba>=3j;3HPPlh$d2OxgEK$8&R;k(PdjtHv%?t%d$22jH{R@|Ou)fEb2Z8R99- zn?vgc8nlTqMiiR6oOH}^N!ku)H47R5-?Hom(ho=uU`9t!BGv^zzU<6xyabh%(}&7y z&+aTDr2Q}Xq;&~rR4m!;Oqs*pM-XXWVg8UbETFne8+N)3hwt{QA;!DApePD8Lh{|P zn}%8swgV6|vu+Xz?`_+|!M>}cDZc>pp=sFuPWCAi|?IQtGr3 zg)Vo_w>i{?qIG7K^4Sv}e?;hto*vURSe@uQ6JbBR^wPJgtof9H5Xlt6 zTJ!t!%_%qh=Zjx`pPqeS0F{yux5XS^N6Y^)3G~X}&@9Q94rBGZB^|J}3KA&xm za3hV_kX3fRA{|I9Odzvi8F9fVwYXP2uKjgYX+)vDJ}SFHtw zJvu(bH+Z^;VF1j3-pP#lUM#iI@Rrj_obvv;>&)#aLnTU70ZabpG$Kl}vQ{n*zx265 z;C~ZRgXgUsabF8Y<;TMeSt+RHC596)Bd7fUVE)Ej#Ma9eFV@!`oY(D&KaS#H-COWe z60Bd1^f4S$$p65D&~~&_Z5E8MRJsk?=X=L1yVj#y%LSGt;+m&5Iln_4Owl`17Mu8( z1+Ou&*+ZTwjM#z6T|GNrWtwM;@b13bI;XoBg~z3wMr=rRY=|awhu3mAw#ne+D6Imk z730+q{G9Fc6PzeiUUYYvh9M21uJ#5c+l4-!a^N!)_4HFrmeEr`t@&Fc(tE$V`#R}- z_z?z$u#8=7XvaG8`E=IZcULgR^Up3t-t#Gki5KxUi0lafBK`U_u8qvoOn#2;)0U_D zuJuMz$Dmc2&NBK?h@TNiOzUemem`-aLxO#C*S-+ya%)4yLCa=>QDwm69_Y6Gs>j}b zG)!6mgM9Y+36O`eJ^jJsVdpqad!*h;H05A&j~8m%0r2mjXw*s4YNyk{Wz4>RYfk)> zPO?V3;p}Ofrn6DyCbL1vZe$wd0{L8;GaM8Y@mnas`8f_tgVRAv2b?F#h1a1s)j;~| zsjENXI1+POmyL}^e@lq1VnA@~(=_@AyQfNIf+~q)740B;8b>QUCK5?UKgRbe)xE>S z#BHhxahTIK?D5R^O(4Dx27Cn>^~*bgyRB0{-Ix%APgR*E zS^@o%&xS5hUzJGf?WAxd5iLRZ!?zxLYamEb^t0)!w+Y2dCL?d_uUT2|1x9U8^Vtx* z%){Z&?*jBg7gc$hFwF1C`75owj1=Z3aJdkV19PFUqiq{MDhPA>lpTwq?PvL&_RGs2 zHz}$=Gphj#A~Bp7kj3|e25uSAB6o|uk_RItdTSS5S3vh!oNL;?hZ*(N2r)WHgDlmB z76Y2%no$CxeHRO;j1rQSqObt83z$Gs^Ey%WehzEBl==wilF+_ zNXiKTAg+eO)+tHmiotDwF#vzqkcBR!Y?<#f50)OqhebF6@;Q9+UHoBb-}RQL(az<1 zVLnz3($?2gLVjvLYfhurHf1p7tmk|!&H*%(W-dlYNLiiBGlHZRMVg-}3P|<#6%jq* z*{4(6yaxh!(*p4r)?YpED*On^ke)rXUTd55Ni=G~6W?rkzmGF2dVL0+b}#uh`;mZK zH@#fOVSUK?B*-YSy5s)V{`<)sQc+VQGt@5^kB=l9cA2C&yH>*{0Knh?_i;kC!N}WX zC=aKaldKWj=ev&`5X>D|Rw2X_+|6a)RC#G2jN9JN*h->6n$2s*2Y#HKm+;q}FJwrT zP+mXZ2ihEQ3~9;MDj`M!v}QhF6_>ch6J%NFhPrW$bcP?2z>a5WhtbnG`0(dph$w67 z{A6<>g+}BlPOLM(??yrOa?qaB%eaYU8E#3*D|?Fl^@rov1E5GS@4Y|C%|*vP)h(Z&PBi!Di#!bVv94h8NlOQQ661()SX{0{ zVO&!Cp1bc1P^L-$PXOg^no>UY+;^YLXYQvbzR^7e@MmfU{=~v+6CsnW{&C?m1(h@y z+o!YOd@(^N&u?A);hNi5xY_3?XR^;m^-~2TCkFjGadgl2my};Ezn;cPsAsBHwl+T& z!^+T}xBt>Z|42)(klfh9md^$rq!%H2rTsh@AdBl;lP;9-0h(g%DrBxlwKZAO8cyb$ zxDTz66$mfCpGtZS;=qI3e@#o(nw)I8V<0%%Gleh*k8CgajHkEnU*rIFk}@Cd_H`&^ z{a5cDmBth7mg|8h_q7O$pAP#t=|MgmP6}5;bDF}L{A;)o}_1u`Se$|^`m9U7IQu#M9MwS93`YIYw zm~IXH9G3SFz-7d~DZ1+q;72ZOeY7SsxT1DAgEM=`@GHI`I5lA6LeZb;HyWh*wHMm> zI_k~~+F+-dj(b1kCHJ;J69G{tN?qa{Is5R#v%utezyh;`2}I1|G{;HMwJewT(ePYy zj5K(w@^b1E(F0nz*s4O1#9mW0jYv~>Dv-c`t*^}Y6K@u5Jf=#*q`78{deS&Uvit%J z`nS;dGAEIomJ{Fs8J7Vk5y*`e%x? zc~JXX{P<3^TOCr9aK6MpWwkT+4s|8BpUK_6JQPTPPgT!2e$=Op*75d}f zd_+KG8Ej>jq%J4QikO}9+Y(Pcn=tne1@jc%IU2T}k;o{%QS1q6<)PvTfnufyknwRY zQ#LxAP{vuobWnkAZ)p|}5XFml+J0U|WF2=6p4-0_%;_?%$g z%!IaD;FG!lizd;It?q^ag5&+e5 zsLgpT#P_dfSM{57L%4^1k2|yC>zHx>&3a|{#OuW!|6o1Nj`q@j@G3h+$TBUK8?(Q; zYNHS);8XHiF~*b4X+eM9p8bs*``U7w&%XM>aNBB2K+#s6Ktm*@VoDk60mk;M!fI=D zeULUX;#X)${407$fE1TV2MyJD$yF z+rhr`otuZ8uDuiSF$d8%8Hv`h9+J_1{m?Q$AlA*Gwqh{WvfFN^%Wlr~8z??dIAc;{RrVwJsAH!)zqJK9s)%ME*f2#63-l8&*mIDJa zFnZuW`>+VWmNX)gLkp}0$J?tVg>JI`p5<_Q-xo^8eym1zhxt2L;X#Wg)O-yRKVfJ$2<1{9vBlEU_AkgjK=IOy3ESs028FY(QoSK>!>+##aJB51lW1%36!rdr zA;ng=l1b_qBKhnk4e$WEO8s(fSS70)KHvwDG|6J_RKS<-+WEt%xnE0-0*pA)WaqR4 zr`~lLa-@`v3~J?nuf)FMK~8FXIk=hY4zQ=5wZ~tC~AHJMsC2W4p2VNgL3G;@+=Ix-WfI-KG=iv-${kte#A{C6EGbb)<8_SSG)q~vUIyOT5>3?F}=oN z?}^A`OlbF=c^Q~8sBj(nVbNoHlfyiqtDZ2@`RxfyqSJRU^0oc=50nnR!q@V{fFXOz z3C3uLqTSb;0fw~E?fFhY+si7`B(($Da=%nUBR#MEI@W}RfsdkxSa&0N_UjRUA?JgI zspDUmWs34P-hwqHV5@4Q$tq~bNE2j={pmKIpF*7pPkhzvIfSmBlS>;U%+gzXR@PM# zRSPQW49b?tp=-ywY{50o*6hN$>Y- zbGBSxN_ev_7uwF}U187=jRyvd>*>`3HyHvtodmeAvpfE zHCRHH5APX5y1m9JdL`h}A(X+C%M&?V&gS}s2&%%gOPs$WLlbD}`3 zaON1TkWSANbbI5>>&6MJxb5_*E$m{fF3j2%B|dG zR_+SV6+!#qyIv7J&ZVXtJU}SamL-ky*K_N(CsA_j1WcDP+laRdjDx0JO@Oz5NuA3R zA6(d=kpkgz%bA82_S0jzYe;Lf6a2fDjnVdF1eks^ZNjwNz;gN9=#8r=^e$629ob;0 z$yc&lxWEG>3JC!Besjmi-iE(qOiIpAsw&Ub3MDllqZM=ID6(@H0|$XNroUcB_}#8r zY)WJ4ajr~1XBP%B<6IF{^x5F5Qg07`6+mHCq~3+vDXwux@NXLIOU6C{t2(Tap(2@# z+LPRxLGGV!K0@$*zLsRUe4VVLju&JG^f0P?&^C#E_R{n}^R5^;;qvsJ_f6&dW>XDk zqQ~bP<(<9YjoPwkAkO!|@nKcF^HU4C&AeowKef1%+TxSE>xCsx+L=N4?}@EitwuIw zLIht=GS*M1D6AL(a(yOjpFRsMtgDpF6TB1P3hl>2X_lil{VW7P`4H1>C@rCj8;B(G zx#F;bKIcO~aOxlcF0u^Ue)j|ar$hn(a^bw@5<=A+;dg?-ZVNiKlM$4X2CpcPrk`I^ z$#)Z$bf|M|n9rRelu6XCT-Pj`Pbzig3oLD}?H}IxTklHBg!p*s#TGwN`oz9)h)R$} z-lXYjAKp~wDkhmVfp_CrGd!fK`P(BI3#u%8+AW>mkI7KIrJB?3ujqt-^@%RjG=xgO zJtP|o<;aTf4MXsR=GzgcD|jB=Itzt5Z8LTUU~(sfYL9{MPtc1JSs8)Pim#?qCq|7n zBL3cM7s{8;cZ?V*LTd@`QMbYK2U#o4FXi&j`Pk04e@-SkYD~79)Uo$F3Fj29cm{J@ zSNp`OUSev95weDxz>lETh8cm6?y~=LX9^n|HML}Q^>K%4xf)d&pZE31_p&GS6}8(n z27|(?Yc-)1v*{BehF}|9ak|Y~EjjLJw!Bj>42g>B&uK`iOhnf23dEM_3gs;t-96$~ zrRWShM@_>Yi2y3(2mz@RwDt*tuR=sP=Q@vDb0b%hy2@tqANMCW-19%cicxpL(P>X* zTD=M1{LEV~nIe>(^Qv4gm_Ej#1Im~yS)$QZivF2Sc{2>*E!M1@B}gO)l(GIYbBIId znubPtV(i;{yEYYz4w$Z2`SvYLn$k;se%`@+aHI}~{h-YWdheyVkT=A9D)C&= ze??u>34A`Wp31WPG68C8_as`t`|)(I)3T#5^yyI*Qp7QmLHNI`QiJm`_Sp$t%f@u< z=+TSox%FO7AD673U*<|*EFkMloj=NsUFO(pUoXYI0&8loW5<866^Joq^kZHw3ZO>} z8nrHmgG~iW1A5KaA9a&cp;twk7>Ul1nd1@z3ah)ezdcM!KlCFa+?d{NXDtD)gu&9| ziQSK@NxHmrQG(Rc?eNZX+0r)l82!Y6W%Wu~IIm>*8z_f+1;gD{Ise3Y7*$Wbi*Oty`&RDy8hU&!0vT>kGyajTiq~_nq5!lK_QLi_GcL)d@O))Il ze&(^EO(~&YyLOzlV40*CHXRljWLa~@jiJFwD3o!N^G;dj2eQITV8Ywxe$sLVUNTqe z!-pP(>r6q90JJ@TC7;xzq-vOoPTnkTl4bZPht)q%q4m9tmZ>~d<-7W8U2C(PwIwPv0zTTtTqp+3zwpI7AQJ@dhSr*Sx`V9kq_Pj z2Ev|i85KHXn8~M~-hC9WW!)A{!8X|bIH#bpLpb7UVV?g|e(1;rgx&$wwRV2LdM3OK zr3P&}oGq-={ug518dy9*>2o)!fNo^;`X-@QM77x`%yWrhrw48Ju^ZgjATrF;!wbR? zeZZ`D`s2%LnZC&I!xLT5)U#n;NwbWJZsudMRk#eNgxT>GDYERG7)j`$8Qz!Ky*H~& zR?ausnX=>Ct1*QRRZhdU(9Y4z#dMQx8&g=q(n(3`!^OrV?c%07%(V<-Mw~^R-%vGv zcw1`wdb@%Vw{qc#ql(uJD&0Pq9?cnJB(8JXP=sWCG+zLv3SG_IJ`178vlx!8v70RN z^X4xQy^@cWZO$&^&*bgPpfeoVDIef-Ie$CtCYmU+7#D@IYM^Wq6H=H6-14zlrf2ILa>v-dyOgYQaX zT4Y;7uvZ+75vH-rsYfd4{0wV134dLXBa)&LN-e)nz?JMW8TG_!iP|;NE(tD7?@@96 zDW<1crf!KUE+zm~8&n1x%-8wV^9Lo!exEV~HR6g9mUgYHn414zg6Gq< z0fv&6MkOSbmKcVPp(Lb3q+{q#X@(ws44m17+YeQMhO#g|KzpZ!VY|Kx)Va{h)vF&O{Ok#RpLxq(h2t!eeE!#H%PZ~RH!eZ9rz^gJ;1_)q9l ze%b$brt37+;cyc2K?X< z&OL=k=2hQ3Nu)$@ms^v@x1&RFR9d987ePq&qVufG>TCrzl6Q>vob1}UH?{5YQ@pKR zit0UxZ4aPs?2XepOx3kSKy32!W|b=2I{6UXi&#NBd>;Wv982UL;kC%pFDEI{t9eQ*EaTwpQuH^0z?H zP{7(IrM{VFbGnYE*{L zJ6oeo=jraORAf6c%IZEqU$1jY-ZW}kGkp1yDUMAO@ipLyqAiVFPvEn>m`MvcdzYI| z0A%Ys5l2k}-0GxBhy$X8b@p-ZPQ<*0HK264v`6`IjimY#v8i`NgrBzEiJcH5a7>u4 zyUk39e30>rfraz{eoaq2-E;r3&dL#?Yz+zVo;oEeFfK=vRQ&YuTm4L4DV^95ESVaE zT^37BNbD;$m@YK9`Y3Odig8M@=iWBO=b<&68K1n#`}2Wu%J3g<%U&e{NvE}q<=WPx zY$sHNXGIxrbCeRc^QUMx1c7QEwZP(ScDT5}cNhYU=P!iO)p4Io{T-=%j?1&Ova}zi zo8Zwenb#&- z1cN}KxyKPaNp~8GT2`sWnh5vhCW@iZ5I=4I<^@q}Ij~a0FoQnZPe%{UT#u-qa)4fJ zz!zY&G%H;Xw;OWk=K55!r?Jamq4xm;a9@^xmDtfu{!BunVSanC)vZWj&jD$S(`==^*&MRW1 zdlD@d?2Y>kW{qisU8^gK$1Bx!vWdvu)n2N&4PD=Uc8}s$wudg3xBjt%h#rd$4KxlN zdy5a{l=p89@Y${L%(IR3AN8$7AmVTWTx2Htc}+Y%ljv#@CmoYfPHv1T5p85PmT#1@-YUA$3nt@}!j4T^m=?8MU(FPoWAdDEd_v;7xGJ(f z@Q5Vp%f)_TRj8!Pue<1PXYXwFI>Jl2CYcO=jds_r5|n|Tx!xUy%amPm(ldoBtY|#GoG*!=dKGUE?vlj%z%`qUPp8<#pMJ z+-$^WV{N@b_T@t*HiRvofvk!8N#2;xl-wiQy(lda`jg%KsHy0bed^9JhXdj5v`-R& z5L18TSErR`TFAnzOytABGoy~odFIk+eg2N>idgkjbv1ZQY%;Z0^t&ng;KMr;341w3 zRt0h@U3&`%Qk6`bfNTAQKTKlZ!o9jnK+<+LeCiVmTw#c=%z?(iXs5ZSj|)lNQoIzd zsaYz%7~}+nBBbfihllTX=n-ta$oH-{cnXcm!5-W)-%{d7lRK*EFBpOVMa9Ih!M;qO zpAT8fiHIt^Czx|&b`jaG)P%=Umxe-uf`t|?JLNT(Ssh=zuGIXVdNU%HTFY9xm5llL zvX%bKr0{e4!@w9jPDSfvHaQLEY67U2QGJoU%W6L~+VnXRi5V{L^~y8p2GY~X9M8`h zJ{gMbVE-oghsk}{7X<1v&n~wF4rlbnXT|cW90vm(dS)*&|3jw6gD0!9Lj>!)32y>l zFe9t3dunG`)^Fusirl2X?CpdH82GBjrTcQTnil7LP(!#rDqR?x40y^d#MBLH;@%-nHAa+xqU=u_eJGt7S=| zdv8k7_z@_*1FRd0;dS9VVs%sm&jA&^fm@Tn@3NS3Ii;q}r!aR0Vn0{hy#*?Y9Ng z;Mq~}^(ggQF*;4YrGXksG`ZU4#gjRwEgVo#RPg0yv*LUFH?3qOO0SkOR9XAC&QAtFe6#0=+$pB1(1V*j=B? zf|GjY0&TIZto(&u9}Dxj1~Py^KMj8mN&x+?tp5J*?vZyvBi|@VH5-d)CQN+0uQR%9 zzSJl{H$`_(wdP@_P%76h;CNIysyoOXPXQJ8W*4s zA$VM(c0B9rE+a2t|ICqsHrO`h1Y5t^&9Ao&GsRDf7X&JFl#RftV&ec->yH~QCYUcG zqjcYLy=KG&15eu^` z;gtf^{e11h>tTpLBy8a`1}M{7qmSYq#ol#|k*KTtan1M4^%+LGxDAoAP02gf5wxX| z@^^L~5UBdC;tZvdNAoNt?#?bK2=S|h27zaf4OoLEKcPYgT{V62p-PRE?R=tphW{xD zB>9Rr&dneF%l^hQZy&E_SStD+NYXwl-NTb%_Vo3eRPN{2jHEV#dSMLjuxWWcU9Ezi z$*3p5uBLy4cWPAA0!ll{LcMk&8mSjXu6}P~X+`KUm(|9+2w`93 zV*Ef-4k2J~kC&Bmq^5@O^j0SRszSw!0*~t`F+wlD7MBU;;3srFY7ia?{4H~Y{R$D^ z?4`GB1}GYk9x27@=4m?%Nl@L$nrVOh>U<(>aE5S`%EYC}xnsmB%~AuKR{EEBn>86~ z^bu_;7T8@VdB#G@eMwYYOw5=gpejZQj zwKm#IrYS4(6M;dpz-ZM$w}~Et6o@r0dONJ|D_ z-^%|xvi}hfME(c_%G@Srp(%Dq}Gt4jAX;RX@%*sOF*k!>$h+aZ+58FPR*qQi#DZ@tDIA*H=`f*lK z(-wQha0|VE9{)uV3k3QBymND%kPsVzPd>$iJOhm>Xq-OALMs52=Ay)?`dwv;3xOvh4zAAKK{QCzxH>viRytPE!b!jdO35Dp#aM8Q{%8DKTf z&DhYzH2SL@-ra5)YBgXmB{1&pg&3+Mzo^W|@lvM4R7AXBb%uQG@unpY2B2VT6w$St zt@Ge;Gc&*1Nu_gnd0tW8)S{E*R;uNd?An2Z!El@JZ75HkT#Oh|b`22h3%nXyaqT;N zP33kAQ`zLgzH^80q{v5~P!2k$L%4tOxzJd4Tdyvam;v%`TlH(A+riBsbZSm2O#WhB z3dwKqjru;|M9HyujYZ}eMODmP5*g`+eaSr?+KlzAt+L9u8#QMUtj2r~zHny@83>Is3`pOFP^`CHB?l?5t7Rw*T;cYQ=kE>rf+wDFZ8j3rB z*K$@N*7_#(+Pz76-S%PF>oNxlkp7X+fRl0<3{c!Vs;tU+2v2wO_MGqOX(_N|cF$G9 zc^plZ+`PTrCEnodPcr!g1R@T5bzdt5g3DR}r26npo<;q%DtP~k(Y$9;eE7m!u3S}} z!Q*{BfBv{voFg5XfNf!_1)Cci|AHVbtt}KPi`u|VHUf9BG_~>a{q`}Io9+UEb>}&G zz}AkE(o+HO3xgWuP*jpUc9GDD<9i&Ar{PeWTxF(W@qeMu&8r8c0`z$@Hl&>Oi^o?9 z?Oj)xEtAt=fvId!5!7J>BlAG*!O6vNPy#Ma*{+_~jJHZ|GArybngj2Co+vBNpFp-gcQ3-y|LvF(&T4YZt!bQ6$1Kkzo)q>-4f?wUEP80;vmgOi7s-o-QjcN4 zw3(IUz^Gv7B^ZzI(FjVkT4b|aRGc<=7&(twnsI~HJH#kAI`JCM&hgr(%9!mB&1Q+f zQ7ClyUx2t=qx26TlG#t}|F+dgI?-5j9>}yGuG6>U7i&mN|IUi>zU5~A84D{eenb3a8PBL5xq z+13KbhcUEjHL8Y(VW;1bS4=K7=Yqm@+;t0q?J+JSss9T5zy5OY5XjO&5$zQBN^e9f zw{@mJSIixt)zg45jw(^&V)16Rs+p2?1mKsql1uFDm3^bE-1R%5oFLAxX3;KyHsA!F zoKUy*VpO;0BL%T%Grzt1^dlbwHnWE0W|`teh9K^Pf^@Ko#{p#EbC!*Wbfz|Vy1h4> zl3mip@I4MfKuL2u=g*Z?1?YG(C~r4%;oV*U9|8ZMX@4+6OnXzJQf(LfB-?tD-s)r!&G?YOYNZC~RQmTUVu-fhd(W4d z6Ji4|4j^6ZEZsG>fM6};MaW(AqcsiT#{Et?ef`-BQB6`DC0sz|O9(@|6Lk7#wNRFM zx5iOlh$|gw1w2+Q6SC*EJ`R4uPKllUeFwv-ep7vr=@LQ*Z-C@nqe*L^~@ zCBY~h5EU7Y^_RXGFzsGpfDU=gmk6};(|sj6G{ynwc}`EclE-z5&Zzzq7I~Mj;sj(C zN!iJ40ki&2c{>e`7 zo^fpnCh-+BJQ5&%iPD>nK{uZ^nd#1(2JTZ7dAzbX%4}IZ6(`Dy1G1~ksMbbgFWd30 z;KkUNurGHelit!>UC*-U7dSoa{>dY&QADH*^-uiIyWuO;ug2oEW6{E-JPu?L9I2 zelk?vTr|}v?V4KO^zqt?#%Uq z(0FP)VArMGmm`-vmMb{vF(Dl}RlA??*$p2^BMdzb1Om9O&m-nJTxs)4d%iFk~eN& zk3d4}6Y#>g$o5&7x~&iZGRx!_6+mlE^GurI91sj=kwAs3Tjd-;6rA5sYT)NDY5a$i z1w{dgTT-@#l3YZH_h)!EOW&aX?retzYbwPpEIrM|Y$LObNXCQwh55|{UHHeC@dSF% z4HUvigQ1V{8}>`AidGIA=AmimJ*JIm3RpZKSi9(?Lv9flGh4!oMXy z%0%_r=99p=SFNANxW!HMe0myX$sorR@;Glyo%m^rGH`+)pK z6cjU3xW7wj!cTJo{l5mfh3QV78l(I=!9}ccAfRgDBGwl3b*S2fI+U=FW`3UdRO8L$Geu=@xa*;QR2@Ei>6DC zYHUfsK7Ssd+=)QHlrDHEDJ!M` zBKm$@Os~Y%_zk6dR^VyI&B3t-`lG0m>$LQ{cb z!!Lx#C>w;a1im$rm|dvqWT^`eWJ6q-Qi(6z+1IHt_sxoIw|sYsUHf?LR@`-ZpscR7 zdAq8kEfM)o9T*bNi;T@K?2;qu zv?$d+t8+R-rRhZNWIx|VNVVUX%#Jr zn<{>$vyksMr7?kLtqBDCK4sl+c`UimA%be3X=-JE?T#;=WMEU;WbNyE4ztO6DTU_M zlRM+9?uhddqIilIcTEHp~_+PX`JZu-`ADTTksl?w*5bP+UNR=lNt^edJ9 z7sMC3IUiwI!3C~Xf7^Q(%Rh4S`eRB7Z{KjsVDKj$ZTIhu#!0!JsA?DzL>KOMHn+lY zcbvL($poqj{NIjGG~vANTxF-c2fpNL(&2K{8^?0i{M&$mci)r{)40p2@ids;Orn7d z<=k$?YucJ)K;UaX16{pq9$2uqO!|&qz@%h<(OHc)CQn9|ncCre5zt{%SVpm``a{6| zEX0Sn&U>YL~SsvS)`O@C&m8-D_KrN6(p)Q=-=jYbikzf>Bnj!Gbb zQ7`#gI4tjg?HNlfUnh~^^H#=IPI#}gXDxghO6sL3UhBejSZ%m=ZuzLF`MxPuLjfn| zyir-n_H9D#tM#h{HuI>`onP!SPyOCW!pusDv1#3(m3Nx zcFPw;TRXEmJ|M7PC0m<7pAb>tSKZPN&=`AnFbBiq6Kn|ACYDcryz!X}XixE05W3#R z%~Q5vdec^nKGrmuyu1^^fZYjDQt+=1kfu4G8obObQXAnJF1isQG1go*HFE#tiRHX8Y`axE zMx1n%8~nsXLH%+?TqklTH%89-M3gi&KPKrHw_o_zt%<LHooGhFM$XpezEi=xJ3 zJ@fK!+S)1D4e@1teJwpbE521*H{G;4RR47LP5bLH2n6qk7=^U_A#I;CjS&^mb}#>W zGbH-pvG^)sHmZqbe{G)H(e`{70MYRevRBK?a2Tw9ZxUVa-0H(gA`gX0@S(2MyV%zi zdUu}3y))54dGL)h1VbF`MntyPP~jW+Ei;rUE;(6KI%%c@iBH?7xO+I)c$DXCfo8c1 zxv7`n*~7>>=RW%Ns$zo#w^=wgB5C~KK?>7Q;HXVk#=6<+pKecc9H zoUGSVcD`Eb{WT!3cA!E)(OUerU`(?AV_ibr)KFYfZaQ}+)-)eF&7hzdZfQOrojs+N zoOt7be%1m=M(OHhXzXTZ0G#ifTX+)#1gHl z>GKLoK6iQy=j&_WD3%Xa!+%cyI$C4YRax4sYx`!#x#f!QN9RmIx%jhw>AW+wa+5#D z{a(h-l1%bOg7&_n&&o1aMnXJZ3LG(Uo;oSf2SZjaR6zFY$&_5;R*}-y1cN0RfupXn zwxqJF%#wenf(DIwb{aeUV!p=1>pUibnIP}m4HYWu+*)v@U_zr)S7@+N%=aVI39O2g z35PO6j=$bPc%gMs9Cfim_)Hh9HpsdW-gzB2pYZJjt|mC@eKDWWKx6WoDM@jR&dld* zoH%yVwa&sE4Wrle)wL-IH8GTR>9TxWzGWA(+m29A_%TvEwJEU}&=%hlem*nta>l|D z?+pgvV3A444(%Mf^;hI}TlFsSy0cUQluC0Z@qrM(ijvwkk(TV1vqg`U&X5&0Pe!{g`dJ}z z*Wkv6u!XYA?@%kjffdCmWEY39UvpuryJ*i#ihU_cWDQjk%VE|W6*_+K5?X(9js diff --git a/vendor/libkqueue/www/slides.odg b/vendor/libkqueue/www/slides.odg deleted file mode 100644 index 5e54a9e9aad3afba5a04d538d4369342dcf10123..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11262 zcmb7K1z1%}*9N4!QyQc>q%=r_2-4DZI5Y=1aOe=EL+LK*l9KL}P6+`)N!4a0j^+kP6tzGYiCXeM-bTD0SL7Rfn7K)A*PO2)<9>~AAqQ+ zs6PN<7=I=V*d5RT>~bURZg01jHUeI|kNb4r2VFV>Vd2?#<{`h(*H%^Ul;X_%_Yh0Kd3kVjBUTMz^zHUff`0OrP2WuNg)q#Aa&Kgb9 zcY%1*x)#lewn^38F%7SL9@c@?t0OICYUG|Vf+KBM6_Dwc%h88jv8JJ}t2?Gk!c9~g z@?0nw?0S7E#7kI206S_{Bc0i(DucUZA7Xqk5-#?>SWrBn11}`SE=m%irq;RgCYA3v zkFsebNQuwYHugJRxPCW?GZJHM!`H-DBfy~|!r{VTT@@8a#9B9?V0d(tE!CDPgD&GL z13%{hWlRr}Py4?2WkaKqhID zl0Azh@^gYp6y?#_EZrIPX=rxhQA=9-9wAkcS#mAoz7x%us&R9E7CO6^s?j;zZPngu zV@A?c%YgHq|4kU7;6S{2)iCjBmkubAN?HS2E;g#~j|m?~3!Dt5ib18vpo-jq_(fNs zq!c1&S-yZR&mPA*!L{GO;NM{z-;a%j46$0?WxH40Kzg}8UuN}MNDGceLQ ztyGB%b&3ole7T$%`4^?wrE=}+Rk<}x6aw=Yc3AG5B*ITsH7*DEuAn!Ck!9Q|mq<*> zn|Sk%z*}{@Q=7e@Bb87+JXDCp8^np40WfiuO$Nl2mm#wQ{uaD+175#KToZpvl8JPR6a*00lPV5%q_;bge&abNWM#=*k z(@{I6Mm8ULIr9fGQA$X|@=6|bUy;YW(A0&#(eW4~P5EllDcU*LRYa0fVs7J|jn*hV zy6ELj_wvFuM9vLI=l#n=!@jMt2b0&x3iz211gGePmm|A_Poi>-gEa6!W$~}jStk_Q zRh-pLon0VGRd%D_%<$KtxE9>XtVo5ZVp`fNiOy1=fj|z#Or7JBEiFcYuasB+GAj-;8G^@DOAHrD5le2 z+L(t3x~~|R^oU$Gu9N4E$grKi#-yEsvAC9ePlm=$Uv+S>#)y1)7Ho*A+dGr^wriAmpG}{0f>(5Sx*G?wKR&qx31O|#yg;& zW>|PGJT5%*+9#o8#G0X8lh0U|CnlfybU9Dae`3!gIT+s|AFSU>8)=pBng^juxV^>T^5 zqS{NnicCD~wtccWzCv8a`hW1`}axO#ndu2bEkY+Bx7^2$t;CoQvyav zWsYn{fHDjb4>w$~svXQrl`+}pYsq)~md{!y#*2}ChAIM2vjPOFk=Kw#rtn1fMcw-k zDUonm3EerX->lthd%kr#mNP5ePu*TL?i`Z1$;VW_fG2(}>iuyT`gl#lh>C7AL#Z4A zgk=+gthKD$O{obi-T$03$Vgttx`57051&C@{d&Z;TYl}zWm9JjzNAp3bbojE47cH> z{k(eeA=G;HbTbmwhj3{_$m{Xs68ZO26`G-Aa-qvSf{xmEe3V~SE$Q&P^qNebge=LA zw)b0IoGFjCgZjQwSshel_)YAHUVmPtb`827J_d9=@uPDUU^=?y*oxC2)6A+up-fL2 z2;KzoRP14&s2}OP9lcLNzG&HS=k*Y8Cd-~!@1~_-jL>4#_9>&* zu06WgY))4OhZQjcw2cI@TF_X`GRMtcAASFJz}ED|*Z26vtf;c}qeQe9JL!b@T97^k ze)yFfJ@VDTQrW8YhMei@4x!>i9;2gJ!l?1dk4D?ChQod5beu+ZA1XnZ`q0^yp0gXh z_@K+%JQ>!pP}LPq!UgTs5Z690H)Hm zlNiHTLqBLOv7!v=t%2e$f!vfu0=0^C`^rdI5Aal@rTn36MnxDY7FOcL)`%R0O9d|8tBERsCyoV;}@+@gtgt4UoQ?SzaYp=0GFS6X)_pTnU z1JBf3D2vP_hbAn@!A~-smr6>iF$A$huMV6Q*@)|6*fsKwE}I$uG4jNM5a&ioG9 ze1rJ{tV^DboK&00XwM4YTn`NMmi~}kR-eqg7==j|QFn(_h-Jz9v{_aUY0~h=GLKHi z(6i0|Yma|YFIwmv% zt`dmX@1cX2x`Y*{9t%vIj&KkQOsu})O-Fn6Fxbrsz|FlI=Lf&`B5^2DOVVtv-$^&< zY4T+#Da(D<&cKK#fG_(=4XTWWfPgpmB$ya_`Cm`_na!wUu2kxKQ1}l;zA@_7H}gLw zXGO~9WC*$ppe<&NbmZ{RGOI;XMinSaP9XcjuCGf{Rd%YD!x8<&NcLF0@##xx5WN)# zYVbCSi8`p@Wl;@$FY!lF|5;xD^(NZW17GR*`w?YR^#vz&s&ljw6ma6_R|4nyA7NsN1Tt3{5-abBv!o!=e;t{Vy;=O7*Fc z!zeQxv67-XvBJnKYRbvzA!eaAh9r1bRtgG>?oXDkug^Zryhu;lH5{NGOb7`(5EJaU zG;G@#7GZjkx_-ZXQg%oJG)z_?XKY>)Gr@@c3hn*FP~oDa?QA~ALL@VHES^`?Y^!cz zDjN~Kv>*lfS@V1Dtpm{+(kaN_4&M3ti>Da6*5DZ} zOa$xNx{@@`7j@=-YI9^#Wq>ctT zu7|D)t9lB@R(pN`$=J+>p zm1k{m%5iv9_$p}-u(fQhl0<*rCI)+mO!*rV9IK|3X3AlX{fWm&!vcmYWC^z0c3%x*ClsFF@7B8vD zoSL=fwn4>8rU)Qil4P3^3jgo{$p~i*?V7v@31z5YFtAmtKzI65cR9z=v(|AojRkmO z(=;w^P@0^z6t4~V{st#5^ovLr(&O!>TUOv?lSK4 z;^ke$5G>aON&X~1s}T5J@=~tP>67}$hZEu~yFM=aoug-={XzzQI7je_zSq|R?#BW* z?1C!4_2M4P`>)`-Wf!;Mfn17+l1@Z8xSQXP@Bqlg^oCoAO295Ot{{jrEI=Se$IZz_ zM*{)_9n7u4mSS{TnsOY1bQ0p|q7D`o)g@3*hqk}@g!at%5 z!eCQ-kh8E0Q26&SgYfUt!aoZ7nd5F}4Yn1dvvP596b1m?+}t?bcsU&)mH=)cAtAtz zw{(9LWe)sP&JhZ+`ypix1c2;7H-QXi05>N$;8ym=!vEE%8`fI@IXF1{Y4lBd{A{itrt@%d@d185-&*Z#Z*BL#mUtt}0d%l;gxP6k2l~BGQ?RxD z{|a*>`=h4616V@L&0&W8XQ#ky<^@;+%uQWPIb5wlZuGa7|E$MS6uW*7h8j^U93%EjRpakx;Q|@l}#bGGzuVVI}cI7KMMR*`ymedJ~&{t z28r`xN3^K%RH3H_n{S2=lz@XAK5=; zEkR%q3?J4uk714c_{UfOqp5j0c^I_7*6uWa%{O+0IM{%IE&yI0E_-es1}UhuojHdP zpWtmNzW{$0@aGKTeDirZyI2Ehezd%U*$oVAI77iMuz5(34j?Z2$7m7$*@L%Fe5M?$JS-5o8zt5zl zi%}{LG)Pj~xKD-m@q%lZA-ondt#Q;R47ahD%MOF0(Vp9Ga^tX7bo27+@DfFIvt`u7 z&(|~S*tdP`(nlNs)=8tr6JudzU~oY^N();A?-Jr)$ZjoXE+!?Zb)wPIsv-2Om-y&> zM<@EO6U%b#n=o%apdP?;zW5N|YfX9ejB+ZL3*N|TL#R(Eek9msY7Q8p83B)CeovO8 z(&6J3+G0D7_6$|)ihfEImS%#g7xPlp*m>k?<^l3yZNL(-pX)}aFhsw3VG&pTrJ7F# zQ$0G_$6gEJs+yK#E-6XvJq|AqQrYFs*M65nmCc6MpVS6BNTU7RPPRG)47bFVH6|7F zpxi15nW?7Vup!r%)Uk(T*NL+1M&9LEGdnRxk2;>Dl`f_rUw%2TEBvT2aOBUtd(|)~ zDA4LWJV|;!lnqaC#*I$P?p}P97hFDAC`4_%khAuYJ+kBp7dv~`Ja#MTGUXAX!J64D z=BZzv2L(R{PKM}*w~DnO)spv2p2^VH_l1fAJU@P6)8GOa1z+v=%zq40mzscNrXdtJ zriGO8Z-G8Jcz5X2UAo7~sz_J6Ra_gSGAH9@dZw(Id~}6CInSpNd+Sz4MZhlOask&C zW9a&1YYL(MxbV8j&vzs8 zaOz{`xZ%G#-`&6S@H4i)eNmNon)IgVUhyowSFqS8%JH=Dca*~eW6NKzgf1cG>cGvm z%JltDYnej5QHT1%Ri9#QAG7t)xIGAM!|d)ecY3gre`LQme2s0u;|q@%NYekwf5!Rs z^ZD_04!Sa#wb=1Ojqf?n<(`?e4Qv7?yxY3bTTg{GYK4d)BCJ+5wyRdMikSW}Tt--} zlM1$2P|q!g#$6`^Ur$+qiNb=T)!k=!+LnPy+|v{m*UuD-4HSD{oj7bHMm!K5=vLeD z-qc;1vU$S>$x#N^9*Imnl`t6z)kmJr{Ll$zt`dmEt@b-mdB*qLb=VT%6C-V{`MPEKfFuPO-hW?t4> zBFA^fkfc`V>TGQUOj0@ouo}ejr_xKHzF{{6$M&xT3h;$QehY|oR0Mi;=HR`}MCzI5 z-4M?7!`>Wz{EjaK-;p({Eam||9$V``Oqz$C=8<}47% z5RYx1G zMdE~ncxz4Drlf>YA9<9nqXvzIy&JY{9NsAZ$w;^-*^`rWTZ4~VP)Q&WoZz@ z_KjFw_Nx2NSeOZ8QkQhzi2c*)>x=M{oln-$JD&cU^oZ z>AXHB%CTenrJz~`8AME+z$sHPSH?_7FTa?hzh8oa?@Lqv%uI?kZ#}7Md>13}B)LOc zjVf>A z)ipwOY}(_?&GdUH*3zpE9L75JJORU$STe+{MV$IWioIM0^XqyJoY$nqQa2@Hu+{n0m+EUW1-%*tKFzHc+W z5s#fQYSYd_R&Rf$MLEfYTJI8qbP%)mD83U(n(}Io5G@MtWThtGgU*Xpu)mPQX@3_< zK?>OTi54`aw)1|dGX0?hw*2{^h4+DOROgdb)V&u}aC&=QolV>FYJ?2At2|#ZL5Jb8VHBH)I&9_$JAYQ>|N&kUBmfxK`Ajuj_m|TUc!`INCAlRkGn! z=$=I(Fq5jzqdl0KUmw8$XE91!3^Z`!ZN7$@#dQe*UOg7hm{T|p(G^eW{UJGjZt;_7QsGw3mc9 zwKW3uGvzLCV6~JXe^j=7hNNendr$VzIf~eFF~(DWm|$ZaOnr6horTK zYYv-Ko-RRj`p}=}Q}J7QMWoa>P^zcZC0n-zP8>Y*5*9xho}`1$I*S*q;7Qv@Z�Q z?ajnE348Kh$RUo6eJXowY4B&Wl~Ow`E3b-p zImx?kuZ)ru=POh9b-p+HF+vJ6ull)rrup)i>U%IB%4^&;5{_Z=wAPT=J};BuJ>D?l z%bzHS7ZDdjmiy{>@O2`B#Qt!0gExw*$SV@ERS1gnhog{9G+`ZE@p zvG+_&6C`&ujtq7d)2GDmq)UAvdh!5-mSi|FQJ7!50Ox8u;jUE~U+~EMs4wJMa+LD4 zHOpFt07lGaaU`5W3#(l_Li@!F_gEcIPdRL z4Rr+%4MN;7LMD#4-QDzqoTE@o<}q-ryW#r%N%kp{tcJ_uUAG z0>7vp%Wkw5)wDMi-7_T-0JAk?53hKi^ZWP@Z^qfnj?VL<5ftBC`^;U}*`4Up5ESf& zyjZ&GLYI8>O8H>+v)C2EjT5-qaB}?)=Hq>WMUnrV9WlY!k+cKY!rJl=KIzN@fNlN2 zT&W-Q4*-NhAb)K4-hsiO+&GPJ2sam4`U!jMTmH=ZdA$q!_jgzrMYM!DRL*9m5Wv4{ z-q5wbYg*Vjz!>*`(<1)|Ek_4Os3XiFg#JHEyHWZ7+vwupVE5m(sQ2 zR}GTEmTA*SpkTL6Q{6BcH6r)j_Ot%SdbW#$r*=B7MSIQBp`syD{fysaz)USIO+FdN zWGosTcmRTBDI;Rn6whe8x`g^CN%Ymz36_!lYfvyt;1f>502)E8Q56<_!ti|cV%)_= z_EXYzeDqL-GY`t`yP-PK7+4m1+8=PHzkm6d8 zw5H7Xxh{!0bli0+jNF;e)~&JI_H#-V)fE}FM0B3z)nOsZq?+Y3Z**Hf#yl+#kBK`4 zF|I*X)DyFCF^zJWNb2`D#Rz&5;4zW?6u8-9omv)JdhE$3iNcIGf z08S#Nwlvm5L3dkxUw*PIUeU+pNUU1j$v69CwYF}!{1MM-nb*a&(FAwD%<4s?05KIk zH|G54^JD`qGPK6<@CY*=B|b99ytn-eO7{qLO!xsUD!2_UEZ=8p)wXM64;+s1;4>A8 zhG^Y8zr}C)R6aHAAPzm)RhasKO?N=k%ar`7`Si|wPUm{>usw5qd$D($9e1uvAT&F`o+|{@%XR*_d(WUC*~+#!B|Q;DXTXOW)6v zY>6QFGBC(K*iKI?2LBFhB1a}>ssqmU(%khp=XKQDRh6g{P$AvFzP_XAx$;3gnt{-m zzn>qSGz29dux*V0W~hBR1oSv$DLU#u zK?PmB#QH;xJ6;O8B!QTzJ8A^8+#|{S`b#kMhFaDyr+Dr_&;0GrHGv`2=elqBe{zC+|jO z&Dc*Rt;flDELYLQoqj;7+UyQ2ylS(fC&qLiirH_{Wt?S>MHcT+*i981abyk%D&t@) zycjf?>A^-lE0jsI>f-Akl1nl(E=~#O*(hGB)FdNP>OXp=Vg&G=C^*XQ#9c4ml2biz zR{l62T9uMZ3!33ip>$+XR5 zJ#87!`<@Tq=mSYrvdcAFD6=-5t$C)XH3JkO(uH-OHO zR@iFqF1eLg#>ZZ5OJ07qKZPn3rY?5BR5M>VbdCvJ(E^o^QC$HGm zB*sR&7H3PZB38EVbnM(yQx6c%*6;gJxy+G^Cmt;4tvkIL5tHgolFz!440oD#0TV!u|W%KUjzSmTpf1 z-fG?U;qONgZVveUN@}p%-;VqJUGeu_hMSWLzfvd6xL@ZMZuM??;@|fme(6!;!VWCL z!n8L#61Q5nX8ulRZ#d$wgbW*b{}$l;JIamLEqlG8zP}O!)qnENe<8xRptlwJ1p)_m zLwtWFuYUmjD-Hf@5B}1GgZpbGYySc17cKsGlpEgoEA9LP%I`G!-*NtG4Lyv@{+*=% zqRsy+itaz4{G!qSj&eh!f29}yfbt)-`rpC++Canq0QNi0{)uxtCV!t8Z;1A4@ZZ&`ZjBh5+UkQBgU#3x2B_!A!3zc*l3|ckVsszVZHggTct&Ywy*5Yp=EDoNETXQj{UTLVpDW0+GLvg{pu+ z7aBkyqR7h^fD}Wu?LFX!$Vo-!DX6gb_8M?QVk9pE1rg5wzBXh<0V!nmvRY0c5Jk)R zKT$L{1p|;s>ij|hMmkPLc0uIU(H|xV5a z`u9IQ_0zj{WzNeR?hx1A8!x)ueY)HouLVE=>?U-VM>X4^oW!1CqLwOrN~!{UwzoyR-t>$laP%^O$EL=D*?&F$DcL|(byl>l6 z+7rdO`-ifD2v-3O80`Suzq`^Cwi5Gt@g?4>RDgGlUfc}S-e`kuGAlw8pEZktwOPqoeFNBs;^8P0y?aj@R_ z{Zj`Nj0QZ>8XwWGV12~vHmur!hb&Xk5ysKV>ey8>SI zhYBMarcTU>)ZR$MNE+>T zI1&XTmIg}0cIqGORu$k>%An8|)0d;-D}ja)NbkCl++d}g!yYR{$B)sOuq7tyH}d1< z98aKD^{?|j<1YF{!Az0eE`NxDOVU~GHnB~`Zih@^ZV1F9g{%=f`U&UdadhE^-5(1F z^)nPf?+@Lp^%0P)YW`%!^AHyBZVyZl8`iHtX9?mF13bC@j_dLcoI zYTGT%Mmrw7S&7c2qWK9J?2!D!(`2kz6Q{wYs+NbL%so)U ziKO|%7AJ>UH!ziut?t8SNCLu42wqf`5zl?^IVUmwN%-o|H{**24zWW?@dt}K%YY?E;H1cpIF(*NOen~gfyLkpM4P;)7*}5FP1Uh5W zP5@QQKN_sOrY-22p|$QDe_}dyL)2B@>$H^>e7u3{ZJb%b^|$z2x^fm=&7021Fxv^Z zYOTTGMZs4HcF;Sr#^{6fhInm)kK8M=zeGW{uMVzAAxW)Z(1x>J5-&%iTm&_r)G#wK_I1eXl$J$raMn#Bh{f=7iRfJ;?1I5W6hCh6DaWjVVs;c9G=+Vuma9E2` zxfAljR}|4>{gkBIYn)X!n~O)6reXvoM(Zs1y0WZWXIHq5EC=kShHq;w947@lW3tts zvA4iYCyDb){9=<}F*_tvcgCc#JS+TylGOi&f~Q}x8OBPD*`JQqx_8YQ5y5FdC%`fR zoicCK8Lw=9zj~LF>jnzHwJJ%b$=l%F6~l8ElBK9yK524GuB3z41`boiA6O@_>~-XB z)- z&k%}p8$`g$w0PsT3Y6Q31HGBbggJ;TfgjchL``C;ooTEDFH_YNTTk=ds!^=w9XzCK zFAq;RJ04iJhpGIVJ@n1+%zBE99; zWRd=>FPsdSwg#A{U}X48VT<9U7&agA9`<4JruLkyWHKkDiH6t(E_uG{z}L8{+;vx#|r3y+#T2KiSt&JzbKDeO z4$#C+x(8e^ZYj+BnE+Veaz2=>aHhr~*-gN+goAR8TP7y9nu@a|Ew3$%HX_DfxFE#B z6V<{bR)+bsHMcCv)b^8h;{mp2DztIRe(&4ILQ=Cu?T>a1L3qze@O7Cj8|>u- zZE~ML*i+5M{-bK;ov?h(w0dM67uy5YQoRt(;qat~sUPpQe~BUHpNNFzN{r@z39!4k zYp1LhO&aGnVKhlfRmr5VAz>n+5JA}<6za{*6L!_|!BPu4G}v>-;A?`L1aA1}hh?j% zc5j@@-n&&%yi4!<&NIt}b~NE?HF#SU%(0*I6GmZPU}mSy5l za_+gUlnw`Y`vJ_1%;r(CCO?HS0C^wxMr{ub+T7*hCJL2W9k4(CqL&tHyD9wD#?o%v z_mQf|$JZXRLqZ9oHHI9<41T^;SWdr*jK|xmixO+J35|hys=BeuiaWzNzY{2ujhjAp z|KMR8jkK3`l@w|8p?Bz~8|A{~P%Jjmv*SZRWv&i{ETgIU;wly~JJ8_g^xYmTA-ZU~;DWirTL> zUmYV9T_qLKw0#}8!vnPAj3I3r&LYX9{-y1ExiWhmrvOXO+s@1Pbtl*$Jq*8?q(;H`*+Jo{#5L!T<9{)%N%ESzHm2M#<i%vHZ9BR47Hy-uS_-HO5|IEPy~=$#g( zq;jyG*a&GU7P{A|Zapvna&do0*PHp`duJ-z zyz5s!RbCt30Nr_)9?0RHqpcKnv>h%u!t<661acF^45t@ba6$$gVYz_zqkIVBq9n#RQeItsh+ZV6 z5+N(w72#CHsPv;$N2Raj>_MUNEpSAx9X=wu0lu&w2!%5E7}(d?s#YZlh;A-l%NtA6 zR$HLtfkEGO9x>!%j*X@a=mheIyN~?y&amzdU@)qkR?oRM(g)5Z3x#ixC)S}&1J;*ZiQMW{ zGUOr{K#t8ez2rI4lDRYy0W*5e%U`<6%}q=m+t+C9>~yK93mMC!Za^Ff;<)ab7*kQf zIU+FUw41!y^pgBhF{3EEr;7ZcIewx?e5FIwc)52D3`zBNcX(&nmxz(Sd5!X;xJge1 z7iqg1Ef}SUO0TY1 z!$&0E?o*e+W0+z2!AiYy{f4X^!farmfU1%Wysq*|i|6SIIRH*iFuB{YxMua*!#uXg za&L5ey^>G#)$lx3#j740Lo6@IP{4V##w`{A%8jXy% zNu`j;=!7MvhBuNW+gR!dT&;7_9MV|$*%W2iC}WP7boPpy^~9yg8bSKdR1Ws2piIzB zI**B)Ozt+rc@^-*(}9$p&ZFquq0A9(=AN^qH%7ha4571E^@vl9HVyVs>)TqnW=cfI z2Y-+DS90!C_6=?oi#Pp#rUv^?yQ@~ZYJp#fMZBd0JFsq_*s2u`yKu)`t1XpFQL^bh zCQ9^5>iWgC;5B7~ir%`gy-6GxPI*4<-DQ*k`sSv;(x(_G52a>al7pr2NRPYB$M%s( zX_Un!*xTbzl?-;!uL~mYQXZVX)hYG5n=6EF%TjU*7PWKnX$ts~IQxW0)RXQh@qXiB zuMBfK9XN3;GZ-`aF-)BS!zk_B+!z%UKjN|2ZQ4^FjIjH9cEaPqJ#h*2*szmaDgZ(P z=1-P)S;V<{?FX@f$?k*Wysb2@EsawkE0^Cy@*MBlU1e_^Xi$!eBj`R#_1M@W<$=r_ zUlvBlMjgi%qW%6@7&&Y@Zj05WvQ?26mJblxA&%yiPk=$MJ@LeRA6Sj`QKTW;+3h{; zAyv|QXcosKT*uqicUmFPEr=nr4q}L9JYy^qdVD40_@BOPDF>^cVJYN+tstCQ6Ebzig8;ww@=%Y}`x<};eOF~d5BHbS7zuDJJ7 zJ^{io1P1BGVSn(E)zGfV>Eq_{OKD=^x}GO(cG>9kn73r|sL@a2 z7?U%8x8qCTXQAxawB0y zU3U`lM`#EFAv-kUrth5*AuxwKB!WOP#1)R#zI}LEHwdgXhYea!psbF&1J8cYdTH$M*`Q~v=$OXS2~n*u)@t-SRW0GX zXX*<4Me5hVWLC$A`^0d$)X0LuC8Y({#-h{ zq4K*U-sdCg#PxD`)zxYSM}HKGP;A(2am85d`O3mQy9 zOZu}I0|^(jcA?L3oXdVYwswebBYB9g{z*6i4{vjHf!(Nr@4v-A^aO+TevBv0==*eU zs;Cb(^@+!f1R*kYku#G!{?74XaOq4P|I64!R%bS=N-s;Zm%+~(J^-ssz~uGo*B`j= zzDc-HP0G10>5hD8W15$mB>bX_CI{uR_=Mz}ypZ*XS!gyWT^+XayCu8vkJ`ke~Q;fs|4TM`~^?q3ig{hdPrJJ4kT3ZoKEcf_wI{KP?0W zFFf}3$EMuHb?WsH=uaq;r@1uyni(sTza=RYjnwJ#juU-FH5rd2FBa-Qo1qz0)tp@0 zAe$V+lLx1on40!egYe|ofY~sVLoUhLk4u5!;bU(z8PCb>pLOl+SDp>}rthzx12mR@a>kC7Eaa7+oF!?wo|pqv6M^_ zuTehugM)(?QS2W2mD&YV_Y^0~%$3rfhf46-O;i?Wm6<{I=K`5M)sqD+2bOyhH%5wz zhO8v{Msn5Vi$;`ycrCPrCdZohBvb%Jc64<3`GNYnmbzm3RMI<6kI^IfS_>W?W2L5f z8Uwayk6+4q*zft%MQ5JACmXwZ%1SmFy8kGOxsVVe6s!V=)Y$}XV-1Tr%D{FAgSd}cUZsaGhwT(t!-tMyRvj};GEXK z+9WIFFW0{V4zHJai=LKu>| zMV`$+_4uDXT&bIzDwX&A=lx#=!Mtr_D>C`BUHwMQNITV)g;XNgP95= zg?jSm(+FVtyJ1KqGs^nXIqYZAF3?b>cIy*9CtZ{8Q#rQ9Cx0K;{ON?m4dUPQ4gC)u za^w2-uen_P=iI>0oRor@Il1}bZw}xya^*K)m<*fzR9PCG$|08*Z8>tLpb&m*+0k8@Tc zT;BPtPvN!Gcw`!C(B&+VBsf*geIfjFwcW`t?o5tgU!2g|eC?6VvvW#P(q|-&Lys0x z#td@@r&@$e&6suM<8S4T&=4KnqlT3L%n%@I)iA9b`uo00 zJFg3lzwv48h}+!&gR}NVV?^zwn2tM+8sas3SA*^RiV&}FxQ1=*e&3WW0AY!_H-mI=*92;= zrdcm|q1UehOjiYEevy60h`{X*=VQj6p%m@Dh>blSJJ6+e*#qS_5MQ;d{ z!+J@@@mzwue2`3&DD*Jbg;^nhy;dtZbmh~%T&hzFY1nOV?>UI9JZY5)IQu+X?^<~D zY!9+OVyzC3o^*~5V7?x4m6UH$EGck=d}Kva588mx9i;IFMn)~xGlYg{SNqMIJHMxu zt-@j*KPfFmzGiJNf+jCOgBH+xvf2rBQCK3u;||u%r3(%t7zZ z5w1s=TvesedG6t#GXRr6yE}8GuSZWrSdQB=&j9Y;p%h!nw}~;ejs{1liYv`5x8FLe z2tHRPPF3Yz{mMqhU_-8p3X}~}?d&uauhCB@J$;?<)S+> zvaT-DJS1qt&J}?xe(d@9UzouOl3;=6W3en|z7(g54<46Hey7ScSn<#=?G+b=)dxaS91lg9ck?&Gh_ zbQsE;xpLhttR8zdp}}`+Ht*`?ykWCl5mLrfHRj6ILE*b{O=@RF>K7-=Ci_%>0xCnw zH;yKS8H2KF^VhvNnv+g^OzT!M#%kqc=^d||!h1E_ey_<+7Jg&}Z^ul}=?K?_ZDnA) zR#y*fexeG(-ubXW0@4TeHIHy6$ggD?Jp2`=ja z?fRaVNoJEXiV4KKC*M*y=tBdL*`Vzw2O_|HJN+#DA41SS+ghE)aV6ZI z_*_%_-^~Z+Da*O^Ci14_wHT!--)#_xa_QU);Iagp~V!vz`gv6=lqIeuQBo8H*h=mLlXb*NNQQX)#w%2H%}O8jco0eRt@g7ePwRMc3l z^V(A#q7O`zhQ!rmY5lKr)i@J-To=a9PBx0xhw=t>AJ0Aa1&%;3laX0YRBnZ?}C|X_f@#Dwh;^O@L{EeRL3=BF&`jYflI1bJQVW%fg zo+wG|wP4P)Q=VRWdM=Fly%llKeV0i6t-&8h4U&kAj;5idjfseG*g{s?%}iH27$;n= zrURzQHx?fs9{_dKyLtjph(Y+REbe?@I@o5ixWwGHHy4^CE&_YmV_Tc?ax!xA9)XA^ z^7Ap;2jqi^8mE;ns&bz>`cq+7wMoujliHumUHzHj|2!>4>pbF%X#k=!G&IyC93KoS z4YL2vn$>SnX!c=tb~cdNCr+3M*fQ<)H0{)#SARB*jKq@sBS9fSFbILT9wA}OdX5}t z6983C3D~-ciHVuLHu<%Qt4Az=A)H?CPiv1CFb6(Wiz~DG%{!`~s*$<{DQB9tq|NU& zWv1U*uFSZGGGS`Nd|uC<0O7JtBco!!uU%OR-wM34&~_W>D*ZGaIs|E04})oI=C4xGgNMEs)St4wvxxv ztB(V?0mN}9EFD&nmZrVcSMM~^5?wr72S)1e+l_e5$6Wyqsu4olRk1sS#WYJ_MkV`u zm%Il4kdD1}R_)a{6?+?!dQlMWI4>fEr!4ZV+1c(YJ2#;mWxb3w3Y+S;o|mZGz^~#n zzmY!op2{xQfI{EK(qeVXSrp(_f(#YMz6?BrmHM9M1EdvCVISq`6vr$yfQ>Z6i!j3w zzM;Uqg17sl{|CVWSTAOgWl5s0-Eh*Ppg+3{+BqlY7-x2<_VV_oYt4~X%Bcu_V-Bs% zu|zz3{cC7Ty?4Jyh?kT?e`S=I8r8%hnA_E<>Rbc<5Swr?bp&__Tu{bZG3g3+N?z=5 zUwyv8m~qX!zG=ju;ALs9s8T+ePMi0Hv?KHxo0wdX?JH+Bq%HR_Q*pH;--EftJs`k= zBE6aIHeOZJ2%xOBw2gZ*&qZ=DXb~Y~Z+=KW?w94yMMWOD6$!^%Tor(PaBHQs@Q~MnTjbWyDWym^MI`cNEb*(a<$^@^ zE3e?hE)XO67uq9U<2ZQ*&7vPvMu+gBwQr4_Y4<33bEuRD72(Ib?K7J_6l8_vi_)=$ z9$uE4XBEH_W-&X2&gFf~0vUc!W#IODcaR?pw$5B&*7q0hYpvIFTMkI)CJ3|b;5`jz z6v&WaU4TecRHOk0gS#?Jl@#KN+3N(F{^4+F2%)?-E|qU5+2A-ue>-ah?<&h$-rkIP zTDme26ZBU4{{HyT3u$B8h}7r{W#Q(*z74VKfxOed?Fl$(<^I?r+Q+`cuQ>euf#T5t z%u@R5>3F*4Slv^2AO`J1N=oS|@v5Z~R{=w{=0Pf-?ev_Q70F*)s`bT<2QPBg?xaa@kTVRn(! z?RgI*!UM~2RfIK&I_KmxQdv4nVG8i@peJOQs*C5Q_+@$^^J#m4H{eUc>Ck&2GqRj< zukDU#PE}Ve_JT0RN7=^8B}~Y}?(sBQ@XP?;VjcV8=K^`&po@au?2|j08^%&q`(0Nd zFl{NF;ZMe;1_dMvAwjpt%C-b0&v!kJ{F)|jmn6eN5vQZoyF*+t0~>HmijcJ=%0#yB zazuVLbEQe{TKh_$94(pqTfm!eqDDbEWCVX6HdiE9_ zW_vt6`^iEYhKcVH(&r%x6K~-E8{jv~&=#Fx_ zmrTVuM5v0@Usun0i%?9%Ud_{7Ic{wZl)B?+(v^C1!zE8vybNEAU{BQwO?08I?k=(G zJKe56s@NDPijW#XUg#9eTVT0?@;0C~z74GZud-qOdk(7vwJuNyzPpe2M`OOxq_WURYbt;VwWa-300 zJzOo>WVlqh;M>L;{L5mzu$FgZ1!Gu%`w(KXJ@dr~rB7qt_r)z3`Z?tCE8E-jhv9g5 zhdJ4ee&@+5^6&eTF6wZW)TdD072{CXM&-wU7{ZC|NpsbfqzLsms~_Vq*vFiE4|!te zqhRT}9|i&>(5v55pTY)I!%RkDj(WL)GVf_#zP;}C^qn$vyN>U^(v}p_5ECDpb)Q}` z&zVsqph0_^&+MS}6z7`+>pl-J>A?QS06{WEUimqcPk~-^A@XyMw5wAet>K71v1PCZ z1@#L>$>jJdApl7FJ!QM|O)1JeGWF^}Frskj|${ts1r9l)lK3HAoDwR)xBbQnP~Z1pZz`hGBwMy z{x)+aijhT;*zmh8n$Y{t#jyY#1cpcJzOZKU1R|HGhZoZLL_1V}huf&9v$Q&0cH85= zr7O7qlAidxC(2hWhNzPixsA%kHa$junktr?^qK9VX-Wjws%)+OUuE2xcrIk{`qy4_ z5JP?~Nw|{UV2XYdFXK0b2aQD4#7SZfO_Ao23j@qKkQ*v&9Yt#KM%x~x``yOjGtu`U zt+_P)Q;pW4KaH9oj&tx-o}J^<-M&3d!jewqTQaby%Y14p&SHM0hz?vf=4ccCUcg)R zz?@3twRfWPi5WihnZFhPIJD(@DvK7d1Al!bkI*Z>D=_jx0NuU5lmn>^R(MLxrIAMk ziL7?}5%BQ~x;irazFzX(d4oC^2PL}|K=|U*RM2cx5e@B#A9e9vx<+9&JRLfyVNUt@ zmwI;potKN>3q4Sa+Akd9D^ZU!y?-6_#j=YRma*3wwfe(YIr)Wlb`>?hpN<(XXUIcC zlzid&oUGOvFXaYrpnFFLaPUHl+PJcG{gDZpI`UW#S~pXcl@A6Wq9@rsm2M_%N7Q)(DH$599*XUDD+GEwL2(<)7dVv8!`&32m^N7H3K~_kg18Ju7wNHw zCEaj)*uQK)szTAuvn9Q^6d%jm#-zaIXnMI_$U2prPjgsiadOQmQvBQYdU$rI&P_=Y7kc4xO{rMB;^wPI5Z7uL=F)Ql7r8t;hhy6HAL;7za&Y z!=uztlw*UC7G3{=PmrXu*~Z<8=AJSnF~6Mw!MYS-ayojl#9X9Tl1h#e!@(Q!Cf@wJ zr{ao0Ed7A(+yt_bPQ4)?r=q1<`UL+(I{em*_%H9!!izB*=nXHV?Oy`jA8i&8G6>UoUWd+wNnigE8-gLOKI53t!U74{zT==(a% z1-Pm^^ZpRMplVRMP>MC{vzo~DDd|#*wmN0e7NjqC-2Bp)tLH5Vld?|b9?sW!0UoUU zu;LUJ_G$}I!du>mUN7U(O7HaV>9jn0PIO5|S)EDwf^95-W;aFShbsy0O46Td9F4jZ zW$LR>Q2vj?P-uN@37L;xK#`sX&nz?VMoU{`G;R9_!8phHq6Dt52OO zek?S4=Tx`jbFEQ{*S8Z7k6ZTOE<}K|OD$_4Yqp<)@jX4okA0Lt)yF${wpNirZcOJ_ z&oPgr7W}mTRz_s>F|fRl+qQEnDnZY-y4p=Qk*{3>Klf=)$9R6A$92fE z_feTC&OBT}-(3T$S|ZC^^|^j5&eVxcuMp205CUYPVI9lagoI> zipNAO!Nl15E)f~qPH!xr((^B1B?-$VsKz+)-4F?uLu zsgKSPwzFZzjrkS7!?9gP7MtUIP8{PrFq>dwr34B3po|1pykP3i6DN}mC3BH$3$>T4 z$pb-cunSe;BMXo{q>(PGJ^HZ{)xQ(Z-(dfrJmBw9|9>-3|F$mtCcT8X7tT;_bNS4X3>x=rQc}; Qx&(RwQ-l^iee>@B0C9{-SO5S3 diff --git a/vendor/libkqueue/www/status.html b/vendor/libkqueue/www/status.html deleted file mode 100644 index 29c3d0074..000000000 --- a/vendor/libkqueue/www/status.html +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - libkqueue - Implementation status - - - -

      Implementation Status

      - -

      kevent.flags

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      FilterEV_ADD
      - EV_DELETE
      EV_ENABLE
      - EV_DISABLE
      EV_DISPATCHEV_ONESHOTEV_CLEAREV_EOF
      EVFILT_READ
      EVFILT_WRITE
      YesYesYesYesYesYes
      EVFILT_AIO
      No
      EVFILT_VNODEYesYesYesYesYes (set internally)N/A
      EVFILT_TIMER
      YesYesYesYesYesN/A
      EVFILT_PROC
      No - This will be difficult to implement fully
      EVFILT_SIGNALYesYesYesYesYes (set internally)N/A
      EVFILT_NETDEV
      No - low priority
      EVFILT_USER
      Yes
      - -

      kevent.fflags

      - -
      -                        Status
      -READ / WRITE
      -    NOTE_LOWAT          No -- Not supported by Linux
      -VNODE
      -    NOTE_DELETE         Yes
      -    NOTE_WRITE          Yes
      -    NOTE_EXTEND         Yes
      -    NOTE_ATTRIB         Yes
      -    NOTE_LINK           Yes
      -    NOTE_RENAME         Yes
      -    NOTE_REVOKE         No -- Not available in Linux 
      -USER
      -    NOTE_FFNOP         Ignore the input fflags.
      -    NOTE_FFAND         Bitwise AND fflags.
      -    NOTE_FFOR          Bitwise OR fflags.
      -    NOTE_COPY          Copy fflags.
      -    NOTE_FFCTRLMASK    Control mask for fflags.
      -    NOTE_FFLAGSMASK    User defined flag mask for fflags.
      -    NOTE_TRIGGER       Cause the event to be triggered.
      -
      -            Filter sets kevent.data structure when returning
      -EV_RECEIPT  Yes
      -kevent.data No
      -
      - --- -Mark Heily - - diff --git a/vendor/libkqueue/www/support.html.in b/vendor/libkqueue/www/support.html.in deleted file mode 100644 index dcb3c4d13..000000000 --- a/vendor/libkqueue/www/support.html.in +++ /dev/null @@ -1,23 +0,0 @@ - -m4_include(header.m4) - -

      Mailing Lists

      - -There are two mailing lists: one for general discussion, and one for announcements. If you subscribe to a mailing list through the web interface, you will need to sign up for a free Google account. If you prefer not to create a Google account, you can subscribe via email instead. -

      -To subscribe to the general discussion group, visit the group's web interface, or send an email to libkqueue+subscribe@googlegroups.com. -

      -To subscribe to the low-traffic annoucements-only group, visit the group's web interface, or send an email to libkqueue-announce+subscribe@googlegroups.com. -

      -Please note that if you use multiple email addresses, Google Groups does not allow you to choose which email address will receive messages. The address on the From: line of the subscribe request will be used as the destination address. -

      -To unsubscribe from either group, send an email to [group name]+unsubscribe@googlegroups.com. If you have any problems subscribing or unsubscribing, send a note to Mark Heily. - -

      Bugs

      - -If you suspect that you have found a bug in libkqueue, please send an email report to the mailing list. If you can reproduce the bug, write a simple testcase and enable debugging output by setting the KQUEUE_DEBUG=y environment variable. Provide this debugging output and the code for the testcase in your bug report. - -

      Contact

      -For more information, contact Mark Heily. - -m4_include(footer.m4) diff --git a/vendor/libkqueue/www/usage.html.in b/vendor/libkqueue/www/usage.html.in deleted file mode 100644 index 978b72758..000000000 --- a/vendor/libkqueue/www/usage.html.in +++ /dev/null @@ -1,174 +0,0 @@ -m4_include(header.m4) - -

      Usage

      - -Here are some issues to be aware of when using this library under any platform: -
      - -
        - -
      1. -The EVFILT_PROC filter is not implemented. -
      2. - -
      3. -The EVFILT_AIO filter is not implemented. -
      4. - -
      5. When a kqueue descriptor is closed, it's resources are not immediately reclaimed. Instead, they will be freed the next time that the kqueue(2) function is called. -
      6. - -
      7. -A signal handler is implicitly installed when a EVFILT_SIGNAL kevent is created. For compatibility with kernel-based kqueue(2), programs must ignore signals that will generate kevents. After an EVFILT_SIGNAL kevent is created, a program must not modify the disposition of the associated signal. The following example shows the proper way to handle SIGUSR1 with a kevent: - -
        -int main() {
        -  int kqfd;
        -  struct kevent kev;
        -
        -  kqfd = kqueue();
        -  signal(SIGUSR1, SIG_IGN);
        -  EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
        -  kevent(kqfd, &kev, 1, NULL, 0, NULL);
        -}
        -
        -
      - -

      Linux

      - -There are several compatibility issues to be aware of when using this library under Linux:
      - -
        - -
      1. The NOTE_LOWAT flag is not supported. According to socket(7),
        -
        -"The select(2) and poll(2) system  calls  currently  do not respect the 
        -SO_RCVLOWAT setting on Linux, and mark a socket readable when even  a  
        -single  byte  of data is available.  A subsequent read from the socket 
        -will block until SO_RCVLOWAT bytes are available."
        -
      2. - -
      3. -The NOTE_REVOKE flag is not supported because Linux does not have -a revoke(2) system call. -
      4. - -
      5. -When an EVFILT_SIGNAL event is generated, the data field -is set to 1 regardless of how many times the signal was received by the process. -
      6. - -
      7. -When an EVFILT_READ event occurs on a listening socket, the data field is set to 1 regardless of how many pending connections are available. - - - -
      - -

      Solaris

      - -Here are the issues to be aware of when using this library under Solaris:
      - -
        - -
      1. -Solaris 10 or newer is required. It should work with OpenSolaris and other Solaris-based distributions, but has not been tested. -
      2. - -
      3. -When an EVFILT_READ event is generated, the data field -is set to 1 regardless of how many bytes are available to read. -
      4. - -
      5. -When an EVFILT_TIMER event is generated, the data field -is set to 1 regardless of how many times the timer has been triggered. -
      6. - -
      7. -The EVFILT_VNODE filter is not implemented. This will eventually be implemented -using the PORT_SOURCE_FILE mechanism described here. -
      8. - -
      9. The EVFILT_TIMER filter is implemented using high-resolution timers. In order to use high-resolution timers, the calling process must hold the PRIV_PROC_CLOCK_HIGHRES privilege. This privilege is not granted to ordinary users by default. It can be granted to individual users by running the following command as root:
        -
        -# usermod -K defaultpriv=basic,proc_clock_highres $user
        -
        -
      - -

      BSD-based systems

      - -There are some differences in the behavior of the kevent(2) system call across the various BSD-based operating systems. Here are some of the differences to be aware of: - -
        - -
      1. FreeBSD 8 does not set the EV_ADD flag for kevents on the eventlist, but OpenBSD and Darwin do. This means you should never use the equality operator (==) to test the flags; use the logical AND operator instead. -
      2. - -
      3. The EVFILT_USER filter behaves differently from other filters with respect to the EV_ONESHOT flag. All other filters will preserve the flag when the event is triggered and placed on the eventlist. The EVFILT_USER filter does not preserve this flag. -
      4. - -
      5. -OpenBSD has the NOTE_TRUNCATE fflag, while FreeBSD and Darwin do not. -
      6. - -
      7. -EVFILT_FS is undocumented and only available on FreeBSD and Darwin. Here is the CVS commit log which could be helpful to document this filter. -
      8. - - -
      - -

      Integration

      - -

      Ordinary Makefile

      - -Here are the steps to use libkqueue in your program if you use an ordinary Makefile: - -
        -
      1. Add ‘pkg-config libkqueue --cflags‘ to the CFLAGS variable. -
      2. Add ‘pkg-config libkqueue --libs‘ to the LDADD variable. -
      3. Add #include <sys/event.h> to the source code. -
      - -

      Autoconf/Automake/Libtool

      - -If your program uses the GNU Autoconf/Automake/Libtool build system, the following steps will allow you to use libkqueue: - -
        - -
      1. Add the following to configure.ac: -
        -#
        -# Prefer native kqueue(2); otherwise use libkqueue if present.
        -#
        -AC_CHECK_HEADER(sys/event.h, [],
        -  [PKG_CHECK_MODULES(KQUEUE, libkqueue)]
        -)
        -
        -
      2. - -
      3. -Add the following to Makefile.am (assuming your program is named "foo"): -
        -foo_CFLAGS+=$(KQUEUE_CFLAGS)
        -foo_LDADD+=$(KQUEUE_LIBS)
        -
        -
      4. -
      - -Instead of using the $(KQUEUE_LIBS) variable, you could just add libkqueue.la to your programs LDADD variable. - -

      Threads

      - -libkqueue uses one or more helper threads, so all programs that link with libkqueue must also link against the pthreads library. Calls to kqueue() and kevent() are safe to be used from multiple threads. - -m4_include(footer.m4) From 6a82981463e3ee5e19560219c288ce860ff85356 Mon Sep 17 00:00:00 2001 From: marius Date: Wed, 4 May 2011 17:39:25 +0000 Subject: [PATCH 0471/1120] Fixed some mistakes within the CMakeLists.txt Made latest revision compatible to windows again git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@500 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/CMakeLists.txt | 7 ------- vendor/libkqueue/src/common/debug.h | 4 +++- vendor/libkqueue/test/CMakeLists.txt | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index d81531306..92155bf8a 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -17,13 +17,6 @@ cmake_minimum_required(VERSION 2.8) INCLUDE (CheckIncludeFiles) -#tests -option(KQUEUE_TESTS "Enable to build tests for libkqueue" OFF) -if(KQUEUE_TESTS) - message("-- Adding tests for libkqueue") - add_subdirectory(test) -endif() - project(kqueue) #files diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index 9fbd1653c..e69ba32ad 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -19,7 +19,9 @@ #include #include -#include +#ifndef _WIN32 +# include +#endif extern int DEBUG_ACTIVE; extern char *DEBUG_IDENT; diff --git a/vendor/libkqueue/test/CMakeLists.txt b/vendor/libkqueue/test/CMakeLists.txt index 770650335..e09c4d754 100644 --- a/vendor/libkqueue/test/CMakeLists.txt +++ b/vendor/libkqueue/test/CMakeLists.txt @@ -56,5 +56,5 @@ else() endif() add_executable(libkqueue-test ${SRC}) -target_link_libraries(libkqueue-test libkqueue ${LIBS}) +target_link_libraries(libkqueue-test kqueue ${LIBS}) set_target_properties(libkqueue-test PROPERTIES DEBUG_POSTFIX "D") From 3d4f6b85b3292f6458241bbacb9e81daf2f23082 Mon Sep 17 00:00:00 2001 From: marius Date: Mon, 9 May 2011 19:04:31 +0000 Subject: [PATCH 0472/1120] Removed unused/unneeded evt_loop implementation git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@501 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/windows/event_loop.c | 269 ---------------------- vendor/libkqueue/src/windows/event_loop.h | 119 ---------- vendor/libkqueue/src/windows/platform.c | 25 +- vendor/libkqueue/src/windows/platform.h | 2 - 4 files changed, 2 insertions(+), 413 deletions(-) delete mode 100644 vendor/libkqueue/src/windows/event_loop.c delete mode 100644 vendor/libkqueue/src/windows/event_loop.h diff --git a/vendor/libkqueue/src/windows/event_loop.c b/vendor/libkqueue/src/windows/event_loop.c deleted file mode 100644 index 64c2b088a..000000000 --- a/vendor/libkqueue/src/windows/event_loop.c +++ /dev/null @@ -1,269 +0,0 @@ -/* -* Copyright (c) 2011 Marius Zwicker -* -* Permission to use, copy, modify, and distribute this software for any -* purpose with or without fee is hereby granted, provided that the above -* copyright notice and this permission notice appear in all copies. -* -* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - - - -#include "../common/private.h" - -/* -* Conditionals on windows -*/ -#if TARGET_WIN_VISTA -// These conditions are supported using Windows Vista and up only. We need a XP compatible workaround here - -# define pthread_cond_init(c,x) InitializeConditionVariable((c)) -# define pthread_cond_destroy(c) -# define pthread_cond_wait(c,m) SleepConditionVariableCS((c),(m), INFINITE) -# define pthread_cond_broadcast(c) WakeAllConditionVariable((c)); -# define pthread_cond_signal(c) WakeConditionVariable((c)); - -#else - -typedef struct { - int unused; -} pthread_condattr_t; - -/* Credits for this pthread_cond_t implementation on windows go to -the authors of http://www.cs.wustl.edu/~schmidt/win32-cv-1.html: -Douglas C. Schmidt and Irfan Pyarali -Department of Computer Science -Washington University, St. Louis, Missouri - -Please note that this implementation is not a fully featured posix condition implementation -but only usable for our purposes as it allows only one thread calling cond_wait at a time. -*/ - -int - pthread_cond_init (pthread_cond_t *cv, - const pthread_condattr_t * attr) -{ - cv->waiters_count_ = 0; - - // Init the second mutex - InitializeCriticalSection(&cv->waiters_count_lock_); - - // Create an auto-reset event. - cv->events_[SIGNAL] = CreateEvent (NULL, // no security - FALSE, // auto-reset event - FALSE, // non-signaled initially - NULL); // unnamed - - // Create a manual-reset event. - cv->events_[BROADCAST] = CreateEvent (NULL, // no security - TRUE, // manual-reset - FALSE, // non-signaled initially - NULL); // unnamed - - return cv->events_[SIGNAL] == 0 || cv->events_[BROADCAST] == 0 ; -} - -int pthread_cond_timedwait(pthread_cond_t *cv, - pthread_mutex_t *external_mutex, const struct timespec* timeout) -{ - DWORD timeout_ms, rv; - int last_waiter = 0; - - /* Convert timeout to milliseconds */ - /* NOTE: loss of precision for timeout values less than 1ms */ - if (timeout == NULL) { - timeout_ms = INFINITE; - } else { - timeout_ms = 0; - if (timeout->tv_sec > 0) - timeout_ms += ((DWORD)timeout->tv_sec) / 1000; - if (timeout->tv_sec > 0) - timeout_ms += timeout->tv_nsec / 1000000; - } - - - - // Avoid race conditions. - EnterCriticalSection (&cv->waiters_count_lock_); - cv->waiters_count_++; - LeaveCriticalSection (&cv->waiters_count_lock_); - - // It's ok to release the here since Win32 - // manual-reset events maintain state when used with - // . This avoids the "lost wakeup" bug... - LeaveCriticalSection (external_mutex); - - // Wait for either event to become signaled due to - // being called or being called. - rv = WaitForMultipleObjects (2, cv->events_, FALSE, timeout_ms); - if( rv == WAIT_TIMEOUT) { - return EVT_TIMEDOUT; - } else if(rv == WAIT_FAILED) { - dbg_lasterror("cond_timedwait failed"); - return EVT_ERR; - } - - EnterCriticalSection (&cv->waiters_count_lock_); - cv->waiters_count_--; - last_waiter = - rv == WAIT_OBJECT_0 + BROADCAST - && cv->waiters_count_ == 0; - LeaveCriticalSection (&cv->waiters_count_lock_); - - // Some thread called . - if (last_waiter) - // We're the last waiter to be notified or to stop waiting, so - // reset the manual event. - ResetEvent (cv->events_[BROADCAST]); - - // Reacquire the . - EnterCriticalSection (external_mutex); - - return 0; -} - -int - pthread_cond_wait (pthread_cond_t *cv, - pthread_mutex_t *external_mutex) -{ - return pthread_cond_timedwait(cv, external_mutex, NULL); -} - -int - pthread_cond_signal (pthread_cond_t *cv) -{ - int have_waiters = 0; - - // Avoid race conditions. - EnterCriticalSection (&cv->waiters_count_lock_); - have_waiters = cv->waiters_count_ > 0; - LeaveCriticalSection (&cv->waiters_count_lock_); - - if (have_waiters) - SetEvent (cv->events_[SIGNAL]); - - return 0; -} - -int - pthread_cond_destroy(pthread_cond_t *cv) -{ - CloseHandle(cv->events_[SIGNAL]); - CloseHandle(cv->events_[BROADCAST]); - - return 0; -} -#endif - -/* -* Event loop implementation -*/ - -void evt_init(evt_loop_t t){ - assert(t); - pthread_mutex_init(&t->access, NULL); - pthread_cond_init(&t->cond, NULL); - t->used = TRUE; -} - -evt_loop_t evt_create(){ - evt_loop_t neu = (evt_loop_t)malloc(sizeof(struct evt_loop_s)); - assert(neu); - memset(neu,0,sizeof(struct evt_loop_s)); - - evt_init(neu); - - return neu; -} - -int evt_signal(evt_loop_t l, int type, void* data){ - // create new item - evt_event_t i = (evt_event_t)malloc(sizeof(struct evt_event_s)); - - assert(l); - - if (i == NULL) - return -1; // creation failed - i->type = type; // link with the given event type - i->data = data; - i->next = NULL; - - pthread_mutex_lock(&l->access); - if (l->last != NULL) - l->last->next = i; - l->last = i; - if (l->first == NULL) { // if this item is first one, signal waiting getitem call - l->first = i; - pthread_cond_signal(&l->cond); - } - pthread_mutex_unlock(&l->access); - return 0; -} - -int evt_run(evt_loop_t l, evt_event_t evt, int max_ct, const struct timespec* timeout){ - evt_event_t curr = NULL; - - assert(l); - assert(evt); - assert(max_ct > 0); - - pthread_mutex_lock(&l->access); - while(1){ - // get item from list, if available - if (l->first == NULL) { - if( pthread_cond_timedwait(&l->cond, &l->access, timeout) == EVT_TIMEDOUT ) // no item available, wait for it - return EVT_TIMEDOUT; - - // in this case we can be sure to hold the mutex again - continue; - } - curr = l->first; - l->first = curr->next; // remove item - if (l->first == NULL) - l->last = NULL; // this was the last item - pthread_mutex_unlock(&l->access); - - assert(curr); - // TODO: Real event array support - // return the current event - memcpy(&(evt[0]), curr, sizeof(struct evt_event_s)); - free(curr); - return 1; - - pthread_mutex_lock(&l->access); - } - -} - -void evt_destroy(evt_loop_t l){ - evt_event_t i = NULL, curr = NULL; - - assert(l); - - if (l->used == FALSE) - return; - - // delete all waiting items - i = l->first; - while (i != NULL) { - curr = i; - i = i->next; - free(curr); - } - - // reset list - l->first = NULL; - l->last = NULL; - - pthread_mutex_destroy(&l->access); - pthread_cond_destroy(&l->cond); - - free(l); -} diff --git a/vendor/libkqueue/src/windows/event_loop.h b/vendor/libkqueue/src/windows/event_loop.h deleted file mode 100644 index 83aa322bf..000000000 --- a/vendor/libkqueue/src/windows/event_loop.h +++ /dev/null @@ -1,119 +0,0 @@ -/* -* Copyright (c) 2011 Marius Zwicker -* -* Permission to use, copy, modify, and distribute this software for any -* purpose with or without fee is hereby granted, provided that the above -* copyright notice and this permission notice appear in all copies. -* -* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - - -#ifndef KQUEUE_WINDOWS_EVENTLOOP_H -#define KQUEUE_WINDOWS_EVENTLOOP_H - -// some condition variable typedefs -#if TARGET_WIN_VISTA -// These conditions are supported using Windows Vista and up only. We need a XP compatible workaround here - -typedef CONDITION_VARIABLE pthread_cond_t; - -#else - -typedef struct { - u_int waiters_count_; - // Count of the number of waiters. - - CRITICAL_SECTION waiters_count_lock_; - // Serialize access to . - -#define SIGNAL 0 -#define BROADCAST 1 -#define MAX_EVENTS 2 - - HANDLE events_[MAX_EVENTS]; - // Signal and broadcast event HANDLEs. -} pthread_cond_t; - -#endif - -// -// A single event item -// -typedef struct evt_event_s { - int type; - void* data; - struct evt_event_s* next; -}* evt_event_t; - -#define EVT_EVENT_INITIALIZER { 0, NULL, NULL } - -// -// An event loop, normally you have one loop per thread -// -typedef struct evt_loop_s { - int id; - void* data; - evt_event_t first; - evt_event_t last; - pthread_mutex_t access; - pthread_cond_t cond; - unsigned char used; -}* evt_loop_t; - -// -// The different event types -// -enum evt_type { - EVT_WAKEUP =0, /* Simply wake the thread, the callback will know what to do */ - EVT_EXIT =1, /* Immediately exit the event loop */ - EVT_CUSTOM =2 /* Some custom event */ -}; - -// -// Flags describing the return values of evt_run -// -enum evt_flags { - EVT_ERR = -3, /* An error occured */ - EVT_TIMEDOUT = -5, /* Timeout elapsed before receiving an event */ -}; - -// -// Creates a new event loop -// -evt_loop_t evt_create(); - -// -// Initializes an existing eventloop (as if it was new) -// -void evt_init(evt_loop_t t); - -// -// Destroys the given event loop, make sure -// that evt-run returned before. This will -// erase all pending events as well -// -void evt_destroy(evt_loop_t l); - -// -// Sends an event of type type with the given data -// to the given event loop -// -int evt_signal(evt_loop_t l, int type, void* data); - -// -// Executes the given event loop. -// Will return in two casees only: -// - The timeout expired (return value EVT_TIMEDOUT) -// - An event was returned (return value corresponds to the number of events returned) -// evt will contain the returned events as an array, with max_ct events maximum -// -int evt_run(evt_loop_t l, evt_event_t evt, int max_ct, const struct timespec* timeout); - -#endif /* KQUEUE_WINDOWS_EVENTLOOP_H */ diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 0bd0a4477..891d54718 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -102,7 +102,7 @@ windows_kqueue_init(struct kqueue *kq) #endif if(filter_register_all(kq) < 0) { - evt_destroy(kq->kq_loop); + CloseHandle(kq->kq_iocp); return (-1); } @@ -112,7 +112,7 @@ windows_kqueue_init(struct kqueue *kq) void windows_kqueue_free(struct kqueue *kq) { - evt_destroy(kq->kq_loop); + CloseHandle(kq->kq_iocp); free(kq); } @@ -150,27 +150,6 @@ windows_kevent_wait(struct kqueue *kq, int no, const struct timespec *timeout) dbg_lasterror("GetQueuedCompletionStatus"); return (-1); } - -#if DEADWOOD - DWORD rv; - - /* Wait for an event */ - dbg_printf("waiting for %u events (timeout=%u ms)", kq->kq_filt_count, (unsigned int)timeout_ms); - rv = evt_run(kq->kq_loop, pending_events, MAX_KEVENT, timeout); - switch (rv) { - case EVT_TIMEDOUT: - dbg_puts("no events within the given timeout"); - retval = 0; - break; - - case EVT_ERR: - dbg_lasterror("WaitForSingleEvent()"); - retval = -1; - - default: - retval = rv; - } -#endif return (retval); } diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index f6e799460..2c56bc434 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -64,7 +64,6 @@ #define KQUEUE_PLATFORM_SPECIFIC \ HANDLE kq_iocp; \ HANDLE kq_synthetic_event; \ - evt_loop_t kq_loop; \ struct filter *kq_filt_ref[EVFILT_SYSCOUNT]; \ size_t kq_filt_count @@ -163,6 +162,5 @@ typedef CRITICAL_SECTION pthread_rwlock_t; #define pthread_rwlock_unlock _cs_unlock #define pthread_rwlock_init(x,y) _cs_init((x)) -#include "event_loop.h" #endif /* ! _KQUEUE_WINDOWS_PLATFORM_H */ From 14ad613ab8cc8937fdc28332642ae8896c787880 Mon Sep 17 00:00:00 2001 From: marius Date: Mon, 9 May 2011 19:05:49 +0000 Subject: [PATCH 0473/1120] Fixed a bug in the static build option in CMakeLists.txt Made some symbols unique w.r.t. libpthread_workqueue to prevent duplicate symbols when linking as static libs git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@502 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/CMakeLists.txt | 3 ++- vendor/libkqueue/src/common/debug.h | 24 ++++++++++++------------ vendor/libkqueue/src/common/kevent.c | 4 ++-- vendor/libkqueue/src/common/kqueue.c | 8 ++++---- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 92155bf8a..9da5ccfac 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -84,7 +84,8 @@ include_directories( #library (static or shared) option(STATIC_KQUEUE "Enable to build libkqueue as static lib" OFF) -if(STATIC_WORKQUEUE) +if(STATIC_KQUEUE) + message("-- building libkqueue as static lib") add_definitions(-DMAKE_STATIC) add_library(kqueue STATIC ${SRC} ${INCL}) else() diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index e69ba32ad..2125ce0b4 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -23,8 +23,8 @@ # include #endif -extern int DEBUG_ACTIVE; -extern char *DEBUG_IDENT; +extern int DEBUG_KQUEUE; +extern char *KQUEUE_DEBUG_IDENT; #if defined(__linux__) # include @@ -39,21 +39,21 @@ extern char *DEBUG_IDENT; #ifndef NDEBUG #define dbg_puts(str) do { \ - if (DEBUG_ACTIVE) \ + if (DEBUG_KQUEUE) \ fprintf(stderr, "%s [%d]: %s(): %s\n", \ - DEBUG_IDENT, THREAD_ID, __func__, str); \ + KQUEUE_DEBUG_IDENT, THREAD_ID, __func__, str); \ } while (0) #define dbg_printf(fmt,...) do { \ - if (DEBUG_ACTIVE) \ + if (DEBUG_KQUEUE) \ fprintf(stderr, "%s [%d]: %s(): "fmt"\n", \ - DEBUG_IDENT, THREAD_ID, __func__, __VA_ARGS__); \ + KQUEUE_DEBUG_IDENT, THREAD_ID, __func__, __VA_ARGS__); \ } while (0) #define dbg_perror(str) do { \ - if (DEBUG_ACTIVE) \ + if (DEBUG_KQUEUE) \ fprintf(stderr, "%s [%d]: %s(): %s: %s (errno=%d)\n", \ - DEBUG_IDENT, THREAD_ID, __func__, str, \ + KQUEUE_DEBUG_IDENT, THREAD_ID, __func__, str, \ strerror(errno), errno); \ } while (0) @@ -61,15 +61,15 @@ extern char *DEBUG_IDENT; # if defined(_WIN32) # define dbg_lasterror(str) do { \ - if (DEBUG_ACTIVE) \ + if (DEBUG_KQUEUE) \ fprintf(stderr, "%s: [%d] %s(): %s: (LastError=%d)\n", \ - DEBUG_IDENT, THREAD_ID, __func__, str, (int)GetLastError()); \ + KQUEUE_DEBUG_IDENT, THREAD_ID, __func__, str, (int)GetLastError()); \ } while (0) # define dbg_wsalasterror(str) do { \ - if (DEBUG_ACTIVE) \ + if (DEBUG_KQUEUE) \ fprintf(stderr, "%s: [%d] %s(): %s: (WSALastError=%d)\n", \ - DEBUG_IDENT, THREAD_ID, __func__, str, (int)WSAGetLastError()); \ + KQUEUE_DEBUG_IDENT, THREAD_ID, __func__, str, (int)WSAGetLastError()); \ } while (0) # else diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 429f64610..2b89e3984 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -250,7 +250,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, return (-1); } - if (DEBUG_ACTIVE) { + if (DEBUG_KQUEUE) { myid = atomic_inc(&_kevent_counter); dbg_printf("--- kevent %u --- (nchanges = %d, nevents = %d)", myid, nchanges, nevents); } else { @@ -303,7 +303,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, } } - if (DEBUG_ACTIVE) { + if (DEBUG_KQUEUE) { int n; dbg_printf("(%u) returning %d events", myid, rv); diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index f82461c9c..8e9b49ff2 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -24,8 +24,8 @@ #include "private.h" -int DEBUG_ACTIVE = 0; -char *DEBUG_IDENT = "KQ"; +int DEBUG_KQUEUE = 0; +char *KQUEUE_DEBUG_IDENT = "KQ"; static unsigned int get_fd_limit(void) @@ -58,11 +58,11 @@ int CONSTRUCTOR libkqueue_init(void) { #ifdef NDEBUG - DEBUG_ACTIVE = 0; + DEBUG_KQUEUE = 0; #else char *s = getenv("KQUEUE_DEBUG"); if (s != NULL && strlen(s) > 0) { - DEBUG_ACTIVE = 1; + DEBUG_KQUEUE = 1; # if defined(_WIN32) && !defined(__GNUC__) /* Enable heap surveillance */ { From 9932614ed2eef117bb34661d2c787aa53754ae79 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 10 May 2011 01:30:02 +0000 Subject: [PATCH 0474/1120] - Fix compilation issues on MinGW. - Improve error handling in test/read.c git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@503 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/config.inc | 2 +- vendor/libkqueue/src/common/debug.h | 4 +++- vendor/libkqueue/src/windows/platform.h | 1 + vendor/libkqueue/test/config.inc | 2 +- vendor/libkqueue/test/kevent.c | 6 +++--- vendor/libkqueue/test/lockstat.c | 8 ++++---- vendor/libkqueue/test/read.c | 18 ++++++++++++------ 7 files changed, 25 insertions(+), 16 deletions(-) diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index e99423ed8..6191d0817 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -98,7 +98,7 @@ post_configure_hook() { fi if [ $target = "windows" ] ; then - platform="src/windows/platform.c src/windows/event_loop.c" + platform="src/windows/platform.c" cflags="$cflags -march=i686 -lws2_32" ldflags="$ldflags -march=i686" ldadd="-lws2_32" diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index 2125ce0b4..68eabe24c 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -19,7 +19,9 @@ #include #include -#ifndef _WIN32 +#ifdef _WIN32 +# include +#else # include #endif diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 2c56bc434..904163d6a 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -86,6 +86,7 @@ */ struct filter; struct kqueue; +struct knote; /* * Hooks and prototypes diff --git a/vendor/libkqueue/test/config.inc b/vendor/libkqueue/test/config.inc index b80227e63..e124b1919 100755 --- a/vendor/libkqueue/test/config.inc +++ b/vendor/libkqueue/test/config.inc @@ -46,7 +46,7 @@ pre_configure_hook() { ldflags="$ldflags -march=i686" ldadd="$ldadd -lws2_32" # KLUDGE: to remove signal.c, proc.c - sources="main.c kevent.c test.c read.c timer.c vnode.c" + sources="main.c kevent.c test.c read.c timer.c user.c vnode.c" fi } diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index 616b37be3..6441ecd4d 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -29,10 +29,10 @@ _test_no_kevents(int kqfd, const char *file, int line) memset(&timeo, 0, sizeof(timeo)); nfds = kevent(kqfd, NULL, 0, &kev, 1, &timeo); if (nfds < 0) - die("kevent(2)"); + err(1, "kevent(2)"); if (nfds > 0) { printf("\n[%s:%d]: Unexpected event:", file, line); - die(kevent_to_str(&kev)); + err(1, kevent_to_str(&kev)); } } @@ -45,7 +45,7 @@ kevent_get(int kqfd) nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); if (nfds < 1) - die("kevent(2)"); + err(1, "kevent(2)"); return (&kev); } diff --git a/vendor/libkqueue/test/lockstat.c b/vendor/libkqueue/test/lockstat.c index 079a113b7..b0ac053cf 100644 --- a/vendor/libkqueue/test/lockstat.c +++ b/vendor/libkqueue/test/lockstat.c @@ -14,11 +14,10 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include "../src/common/debug.h" +#include "../src/common/private.h" -int DEBUG_ACTIVE = 1; -char * DEBUG_IDENT = "lockstat"; +int DEBUG_KQUEUE = 1; +char * KQUEUE_DEBUG_IDENT = "lockstat"; struct foo { tracing_mutex_t foo_lock; @@ -36,5 +35,6 @@ int main() { tracing_mutex_unlock(&x.foo_lock); tracing_mutex_assert(&x.foo_lock, MTX_UNLOCKED); + puts("+OK"); return (0); } diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 71b05017b..c2444f2bf 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -253,11 +253,15 @@ test_kevent_socket_listen_backlog(void) memset(&sain, 0, sizeof(sain)); sain.sin_family = AF_INET; sain.sin_port = htons(port); - if ((srvr = socket(PF_INET, SOCK_STREAM, 0)) < 0) abort(); + if ((srvr = socket(PF_INET, SOCK_STREAM, 0)) < 0) + err(1, "socket()"); if (setsockopt(srvr, SOL_SOCKET, SO_REUSEADDR, - (char *) &one, sizeof(one)) != 0) abort(); - if (bind(srvr, (struct sockaddr *) &sain, sa_len) < 0) abort(); - if (listen(srvr, 100) < 0) abort(); + (char *) &one, sizeof(one)) != 0) + err(1, "setsockopt()"); + if (bind(srvr, (struct sockaddr *) &sain, sa_len) < 0) + err(1, "bind()"); + if (listen(srvr, 100) < 0) + err(1, "listen()"); /* Watch for events on the socket */ test_no_kevents(kqfd); @@ -268,8 +272,10 @@ test_kevent_socket_listen_backlog(void) sain.sin_family = AF_INET; sain.sin_port = htons(port); sain.sin_addr.s_addr = inet_addr("127.0.0.1"); - if ((clnt = socket(AF_INET, SOCK_STREAM, 0)) < 0) abort(); - if (connect(clnt, (struct sockaddr *) &sain, sa_len) < 0) abort(); + if ((clnt = socket(AF_INET, SOCK_STREAM, 0)) < 0) + err(1, "socket()"); + if (connect(clnt, (struct sockaddr *) &sain, sa_len) < 0) + err(1, "connect()"); /* Verify that data=1 */ kev.data = 1; From ab05838156f58bd307ee619153c33e2efc30cdd9 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 10 May 2011 01:59:38 +0000 Subject: [PATCH 0475/1120] Fix the 'make debug' target under Windows. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@504 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile index 875927a08..d1cfbdac1 100644 --- a/vendor/libkqueue/test/Makefile +++ b/vendor/libkqueue/test/Makefile @@ -28,7 +28,7 @@ check: kqtest LD_LIBRARY_PATH="..:/usr/sfw/lib/64" PATH="$$PATH:.." ./kqtest debug: kqtest - LD_LIBRARY_PATH="..:/usr/sfw/lib/64" gdb ./kqtest + LD_LIBRARY_PATH="..:/usr/sfw/lib/64" PATH="$$PATH:.." gdb ./kqtest valgrind: kqtest LD_LIBRARY_PATH="..:/usr/sfw/lib/64" \ From 016c60c494b8e67f2367e831894fc407233c8e76 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 10 May 2011 02:34:24 +0000 Subject: [PATCH 0476/1120] - Fix a use-after-free bug with EV_ONESHOT that was introduced in r494. - Test for incorrect usage of knote_lock() and knote_unlock() git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@505 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/knote.c | 14 ++++++++++++++ vendor/libkqueue/src/common/private.h | 4 ++-- vendor/libkqueue/src/linux/platform.c | 7 ++++--- vendor/libkqueue/src/windows/platform.c | 7 ++++--- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index ccdb72559..8df1353cf 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -172,3 +172,17 @@ knote_disable(struct filter *filt, struct knote *kn) } //TODO: knote_enable() + +void +knote_lock(struct knote *kn) +{ + tracing_mutex_assert(&kn->kn_mtx, MTX_UNLOCKED); + tracing_mutex_lock(&(kn)->kn_mtx); +} + +void +knote_unlock(struct knote *kn) +{ + tracing_mutex_assert(&kn->kn_mtx, MTX_LOCKED); + tracing_mutex_unlock(&(kn)->kn_mtx); +} diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index e4d21ed1f..1cc8e7f4a 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -194,8 +194,8 @@ void knote_insert(struct filter *, struct knote *); int knote_delete(struct filter *, struct knote *); int knote_init(void); int knote_disable(struct filter *, struct knote *); -#define knote_lock(kn) tracing_mutex_lock(&(kn)->kn_mtx) -#define knote_unlock(kn) tracing_mutex_unlock(&(kn)->kn_mtx) +void knote_lock(struct knote *); +void knote_unlock(struct knote *); int filter_lookup(struct filter **, struct kqueue *, short); int filter_register_all(struct kqueue *); diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index d06e3f972..8b4f00fde 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -172,10 +172,11 @@ linux_kevent_copyout(struct kqueue *kq, int nready, */ if (eventlist->flags & EV_DISPATCH) knote_disable(filt, kn); //FIXME: Error checking - if (eventlist->flags & EV_ONESHOT) + if (eventlist->flags & EV_ONESHOT) { knote_delete(filt, kn); //FIXME: Error checking - - knote_unlock(kn); + } else { + knote_unlock(kn); + } /* If an empty kevent structure is returned, the event is discarded. */ /* TODO: add these semantics to windows + solaris platform.c */ diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 891d54718..6e60ed8b4 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -181,10 +181,11 @@ windows_kevent_copyout(struct kqueue *kq, int nready, */ if (eventlist->flags & EV_DISPATCH) knote_disable(filt, kn); //TODO: Error checking - if (eventlist->flags & EV_ONESHOT) + if (eventlist->flags & EV_ONESHOT) { knote_delete(filt, kn); //TODO: Error checking - - knote_unlock(kn); + } else { + knote_unlock(kn); + } /* If an empty kevent structure is returned, the event is discarded. */ if (fastpath(eventlist->filter != 0)) { From 8706bdb01b1c2d711c91af593c309e4b89f7d29f Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 10 May 2011 02:51:59 +0000 Subject: [PATCH 0477/1120] Make knote_lock() and knote_unlock() macros again, so the assert() will provide useful information git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@506 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/knote.c | 12 ------------ vendor/libkqueue/src/common/private.h | 11 ++++++++++- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 8df1353cf..14791b2fb 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -173,16 +173,4 @@ knote_disable(struct filter *filt, struct knote *kn) //TODO: knote_enable() -void -knote_lock(struct knote *kn) -{ - tracing_mutex_assert(&kn->kn_mtx, MTX_UNLOCKED); - tracing_mutex_lock(&(kn)->kn_mtx); -} -void -knote_unlock(struct knote *kn) -{ - tracing_mutex_assert(&kn->kn_mtx, MTX_LOCKED); - tracing_mutex_unlock(&(kn)->kn_mtx); -} diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 1cc8e7f4a..efa329288 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -195,7 +195,16 @@ int knote_delete(struct filter *, struct knote *); int knote_init(void); int knote_disable(struct filter *, struct knote *); void knote_lock(struct knote *); -void knote_unlock(struct knote *); + +#define knote_lock(kn) do { \ + tracing_mutex_assert(&(kn)->kn_mtx, MTX_UNLOCKED); \ + tracing_mutex_lock(&(kn)->kn_mtx); \ +} while (0) + +#define knote_unlock(kn) do { \ + tracing_mutex_assert(&(kn)->kn_mtx, MTX_LOCKED); \ + tracing_mutex_unlock(&(kn)->kn_mtx); \ +} while (0) int filter_lookup(struct filter **, struct kqueue *, short); int filter_register_all(struct kqueue *); From a16979abc91ba9e0fafb18347b3204388cfa683f Mon Sep 17 00:00:00 2001 From: marius Date: Sat, 14 May 2011 11:49:21 +0000 Subject: [PATCH 0478/1120] * Fixed a compiler warning when using clang on Ubuntu 11.04 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@507 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/linux/read.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index e8a3fb486..c81d16743 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -210,6 +210,9 @@ evfilt_read_knote_delete(struct filter *filt, struct knote *kn) } else { return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); } + + // clang will complain about not returning a value otherwise + return (-1); } int @@ -230,6 +233,9 @@ evfilt_read_knote_enable(struct filter *filt, struct knote *kn) } else { return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); } + + // clang will complain about not returning a value otherwise + return (-1); } int From c94da5c6f266404f484660c45085530b7a510285 Mon Sep 17 00:00:00 2001 From: jocke Date: Thu, 19 May 2011 07:35:47 +0000 Subject: [PATCH 0479/1120] Avoid possible overrun of sigtbl[] if signal would be == SIGNAL_MAX. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@508 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/signal.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/solaris/signal.c b/vendor/libkqueue/src/solaris/signal.c index 03d0886e9..88cf93d26 100644 --- a/vendor/libkqueue/src/solaris/signal.c +++ b/vendor/libkqueue/src/solaris/signal.c @@ -33,9 +33,12 @@ signal_handler(int sig) { struct sentry *s; - if (sig < 0 || sig > SIGNAL_MAX) - return; //TODO: DEBUG OUTPUT - + if (sig < 0 || sig >= SIGNAL_MAX) // 0..31 are valid + { + dbg_printf("Received unexpected signal %d", sig); + return; + } + s = &sigtbl[sig]; dbg_printf("sig=%d %d", sig, s->st_signum); atomic_inc((volatile uint32_t *) &s->st_count); From ff1de8640aadf1b99ffb035b37a4fb2e0372f420 Mon Sep 17 00:00:00 2001 From: jocke Date: Thu, 19 May 2011 07:36:55 +0000 Subject: [PATCH 0480/1120] Match signed type of 'filt' coming in (alternatively change line 175 and remove otherwise useless comparison < 0). git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@509 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/filter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index 1b4708e22..678fa785b 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -156,7 +156,7 @@ filter_lookup(struct filter **filt, struct kqueue *kq, short id) const char * filter_name(short filt) { - unsigned int id; + int id; const char *fname[EVFILT_SYSCOUNT] = { "EVFILT_READ", "EVFILT_WRITE", From 54942e1cfa0760cb1dc3e971128afc67697a5372 Mon Sep 17 00:00:00 2001 From: jocke Date: Thu, 19 May 2011 13:38:37 +0000 Subject: [PATCH 0481/1120] Fix proper semantics for read events on Solaris, fixing kqtest failure. According to the original kqueue paper, such events should not be signaled (which is also tested by kqtest). git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@510 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/platform.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index 0d58549c9..ce997b265 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -148,11 +148,12 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, port_event_t *evt; struct knote *kn; struct filter *filt; - int i, rv; + int i, rv, skip_event, skipped_events = 0; for (i = 0; i < nready; i++) { evt = &evbuf[i]; kn = evt->portev_user; + skip_event = 0; dbg_printf("event=%s", port_event_dump(evt)); switch (evt->portev_source) { case PORT_SOURCE_FD: @@ -166,7 +167,10 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, || kn->kev.flags & EV_ONESHOT)) { rv = filt->kn_create(filt, kn); } - + + if (eventlist->data == 0) // if zero data is returned, we raced with a read of data from the socket, skip event to have proper semantics + skip_event = 1; + break; case PORT_SOURCE_TIMER: @@ -209,10 +213,13 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, if (eventlist->flags & EV_ONESHOT) knote_delete(filt, kn); //TODO: Error checking - eventlist++; + if (skip_event) + skipped_events++; + else + eventlist++; } - return (nready); + return (nready - skipped_events); } const struct kqueue_vtable kqops = From 8a4cf96fac4561d8440dcbb7d69486983df16f1a Mon Sep 17 00:00:00 2001 From: jocke Date: Thu, 19 May 2011 14:18:22 +0000 Subject: [PATCH 0482/1120] Analogous knote locking logic compared to Linux implementation, now we don't fail assertions any more. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@511 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/solaris/platform.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index ce997b265..9930c6ca7 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -155,6 +155,9 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, kn = evt->portev_user; skip_event = 0; dbg_printf("event=%s", port_event_dump(evt)); + + knote_lock(kn); + switch (evt->portev_source) { case PORT_SOURCE_FD: //XXX-FIXME WHAT ABOUT WRITE??? @@ -201,6 +204,7 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, if (rv < 0) { dbg_puts("kevent_copyout failed"); + knote_unlock(kn); return (-1); } @@ -211,7 +215,13 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, if (eventlist->flags & EV_DISPATCH) knote_disable(filt, kn); //TODO: Error checking if (eventlist->flags & EV_ONESHOT) + { knote_delete(filt, kn); //TODO: Error checking + } + else + { + knote_unlock(kn); + } if (skip_event) skipped_events++; From ce582c84c8650381533f5981a09ef046e8d3b6c9 Mon Sep 17 00:00:00 2001 From: jocke Date: Fri, 20 May 2011 05:47:20 +0000 Subject: [PATCH 0483/1120] Updated Xcode project git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@512 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- .../libkqueue.xcodeproj/project.pbxproj | 62 +- .../UserInterfaceState.xcuserstate | 5940 +++++++++++++---- 2 files changed, 4848 insertions(+), 1154 deletions(-) diff --git a/vendor/libkqueue/libkqueue.xcodeproj/project.pbxproj b/vendor/libkqueue/libkqueue.xcodeproj/project.pbxproj index b463c3d39..d97bc2963 100644 --- a/vendor/libkqueue/libkqueue.xcodeproj/project.pbxproj +++ b/vendor/libkqueue/libkqueue.xcodeproj/project.pbxproj @@ -7,6 +7,24 @@ objects = { /* Begin PBXFileReference section */ + 8547D6CE1384F4FA00830A5D /* read.c */ = {isa = PBXFileReference; fileEncoding = 4; path = read.c; sourceTree = ""; }; + 8547D6CF1384F4FA00830A5D /* write.c */ = {isa = PBXFileReference; fileEncoding = 4; path = write.c; sourceTree = ""; }; + 8547D6D01384F50F00830A5D /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; path = debug.h; sourceTree = ""; }; + 8547D6D11384F52100830A5D /* read.c */ = {isa = PBXFileReference; fileEncoding = 4; path = read.c; sourceTree = ""; }; + 8547D6D21384F52100830A5D /* user.c */ = {isa = PBXFileReference; fileEncoding = 4; path = user.c; sourceTree = ""; }; + 8547D6D61385034E00830A5D /* read.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = read.c; sourceTree = ""; }; + 8547D6D81385034E00830A5D /* signal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = signal.c; sourceTree = ""; }; + 8547D6D91385034E00830A5D /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; }; + 8547D6DC1385034E00830A5D /* vnode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vnode.c; sourceTree = ""; }; + 8547D6E21385034E00830A5D /* test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = test.c; sourceTree = ""; }; + 8547D6E41385034E00830A5D /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 8547D6E61385034E00830A5D /* proc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = proc.c; sourceTree = ""; }; + 8547D6E71385034E00830A5D /* timer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = timer.c; sourceTree = ""; }; + 8547D6E81385034E00830A5D /* user.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = user.c; sourceTree = ""; }; + 8547D6EA1385034E00830A5D /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 8547D6EC1385034E00830A5D /* kevent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kevent.c; sourceTree = ""; }; + 8547D6F01385034E00830A5D /* lockstat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lockstat.c; sourceTree = ""; }; + 8547D6F11385034E00830A5D /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; 85F0626E131E3AB10013C05E /* event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = event.h; path = include/sys/event.h; sourceTree = ""; }; 85F062A1131E3AE90013C05E /* filter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = filter.c; sourceTree = ""; }; 85F062A2131E3AE90013C05E /* kevent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kevent.c; sourceTree = ""; }; @@ -17,7 +35,6 @@ 85F062A7131E3AE90013C05E /* private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = private.h; sourceTree = ""; }; 85F062A8131E3AE90013C05E /* alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = alloc.h; sourceTree = ""; }; 85F062A9131E3AE90013C05E /* tree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tree.h; sourceTree = ""; }; - 85F062AB131E3AE90013C05E /* socket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = socket.c; sourceTree = ""; }; 85F062AC131E3AE90013C05E /* platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform.h; sourceTree = ""; }; 85F062AD131E3AE90013C05E /* signal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = signal.c; sourceTree = ""; }; 85F062AE131E3AE90013C05E /* vnode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vnode.c; sourceTree = ""; }; @@ -44,6 +61,42 @@ /* End PBXFileReference section */ /* Begin PBXGroup section */ + 8547D6D31385034E00830A5D /* test */ = { + isa = PBXGroup; + children = ( + 8547D6D61385034E00830A5D /* read.c */, + 8547D6D81385034E00830A5D /* signal.c */, + 8547D6D91385034E00830A5D /* common.h */, + 8547D6DC1385034E00830A5D /* vnode.c */, + 8547D6E21385034E00830A5D /* test.c */, + 8547D6E61385034E00830A5D /* proc.c */, + 8547D6E71385034E00830A5D /* timer.c */, + 8547D6E81385034E00830A5D /* user.c */, + 8547D6EC1385034E00830A5D /* kevent.c */, + 8547D6F01385034E00830A5D /* lockstat.c */, + 8547D6F11385034E00830A5D /* main.c */, + 8547D6E31385034E00830A5D /* libdispatch */, + 8547D6E91385034E00830A5D /* stress */, + ); + path = test; + sourceTree = ""; + }; + 8547D6E31385034E00830A5D /* libdispatch */ = { + isa = PBXGroup; + children = ( + 8547D6E41385034E00830A5D /* main.c */, + ); + path = libdispatch; + sourceTree = ""; + }; + 8547D6E91385034E00830A5D /* stress */ = { + isa = PBXGroup; + children = ( + 8547D6EA1385034E00830A5D /* main.c */, + ); + path = stress; + sourceTree = ""; + }; 85F06227131E3A3D0013C05E = { isa = PBXGroup; children = ( @@ -53,12 +106,14 @@ 85F062B3131E3AE90013C05E /* posix */, 85F062BB131E3AE90013C05E /* solaris */, 85F062C2131E3AE90013C05E /* windows */, + 8547D6D31385034E00830A5D /* test */, ); sourceTree = ""; }; 85F062A0131E3AE90013C05E /* common */ = { isa = PBXGroup; children = ( + 8547D6D01384F50F00830A5D /* debug.h */, 85F062A1131E3AE90013C05E /* filter.c */, 85F062A2131E3AE90013C05E /* kevent.c */, 85F062A3131E3AE90013C05E /* queue.h */, @@ -76,7 +131,8 @@ 85F062AA131E3AE90013C05E /* linux */ = { isa = PBXGroup; children = ( - 85F062AB131E3AE90013C05E /* socket.c */, + 8547D6CE1384F4FA00830A5D /* read.c */, + 8547D6CF1384F4FA00830A5D /* write.c */, 85F062AC131E3AE90013C05E /* platform.h */, 85F062AD131E3AE90013C05E /* signal.c */, 85F062AE131E3AE90013C05E /* vnode.c */, @@ -121,6 +177,8 @@ 85F062C2131E3AE90013C05E /* windows */ = { isa = PBXGroup; children = ( + 8547D6D11384F52100830A5D /* read.c */, + 8547D6D21384F52100830A5D /* user.c */, 85F062C3131E3AE90013C05E /* platform.c */, 85F062C4131E3AE90013C05E /* timer.c */, 85F062C5131E3AE90013C05E /* platform.h */, diff --git a/vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/xcuserdata/jocke.xcuserdatad/UserInterfaceState.xcuserstate b/vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/xcuserdata/jocke.xcuserdatad/UserInterfaceState.xcuserstate index 8400fe9ce..ee4ba9047 100644 --- a/vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/xcuserdata/jocke.xcuserdatad/UserInterfaceState.xcuserstate +++ b/vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/xcuserdata/jocke.xcuserdatad/UserInterfaceState.xcuserstate @@ -11,7 +11,7 @@ $class CF$UID - 52 + 78 NS.keys @@ -32,7 +32,7 @@ CF$UID - 196 + 220 @@ -42,7 +42,7 @@ $class CF$UID - 43 + 66 NS.keys @@ -79,15 +79,15 @@ CF$UID - 194 + 12 CF$UID - 21 + 14 CF$UID - 5 + 10 CF$UID @@ -95,119 +95,134 @@ CF$UID - 195 + 15 - IDEWorkspaceTabController_EC0EC534-0E04-4AE1-A499-3DB51327C249 + IDEWindowFrame IDEOrderedWorkspaceTabControllers IDEWindowToolbarIsVisible IDEActiveWorkspaceTabController IDEWorkspaceWindowControllerUniqueIdentifier - IDEWindowFrame + IDEWorkspaceTabController_EC0EC534-0E04-4AE1-A499-3DB51327C249 + {{225, 30}, {1453, 1036}} $class CF$UID - 43 + 13 + + NS.objects + + + CF$UID + 10 + + + + + $classes + + NSArray + NSObject + + $classname + NSArray + + + + $class + + CF$UID + 66 NS.keys CF$UID - 12 + 16 CF$UID - 13 + 17 CF$UID - 14 + 18 CF$UID - 15 + 19 CF$UID - 16 + 20 CF$UID - 17 + 21 CF$UID - 18 + 22 CF$UID - 19 + 23 NS.objects CF$UID - 20 + 24 CF$UID - 21 + 14 CF$UID - 22 + 46 CF$UID - 150 + 164 CF$UID - 156 + 171 CF$UID - 185 + 210 CF$UID - 31 + 120 CF$UID - 42 + 219 - IDETabLabel - IDEShowNavigator IDEEditorArea + IDEShowNavigator + AssistantEditorsLayout IDEWorkspaceTabControllerUtilityAreaSplitView IDENavigatorArea IDEWorkspaceTabControllerDesignAreaSplitView IDEShowUtilities - AssistantEditorsLayout - libkqueue.xcodeproj - + IDETabLabel $class CF$UID - 43 + 66 NS.keys - - CF$UID - 23 - - - CF$UID - 24 - CF$UID 25 @@ -232,85 +247,150 @@ CF$UID 30 + + CF$UID + 31 + + + CF$UID + 32 + + + CF$UID + 33 + NS.objects CF$UID - 31 + 34 CF$UID - 32 + 56 CF$UID - 66 + 89 CF$UID - 21 + 14 CF$UID - 42 + 46 CF$UID - 130 + 129 CF$UID - 138 + 155 CF$UID - 139 + 163 + + + CF$UID + 120 - ShowDebuggerArea + layoutTree IDEEDitorArea_DebugArea IDEEditorMode_Standard IDEShowEditor EditorMode + IDEEditorMode_Version DebuggerSplitView DefaultPersistentRepresentations - layoutTree - + ShowDebuggerArea $class CF$UID - 43 + 55 + + geniusEditorContextNode + + CF$UID + 0 + + primaryEditorContextNode + + CF$UID + 35 + + rootLayoutTreeNode + + CF$UID + 52 + + + + $class + + CF$UID + 54 + + children + + CF$UID + 0 + + contentType + 1 + documentArchivableRepresentation + + CF$UID + 36 + + orientation + 0 + parent + + CF$UID + 52 + + + + $class + + CF$UID + 51 + + DocumentLocation + + CF$UID + 47 + + DomainIdentifier + + CF$UID + 37 + + IdentifierPath + + CF$UID + 38 + + IndexOfDocumentIdentifier + + CF$UID + 46 + + + Xcode.IDENavigableItemDomain.WorkspaceStructure + + $class + + CF$UID + 13 - NS.keys - - - CF$UID - 33 - - - CF$UID - 34 - - - CF$UID - 35 - - - CF$UID - 36 - - - CF$UID - 37 - - - CF$UID - 38 - - NS.objects @@ -319,306 +399,293 @@ CF$UID - 40 + 42 CF$UID 44 - - CF$UID - 39 - - - CF$UID - 57 - - - CF$UID - 63 - - LayoutFocusMode - console - IDEDebuggerAreaSplitView - LayoutMode - IDEDebugArea_SplitView - variables - 1 $class CF$UID - 43 + 41 + + Identifier + + CF$UID + 40 - NS.keys - - - CF$UID - 41 - - - NS.objects - - - CF$UID - 42 - - - ConsoleFilterMode - 0 + kevent.c $classes - NSMutableDictionary - NSDictionary + IDEArchivableStringIndexPair NSObject $classname - NSMutableDictionary + IDEArchivableStringIndexPair $class + + CF$UID + 41 + + Identifier CF$UID 43 - NS.keys - - - CF$UID - 45 - - - NS.objects - - - CF$UID - 46 - - - DVTSplitViewItems + common $class CF$UID - 56 + 41 + + Identifier + + CF$UID + 45 - NS.objects - - - CF$UID - 47 - - - CF$UID - 53 - - + libkqueue + 0 $class CF$UID - 52 + 50 - NS.keys + documentURL + + CF$UID + 48 + + timestamp + + CF$UID + 0 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/kevent.c + + + $classes - - CF$UID - 48 - - - CF$UID - 49 - + NSMutableString + NSString + NSObject - NS.objects + $classname + NSMutableString + + + $classes - - CF$UID - 50 - - - CF$UID - 51 - + DVTDocumentLocation + NSObject + $classname + DVTDocumentLocation - DVTIdentifier - DVTViewMagnitude - VariablesView - 570 $classes - NSDictionary + IDENavigableItemArchivableRepresentation NSObject $classname - NSDictionary + IDENavigableItemArchivableRepresentation $class CF$UID - 52 + 54 - NS.keys + children + + CF$UID + 53 + + contentType + 0 + documentArchivableRepresentation + + CF$UID + 0 + + orientation + 0 + parent + + CF$UID + 0 + + + + $class + + CF$UID + 13 + + NS.objects CF$UID - 48 - - - CF$UID - 49 + 35 - NS.objects + + + $classes - - CF$UID - 54 - - - CF$UID - 55 - + IDEWorkspaceTabControllerLayoutTreeNode + NSObject + $classname + IDEWorkspaceTabControllerLayoutTreeNode - ConsoleArea - 569 $classes - NSMutableArray - NSArray + IDEWorkspaceTabControllerLayoutTree NSObject $classname - NSMutableArray + IDEWorkspaceTabControllerLayoutTree $class CF$UID - 43 + 66 NS.keys CF$UID - 45 + 57 - - NS.objects - CF$UID 58 - - - - $class - - CF$UID - 56 - - NS.objects - CF$UID 59 CF$UID - 61 + 60 - - - - $class - - CF$UID - 52 - - NS.keys - CF$UID - 48 + 61 CF$UID - 49 + 62 NS.objects CF$UID - 50 + 63 + + + CF$UID + 64 CF$UID - 60 + 67 + + + CF$UID + 63 + + + CF$UID + 70 + + + CF$UID + 83 - 570 + LayoutFocusMode + console + variables + LayoutMode + IDEDebuggerAreaSplitView + IDEDebugArea_SplitView + 1 $class CF$UID - 52 + 66 NS.keys CF$UID - 48 - - - CF$UID - 49 + 65 NS.objects CF$UID - 54 - - - CF$UID - 62 + 46 - 569 + ConsoleFilterMode + + $classes + + NSMutableDictionary + NSDictionary + NSObject + + $classname + NSMutableDictionary + $class CF$UID - 43 + 66 NS.keys CF$UID - 64 + 68 NS.objects CF$UID - 65 + 69 @@ -628,476 +695,445 @@ $class CF$UID - 43 + 66 NS.keys CF$UID - 67 + 71 NS.objects CF$UID - 68 + 72 - EditorLayout_PersistentRepresentation + DVTSplitViewItems $class CF$UID - 43 + 82 - NS.keys + NS.objects CF$UID - 69 + 73 - - NS.objects - CF$UID - 70 + 79 - Main $class CF$UID - 52 + 78 NS.keys CF$UID - 71 - - - CF$UID - 72 + 74 CF$UID - 73 + 75 NS.objects CF$UID - 74 - - - CF$UID - 42 + 76 CF$UID - 128 + 77 - EditorLayout_StateSavingStateDictionaries - EditorLayout_Selected - EditorLayout_Geometry + DVTIdentifier + DVTViewMagnitude + VariablesView + 555 - $class - - CF$UID - 90 - - NS.objects + $classes - - CF$UID - 75 - + NSDictionary + NSObject + $classname + NSDictionary $class CF$UID - 43 + 78 NS.keys CF$UID - 76 - - - CF$UID - 77 - - - CF$UID - 78 - - - CF$UID - 79 - - - CF$UID - 80 - - - CF$UID - 81 + 74 CF$UID - 82 + 75 NS.objects CF$UID - 83 - - - CF$UID - 84 - - - CF$UID - 97 - - - CF$UID - 123 - - - CF$UID - 123 - - - CF$UID - 124 + 80 CF$UID - 125 + 81 - FileDataType - ArchivableRepresentation - EditorState - NavigableItemName - DocumentNavigableItemName - DocumentExtensionIdentifier - DocumentURL - com.apple.xcode.project + ConsoleArea + 554 - $class - - CF$UID - 96 - - DocumentLocation - - CF$UID - 92 - - DomainIdentifier - - CF$UID - 85 - - IdentifierPath - - CF$UID - 86 - - IndexOfDocumentIdentifier - - CF$UID - 91 - + $classes + + NSMutableArray + NSArray + NSObject + + $classname + NSMutableArray - Xcode.IDENavigableItemDomain.WorkspaceStructure $class CF$UID - 90 + 66 - NS.objects + NS.keys CF$UID - 87 + 71 - - - $class - - CF$UID - 89 - - Identifier - - CF$UID - 88 - - - libkqueue - - $classes - - IDEArchivableStringIndexPair - NSObject - - $classname - IDEArchivableStringIndexPair - - - $classes + NS.objects - NSArray - NSObject + + CF$UID + 84 + - $classname - NSArray - - 9223372036854775807 - - $class - - CF$UID - 95 - - documentURL - - CF$UID - 93 - - timestamp - - CF$UID - 0 - $class CF$UID - 94 + 82 - NS.string - file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue.xcodeproj/ - - - $classes - - NSMutableString - NSString - NSObject - - $classname - NSMutableString - - - $classes - - DVTDocumentLocation - NSObject - - $classname - DVTDocumentLocation - - - $classes + NS.objects - IDENavigableItemArchivableRepresentation - NSObject + + CF$UID + 85 + + + CF$UID + 87 + - $classname - IDENavigableItemArchivableRepresentation $class CF$UID - 52 + 78 NS.keys CF$UID - 98 - - - CF$UID - 99 + 74 CF$UID - 100 + 75 + + NS.objects + CF$UID - 101 + 76 CF$UID - 102 + 86 - NS.objects + + 555 + + $class + + CF$UID + 78 + + NS.keys CF$UID - 103 - - - CF$UID - 104 + 74 CF$UID - 111 + 75 + + NS.objects + CF$UID - 112 + 80 CF$UID - 122 + 88 - Xcode3ProjectEditorPreviousProjectEditorClass - Xcode3ProjectEditor.sourceList.splitview - Xcode3ProjectEditorPreviousTargetEditorClass - Xcode3ProjectEditorSelectedDocumentLocations - Xcode3ProjectEditor_Xcode3InfoEditor - Xcode3ProjectInfoEditor + 554 $class CF$UID - 43 + 66 NS.keys CF$UID - 45 + 90 NS.objects CF$UID - 105 + 91 + EditorLayout_PersistentRepresentation $class CF$UID - 56 + 66 - NS.objects + NS.keys CF$UID - 106 + 92 + + NS.objects + CF$UID - 109 + 93 + Main $class CF$UID - 52 + 78 NS.keys CF$UID - 48 + 94 + + + CF$UID + 95 CF$UID - 49 + 96 NS.objects CF$UID - 107 + 97 + + + CF$UID + 46 CF$UID - 108 + 127 - - 170 + EditorLayout_StateSavingStateDictionaries + EditorLayout_Selected + EditorLayout_Geometry $class CF$UID - 52 + 13 + + NS.objects + + + CF$UID + 98 + + + + + $class + + CF$UID + 66 NS.keys CF$UID - 48 + 99 + + + CF$UID + 100 + + + CF$UID + 101 + + + CF$UID + 102 + + + CF$UID + 103 + + + CF$UID + 104 CF$UID - 49 + 105 NS.objects + + CF$UID + 106 + CF$UID 107 CF$UID - 110 + 113 + + + CF$UID + 122 + + + CF$UID + 40 + + + CF$UID + 123 + + + CF$UID + 124 - 970 - Xcode3InfoEditor + FileDataType + ArchivableRepresentation + EditorState + NavigableItemName + DocumentNavigableItemName + DocumentExtensionIdentifier + DocumentURL + public.c-source + + $class + + CF$UID + 51 + + DocumentLocation + + CF$UID + 47 + + DomainIdentifier + + CF$UID + 37 + + IdentifierPath + + CF$UID + 108 + + IndexOfDocumentIdentifier + + CF$UID + 46 + + $class CF$UID - 90 + 13 NS.objects CF$UID - 113 + 109 + + + CF$UID + 110 + + + CF$UID + 111 @@ -1105,45 +1141,70 @@ $class CF$UID - 121 + 41 - documentURL + Identifier CF$UID - 114 + 40 - selection + + + $class CF$UID - 116 + 41 - timestamp + Identifier CF$UID - 115 + 43 - file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue.xcodeproj/ - 320748289.82216001 $class CF$UID - 43 + 41 + + Identifier + + CF$UID + 112 + + + libkqueue + + $class + + CF$UID + 78 NS.keys CF$UID - 117 + 114 CF$UID - 118 + 115 + + + CF$UID + 116 + + + CF$UID + 117 NS.objects + + CF$UID + 118 + CF$UID 119 @@ -1152,40 +1213,27 @@ CF$UID 120 + + CF$UID + 121 + - Editor - Target - Xcode3InfoEditor - libkqueue - - $classes - - Xcode3ProjectDocumentLocation - DVTDocumentLocation - NSObject - - $classname - Xcode3ProjectDocumentLocation - - - $class - - CF$UID - 43 - - NS.keys - - NS.objects - - - libkqueue - Xcode.Xcode3ProjectSupport.EditorDocument.Xcode3Project + PrimaryDocumentTimestamp + PrimaryDocumentVisibleCharacterRange + HideAllIssues + PrimaryDocumentSelectedCharacterRange + 327515822.77097303 + {6982, 1750} + + {8174, 11} + kevent() + Xcode.IDEKit.EditorDocument.SourceCode $class CF$UID - 127 + 126 NS.base @@ -1195,10 +1243,10 @@ NS.relative CF$UID - 126 + 125 - file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue.xcodeproj/ + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/kevent.c $classes @@ -1212,53 +1260,65 @@ $class CF$UID - 90 + 13 NS.objects CF$UID - 129 + 128 - {{0, 0}, {1140, 876}} + {{0, 0}, {1110, 938}} $class CF$UID - 43 + 66 NS.keys CF$UID - 45 + 130 + + + CF$UID + 90 NS.objects + + CF$UID + 46 + CF$UID 131 + VersionsEditorSubmode $class CF$UID - 56 + 66 - NS.objects + NS.keys CF$UID - 132 + 92 + + NS.objects + CF$UID - 135 + 132 @@ -1266,17 +1326,21 @@ $class CF$UID - 52 + 78 NS.keys CF$UID - 48 + 94 CF$UID - 49 + 95 + + + CF$UID + 96 NS.objects @@ -1285,142 +1349,426 @@ CF$UID 133 + + CF$UID + 46 + + + CF$UID + 153 + + + + + $class + + CF$UID + 13 + + NS.objects + CF$UID 134 - IDEEditor - 203 $class CF$UID - 52 + 66 NS.keys CF$UID - 48 + 99 + + + CF$UID + 100 + + + CF$UID + 101 + + + CF$UID + 102 + + + CF$UID + 103 + + + CF$UID + 104 CF$UID - 49 + 105 NS.objects CF$UID - 136 + 106 CF$UID - 137 + 135 + + + CF$UID + 145 + + + CF$UID + 149 + + + CF$UID + 138 + + + CF$UID + 150 + + + CF$UID + 151 - IDEDebuggerArea - 115 $class CF$UID - 43 + 51 + + DocumentLocation + + CF$UID + 143 + + DomainIdentifier + + CF$UID + 37 + + IdentifierPath + + CF$UID + 136 + + IndexOfDocumentIdentifier + + CF$UID + 46 + + + + $class + + CF$UID + 13 - NS.keys - NS.objects - + + + CF$UID + 137 + + + CF$UID + 139 + + + CF$UID + 141 + + $class CF$UID - 149 + 41 - geniusEditorContextNode + Identifier CF$UID - 0 + 138 - primaryEditorContextNode + + read.c + + $class + + CF$UID + 41 + + Identifier CF$UID 140 - rootLayoutTreeNode + + test + + $class + + CF$UID + 41 + + Identifier CF$UID - 146 + 142 + libkqueue $class CF$UID - 148 + 50 - children + documentURL + + CF$UID + 144 + + timestamp CF$UID 0 - contentType - 1 - documentArchivableRepresentation + + + $class CF$UID - 141 + 49 - orientation - 0 - parent + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/read.c + + + $class CF$UID - 146 + 78 + NS.keys + + + CF$UID + 114 + + + CF$UID + 115 + + + CF$UID + 116 + + + CF$UID + 117 + + + NS.objects + + + CF$UID + 146 + + + CF$UID + 147 + + + CF$UID + 120 + + + CF$UID + 148 + + + 327507826.66487598 + {6959, 1898} + {7915, 8} + test_kevent_socket_dispatch() + Xcode.IDEKit.EditorDocument.SourceCodeComparisonEditor $class CF$UID - 96 + 126 - DocumentLocation + NS.base CF$UID - 92 + 0 - DomainIdentifier + NS.relative CF$UID - 85 + 152 - IdentifierPath + + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/read.c + + $class CF$UID - 142 + 13 - IndexOfDocumentIdentifier + NS.objects + + + CF$UID + 154 + + + + {{0, 0}, {1193, 938}} + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 71 + + + NS.objects + + + CF$UID + 156 + + + + + $class + + CF$UID + 82 + + NS.objects + + + CF$UID + 157 + + + CF$UID + 160 + + + + + $class + + CF$UID + 78 + + NS.keys + + + CF$UID + 74 + + + CF$UID + 75 + + + NS.objects + + + CF$UID + 158 + + + CF$UID + 159 + + + + IDEEditor + 203 + + $class + + CF$UID + 78 + + NS.keys + + + CF$UID + 74 + + + CF$UID + 75 + + + NS.objects + + + CF$UID + 161 + + + CF$UID + 162 + + + + IDEDebuggerArea + 115 + + $class CF$UID - 145 + 66 + NS.keys + + NS.objects + $class CF$UID - 90 + 66 + NS.keys + + + CF$UID + 71 + + NS.objects CF$UID - 143 + 165 @@ -1428,1382 +1776,4669 @@ $class CF$UID - 89 + 82 + + NS.objects + + + CF$UID + 166 + + + CF$UID + 169 + + + + + $class + + CF$UID + 78 + + NS.keys + + + CF$UID + 74 + + + CF$UID + 75 + + + NS.objects + + + CF$UID + 167 + + + CF$UID + 168 + + + + + 727 + + $class + + CF$UID + 78 + + NS.keys + + + CF$UID + 74 + + + CF$UID + 75 + + + NS.objects + + + CF$UID + 167 + + + CF$UID + 170 + + + + 211 + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 172 + + + CF$UID + 173 + + + CF$UID + 174 + + + NS.objects + + + CF$UID + 175 + + + CF$UID + 172 + + + CF$UID + 188 + + + + Xcode.IDEKit.Navigator.BatchFind + SelectedNavigator + Xcode.IDEKit.Navigator.Structure + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 176 + + + CF$UID + 177 + + + CF$UID + 178 + + + CF$UID + 179 + + + CF$UID + 180 + + + CF$UID + 181 + + + CF$UID + 182 + + + NS.objects + + + CF$UID + 46 + + + CF$UID + 120 + + + CF$UID + 167 + + + CF$UID + 183 + + + CF$UID + 184 + + + CF$UID + 46 + + + CF$UID + 186 + + + + IDEBatchFindNavigatorScrollPosition + IDEBatchFindNavigatorShowsOptions + IDEBatchFindNavigatorReplaceString + IDEBatchFindNavigatorFindString + IDEBatchFindNavigatorSelectedRowIndexes + IDEBatchFindNavigatorFindMode + IDEBatchFindNavigatorCollapsedGroups + WITEM_CACHE + + $class + + CF$UID + 185 + + NSLength + 1 + NSLocation + 2 + NSRangeCount + 1 + + + $classes + + NSIndexSet + NSObject + + $classname + NSIndexSet + + + $class + + CF$UID + 187 + + NSRangeCount + 0 + + + $classes + + NSMutableIndexSet + NSIndexSet + NSObject + + $classname + NSMutableIndexSet + + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 189 + + + CF$UID + 190 + + + CF$UID + 191 + + + CF$UID + 192 + + + CF$UID + 193 + + + CF$UID + 194 + + + CF$UID + 195 + + + NS.objects + + + CF$UID + 196 + + + CF$UID + 120 + + + CF$UID + 197 + + + CF$UID + 120 + + + CF$UID + 120 + + + CF$UID + 199 + + + CF$UID + 202 + + + + IDEVisibleRect + IDEUnsavedDocumentFilteringEnabled + IDENavigatorExpandedItemsBeforeFilteringSet + IDERecentDocumentFilteringEnabled + IDESCMStatusFilteringEnabled + IDESelectedObjects + IDEExpandedItemsSet + {{0, 0}, {342, 894}} + + $class + + CF$UID + 198 + + NS.objects + + + + $classes + + NSSet + NSObject + + $classname + NSSet + + + $class + + CF$UID + 13 + + NS.objects + + + CF$UID + 200 + + + + + $class + + CF$UID + 82 + + NS.objects + + + CF$UID + 201 + + + CF$UID + 43 + + + CF$UID + 40 + + + + libkqueue + + $class + + CF$UID + 198 + + NS.objects + + + CF$UID + 203 + + + CF$UID + 204 + + + CF$UID + 205 + + + CF$UID + 207 + + + CF$UID + 209 + + + + + $class + + CF$UID + 82 + + NS.objects + + + CF$UID + 201 + + + + + $class + + CF$UID + 82 + + NS.objects + + + CF$UID + 201 + + + CF$UID + 43 + + + + + $class + + CF$UID + 82 + + NS.objects + + + CF$UID + 201 + + + CF$UID + 206 + + + + linux + + $class + + CF$UID + 82 + + NS.objects + + + CF$UID + 201 + + + CF$UID + 208 + + + + solaris + + $class + + CF$UID + 82 + + NS.objects + + + CF$UID + 201 + + + CF$UID + 140 + + + + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 71 + + + NS.objects + + + CF$UID + 211 + + + + + $class + + CF$UID + 82 + + NS.objects + + + CF$UID + 212 + + + CF$UID + 214 + + + CF$UID + 216 + + + + + $class + + CF$UID + 78 + + NS.keys + + + CF$UID + 74 + + + CF$UID + 75 + + + NS.objects + + + CF$UID + 20 + + + CF$UID + 213 + + + + 343 + + $class + + CF$UID + 78 + + NS.keys + + + CF$UID + 74 + + + CF$UID + 75 + + + NS.objects + + + CF$UID + 16 + + + CF$UID + 215 + + + + 1110 + + $class + + CF$UID + 78 + + NS.keys + + + CF$UID + 74 + + + CF$UID + 75 + + + NS.objects + + + CF$UID + 217 + + + CF$UID + 218 + + + + IDEUtilitiesArea + 260 + kevent.c + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 221 + + + CF$UID + 222 + + + CF$UID + 223 + + + CF$UID + 224 + + + CF$UID + 225 + + + CF$UID + 226 + + + CF$UID + 227 + + + CF$UID + 228 + + + CF$UID + 229 + + + NS.objects + + + CF$UID + 120 + + + CF$UID + 230 + + + CF$UID + 46 + + + CF$UID + 502 + + + CF$UID + 505 + + + CF$UID + 510 + + + CF$UID + 511 + + + CF$UID + 120 + + + CF$UID + 120 + + + + BreakpointsActivated + DefaultEditorStatesForURLs + DebuggingWindowBehavior + ActiveScheme + ActiveRunDestination + DocumentWindows + RecentEditorDocumentURLs + AppFocusInMiniDebugging + MiniDebuggingConsole + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 150 + + + CF$UID + 231 + + + CF$UID + 123 + + + NS.objects + + + CF$UID + 232 + + + CF$UID + 288 + + + CF$UID + 360 + + + + Xcode.Xcode3ProjectSupport.EditorDocument.Xcode3Project + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 233 + + + CF$UID + 234 + + + CF$UID + 236 + + + CF$UID + 238 + + + CF$UID + 239 + + + CF$UID + 241 + + + CF$UID + 243 + + + CF$UID + 245 + + + CF$UID + 247 + + + CF$UID + 249 + + + NS.objects + + + CF$UID + 251 + + + CF$UID + 254 + + + CF$UID + 257 + + + CF$UID + 260 + + + CF$UID + 264 + + + CF$UID + 268 + + + CF$UID + 272 + + + CF$UID + 276 + + + CF$UID + 280 + + + CF$UID + 284 + + + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 48 + + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 235 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/solaris/signal.c + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 237 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/filter.c + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 144 + + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 240 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/windows/read.c + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 242 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/proc.c + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 244 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/solaris/platform.c + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 246 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/linux/read.c + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 248 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/solaris/socket.c + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 250 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/knote.c + + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 117 + + + CF$UID + 114 + + + CF$UID + 115 + + + NS.objects + + + CF$UID + 252 + + + CF$UID + 253 + + + CF$UID + 252 + + + + {0, 0} + 327502698.73993701 + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 117 + + + CF$UID + 115 + + + CF$UID + 114 + + + NS.objects + + + CF$UID + 252 + + + CF$UID + 255 + + + CF$UID + 256 + + + + {641, 1780} + 327483300.588404 + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 117 + + + CF$UID + 115 + + + CF$UID + 114 + + + NS.objects + + + CF$UID + 252 + + + CF$UID + 258 + + + CF$UID + 259 + + + + {3292, 1552} + 327483354.533373 + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 114 + + + CF$UID + 115 + + + CF$UID + 116 + + + CF$UID + 117 + + + NS.objects + + + CF$UID + 261 + + + CF$UID + 262 + + + CF$UID + 120 + + + CF$UID + 263 + + + + 327507825.58967799 + {6959, 1898} + {7915, 8} + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 117 + + + CF$UID + 115 + + + CF$UID + 114 + + + NS.objects + + + CF$UID + 265 + + + CF$UID + 266 + + + CF$UID + 267 + + + + {4061, 8} + {1239, 1734} + 327507729.79866397 + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 117 + + + CF$UID + 115 + + + CF$UID + 114 + + + NS.objects + + + CF$UID + 269 + + + CF$UID + 270 + + + CF$UID + 271 + + + + {4776, 8} + {981, 1624} + 327507731.96671999 + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 114 + + + CF$UID + 115 + + + CF$UID + 116 + + + CF$UID + 117 + + + NS.objects + + + CF$UID + 273 + + + CF$UID + 274 + + + CF$UID + 120 + + + CF$UID + 275 + + + + 327507815.27077597 + {3447, 2155} + {2760, 0} + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 117 + + + CF$UID + 115 + + + CF$UID + 114 + + + NS.objects + + + CF$UID + 277 + + + CF$UID + 278 + + + CF$UID + 279 + + + + {4874, 8} + {3953, 1837} + 327507753.85920501 + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 117 + + + CF$UID + 115 + + + CF$UID + 114 + + + NS.objects + + + CF$UID + 281 + + + CF$UID + 282 + + + CF$UID + 283 + + + + {1080, 0} + {1932, 1806} + 327507765.95997798 + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 117 + + + CF$UID + 115 + + + CF$UID + 114 + + + NS.objects + + + CF$UID + 285 + + + CF$UID + 286 + + + CF$UID + 287 + + + + {896, 0} + {0, 1554} + 327507820.57061797 + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 289 + + + CF$UID + 291 + + + CF$UID + 293 + + + NS.objects + + + CF$UID + 295 + + + CF$UID + 320 + + + CF$UID + 347 + + + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 290 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/libkqueue.xcodeproj/ + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 292 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue.xcodeproj/ + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 294 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue/libkqueue.xcodeproj + + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 296 + + + CF$UID + 297 + + + CF$UID + 298 + + + CF$UID + 299 + + + CF$UID + 300 + + + NS.objects + + + CF$UID + 301 + + + CF$UID + 302 + + + CF$UID + 308 + + + CF$UID + 309 + + + CF$UID + 319 + + + + Xcode3ProjectEditorPreviousProjectEditorClass + Xcode3ProjectEditor.sourceList.splitview + Xcode3ProjectEditorPreviousTargetEditorClass + Xcode3ProjectEditorSelectedDocumentLocations + Xcode3ProjectEditor_Xcode3InfoEditor + Xcode3ProjectInfoEditor + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 71 + + + NS.objects + + + CF$UID + 303 + + + + + $class + + CF$UID + 82 + + NS.objects + + + CF$UID + 304 + + + CF$UID + 306 + + + + + $class + + CF$UID + 78 + + NS.keys + + + CF$UID + 74 + + + CF$UID + 75 + + + NS.objects + + + CF$UID + 167 + + + CF$UID + 305 + + + + 170 + + $class + + CF$UID + 78 + + NS.keys + + + CF$UID + 74 + + + CF$UID + 75 + + + NS.objects + + + CF$UID + 167 + + + CF$UID + 307 + + + + 1023 + Xcode3InfoEditor + + $class + + CF$UID + 13 + + NS.objects + + + CF$UID + 310 + + + + + $class + + CF$UID + 318 + + documentURL + + CF$UID + 311 + + selection + + CF$UID + 313 + + timestamp + + CF$UID + 312 + + + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/libkqueue.xcodeproj/ + 327480573.75054502 + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 314 + + + CF$UID + 315 + + + NS.objects + + + CF$UID + 316 + + + CF$UID + 317 + + + + Editor + Target + Xcode3InfoEditor + libkqueue + + $classes + + Xcode3ProjectDocumentLocation + DVTDocumentLocation + NSObject + + $classname + Xcode3ProjectDocumentLocation + + + $class + + CF$UID + 66 + + NS.keys + + NS.objects + + + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 321 + + + CF$UID + 322 + + + CF$UID + 323 + + + CF$UID + 324 + + + CF$UID + 325 + + + NS.objects + + + CF$UID + 326 + + + CF$UID + 327 + + + CF$UID + 337 + + + CF$UID + 338 + + + CF$UID + 346 + + + + Xcode3ProjectEditorPreviousProjectEditorClass + Xcode3ProjectEditor.sourceList.splitview + Xcode3ProjectEditorPreviousTargetEditorClass + Xcode3ProjectEditorSelectedDocumentLocations + Xcode3ProjectEditor_Xcode3InfoEditor + Xcode3ProjectInfoEditor + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 328 + + + NS.objects + + + CF$UID + 329 + + + + DVTSplitViewItems + + $class + + CF$UID + 82 + + NS.objects + + + CF$UID + 330 + + + CF$UID + 335 + + + + + $class + + CF$UID + 78 + + NS.keys + + + CF$UID + 331 + + + CF$UID + 332 + + + NS.objects + + + CF$UID + 333 + + + CF$UID + 334 + + + + DVTIdentifier + DVTViewMagnitude + + 170 + + $class + + CF$UID + 78 + + NS.keys + + + CF$UID + 331 + + + CF$UID + 332 + + + NS.objects + + + CF$UID + 333 + + + CF$UID + 336 + + + + 970 + Xcode3InfoEditor + + $class + + CF$UID + 13 + + NS.objects + + + CF$UID + 339 + + + + + $class + + CF$UID + 318 + + documentURL + + CF$UID + 340 + + selection + + CF$UID + 342 + + timestamp + + CF$UID + 341 + + + file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue.xcodeproj/ + 320748289.81788599 + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 343 + + + CF$UID + 344 + + + NS.objects + + + CF$UID + 337 + + + CF$UID + 345 + + + + Editor + Target + libkqueue + + $class + + CF$UID + 66 + + NS.keys + + NS.objects + + + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 321 + + + CF$UID + 322 + + + CF$UID + 323 + + + CF$UID + 324 + + + CF$UID + 325 + + + NS.objects + + + CF$UID + 326 + + + CF$UID + 348 + + + CF$UID + 337 + + + CF$UID + 354 + + + CF$UID + 359 + + + + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 328 + + + NS.objects + + + CF$UID + 349 + + + + + $class + + CF$UID + 82 + + NS.objects + + + CF$UID + 350 + + + CF$UID + 352 + + + + + $class + + CF$UID + 78 + + NS.keys + + + CF$UID + 331 + + + CF$UID + 332 + + + NS.objects + + + CF$UID + 333 + + + CF$UID + 351 + + + + 162 + + $class + + CF$UID + 78 + + NS.keys + + + CF$UID + 331 + + + CF$UID + 332 + + + NS.objects + + + CF$UID + 333 + + + CF$UID + 353 + + + + 978 + + $class + + CF$UID + 13 + + NS.objects + + + CF$UID + 355 + + + + + $class + + CF$UID + 318 + + documentURL + + CF$UID + 356 + + selection + + CF$UID + 358 + + timestamp + + CF$UID + 357 + + + file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue/libkqueue.xcodeproj/ + 320748102.08692503 + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 343 + + + CF$UID + 344 + + + NS.objects + + + CF$UID + 337 + + + CF$UID + 345 + + + + + $class + + CF$UID + 66 + + NS.keys + + NS.objects + + + + $class + + CF$UID + 66 + + NS.keys + + + CF$UID + 361 + + + CF$UID + 363 + + + CF$UID + 365 + + + CF$UID + 247 + + + CF$UID + 367 + + + CF$UID + 369 + + + CF$UID + 371 + + + CF$UID + 373 + + + CF$UID + 245 + + + CF$UID + 239 + + + CF$UID + 241 + + + CF$UID + 375 + + + CF$UID + 377 + + + CF$UID + 233 + + + CF$UID + 379 + + + CF$UID + 234 + + + CF$UID + 381 + + + CF$UID + 383 + + + CF$UID + 385 + + + CF$UID + 387 + + + CF$UID + 389 + + + CF$UID + 236 + + + CF$UID + 391 + + + CF$UID + 393 + + + CF$UID + 395 + + + CF$UID + 397 + + + CF$UID + 399 + + + NS.objects + + + CF$UID + 401 + + + CF$UID + 405 + + + CF$UID + 408 + + + CF$UID + 411 + + + CF$UID + 415 + + + CF$UID + 418 + + + CF$UID + 421 + + + CF$UID + 425 + + + CF$UID + 428 + + + CF$UID + 432 + + + CF$UID + 436 + + + CF$UID + 440 + + + CF$UID + 444 + + + CF$UID + 448 + + + CF$UID + 452 + + + CF$UID + 456 + + + CF$UID + 460 + + + CF$UID + 464 + + + CF$UID + 468 + + + CF$UID + 472 + + + CF$UID + 476 + + + CF$UID + 480 + + + CF$UID + 484 + + + CF$UID + 487 + + + CF$UID + 491 + + + CF$UID + 495 + + + CF$UID + 498 + + + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 362 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/knote.c + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 364 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/kqueue.c + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 366 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/CMakeLists.txt + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 368 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/kqtest.sln + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 370 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/solaris/timer.c + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 372 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/windows/timer.c + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 374 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/include/sys/event.h + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 376 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/debug.h + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 378 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/read.c + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 380 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/kevent.c + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 382 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/signal.c + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 384 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/linux/platform.c + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 386 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/solaris/platform.c + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 388 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/posix/signal.c + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 390 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/linux/write.c + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 392 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/config.mk + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 394 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/linux/signal.c + + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 396 + + + + $class + + CF$UID + 49 + + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/windows/platform.c + + + $class + + CF$UID + 126 - Identifier + NS.base CF$UID - 144 + 0 + + NS.relative + + CF$UID + 398 - libkqueue - 9223372036854775807 $class CF$UID - 148 + 49 - children + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/config.h + + + $class CF$UID - 147 + 126 - contentType - 0 - documentArchivableRepresentation + NS.base CF$UID 0 - orientation - 0 - parent + NS.relative CF$UID - 0 + 400 $class CF$UID - 90 + 49 - NS.objects + NS.string + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/private.h + + + $class + + CF$UID + 66 + + NS.keys CF$UID - 140 + 114 + + + CF$UID + 115 + + + CF$UID + 116 + + + CF$UID + 117 - - - $classes - - IDEWorkspaceTabControllerLayoutTreeNode - NSObject - - $classname - IDEWorkspaceTabControllerLayoutTreeNode - - - $classes + NS.objects - IDEWorkspaceTabControllerLayoutTree - NSObject + + CF$UID + 402 + + + CF$UID + 403 + + + CF$UID + 120 + + + CF$UID + 404 + - $classname - IDEWorkspaceTabControllerLayoutTree + 327515288.24181002 + {2380, 1756} + {3481, 46} $class CF$UID - 43 + 66 NS.keys CF$UID - 45 + 114 + + + CF$UID + 115 + + + CF$UID + 116 + + + CF$UID + 117 NS.objects CF$UID - 151 + 406 + + + CF$UID + 407 + + + CF$UID + 120 + + + CF$UID + 252 + 327501746.70619398 + {1942, 1354} $class CF$UID - 56 + 66 + NS.keys + + + CF$UID + 114 + + + CF$UID + 115 + + + CF$UID + 116 + + + CF$UID + 117 + + NS.objects CF$UID - 152 + 409 CF$UID - 154 + 410 + + + CF$UID + 120 + + + CF$UID + 252 + 327484326.94135398 + {0, 1437} $class CF$UID - 52 + 66 NS.keys CF$UID - 48 + 114 + + + CF$UID + 115 + + + CF$UID + 116 CF$UID - 49 + 117 NS.objects CF$UID - 107 + 412 CF$UID - 153 + 413 + + + CF$UID + 120 + + + CF$UID + 414 - 652 + 327510440.30511099 + {806, 1549} + {1554, 14} $class CF$UID - 52 + 66 NS.keys CF$UID - 48 + 114 + + + CF$UID + 115 + + + CF$UID + 116 CF$UID - 49 + 117 NS.objects CF$UID - 107 + 416 CF$UID - 155 + 417 + + + CF$UID + 120 + + + CF$UID + 252 - 224 + 327484267.83185202 + {0, 880} $class CF$UID - 43 + 66 NS.keys CF$UID - 157 + 114 CF$UID - 158 + 115 + + + CF$UID + 116 + + + CF$UID + 117 NS.objects CF$UID - 158 + 419 CF$UID - 159 + 420 + + + CF$UID + 120 + + + CF$UID + 252 - SelectedNavigator - Xcode.IDEKit.Navigator.Structure + 327502220.41982299 + {0, 2018} $class CF$UID - 43 + 66 NS.keys CF$UID - 160 + 114 CF$UID - 161 + 115 CF$UID - 162 + 116 CF$UID - 163 + 117 + + NS.objects + CF$UID - 164 + 422 CF$UID - 165 + 423 CF$UID - 166 + 120 + + + CF$UID + 424 - NS.objects + + 327510899.55966902 + {2630, 1684} + {3654, 12} + + $class + + CF$UID + 66 + + NS.keys CF$UID - 167 + 114 CF$UID - 31 + 115 CF$UID - 168 + 116 CF$UID - 31 + 117 + + + NS.objects + + + CF$UID + 426 CF$UID - 31 + 427 CF$UID - 170 + 120 CF$UID - 173 + 252 - IDEVisibleRect - IDEUnsavedDocumentFilteringEnabled - IDENavigatorExpandedItemsBeforeFilteringSet - IDERecentDocumentFilteringEnabled - IDESCMStatusFilteringEnabled - IDESelectedObjects - IDEExpandedItemsSet - {{0, 0}, {259, 832}} + 327501403.16790402 + {0, 2611} $class CF$UID - 169 + 66 + NS.keys + + + CF$UID + 114 + + + CF$UID + 115 + + + CF$UID + 116 + + + CF$UID + 117 + + NS.objects - - - - $classes - NSSet - NSObject + + CF$UID + 429 + + + CF$UID + 430 + + + CF$UID + 120 + + + CF$UID + 431 + - $classname - NSSet + 327508285.43267101 + {3358, 2094} + {4911, 7} $class CF$UID - 90 + 66 - NS.objects + NS.keys CF$UID - 171 + 114 + + + CF$UID + 115 + + + CF$UID + 116 + + + CF$UID + 117 - - - $class - - CF$UID - 56 - NS.objects CF$UID - 172 + 433 + + + CF$UID + 434 + + + CF$UID + 120 + + + CF$UID + 435 - libkqueue + 327508343.95512998 + {3020, 1730} + {4061, 8} $class CF$UID - 169 + 66 - NS.objects + NS.keys CF$UID - 174 + 114 CF$UID - 175 + 115 CF$UID - 177 + 116 CF$UID - 179 + 117 + + NS.objects + CF$UID - 181 + 437 CF$UID - 183 + 438 + + + CF$UID + 120 + + + CF$UID + 439 + 327508336.51981598 + {3119, 1726} + {4776, 8} $class CF$UID - 56 + 66 - NS.objects + NS.keys CF$UID - 172 + 114 + + + CF$UID + 115 + + + CF$UID + 116 + + + CF$UID + 117 - - - $class - - CF$UID - 56 - NS.objects CF$UID - 172 + 441 CF$UID - 176 + 442 + + + CF$UID + 120 + + + CF$UID + 443 - windows + 327511143.49480402 + {2256, 2475} + {3507, 18} $class CF$UID - 56 + 66 - NS.objects + NS.keys CF$UID - 172 + 114 CF$UID - 178 + 115 + + + CF$UID + 116 + + + CF$UID + 117 - - solaris - - $class - - CF$UID - 56 - NS.objects CF$UID - 172 + 445 CF$UID - 180 + 446 + + + CF$UID + 120 + + + CF$UID + 447 - common + 327510568.35661697 + {9888, 1763} + {11545, 0} $class CF$UID - 56 + 66 - NS.objects + NS.keys CF$UID - 172 + 114 CF$UID - 182 + 115 + + + CF$UID + 116 + + + CF$UID + 117 - - posix - - $class - - CF$UID - 56 - NS.objects CF$UID - 172 + 449 CF$UID - 184 + 450 + + + CF$UID + 120 + + + CF$UID + 451 - linux + 327515822.76584601 + {6982, 1750} + {8174, 11} $class CF$UID - 43 + 66 NS.keys CF$UID - 45 + 114 - - NS.objects - CF$UID - 186 + 115 + + + CF$UID + 116 + + + CF$UID + 117 - - - $class - - CF$UID - 56 - NS.objects CF$UID - 187 + 453 CF$UID - 189 + 454 CF$UID - 191 + 120 + + + CF$UID + 455 + 327484401.83084399 + {0, 1977} + {892, 15} $class CF$UID - 52 + 66 NS.keys CF$UID - 48 + 114 + + + CF$UID + 115 + + + CF$UID + 116 CF$UID - 49 + 117 NS.objects CF$UID - 16 + 457 CF$UID - 188 + 458 + + + CF$UID + 120 + + + CF$UID + 459 - 260 + 327514969.09328401 + {2608, 1740} + {3613, 11} $class CF$UID - 52 + 66 NS.keys CF$UID - 48 + 114 + + + CF$UID + 115 + + + CF$UID + 116 CF$UID - 49 + 117 NS.objects CF$UID - 14 + 461 CF$UID - 190 + 462 + + + CF$UID + 120 + + + CF$UID + 463 - 1140 + 327510759.63499302 + {1547, 1617} + {2310, 26} $class CF$UID - 52 + 66 NS.keys CF$UID - 48 + 114 CF$UID - 49 + 115 - - NS.objects - CF$UID - 192 + 116 CF$UID - 193 + 117 - - IDEUtilitiesArea - 260 - - $class - - CF$UID - 90 - NS.objects CF$UID - 5 + 465 + + + CF$UID + 466 + + + CF$UID + 120 + + + CF$UID + 467 - {{424, 161}, {1400, 952}} + 327510518.82097101 + {3548, 1751} + {4489, 10} $class CF$UID - 43 + 66 NS.keys CF$UID - 197 - - - CF$UID - 198 + 114 CF$UID - 199 + 115 CF$UID - 200 + 116 CF$UID - 201 + 117 + + NS.objects + CF$UID - 202 + 469 CF$UID - 203 + 470 CF$UID - 204 + 120 CF$UID - 205 + 471 - NS.objects + + 327511788.54017502 + {3042, 2286} + {3942, 11} + + $class + + CF$UID + 66 + + NS.keys CF$UID - 31 - - - CF$UID - 206 + 114 CF$UID - 42 + 115 CF$UID - 255 + 116 CF$UID - 258 + 117 + + NS.objects + CF$UID - 263 + 473 CF$UID - 264 + 474 CF$UID - 31 + 120 CF$UID - 31 + 475 - BreakpointsActivated - DefaultEditorStatesForURLs - DebuggingWindowBehavior - ActiveScheme - ActiveRunDestination - DocumentWindows - RecentEditorDocumentURLs - AppFocusInMiniDebugging - MiniDebuggingConsole + 327511824.70484197 + {3125, 1625} + {4189, 11} $class CF$UID - 43 + 66 NS.keys CF$UID - 207 + 114 - - NS.objects - CF$UID - 208 + 115 - - - Xcode.Xcode3ProjectSupport.EditorDocument.Xcode3Project - - $class - - CF$UID - 43 - - NS.keys - CF$UID - 209 + 116 CF$UID - 211 + 117 NS.objects CF$UID - 213 + 477 + + + CF$UID + 478 + + + CF$UID + 120 CF$UID - 240 + 479 + 327508472.07515299 + {1328, 1840} + {2431, 7} $class CF$UID - 127 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 210 - - - - $class - - CF$UID - 94 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue/libkqueue.xcodeproj - - - $class - - CF$UID - 127 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 212 - - - - $class - - CF$UID - 94 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue.xcodeproj/ - - - $class - - CF$UID - 43 + 66 NS.keys CF$UID - 214 - - - CF$UID - 215 + 114 CF$UID - 216 + 115 CF$UID - 217 + 116 CF$UID - 218 + 117 NS.objects CF$UID - 219 - - - CF$UID - 220 + 481 CF$UID - 230 + 482 CF$UID - 231 + 120 CF$UID - 239 + 483 - Xcode3ProjectEditorPreviousProjectEditorClass - Xcode3ProjectEditor.sourceList.splitview - Xcode3ProjectEditorPreviousTargetEditorClass - Xcode3ProjectEditorSelectedDocumentLocations - Xcode3ProjectEditor_Xcode3InfoEditor - Xcode3ProjectInfoEditor + 327501730.97626501 + {2013, 1857} + {954, 11} $class CF$UID - 43 + 66 NS.keys CF$UID - 221 + 114 - - NS.objects - CF$UID - 222 + 115 + + + CF$UID + 116 + + + CF$UID + 117 - - DVTSplitViewItems - - $class - - CF$UID - 56 - NS.objects CF$UID - 223 + 485 CF$UID - 228 + 486 + + + CF$UID + 120 + + + CF$UID + 252 + 327484259.86375898 + {0, 798} $class CF$UID - 52 + 66 NS.keys CF$UID - 224 + 114 CF$UID - 225 + 115 + + + CF$UID + 116 + + + CF$UID + 117 NS.objects CF$UID - 226 + 488 CF$UID - 227 + 489 + + + CF$UID + 120 + + + CF$UID + 490 - DVTIdentifier - DVTViewMagnitude - - 162 + 327510511.21733099 + {2366, 1519} + {2964, 0} $class CF$UID - 52 + 66 NS.keys CF$UID - 224 + 114 CF$UID - 225 + 115 - - NS.objects - CF$UID - 226 + 116 CF$UID - 229 + 117 - - 978 - Xcode3InfoEditor - - $class - - CF$UID - 90 - NS.objects CF$UID - 232 + 492 + + + CF$UID + 493 + + + CF$UID + 120 + + + CF$UID + 494 + 327511609.71706301 + {3199, 1940} + {4798, 12} $class CF$UID - 121 - - documentURL - - CF$UID - 233 - - selection - - CF$UID - 235 - - timestamp - - CF$UID - 234 - - - file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue/libkqueue.xcodeproj/ - 320748102.08692503 - - $class - - CF$UID - 43 + 66 NS.keys CF$UID - 236 + 114 + + + CF$UID + 115 + + + CF$UID + 116 CF$UID - 237 + 117 NS.objects CF$UID - 230 + 496 CF$UID - 238 + 497 + + + CF$UID + 120 + + + CF$UID + 252 - Editor - Target - libkqueue - - $class - - CF$UID - 43 - - NS.keys - - NS.objects - - + 327484310.625539 + {0, 406} $class CF$UID - 43 + 66 NS.keys CF$UID - 98 - - - CF$UID - 99 + 114 CF$UID - 100 + 115 CF$UID - 101 + 116 CF$UID - 102 + 117 NS.objects CF$UID - 241 - - - CF$UID - 242 + 499 CF$UID - 248 + 500 CF$UID - 249 + 120 CF$UID - 254 + 501 - Xcode3ProjectInfoEditor + 327510895.31517202 + {3808, 2573} + {6073, 12} $class CF$UID - 43 + 66 NS.keys CF$UID - 45 + 503 NS.objects CF$UID - 243 + 504 + IDENameString + libkqueue $class CF$UID - 56 + 66 - NS.objects + NS.keys CF$UID - 244 + 506 CF$UID - 246 + 507 - - - $class - - CF$UID - 52 - - NS.keys + NS.objects CF$UID - 48 + 508 CF$UID - 49 + 509 + + IDEDeviceLocation + IDEDeviceArchitecture + dvtdevice-local-computer:localhost + x86_64 + + $class + + CF$UID + 82 + NS.objects CF$UID - 107 - - - CF$UID - 245 + 2 - 170 $class CF$UID - 52 + 82 - NS.keys + NS.objects CF$UID - 48 + 512 CF$UID - 49 + 514 - - NS.objects - CF$UID - 107 + 516 CF$UID - 247 + 518 + + + CF$UID + 520 + + + CF$UID + 522 + + + CF$UID + 524 + + + CF$UID + 526 + + + CF$UID + 528 + + + CF$UID + 530 - 970 - Xcode3InfoEditor $class CF$UID - 90 + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 513 - NS.objects - - - CF$UID - 250 - - + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/kevent.c $class CF$UID - 121 + 126 - documentURL + NS.base CF$UID - 114 + 0 - selection + NS.relative CF$UID - 252 + 515 - timestamp + + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/knote.c + + $class + + CF$UID + 126 + + NS.base + + CF$UID + 0 + + NS.relative CF$UID - 251 + 517 - 320748289.81788599 + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/solaris/signal.c $class CF$UID - 43 + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 519 - NS.keys - - - CF$UID - 117 - - - CF$UID - 118 - - - NS.objects - - - CF$UID - 253 - - - CF$UID - 120 - - - Xcode3InfoEditor + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/posix/signal.c $class CF$UID - 43 + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 521 - NS.keys - - NS.objects - + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/solaris/platform.c $class CF$UID - 43 + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 523 - NS.keys - - - CF$UID - 256 - - - NS.objects - - - CF$UID - 257 - - - IDENameString - libkqueue + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/windows/platform.c $class CF$UID - 43 + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 525 - NS.keys - - - CF$UID - 259 - - - CF$UID - 260 - - - NS.objects - - - CF$UID - 261 - - - CF$UID - 262 - - - IDEDeviceLocation - IDEDeviceArchitecture - dvtdevice-local-computer:localhost - x86_64 + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/debug.h $class CF$UID - 56 + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 527 - NS.objects - - - CF$UID - 2 - - + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/windows/timer.c $class CF$UID - 56 + 126 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 529 - NS.objects - - - CF$UID - 265 - - + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/private.h $class CF$UID - 127 + 126 NS.base @@ -2813,9 +6448,10 @@ NS.relative CF$UID - 114 + 531 + file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/signal.c $top From 36e39bd927a7e6acc3616352f208a9e2b8fcce4e Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 22 May 2011 00:28:35 +0000 Subject: [PATCH 0484/1120] Add -Wextra to CFLAGS and fix all related warnings on Linux. This will also need to be done on Solaris. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@513 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/TODO | 6 ++++++ vendor/libkqueue/config.inc | 2 +- vendor/libkqueue/src/common/kevent.c | 10 +++++----- vendor/libkqueue/src/common/knote.c | 4 ++-- vendor/libkqueue/src/common/private.h | 2 +- vendor/libkqueue/src/linux/platform.c | 17 +++++++++++------ vendor/libkqueue/src/linux/read.c | 3 +++ vendor/libkqueue/src/linux/signal.c | 9 +++++---- vendor/libkqueue/src/linux/timer.c | 7 +++++-- vendor/libkqueue/src/linux/user.c | 13 +++++++++---- vendor/libkqueue/src/linux/vnode.c | 9 ++++++--- vendor/libkqueue/src/linux/write.c | 3 +++ vendor/libkqueue/src/posix/platform.c | 4 ++-- vendor/libkqueue/src/posix/platform.h | 4 ++++ 14 files changed, 63 insertions(+), 30 deletions(-) diff --git a/vendor/libkqueue/TODO b/vendor/libkqueue/TODO index 37e87b573..6ebb725fd 100644 --- a/vendor/libkqueue/TODO +++ b/vendor/libkqueue/TODO @@ -1,4 +1,10 @@ + * Create a FILTER_DECL() macro that initializes the 'struct filter' object, + with all members properly initialized. Then -Wno-missing-field-initializers + can be removed from CFLAGS. + + * Implement the knote_modify() hook for all filters. + * Add a dbg_printf() statement within kevent_wait() to report the value of the timeout. diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc index 6191d0817..1a0c2095c 100644 --- a/vendor/libkqueue/config.inc +++ b/vendor/libkqueue/config.inc @@ -3,7 +3,7 @@ version="2.0a" abi_major="0" abi_minor="0" abi_version="$abi_major.$abi_minor" -cflags="-Wall -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600" +cflags="-Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600" ldflags="" sources="src/common/filter.c src/common/knote.c src/common/map.c src/common/kevent.c src/common/kqueue.c" diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 2b89e3984..9a30b98b6 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -31,7 +31,7 @@ static const char * kevent_filter_dump(const struct kevent *kev) { - static char __thread buf[64]; + static __thread char buf[64]; snprintf(&buf[0], sizeof(buf), "%d (%s)", kev->filter, filter_name(kev->filter)); @@ -41,7 +41,7 @@ kevent_filter_dump(const struct kevent *kev) static const char * kevent_fflags_dump(const struct kevent *kev) { - static char __thread buf[1024]; + static __thread char buf[1024]; #define KEVFFL_DUMP(attrib) \ if (kev->fflags & attrib) \ @@ -74,7 +74,7 @@ kevent_fflags_dump(const struct kevent *kev) static const char * kevent_flags_dump(const struct kevent *kev) { - static char __thread buf[1024]; + static __thread char buf[1024]; #define KEVFL_DUMP(attrib) \ if (kev->flags & attrib) \ @@ -101,7 +101,7 @@ kevent_flags_dump(const struct kevent *kev) const char * kevent_dump(const struct kevent *kev) { - static char __thread buf[1024]; + static __thread char buf[1024]; snprintf((char *) &buf[0], sizeof(buf), "{ ident=%d, filter=%s, %s, %s, data=%d, udata=%p }", @@ -147,7 +147,7 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) kn->kn_kq = kq; assert(filt->kn_create); if (filt->kn_create(filt, kn) < 0) { - knote_release(filt, kn); + knote_release(kn); errno = EFAULT; return (-1); } diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 14791b2fb..76b8c00d2 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -53,7 +53,7 @@ knote_new(void) } void -knote_release(struct filter *filt, struct knote *kn) +knote_release(struct knote *kn) { assert (kn->kn_ref > 0); @@ -114,7 +114,7 @@ knote_delete(struct filter *filt, struct knote *kn) kn->kn_flags |= KNFL_KNOTE_DELETED; - knote_release(filt, kn); + knote_release(kn); return (0); } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index efa329288..161f58772 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -189,7 +189,7 @@ struct knote * knote_lookup(struct filter *, short); //DEADWOOD: struct knote * knote_get_by_data(struct filter *filt, intptr_t); struct knote * knote_new(void); #define knote_retain(kn) atomic_inc(&kn->kn_ref) -void knote_release(struct filter *, struct knote *); +void knote_release(struct knote *); void knote_insert(struct filter *, struct knote *); int knote_delete(struct filter *, struct knote *); int knote_init(void); diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 8b4f00fde..e8f35ff84 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -23,7 +23,7 @@ const struct filter evfilt_proc = EVFILT_NOTIMPL; * Per-thread epoll event buffer used to ferry data between * kevent_wait() and kevent_copyout(). */ -static struct epoll_event __thread epevt[MAX_KEVENT]; +static __thread struct epoll_event epevt[MAX_KEVENT]; const struct kqueue_vtable kqops = { linux_kqueue_init, @@ -80,7 +80,7 @@ linux_kqueue_init(struct kqueue *kq) } void -linux_kqueue_free(struct kqueue *kq) +linux_kqueue_free(struct kqueue *kq UNUSED) { abort();//FIXME } @@ -146,7 +146,7 @@ linux_kevent_wait( int linux_kevent_copyout(struct kqueue *kq, int nready, - struct kevent *eventlist, int nevents) + struct kevent *eventlist, int nevents UNUSED) { struct epoll_event *ev; struct filter *filt; @@ -247,11 +247,13 @@ int linux_eventfd_lower(struct eventfd *e) { uint64_t cur; + ssize_t n; int rv = 0; /* Reset the counter */ dbg_puts("lowering event level"); - if (read(e->ef_id, &cur, sizeof(cur)) < sizeof(cur)) { + n = read(e->ef_id, &cur, sizeof(cur)); + if (n < 0) { switch (errno) { case EAGAIN: /* Not considered an error */ @@ -265,7 +267,10 @@ linux_eventfd_lower(struct eventfd *e) dbg_printf("read(2): %s", strerror(errno)); rv = -1; } - } + } else if (n != sizeof(cur)) { + dbg_puts("short read"); + rv = -1; + } return (rv); } @@ -322,7 +327,7 @@ linux_get_descriptor_type(struct knote *kn) char * epoll_event_dump(struct epoll_event *evt) { - static char __thread buf[128]; + static __thread char buf[128]; if (evt == NULL) return "(null)"; diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index c81d16743..7ec4f0cfa 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -191,6 +191,9 @@ int evfilt_read_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { + (void) filt; + (void) kn; + (void) kev; return (-1); /* STUB */ } diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index 067cd96aa..341c176b2 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -24,7 +24,7 @@ signalfd_reset(int sigfd) /* Discard any pending signal */ n = read(sigfd, &sig, sizeof(sig)); - if (n < sizeof(sig)) { + if (n < 0 || n != sizeof(sig)) { if (errno == EWOULDBLOCK) return; //FIXME: eintr? @@ -94,7 +94,7 @@ signalfd_create(int epfd, void *ptr, int signum) } int -evfilt_signal_copyout(struct kevent *dst, struct knote *src, void *unused) +evfilt_signal_copyout(struct kevent *dst, struct knote *src, void *x UNUSED) { int sigfd; @@ -128,8 +128,9 @@ evfilt_signal_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_signal_knote_modify(struct filter *filt, struct knote *kn, - const struct kevent *kev) +evfilt_signal_knote_modify(struct filter *filt UNUSED, + struct knote *kn UNUSED, + const struct kevent *kev UNUSED) { /* Nothing to do since the signal number does not change. */ diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 6b4d85e70..90fe1323e 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -20,7 +20,7 @@ static char * itimerspec_dump(struct itimerspec *ts) { - static char __thread buf[1024]; + static __thread char buf[1024]; snprintf(buf, sizeof(buf), "itimer: [ interval=%lu s %lu ns, next expire=%lu s %lu ns ]", @@ -73,7 +73,7 @@ evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr) timer has been trigered. */ n = read(src->data.pfd, &expired, sizeof(expired)); - if (n < 0 || n < sizeof(expired)) { + if (n != sizeof(expired)) { dbg_puts("invalid read from timerfd"); expired = 1; /* Fail gracefully */ } @@ -122,6 +122,9 @@ int evfilt_timer_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { + (void)filt; + (void)kn; + (void)kev; return (0); /* STUB */ } diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index 841510369..48f61819b 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -61,11 +61,13 @@ static int eventfd_lower(int evfd) { uint64_t cur; + ssize_t n; int rv = 0; /* Reset the counter */ dbg_puts("lowering event level"); - if (read(evfd, &cur, sizeof(cur)) < sizeof(cur)) { + n = read(evfd, &cur, sizeof(cur)); + if (n < 0) { switch (errno) { case EAGAIN: /* Not considered an error */ @@ -79,13 +81,16 @@ eventfd_lower(int evfd) dbg_printf("read(2): %s", strerror(errno)); rv = -1; } - } + } else if (n != sizeof(cur)) { + dbg_puts("short read"); + rv = -1; + } return (rv); } int -evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr) +evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) { memcpy(dst, &src->kev, sizeof(*dst)); dst->fflags &= ~NOTE_FFCTRLMASK; //FIXME: Not sure if needed @@ -140,7 +145,7 @@ evfilt_user_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_user_knote_modify(struct filter *filt, struct knote *kn, +evfilt_user_knote_modify(struct filter *filt UNUSED, struct knote *kn, const struct kevent *kev) { unsigned int ffctrl; diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 70f5d0a83..315ffbf8c 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -19,7 +19,7 @@ static char * inotify_mask_dump(uint32_t mask) { - static char __thread buf[1024]; + static __thread char buf[1024]; #define INEVT_MASK_DUMP(attrib) \ if (mask & attrib) \ @@ -46,7 +46,7 @@ inotify_mask_dump(uint32_t mask) static char * inotify_event_dump(struct inotify_event *evt) { - static char __thread buf[1024]; + static __thread char buf[1024]; snprintf(buf, sizeof(buf), "wd=%d mask=%s", evt->wd, @@ -165,7 +165,7 @@ delete_watch(struct filter *filt, struct knote *kn) } int -evfilt_vnode_copyout(struct kevent *dst, struct knote *src, void *ptr) +evfilt_vnode_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) { struct inotify_event evt; struct stat sb; @@ -241,6 +241,9 @@ int evfilt_vnode_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { + (void)filt; + (void)kn; + (void)kev; return (-1); /* FIXME - STUB */ } diff --git a/vendor/libkqueue/src/linux/write.c b/vendor/libkqueue/src/linux/write.c index 76bb7488f..4c95a678b 100644 --- a/vendor/libkqueue/src/linux/write.c +++ b/vendor/libkqueue/src/linux/write.c @@ -87,6 +87,9 @@ int evfilt_socket_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { + (void) filt; + (void) kn; + (void) kev; return (-1); /* STUB */ } diff --git a/vendor/libkqueue/src/posix/platform.c b/vendor/libkqueue/src/posix/platform.c index 660e9ce5d..d00686855 100644 --- a/vendor/libkqueue/src/posix/platform.c +++ b/vendor/libkqueue/src/posix/platform.c @@ -17,13 +17,13 @@ #include "../common/private.h" int -posix_kqueue_init(struct kqueue *kq) +posix_kqueue_init(struct kqueue *kq UNUSED) { return (0); } void -posix_kqueue_free(struct kqueue *kq) +posix_kqueue_free(struct kqueue *kq UNUSED) { } diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 5f8d45909..b1691719f 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -36,6 +36,9 @@ #define fastpath(x) __builtin_expect((x), 1) #define slowpath(x) __builtin_expect((x), 0) +/* + * GCC-compatible attributes + */ #ifdef MAKE_STATIC # define CONSTRUCTOR #else @@ -43,6 +46,7 @@ #endif #define VISIBLE __attribute__((visibility("default"))) #define HIDDEN __attribute__((visibility("hidden"))) +#define UNUSED __attribute__((unused)) #include #include From 7bd5e56d8c5de941507af1c29324e9c3d7d358e3 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 22 May 2011 00:57:44 +0000 Subject: [PATCH 0485/1120] Fix tracing_mutex_assert() by tracking the thread ID of the lock owner and behave properly when the mutex is held by another thread. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@514 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/debug.h | 11 ++++++++++- vendor/libkqueue/test/lockstat.c | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index 68eabe24c..8e20f9dd0 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -92,26 +92,35 @@ extern char *KQUEUE_DEBUG_IDENT; typedef struct { pthread_mutex_t mtx_lock; int mtx_status; + int mtx_owner; } tracing_mutex_t; # define tracing_mutex_init(mtx, attr) do { \ pthread_mutex_init(&(mtx)->mtx_lock, (attr)); \ (mtx)->mtx_status = MTX_UNLOCKED; \ + (mtx)->mtx_owner = -1; \ } while (0) # define tracing_mutex_destroy(mtx) pthread_mutex_destroy(&(mtx)->mtx_lock) -# define tracing_mutex_assert(x,y) assert((x)->mtx_status == (y)) +# define tracing_mutex_assert(x,y) do { \ + if ((y) == MTX_UNLOCKED) \ + assert((x)->mtx_status == MTX_UNLOCKED || (x)->mtx_owner != THREAD_ID); \ + else if ((y) == MTX_LOCKED) \ + assert((x)->mtx_status == MTX_LOCKED); \ +} while (0) # define tracing_mutex_lock(x) do { \ dbg_printf("waiting for %s", #x); \ pthread_mutex_lock(&((x)->mtx_lock)); \ dbg_printf("locked %s", #x); \ + (x)->mtx_owner = THREAD_ID; \ (x)->mtx_status = MTX_LOCKED; \ } while (0) # define tracing_mutex_unlock(x) do { \ (x)->mtx_status = MTX_UNLOCKED; \ + (x)->mtx_owner = -1; \ pthread_mutex_unlock(&((x)->mtx_lock)); \ dbg_printf("unlocked %s", # x); \ } while (0) diff --git a/vendor/libkqueue/test/lockstat.c b/vendor/libkqueue/test/lockstat.c index b0ac053cf..2ee3ff8a7 100644 --- a/vendor/libkqueue/test/lockstat.c +++ b/vendor/libkqueue/test/lockstat.c @@ -14,6 +14,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include #include "../src/common/private.h" int DEBUG_KQUEUE = 1; @@ -23,11 +25,20 @@ struct foo { tracing_mutex_t foo_lock; }; +void *test_assertion(void *_x) +{ + struct foo *x = (struct foo *) _x; + tracing_mutex_assert(&x->foo_lock, MTX_UNLOCKED); + pthread_exit(NULL); +} + /* * Test the lockstat.h API */ int main() { struct foo x; + pthread_t tid; + void *rv; tracing_mutex_init(&x.foo_lock, NULL); tracing_mutex_lock(&x.foo_lock); @@ -35,6 +46,16 @@ int main() { tracing_mutex_unlock(&x.foo_lock); tracing_mutex_assert(&x.foo_lock, MTX_UNLOCKED); + /* + * Ensure that the assert() function works when there + * are multiple threads contenting for the mutex. + */ + tracing_mutex_lock(&x.foo_lock); + if (pthread_create(&tid, NULL, test_assertion, &x) != 0) + err(1, "pthread_create"); + pthread_join(tid, &rv); + tracing_mutex_unlock(&x.foo_lock); + puts("+OK"); return (0); } From 18a74afec02727c6041b25b979095e131f490a55 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 22 May 2011 01:20:24 +0000 Subject: [PATCH 0486/1120] Another tracing_mutex_assert() fix git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@515 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/debug.h | 4 +++- vendor/libkqueue/test/lockstat.c | 22 ++++++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index 8e20f9dd0..168b5d2a9 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -107,7 +107,9 @@ typedef struct { if ((y) == MTX_UNLOCKED) \ assert((x)->mtx_status == MTX_UNLOCKED || (x)->mtx_owner != THREAD_ID); \ else if ((y) == MTX_LOCKED) \ - assert((x)->mtx_status == MTX_LOCKED); \ + assert((x)->mtx_status == MTX_LOCKED && (x)->mtx_owner == THREAD_ID); \ + else \ + abort(); \ } while (0) # define tracing_mutex_lock(x) do { \ diff --git a/vendor/libkqueue/test/lockstat.c b/vendor/libkqueue/test/lockstat.c index 2ee3ff8a7..6cd67ad39 100644 --- a/vendor/libkqueue/test/lockstat.c +++ b/vendor/libkqueue/test/lockstat.c @@ -25,11 +25,19 @@ struct foo { tracing_mutex_t foo_lock; }; -void *test_assertion(void *_x) +void *test_assert_unlocked(void *_x) { struct foo *x = (struct foo *) _x; - tracing_mutex_assert(&x->foo_lock, MTX_UNLOCKED); - pthread_exit(NULL); + tracing_mutex_assert(&x->foo_lock, MTX_UNLOCKED); + pthread_exit(NULL); +} + +void *test_assert_locked(void *_x) +{ + struct foo *x = (struct foo *) _x; + puts("The following assertion should fail"); + tracing_mutex_assert(&x->foo_lock, MTX_LOCKED); + pthread_exit(NULL); } /* @@ -51,8 +59,14 @@ int main() { * are multiple threads contenting for the mutex. */ tracing_mutex_lock(&x.foo_lock); - if (pthread_create(&tid, NULL, test_assertion, &x) != 0) + if (pthread_create(&tid, NULL, test_assert_unlocked, &x) != 0) + err(1, "pthread_create"); + pthread_join(tid, &rv); + tracing_mutex_unlock(&x.foo_lock); + tracing_mutex_lock(&x.foo_lock); + if (pthread_create(&tid, NULL, test_assert_locked, &x) != 0) err(1, "pthread_create"); + sleep(3); // Crude way to ensure the other thread is scheduled pthread_join(tid, &rv); tracing_mutex_unlock(&x.foo_lock); From ab79f2ede7ca5c4d38141b59b221dc0c899ad105 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 22 May 2011 02:44:16 +0000 Subject: [PATCH 0487/1120] - Build two versions of the library: one for debugging, and one for release. - Link kqtest against libkqueue_debug.so - Build git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@516 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 19 ++++++++++++------- vendor/libkqueue/src/linux/vnode.c | 3 +++ vendor/libkqueue/test/config.inc | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 920325342..8e42e591c 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -22,20 +22,25 @@ include config.mk .PHONY :: install uninstall check dist dist-upload clean merge distclean fresh-build rpm edit cscope -all: $(PROGRAM).so.$(ABI_VERSION) +all: $(PROGRAM).so.$(ABI_VERSION) $(PROGRAM)_debug.so $(PROGRAM).a %.o: %.c $(DEPS) - $(CC) -c -o $@ -I./include -I./src/common $(CFLAGS) $< + $(CC) -c -o $@ -I./include -I./src/common -DNDEBUG $(CFLAGS) $< $(PROGRAM).a: $(OBJS) $(AR) rcs $(PROGRAM).a $(OBJS) + strip --strip-unneeded $(PROGRAM).a $(PROGRAM).so.$(ABI_VERSION): $(OBJS) - $(LD) -shared $(LDFLAGS) $(OBJS) $(LDADD) + $(CC) -o $@ -I./include -I./src/common -shared $(LDFLAGS) -DNDEBUG $(CFLAGS) $(SOURCES) $(LDADD) + strip --strip-unneeded $(PROGRAM).so.$(ABI_VERSION) $(LN) -sf $(PROGRAM).so.$(ABI_VERSION) $(PROGRAM).so.$(ABI_MAJOR) $(LN) -sf $(PROGRAM).so.$(ABI_VERSION) $(PROGRAM).so -install: $(PROGRAM).so.$(ABI_VERSION) +$(PROGRAM)_debug.so: + $(CC) -o $@ -I./include -I./src/common -shared $(CFLAGS) -O0 $(SOURCES) $(LDADD) + +install: all $(INSTALL) -d -m 755 $(INCLUDEDIR)/kqueue/sys $(INSTALL) -m 644 include/sys/event.h $(INCLUDEDIR)/kqueue/sys/event.h $(INSTALL) -d -m 755 $(LIBDIR) @@ -43,7 +48,7 @@ install: $(PROGRAM).so.$(ABI_VERSION) $(INSTALL) -m 644 $(PROGRAM).so.$(ABI_MAJOR) $(LIBDIR) $(LN) -sf $(PROGRAM).so.$(ABI_VERSION) $(LIBDIR)/$(PROGRAM).so.$(ABI_MAJOR) $(LN) -sf $(PROGRAM).so.$(ABI_VERSION) $(LIBDIR)/$(PROGRAM).so - $(INSTALL) -m 644 $(PROGRAM).la $(LIBDIR) + $(INSTALL) -m 644 $(PROGRAM)_debug.so $(LIBDIR) $(INSTALL) -d -m 755 $(LIBDIR)/pkgconfig $(INSTALL) -m 644 libkqueue.pc $(LIBDIR)/pkgconfig $(INSTALL) -d -m 755 $(MANDIR)/man2 @@ -61,10 +66,10 @@ uninstall: test/config.mk: cd test && ../configure -check: clean $(PROGRAM).so.$(ABI_VERSION) test/config.mk +check: clean all test/config.mk cd test && make check -debug: clean $(PROGRAM).so.$(ABI_VERSION) test/config.mk +debug: clean all test/config.mk cd test && make debug debug-check: clean test/config.mk diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 315ffbf8c..69434675d 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -16,6 +16,7 @@ #include "private.h" +#ifndef NDEBUG static char * inotify_mask_dump(uint32_t mask) { @@ -55,6 +56,8 @@ inotify_event_dump(struct inotify_event *evt) return (buf); } +#endif /* !NDEBUG */ + /* TODO: USE this to get events with name field */ int diff --git a/vendor/libkqueue/test/config.inc b/vendor/libkqueue/test/config.inc index e124b1919..ea5360fec 100755 --- a/vendor/libkqueue/test/config.inc +++ b/vendor/libkqueue/test/config.inc @@ -17,7 +17,7 @@ pre_configure_hook() { then ldadd="$ldadd ../libkqueue.so" else - ldadd="$ldadd -lkqueue -lpthread -lrt" + ldadd="$ldadd -lkqueue_debug -lpthread -lrt" fi } From 61a248296f155b600a60273c7de49b1d56b10b8c Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 22 May 2011 03:01:24 +0000 Subject: [PATCH 0488/1120] - Build the static library with MAKE_STATIC to expose libkqueue_init(). - Build a statically-linked version of kqtest during 'make check'. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@517 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 7 +++++-- vendor/libkqueue/test/Makefile | 9 +++++++-- vendor/libkqueue/test/main.c | 3 +++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index 8e42e591c..d6bc875c4 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -27,9 +27,12 @@ all: $(PROGRAM).so.$(ABI_VERSION) $(PROGRAM)_debug.so $(PROGRAM).a %.o: %.c $(DEPS) $(CC) -c -o $@ -I./include -I./src/common -DNDEBUG $(CFLAGS) $< -$(PROGRAM).a: $(OBJS) - $(AR) rcs $(PROGRAM).a $(OBJS) +$(PROGRAM).a: + rm -f *.o + $(CC) -c -I./include -I./src/common -DNDEBUG -DMAKE_STATIC=1 -static $(CFLAGS) $(SOURCES) $(LDADD) + $(AR) rcs $(PROGRAM).a *.o strip --strip-unneeded $(PROGRAM).a + rm *.o $(PROGRAM).so.$(ABI_VERSION): $(OBJS) $(CC) -o $@ -I./include -I./src/common -shared $(LDFLAGS) -DNDEBUG $(CFLAGS) $(SOURCES) $(LDADD) diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile index d1cfbdac1..375dd8a21 100644 --- a/vendor/libkqueue/test/Makefile +++ b/vendor/libkqueue/test/Makefile @@ -14,9 +14,11 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # +tests=kqtest lockstat static-lib-test + include config.mk -all: kqtest lockstat +all: $(tests) lockstat: lockstat.c $(CC) -o lockstat $(CFLAGS) lockstat.c $(LDADD) @@ -24,6 +26,9 @@ lockstat: lockstat.c kqtest: $(SOURCES) $(CC) -o kqtest $(CFLAGS) $(SOURCES) $(LDADD) +static-lib-test: $(SOURCES) + $(CC) -o static-lib-test -DMAKE_STATIC=1 $(CFLAGS) $(SOURCES) ../libkqueue.a -lpthread + check: kqtest LD_LIBRARY_PATH="..:/usr/sfw/lib/64" PATH="$$PATH:.." ./kqtest @@ -59,5 +64,5 @@ edit: $(EDITOR) *.[ch] clean: - rm -f *.o *.a kqtest lockstat + rm -f *.o *.a $(tests) for x in libdispatch stress; do cd $$x && make clean && cd ..; done diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 1f1c7b7d1..2ad479c64 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -149,6 +149,9 @@ main(int argc, char **argv) char *arg; int match, kqfd; +#ifdef MAKE_STATIC + libkqueue_init(); +#endif #ifdef _WIN32 /* Initialize the Winsock library */ From f72e7b60858ef3288e1e3de7f2b635a4942d948b Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 22 May 2011 03:29:14 +0000 Subject: [PATCH 0489/1120] Fix compilation issues on Solaris 10 with GCC 4.5 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@518 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 4 +- vendor/libkqueue/configure | 13 +++++- vendor/libkqueue/src/common/debug.h | 2 +- vendor/libkqueue/src/solaris/platform.c | 62 +++++++++++++------------ vendor/libkqueue/src/solaris/signal.c | 6 +-- vendor/libkqueue/src/solaris/socket.c | 3 ++ vendor/libkqueue/src/solaris/timer.c | 13 ++++-- vendor/libkqueue/src/solaris/user.c | 10 ++-- 8 files changed, 66 insertions(+), 47 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index d6bc875c4..f452e20a6 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -31,12 +31,12 @@ $(PROGRAM).a: rm -f *.o $(CC) -c -I./include -I./src/common -DNDEBUG -DMAKE_STATIC=1 -static $(CFLAGS) $(SOURCES) $(LDADD) $(AR) rcs $(PROGRAM).a *.o - strip --strip-unneeded $(PROGRAM).a + $(STRIP) $(PROGRAM).a rm *.o $(PROGRAM).so.$(ABI_VERSION): $(OBJS) $(CC) -o $@ -I./include -I./src/common -shared $(LDFLAGS) -DNDEBUG $(CFLAGS) $(SOURCES) $(LDADD) - strip --strip-unneeded $(PROGRAM).so.$(ABI_VERSION) + $(STRIP) $(PROGRAM).so.$(ABI_VERSION) $(LN) -sf $(PROGRAM).so.$(ABI_VERSION) $(PROGRAM).so.$(ABI_MAJOR) $(LN) -sf $(PROGRAM).so.$(ABI_VERSION) $(PROGRAM).so diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index 7db442928..c6860a847 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -24,7 +24,7 @@ make_exports="program version target api distfile \ cflags ldflags ldadd libdepends \ sources objs deps mans headers extra_dist subdirs \ abi_major abi_minor abi_version \ - cc cpp ld ln ar install diff" + cc cpp ld ln ar install diff strip" required_headers= optional_headers= @@ -252,6 +252,16 @@ check_diff() { echo "found" } +check_strip() { + printf "checking for a suitable strip(1) command.. " + if [ "`uname -s`" = "SunOS" ] ; then + finalize strip "/usr/sfw/bin/gstrip --strip-unneeded" + else + finalize strip "/usr/bin/strip --strip-unneeded" + fi + echo "found" +} + subst_vars() { outfile=$1 @@ -312,6 +322,7 @@ check_linker check_archiver check_install check_diff +check_strip finalize program "$program" finalize version "$version" diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index 168b5d2a9..1d1aa4f95 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -32,7 +32,7 @@ extern char *KQUEUE_DEBUG_IDENT; # include # define THREAD_ID ((pid_t) syscall(__NR_gettid)) #elif defined(__sun) -# define THREAD_ID (pthread_self()) +# define THREAD_ID ((int) pthread_self()) #elif defined(_WIN32) # define THREAD_ID (int)(GetCurrentThreadId()) #else diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index 9930c6ca7..bbaa1a64a 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -19,43 +19,19 @@ const struct filter evfilt_vnode = EVFILT_NOTIMPL; const struct filter evfilt_proc = EVFILT_NOTIMPL; -static char * port_event_dump(port_event_t *evt); - /* * Per-thread port event buffer used to ferry data between * kevent_wait() and kevent_copyout(). */ -static port_event_t __thread evbuf[MAX_KEVENT]; +static __thread port_event_t evbuf[MAX_KEVENT]; -int -solaris_kqueue_init(struct kqueue *kq) -{ - if ((kq->kq_id = port_create()) < 0) { - dbg_perror("port_create(2)"); - return (-1); - } - dbg_printf("created event port; fd=%d", kq->kq_id); - - if (filter_register_all(kq) < 0) { - close(kq->kq_id); - return (-1); - } - - return (0); -} - -void -solaris_kqueue_free(struct kqueue *kq) -{ - (void) close(kq->kq_id); - dbg_printf("closed event port; fd=%d", kq->kq_id); -} +#ifndef NDEBUG /* Dump a poll(2) events bitmask */ static char * poll_events_dump(short events) { - static char __thread buf[512]; + static __thread char buf[512]; #define _PL_DUMP(attrib) \ if (events == attrib) \ @@ -81,7 +57,7 @@ poll_events_dump(short events) static char * port_event_dump(port_event_t *evt) { - static char __thread buf[512]; + static __thread char buf[512]; if (evt == NULL) { snprintf(&buf[0], sizeof(buf), "NULL ?!?!\n"); @@ -110,10 +86,36 @@ port_event_dump(port_event_t *evt) return (&buf[0]); } +#endif /* !NDEBUG */ + +int +solaris_kqueue_init(struct kqueue *kq) +{ + if ((kq->kq_id = port_create()) < 0) { + dbg_perror("port_create(2)"); + return (-1); + } + dbg_printf("created event port; fd=%d", kq->kq_id); + + if (filter_register_all(kq) < 0) { + close(kq->kq_id); + return (-1); + } + + return (0); +} + +void +solaris_kqueue_free(struct kqueue *kq) +{ + (void) close(kq->kq_id); + dbg_printf("closed event port; fd=%d", kq->kq_id); +} + int solaris_kevent_wait( struct kqueue *kq, - int nevents, + int nevents UNUSED, const struct timespec *ts) { @@ -143,7 +145,7 @@ solaris_kevent_wait( int solaris_kevent_copyout(struct kqueue *kq, int nready, - struct kevent *eventlist, int nevents) + struct kevent *eventlist, int nevents UNUSED) { port_event_t *evt; struct knote *kn; diff --git a/vendor/libkqueue/src/solaris/signal.c b/vendor/libkqueue/src/solaris/signal.c index 88cf93d26..e973e842f 100644 --- a/vendor/libkqueue/src/solaris/signal.c +++ b/vendor/libkqueue/src/solaris/signal.c @@ -108,7 +108,7 @@ evfilt_signal_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_signal_knote_modify(struct filter *filt, struct knote *kn, +evfilt_signal_knote_modify(struct filter *filt UNUSED, struct knote *kn, const struct kevent *kev) { kn->kev.flags = kev->flags | EV_CLEAR; @@ -116,7 +116,7 @@ evfilt_signal_knote_modify(struct filter *filt, struct knote *kn, } int -evfilt_signal_knote_delete(struct filter *filt, struct knote *kn) +evfilt_signal_knote_delete(struct filter *filt UNUSED, struct knote *kn) { return ignore_signal(kn->kev.ident); } @@ -128,7 +128,7 @@ evfilt_signal_knote_enable(struct filter *filt, struct knote *kn) } int -evfilt_signal_knote_disable(struct filter *filt, struct knote *kn) +evfilt_signal_knote_disable(struct filter *filt UNUSED, struct knote *kn) { return ignore_signal(kn->kev.ident); } diff --git a/vendor/libkqueue/src/solaris/socket.c b/vendor/libkqueue/src/solaris/socket.c index 5b6533aee..83f8f4b40 100644 --- a/vendor/libkqueue/src/solaris/socket.c +++ b/vendor/libkqueue/src/solaris/socket.c @@ -65,6 +65,9 @@ evfilt_socket_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { dbg_puts("XXX-FIXME"); + (void)filt; + (void)kn; + (void)kev; return (-1); /* STUB */ } diff --git a/vendor/libkqueue/src/solaris/timer.c b/vendor/libkqueue/src/solaris/timer.c index 3c854d63b..e0895bfe3 100644 --- a/vendor/libkqueue/src/solaris/timer.c +++ b/vendor/libkqueue/src/solaris/timer.c @@ -34,7 +34,7 @@ static char * itimerspec_dump(struct itimerspec *ts) { - static char __thread buf[1024]; + static __thread char buf[1024]; snprintf(buf, sizeof(buf), "itimer: [ interval=%lu s %lu ns, next expire=%lu s %lu ns ]", @@ -73,19 +73,19 @@ convert_msec_to_itimerspec(struct itimerspec *dst, int src, int oneshot) } int -evfilt_timer_init(struct filter *filt) +evfilt_timer_init(struct filter *filt UNUSED) { return (0); } void -evfilt_timer_destroy(struct filter *filt) +evfilt_timer_destroy(struct filter *filt UNUSED) { return; } int -evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr) +evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) { /* port_event_t *pe = (port_event_t *) ptr; */ @@ -147,11 +147,14 @@ int evfilt_timer_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { + (void)filt; + (void)kn; + (void)kev; return (-1); /* STUB */ } int -evfilt_timer_knote_delete(struct filter *filt, struct knote *kn) +evfilt_timer_knote_delete(struct filter *filt UNUSED, struct knote *kn) { if (kn->kev.flags & EV_DISABLE) return (0); diff --git a/vendor/libkqueue/src/solaris/user.c b/vendor/libkqueue/src/solaris/user.c index 632ffd821..c3ee163dd 100644 --- a/vendor/libkqueue/src/solaris/user.c +++ b/vendor/libkqueue/src/solaris/user.c @@ -17,7 +17,7 @@ #include "private.h" int -evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr) +evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) { //port_event_t *pe = (port_event_t *) ptr; @@ -49,7 +49,7 @@ evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr) int -evfilt_user_knote_create(struct filter *filt, struct knote *kn) +evfilt_user_knote_create(struct filter *filt UNUSED, struct knote *kn UNUSED) { #if TODO u_int ffctrl; @@ -104,13 +104,13 @@ evfilt_user_knote_modify(struct filter *filt, struct knote *kn, } int -evfilt_user_knote_delete(struct filter *filt, struct knote *kn) +evfilt_user_knote_delete(struct filter *filt UNUSED, struct knote *kn UNUSED) { return (0); } int -evfilt_user_knote_enable(struct filter *filt, struct knote *kn) +evfilt_user_knote_enable(struct filter *filt UNUSED, struct knote *kn UNUSED) { /* FIXME: what happens if NOTE_TRIGGER is in fflags? should the event fire? */ @@ -118,7 +118,7 @@ evfilt_user_knote_enable(struct filter *filt, struct knote *kn) } int -evfilt_user_knote_disable(struct filter *filt, struct knote *kn) +evfilt_user_knote_disable(struct filter *filt UNUSED, struct knote *kn UNUSED) { return (0); } From 79987f9197f4ba2b714038820f54cbaf4fa45d53 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 25 May 2011 02:10:36 +0000 Subject: [PATCH 0490/1120] Eliminate the use of global state variables in kqtest to allow the tests to be run in parallel. Add two kqtest options: one for iterations, and one for concurrency. Use -rpath when building kqtest instead of using LD_LIBRARY_PATH git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@519 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 2 +- vendor/libkqueue/test/Makefile | 6 +- vendor/libkqueue/test/common.h | 48 ++++-- vendor/libkqueue/test/config.inc | 2 +- vendor/libkqueue/test/kevent.c | 22 ++- vendor/libkqueue/test/main.c | 146 +++++++++++----- vendor/libkqueue/test/proc.c | 29 ++-- vendor/libkqueue/test/read.c | 285 ++++++++++++++++--------------- vendor/libkqueue/test/signal.c | 107 ++++++------ vendor/libkqueue/test/timer.c | 110 ++++++------ vendor/libkqueue/test/user.c | 124 +++++++------- vendor/libkqueue/test/vnode.c | 160 +++++++++-------- 12 files changed, 571 insertions(+), 470 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index f452e20a6..a439a0516 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -41,7 +41,7 @@ $(PROGRAM).so.$(ABI_VERSION): $(OBJS) $(LN) -sf $(PROGRAM).so.$(ABI_VERSION) $(PROGRAM).so $(PROGRAM)_debug.so: - $(CC) -o $@ -I./include -I./src/common -shared $(CFLAGS) -O0 $(SOURCES) $(LDADD) + $(CC) -o $@ -I./include -I./src/common -shared -rdynamic $(CFLAGS) -g3 -O0 $(SOURCES) $(LDADD) install: all $(INSTALL) -d -m 755 $(INCLUDEDIR)/kqueue/sys diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile index 375dd8a21..30ec63801 100644 --- a/vendor/libkqueue/test/Makefile +++ b/vendor/libkqueue/test/Makefile @@ -24,16 +24,16 @@ lockstat: lockstat.c $(CC) -o lockstat $(CFLAGS) lockstat.c $(LDADD) kqtest: $(SOURCES) - $(CC) -o kqtest $(CFLAGS) $(SOURCES) $(LDADD) + $(CC) -rdynamic -o kqtest $(CFLAGS) $(SOURCES) $(LDADD) static-lib-test: $(SOURCES) $(CC) -o static-lib-test -DMAKE_STATIC=1 $(CFLAGS) $(SOURCES) ../libkqueue.a -lpthread check: kqtest - LD_LIBRARY_PATH="..:/usr/sfw/lib/64" PATH="$$PATH:.." ./kqtest + LD_LIBRARY_PATH="..:/usr/sfw/lib/64" PATH="$$PATH:.." ./kqtest $(KQTEST_OPTS) debug: kqtest - LD_LIBRARY_PATH="..:/usr/sfw/lib/64" PATH="$$PATH:.." gdb ./kqtest + LD_LIBRARY_PATH="..:/usr/sfw/lib/64" PATH="$$PATH:.." gdb ./kqtest $(KQTEST_OPTS) valgrind: kqtest LD_LIBRARY_PATH="..:/usr/sfw/lib/64" \ diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 081d1d632..61006952e 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -46,6 +46,7 @@ #include #include #include +#include #include #include "config.h" #else @@ -54,27 +55,48 @@ # define HAVE_EVFILT_USER 1 #endif - -void test_evfilt_read(int); -void test_evfilt_signal(int); -void test_evfilt_vnode(int); -void test_evfilt_timer(int); -void test_evfilt_proc(int); +struct test_context; + +struct unit_test { + const char *ut_name; + int ut_enabled; + void (*ut_func)(struct test_context *); +}; + +struct test_context { + struct unit_test tests[50]; //TODO: use MAX_TESTS instead of magic number + int iterations; + int concurrency; + int iteration; + int kqfd; + + /* EVFILT_READ and EVFILT_WRITE */ + int client_fd; + int server_fd; + + /* EVFILT_VNODE */ + int vnode_fd; + char testfile[1024]; +}; + +void test_evfilt_read(struct test_context *); +void test_evfilt_signal(struct test_context *); +void test_evfilt_vnode(struct test_context *); +void test_evfilt_timer(struct test_context *); +void test_evfilt_proc(struct test_context *); #if HAVE_EVFILT_USER -void test_evfilt_user(int); +void test_evfilt_user(struct test_context *); #endif -#define test(f,...) do { \ +#define test(f,ctx,...) do { \ test_begin("test_"#f"()\t"__VA_ARGS__); \ - test_##f();\ + test_##f(ctx);\ test_end(); \ } while (/*CONSTCOND*/0) extern const char * kevent_to_str(struct kevent *); -struct kevent * kevent_get(int); -struct kevent * kevent_get_hires(int); - - +void kevent_get(struct kevent *, int); +void kevent_get_hires(struct kevent *, int); void kevent_update(int kqfd, struct kevent *kev); #define kevent_cmp(a,b) _kevent_cmp(a,b, __FILE__, __LINE__) diff --git a/vendor/libkqueue/test/config.inc b/vendor/libkqueue/test/config.inc index ea5360fec..72d30b716 100755 --- a/vendor/libkqueue/test/config.inc +++ b/vendor/libkqueue/test/config.inc @@ -2,7 +2,7 @@ program=libkqueue-test version=0.1 -cflags="-g -O0 -Wall -Werror" +cflags="-g -O0 -Wall -Werror -Wl,-rpath,.." sources="main.c kevent.c test.c proc.c read.c signal.c timer.c vnode.c" pre_configure_hook() { diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index 6441ecd4d..ff60932d4 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -37,37 +37,35 @@ _test_no_kevents(int kqfd, const char *file, int line) } /* Retrieve a single kevent */ -struct kevent * -kevent_get(int kqfd) +void +kevent_get(struct kevent *kev, int kqfd) { + struct kevent buf; int nfds; - static struct kevent __thread kev; - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + if (kev == NULL) + kev = &buf; + + nfds = kevent(kqfd, NULL, 0, kev, 1, NULL); if (nfds < 1) err(1, "kevent(2)"); - - return (&kev); } /* In Linux, a kevent() call with less than 1ms resolution will perform a pselect() call to obtain the higer resolution. This test exercises that codepath. */ -struct kevent * -kevent_get_hires(int kqfd) +void +kevent_get_hires(struct kevent *kev, int kqfd) { int nfds; struct timespec timeo; - static struct kevent __thread kev; timeo.tv_sec = 0; timeo.tv_nsec = 500000; - nfds = kevent(kqfd, NULL, 0, &kev, 1, &timeo); + nfds = kevent(kqfd, NULL, 0, kev, 1, &timeo); if (nfds < 1) die("kevent(2)"); - - return (&kev); } char * diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 2ad479c64..03cc49c03 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -16,12 +16,8 @@ #include "common.h" -struct unit_test { - const char *ut_name; - int ut_enabled; - void (*ut_func)(int); -}; - +/* Maximum number of threads that can be created */ +#define MAX_THREADS 100 void test_kqueue_descriptor_is_pollable(void) @@ -59,7 +55,7 @@ test_kqueue_descriptor_is_pollable(void) * has been closed. This technique is used in kqueue_validate() */ static void -test_peer_close_detection(void) +test_peer_close_detection(void *unused) { #ifdef _WIN32 return; @@ -90,7 +86,7 @@ test_peer_close_detection(void) } void -test_kqueue(void) +test_kqueue(void *unused) { int kqfd; @@ -102,7 +98,7 @@ test_kqueue(void) } void -test_ev_receipt(void) +test_ev_receipt(void *unused) { int kq; struct kevent kev; @@ -124,14 +120,91 @@ test_ev_receipt(void) #endif } +void +run_iteration(struct test_context *ctx) +{ + struct unit_test *test; + + for (test = &ctx->tests[0]; test->ut_name != NULL; test++) { + if (test->ut_enabled) + test->ut_func(ctx); + } + free(ctx); +} + +void +test_harness(struct unit_test tests[], int iterations, int concurrency) +{ + int i, j, n, kqfd; + pthread_t tid[MAX_THREADS]; + struct test_context *ctx; + int rv; + + if (concurrency >= MAX_THREADS) + errx(1, "Too many threads"); + + printf("Running %d iterations using %d worker threads\n", + iterations, concurrency); + + testing_begin(); + + test(peer_close_detection, NULL); + + test(kqueue, NULL); + + if ((kqfd = kqueue()) < 0) + die("kqueue()"); + + test(ev_receipt, NULL); + /* TODO: this fails now, but would be good later + test(kqueue_descriptor_is_pollable); + */ + + n = 0; + for (i = 0; i < iterations; i++) { + for (j = 0; j < concurrency; j++) { + /* Create a unique context object for each thread */ + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) + abort(); + ctx->iteration = n++; + ctx->kqfd = kqfd; + memcpy(&ctx->tests, tests, sizeof(ctx->tests)); //FIXME: invalid read + ctx->iterations = iterations; + ctx->concurrency = concurrency; + + rv = pthread_create(&tid[j], NULL, (void * (*)(void *)) run_iteration, ctx); + if (rv != 0) + err(1, "pthread_create"); + } + for (j = 0; j < concurrency; j++) { + pthread_join(tid[j], NULL); + } + } + testing_end(); + + close(kqfd); +} + +void +usage(void) +{ + printf("usage:\n" + " -h This message\n" + " -n Number of iterations (default: 1)\n" + " -c Number of threads running concurrently (default: 1)\n" + "\n\n" + ); + exit(1); +} + int main(int argc, char **argv) { struct unit_test tests[] = { { "socket", 1, test_evfilt_read }, #ifndef _WIN32 - - { "signal", 1, test_evfilt_signal }, + { "signal", 0, test_evfilt_signal }, #endif #if FIXME { "proc", 1, test_evfilt_proc }, @@ -146,8 +219,9 @@ main(int argc, char **argv) { NULL, 0, NULL }, }; struct unit_test *test; + int c, i, concurrency, iterations; char *arg; - int match, kqfd; + int match; #ifdef MAKE_STATIC libkqueue_init(); @@ -160,16 +234,33 @@ main(int argc, char **argv) err(1, "WSAStartup failed"); #endif + iterations = 1; + concurrency = 1; + while ((c = getopt (argc, argv, "hc:n:")) != -1) { + switch (c) { + case 'c': + concurrency = atoi(optarg); + break; + case 'h': + usage(); + break; + case 'n': + iterations = atoi(optarg); + break; + default: + usage(); + } + } + /* If specific tests are requested, disable all tests by default */ - if (argc > 1) { + if (optind < argc) { for (test = &tests[0]; test->ut_name != NULL; test++) { test->ut_enabled = 0; } } - - while (argc > 1) { + for (i = optind; i < argc; i++) { match = 0; - arg = argv[1]; + arg = argv[i]; for (test = &tests[0]; test->ut_name != NULL; test++) { if (strcmp(arg, test->ut_name) == 0) { test->ut_enabled = 1; @@ -183,30 +274,9 @@ main(int argc, char **argv) } else { printf("enabled test: %s\n", arg); } - argv++; - argc--; } - testing_begin(); - - test(peer_close_detection); - - test(kqueue); - - if ((kqfd = kqueue()) < 0) - die("kqueue()"); - - for (test = &tests[0]; test->ut_name != NULL; test++) { - if (test->ut_enabled) - test->ut_func(kqfd); - } - - test(ev_receipt); - /* TODO: this fails now, but would be good later - test(kqueue_descriptor_is_pollable); - */ - - testing_end(); + test_harness(tests, iterations, concurrency); return (0); } diff --git a/vendor/libkqueue/test/proc.c b/vendor/libkqueue/test/proc.c index eae913d1a..8c0a23f34 100644 --- a/vendor/libkqueue/test/proc.c +++ b/vendor/libkqueue/test/proc.c @@ -27,7 +27,7 @@ sig_handler(int signum) } static void -test_kevent_proc_add(void) +test_kevent_proc_add(struct test_context *ctx) { struct kevent kev; @@ -37,7 +37,7 @@ test_kevent_proc_add(void) } static void -test_kevent_proc_delete(void) +test_kevent_proc_delete(struct test_context *ctx) { struct kevent kev; @@ -50,9 +50,9 @@ test_kevent_proc_delete(void) } static void -test_kevent_proc_get(void) +test_kevent_proc_get(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, buf; /* Create a child that waits to be killed and then exits */ pid = fork(); @@ -70,13 +70,14 @@ test_kevent_proc_get(void) printf(" -- killing process %d\n", (int) pid); if (kill(pid, SIGUSR1) < 0) die("kill"); - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&buf, kqfd); + kevent_cmp(&kev, &buf); test_no_kevents(kqfd); } #ifdef TODO void -test_kevent_signal_disable(void) +test_kevent_signal_disable(struct test_context *ctx) { const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)"; struct kevent kev; @@ -102,7 +103,7 @@ test_kevent_signal_disable(void) } void -test_kevent_signal_enable(void) +test_kevent_signal_enable(struct test_context *ctx) { const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)"; struct kevent kev; @@ -139,7 +140,7 @@ test_kevent_signal_enable(void) } void -test_kevent_signal_del(void) +test_kevent_signal_del(struct test_context *ctx) { const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)"; struct kevent kev; @@ -165,7 +166,7 @@ test_kevent_signal_del(void) } void -test_kevent_signal_oneshot(void) +test_kevent_signal_oneshot(struct test_context *ctx) { const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)"; struct kevent kev; @@ -199,10 +200,8 @@ test_kevent_signal_oneshot(void) #endif void -test_evfilt_proc(int _kqfd) +test_evfilt_proc(struct test_context *ctx) { - kqfd = _kqfd; - signal(SIGUSR1, sig_handler); /* Create a child that waits to be killed and then exits */ @@ -213,9 +212,9 @@ test_evfilt_proc(int _kqfd) } printf(" -- child created (pid %d)\n", (int) pid); - test(kevent_proc_add); - test(kevent_proc_delete); - test(kevent_proc_get); + test(kevent_proc_add, ctx); + test(kevent_proc_delete, ctx); + test(kevent_proc_get, ctx); signal(SIGUSR1, SIG_DFL); diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index c2444f2bf..f88ebc420 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -17,9 +17,6 @@ #include "common.h" -static int __thread kqfd; -static int __thread client_fd; -static int __thread server_fd; /* * Create a connected TCP socket. @@ -41,8 +38,10 @@ create_socket_connection(int *client, int *server, const short port) if (setsockopt(srvr, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one)) != 0) err(1, "setsockopt"); - if (bind(srvr, (struct sockaddr *) &sain, sa_len) < 0) - err(1, "bind"); + if (bind(srvr, (struct sockaddr *) &sain, sa_len) < 0) { + printf("unable to bind to port %d\n", port); + err(1, "bind-1"); + } if (listen(srvr, 100) < 0) err(1, "listen"); @@ -62,87 +61,88 @@ create_socket_connection(int *client, int *server, const short port) } static void -kevent_socket_drain(void) +kevent_socket_drain(struct test_context *ctx) { char buf[1]; /* Drain the read buffer, then make sure there are no more events. */ - if (recv(client_fd, &buf[0], 1, 0) < 1) + if (recv(ctx->client_fd, &buf[0], 1, 0) < 1) die("recv(2)"); } static void -kevent_socket_fill(void) +kevent_socket_fill(struct test_context *ctx) { - if (send(server_fd, ".", 1, 0) < 1) + if (send(ctx->server_fd, ".", 1, 0) < 1) die("send(2)"); } void -test_kevent_socket_add(void) +test_kevent_socket_add(struct test_context *ctx) { struct kevent kev; - kevent_add(kqfd, &kev, client_fd, EVFILT_READ, EV_ADD, 0, 0, &client_fd); + kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD, 0, 0, &ctx->client_fd); } void -test_kevent_socket_add_without_ev_add(void) +test_kevent_socket_add_without_ev_add(struct test_context *ctx) { struct kevent kev; /* Try to add a kevent without specifying EV_ADD */ - EV_SET(&kev, client_fd, EVFILT_READ, 0, 0, 0, &client_fd); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0) + EV_SET(&kev, ctx->client_fd, EVFILT_READ, 0, 0, 0, &ctx->client_fd); + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) == 0) die("kevent should have failed"); - kevent_socket_fill(); - test_no_kevents(kqfd); - kevent_socket_drain(); + kevent_socket_fill(ctx); + test_no_kevents(ctx->kqfd); + kevent_socket_drain(ctx); /* Try to delete a kevent which does not exist */ kev.flags = EV_DELETE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0) + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) == 0) die("kevent should have failed"); } void -test_kevent_socket_get(void) +test_kevent_socket_get(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; - EV_SET(&kev, client_fd, EVFILT_READ, EV_ADD, 0, 0, &client_fd); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + EV_SET(&kev, ctx->client_fd, EVFILT_READ, EV_ADD, 0, 0, &ctx->client_fd); + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent:1"); - kevent_socket_fill(); + kevent_socket_fill(ctx); kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); - kevent_socket_drain(); - test_no_kevents(kqfd); + kevent_socket_drain(ctx); + test_no_kevents(ctx->kqfd); kev.flags = EV_DELETE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent:2"); } void -test_kevent_socket_clear(void) +test_kevent_socket_clear(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; - test_no_kevents(kqfd); - kevent_socket_drain(); + test_no_kevents(ctx->kqfd); + kevent_socket_drain(ctx); - EV_SET(&kev, client_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &client_fd); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + EV_SET(&kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &ctx->client_fd); + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent1"); - kevent_socket_fill(); - kevent_socket_fill(); + kevent_socket_fill(ctx); + kevent_socket_fill(ctx); /* Solaris does not offer a way to get the amount of data pending */ #if defined(__sun__) @@ -150,88 +150,91 @@ test_kevent_socket_clear(void) #else kev.data = 2; #endif - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); /* We filled twice, but drain once. Edge-triggered would not generate additional events. */ - kevent_socket_drain(); - test_no_kevents(kqfd); + kevent_socket_drain(ctx); + test_no_kevents(ctx->kqfd); - kevent_socket_drain(); - EV_SET(&kev, client_fd, EVFILT_READ, EV_DELETE, 0, 0, &client_fd); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + kevent_socket_drain(ctx); + EV_SET(&kev, ctx->client_fd, EVFILT_READ, EV_DELETE, 0, 0, &ctx->client_fd); + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent2"); } void -test_kevent_socket_disable_and_enable(void) +test_kevent_socket_disable_and_enable(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; /* Add an event, then disable it. */ - EV_SET(&kev, client_fd, EVFILT_READ, EV_ADD, 0, 0, &client_fd); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + EV_SET(&kev, ctx->client_fd, EVFILT_READ, EV_ADD, 0, 0, &ctx->client_fd); + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent"); - EV_SET(&kev, client_fd, EVFILT_READ, EV_DISABLE, 0, 0, &client_fd); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + EV_SET(&kev, ctx->client_fd, EVFILT_READ, EV_DISABLE, 0, 0, &ctx->client_fd); + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent"); - kevent_socket_fill(); - test_no_kevents(kqfd); + kevent_socket_fill(ctx); + test_no_kevents(ctx->kqfd); /* Re-enable the knote, then see if an event is generated */ kev.flags = EV_ENABLE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent"); kev.flags = EV_ADD; kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); - kevent_socket_drain(); + kevent_socket_drain(ctx); kev.flags = EV_DELETE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent"); } void -test_kevent_socket_del(void) +test_kevent_socket_del(struct test_context *ctx) { struct kevent kev; - EV_SET(&kev, client_fd, EVFILT_READ, EV_DELETE, 0, 0, &client_fd); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + EV_SET(&kev, ctx->client_fd, EVFILT_READ, EV_DELETE, 0, 0, &ctx->client_fd); + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent"); - kevent_socket_fill(); - test_no_kevents(kqfd); - kevent_socket_drain(); + kevent_socket_fill(ctx); + test_no_kevents(ctx->kqfd); + kevent_socket_drain(ctx); } void -test_kevent_socket_oneshot(void) +test_kevent_socket_oneshot(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; /* Re-add the watch and make sure no events are pending */ - kevent_add(kqfd, &kev, client_fd, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &client_fd); - test_no_kevents(kqfd); + kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &ctx->client_fd); + test_no_kevents(ctx->kqfd); - kevent_socket_fill(); + kevent_socket_fill(ctx); kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); /* Verify that the kernel watch has been deleted */ - kevent_socket_fill(); - test_no_kevents(kqfd); - kevent_socket_drain(); + kevent_socket_fill(ctx); + test_no_kevents(ctx->kqfd); + kevent_socket_drain(ctx); /* Verify that the kevent structure does not exist. */ kev.flags = EV_DELETE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0) + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) == 0) die("kevent() should have failed"); } @@ -240,15 +243,17 @@ test_kevent_socket_oneshot(void) * a pending connection. */ void -test_kevent_socket_listen_backlog(void) +test_kevent_socket_listen_backlog(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; struct sockaddr_in sain; socklen_t sa_len = sizeof(sain); int one = 1; - const short port = 14973; + short port; int clnt, srvr; + port = 14973 + ctx->iteration; + /* Create a passive socket */ memset(&sain, 0, sizeof(sain)); sain.sin_family = AF_INET; @@ -259,14 +264,14 @@ test_kevent_socket_listen_backlog(void) (char *) &one, sizeof(one)) != 0) err(1, "setsockopt()"); if (bind(srvr, (struct sockaddr *) &sain, sa_len) < 0) - err(1, "bind()"); + err(1, "bind-2", port); if (listen(srvr, 100) < 0) err(1, "listen()"); /* Watch for events on the socket */ - test_no_kevents(kqfd); - kevent_add(kqfd, &kev, srvr, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, NULL); - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); + kevent_add(ctx->kqfd, &kev, srvr, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, NULL); + test_no_kevents(ctx->kqfd); /* Simulate a client connecting to the server */ sain.sin_family = AF_INET; @@ -279,45 +284,48 @@ test_kevent_socket_listen_backlog(void) /* Verify that data=1 */ kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); - test_no_kevents(kqfd); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); + test_no_kevents(ctx->kqfd); } #if HAVE_EV_DISPATCH void -test_kevent_socket_dispatch(void) +test_kevent_socket_dispatch(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; /* Re-add the watch and make sure no events are pending */ - kevent_add(kqfd, &kev, client_fd, EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &client_fd); - test_no_kevents(kqfd); + kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &ctx->client_fd); + test_no_kevents(ctx->kqfd); /* The event will occur only once, even though EV_CLEAR is not specified. */ - kevent_socket_fill(); + kevent_socket_fill(ctx); kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); - test_no_kevents(kqfd); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); + test_no_kevents(ctx->kqfd); /* Re-enable the kevent */ /* FIXME- is EV_DISPATCH needed when rearming ? */ - kevent_add(kqfd, &kev, client_fd, EVFILT_READ, EV_ENABLE | EV_DISPATCH, 0, 0, &client_fd); + kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ENABLE | EV_DISPATCH, 0, 0, &ctx->client_fd); kev.data = 1; kev.flags = EV_ADD | EV_DISPATCH; /* FIXME: may not be portable */ - kevent_cmp(&kev, kevent_get(kqfd)); - test_no_kevents(kqfd); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); + test_no_kevents(ctx->kqfd); /* Since the knote is disabled, the EV_DELETE operation succeeds. */ - kevent_add(kqfd, &kev, client_fd, EVFILT_READ, EV_DELETE, 0, 0, &client_fd); + kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_DELETE, 0, 0, &ctx->client_fd); - kevent_socket_drain(); + kevent_socket_drain(ctx); } #endif /* HAVE_EV_DISPATCH */ #if BROKEN_ON_LINUX void -test_kevent_socket_lowat(void) +test_kevent_socket_lowat(struct test_context *ctx) { struct kevent kev; @@ -325,54 +333,54 @@ test_kevent_socket_lowat(void) /* Re-add the watch and make sure no events are pending */ puts("-- re-adding knote, setting low watermark to 2 bytes"); - EV_SET(&kev, client_fd, EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &client_fd); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + EV_SET(&kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &ctx->client_fd); + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("%s", test_id); test_no_kevents(); puts("-- checking that one byte does not trigger an event.."); - kevent_socket_fill(); + kevent_socket_fill(ctx); test_no_kevents(); puts("-- checking that two bytes triggers an event.."); - kevent_socket_fill(); - if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) + kevent_socket_fill(ctx); + if (kevent(ctx->kqfd, NULL, 0, &kev, 1, NULL) != 1) die("%s", test_id); - KEV_CMP(kev, client_fd, EVFILT_READ, 0); + KEV_CMP(kev, ctx->client_fd, EVFILT_READ, 0); test_no_kevents(); - kevent_socket_drain(); - kevent_socket_drain(); + kevent_socket_drain(ctx); + kevent_socket_drain(ctx); } #endif void -test_kevent_socket_eof(void) +test_kevent_socket_eof(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; /* Re-add the watch and make sure no events are pending */ - kevent_add(kqfd, &kev, client_fd, EVFILT_READ, EV_ADD, 0, 0, &client_fd); - test_no_kevents(kqfd); + kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD, 0, 0, &ctx->client_fd); + test_no_kevents(ctx->kqfd); - //if (shutdown(server_fd, SHUT_RDWR) < 0) + //if (shutdown(ctx->server_fd, SHUT_RDWR) < 0) // die("close(2)"); - if (close(server_fd) < 0) + if (close(ctx->server_fd) < 0) die("close(2)"); kev.flags |= EV_EOF; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); /* Delete the watch */ - kevent_add(kqfd, &kev, client_fd, EVFILT_READ, EV_DELETE, 0, 0, &client_fd); + kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_DELETE, 0, 0, &ctx->client_fd); } /* Test if EVFILT_READ works with regular files */ void -test_kevent_regular_file(void) +test_kevent_regular_file(struct test_context *ctx) { - struct kevent kev; - struct kevent *kev2; + struct kevent kev, ret; off_t curpos; int fd; @@ -381,55 +389,54 @@ test_kevent_regular_file(void) abort(); EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, &fd); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent"); - kev2 = kevent_get(kqfd); + kevent_get(&ret, ctx->kqfd); /* Set file position to EOF-1 */ - kev2->data--; - if ((curpos = lseek(fd, kev2->data, SEEK_SET)) != kev2->data) { + ret.data--; + if ((curpos = lseek(fd, ret.data, SEEK_SET)) != ret.data) { printf("seek to %u failed with rv=%lu\n", - (unsigned int) kev2->data, curpos); + (unsigned int) ret.data, curpos); abort(); } /* Set file position to EOF */ - (void) kevent_get(kqfd); - kev2->data = curpos + 1; - if ((curpos = lseek(fd, kev2->data, SEEK_SET)) != kev2->data) { + kevent_get(NULL, ctx->kqfd); + ret.data = curpos + 1; + if ((curpos = lseek(fd, ret.data, SEEK_SET)) != ret.data) { printf("seek to %u failed with rv=%lu\n", - (unsigned int) kev2->data, curpos); + (unsigned int) ret.data, curpos); abort(); } - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); kev.flags = EV_DELETE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent"); close(fd); } void -test_evfilt_read(int _kqfd) +test_evfilt_read(struct test_context *ctx) { - create_socket_connection(&client_fd, &server_fd, 23456); - - kqfd = _kqfd; - test(kevent_socket_add); - test(kevent_socket_del); - test(kevent_socket_add_without_ev_add); - test(kevent_socket_get); - test(kevent_socket_disable_and_enable); - test(kevent_socket_oneshot); - test(kevent_socket_clear); + create_socket_connection(&ctx->client_fd, &ctx->server_fd, ctx->iteration + 23456); + + test(kevent_socket_add, ctx); + test(kevent_socket_del, ctx); + test(kevent_socket_add_without_ev_add, ctx); + test(kevent_socket_get, ctx); + test(kevent_socket_disable_and_enable, ctx); + test(kevent_socket_oneshot, ctx); + test(kevent_socket_clear, ctx); #if HAVE_EV_DISPATCH - test(kevent_socket_dispatch); + test(kevent_socket_dispatch, ctx); #endif - test(kevent_socket_listen_backlog); - test(kevent_socket_eof); - test(kevent_regular_file); - close(client_fd); - close(server_fd); + test(kevent_socket_listen_backlog, ctx); + test(kevent_socket_eof, ctx); + test(kevent_regular_file, ctx); + close(ctx->client_fd); + close(ctx->server_fd); } diff --git a/vendor/libkqueue/test/signal.c b/vendor/libkqueue/test/signal.c index c139e74ce..d2513eaa9 100644 --- a/vendor/libkqueue/test/signal.c +++ b/vendor/libkqueue/test/signal.c @@ -16,50 +16,49 @@ #include "common.h" -static int __thread kqfd; - void -test_kevent_signal_add(void) +test_kevent_signal_add(struct test_context *ctx) { struct kevent kev; - kevent_add(kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); } void -test_kevent_signal_get(void) +test_kevent_signal_get(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; - kevent_add(kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); if (kill(getpid(), SIGUSR1) < 0) die("kill"); kev.flags |= EV_CLEAR; kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); } void -test_kevent_signal_disable(void) +test_kevent_signal_disable(struct test_context *ctx) { struct kevent kev; - kevent_add(kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, NULL); if (kill(getpid(), SIGUSR1) < 0) die("kill"); - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); } void -test_kevent_signal_enable(void) +test_kevent_signal_enable(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; - kevent_add(kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL); if (kill(getpid(), SIGUSR1) < 0) die("kill"); @@ -70,122 +69,126 @@ test_kevent_signal_enable(void) #else kev.data = 2; // one extra time from test_kevent_signal_disable() #endif - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); /* Delete the watch */ kev.flags = EV_DELETE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent"); } void -test_kevent_signal_del(void) +test_kevent_signal_del(struct test_context *ctx) { struct kevent kev; /* Delete the kevent */ - kevent_add(kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL); signal(SIGUSR1, SIG_IGN); if (kill(getpid(), SIGUSR1) < 0) die("kill"); - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); } void -test_kevent_signal_oneshot(void) +test_kevent_signal_oneshot(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; - kevent_add(kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL); if (kill(getpid(), SIGUSR1) < 0) die("kill"); kev.flags |= EV_CLEAR; kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); /* Send another one and make sure we get no events */ - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); if (kill(getpid(), SIGUSR1) < 0) die("kill"); - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); } void -test_kevent_signal_modify(void) +test_kevent_signal_modify(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; - kevent_add(kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); - kevent_add(kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, ((void *)-1)); + kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, ((void *)-1)); if (kill(getpid(), SIGUSR1) < 0) die("kill"); kev.flags |= EV_CLEAR; kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); - test_kevent_signal_del(); + test_kevent_signal_del(ctx); } #if HAVE_EV_DISPATCH void -test_kevent_signal_dispatch(void) +test_kevent_signal_dispatch(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); - kevent_add(kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_CLEAR | EV_DISPATCH, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_CLEAR | EV_DISPATCH, 0, 0, NULL); /* Get one event */ if (kill(getpid(), SIGUSR1) < 0) die("kill"); kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); /* Confirm that the knote is disabled */ if (kill(getpid(), SIGUSR1) < 0) die("kill"); - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); /* Enable the knote and make sure no events are pending */ - kevent_add(kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE | EV_DISPATCH, 0, 0, NULL); - test_no_kevents(kqfd); + kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE | EV_DISPATCH, 0, 0, NULL); + test_no_kevents(ctx->kqfd); /* Get the next event */ if (kill(getpid(), SIGUSR1) < 0) die("kill"); kev.flags = EV_ADD | EV_CLEAR | EV_DISPATCH; kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); /* Remove the knote and ensure the event no longer fires */ - kevent_add(kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL); if (kill(getpid(), SIGUSR1) < 0) die("kill"); - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); } #endif /* HAVE_EV_DISPATCH */ void -test_evfilt_signal(int _kqfd) +test_evfilt_signal(struct test_context *ctx) { signal(SIGUSR1, SIG_IGN); - kqfd = _kqfd; - test(kevent_signal_add); - test(kevent_signal_del); - test(kevent_signal_get); - test(kevent_signal_disable); - test(kevent_signal_enable); - test(kevent_signal_oneshot); - test(kevent_signal_modify); + test(kevent_signal_add, ctx); + test(kevent_signal_del, ctx); + test(kevent_signal_get, ctx); + test(kevent_signal_disable, ctx); + test(kevent_signal_enable, ctx); + test(kevent_signal_oneshot, ctx); + test(kevent_signal_modify, ctx); #if HAVE_EV_DISPATCH - test(kevent_signal_dispatch); + test(kevent_signal_dispatch, ctx); #endif } diff --git a/vendor/libkqueue/test/timer.c b/vendor/libkqueue/test/timer.c index a18786f45..79cd30822 100644 --- a/vendor/libkqueue/test/timer.c +++ b/vendor/libkqueue/test/timer.c @@ -16,151 +16,155 @@ #include "common.h" -static int __thread kqfd; - void -test_kevent_timer_add(void) +test_kevent_timer_add(struct test_context *ctx) { struct kevent kev; - kevent_add(kqfd, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL); } void -test_kevent_timer_del(void) +test_kevent_timer_del(struct test_context *ctx) { struct kevent kev; - kevent_add(kqfd, &kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); } void -test_kevent_timer_get(void) +test_kevent_timer_get(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; - kevent_add(kqfd, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL); kev.flags |= EV_CLEAR; kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); - kevent_add(kqfd, &kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); } static void -test_kevent_timer_oneshot(void) +test_kevent_timer_oneshot(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); - kevent_add(kqfd, &kev, 2, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 500,NULL); + kevent_add(ctx->kqfd, &kev, 2, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 500,NULL); /* Retrieve the event */ kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT; kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); /* Check if the event occurs again */ sleep(3); - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); } static void -test_kevent_timer_periodic(void) +test_kevent_timer_periodic(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); - kevent_add(kqfd, &kev, 3, EVFILT_TIMER, EV_ADD, 0, 1000,NULL); + kevent_add(ctx->kqfd, &kev, 3, EVFILT_TIMER, EV_ADD, 0, 1000,NULL); /* Retrieve the event */ kev.flags = EV_ADD | EV_CLEAR; kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); /* Check if the event occurs again */ sleep(1); - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); /* Delete the event */ kev.flags = EV_DELETE; - kevent_update(kqfd, &kev); + kevent_update(ctx->kqfd, &kev); } static void -test_kevent_timer_disable_and_enable(void) +test_kevent_timer_disable_and_enable(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); /* Add the watch and immediately disable it */ - kevent_add(kqfd, &kev, 4, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 2000,NULL); + kevent_add(ctx->kqfd, &kev, 4, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 2000,NULL); kev.flags = EV_DISABLE; - kevent_update(kqfd, &kev); - test_no_kevents(kqfd); + kevent_update(ctx->kqfd, &kev); + test_no_kevents(ctx->kqfd); /* Re-enable and check again */ kev.flags = EV_ENABLE; - kevent_update(kqfd, &kev); + kevent_update(ctx->kqfd, &kev); kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT; kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); } #if HAVE_EV_DISPATCH void -test_kevent_timer_dispatch(void) +test_kevent_timer_dispatch(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); - kevent_add(kqfd, &kev, 4, EVFILT_TIMER, EV_ADD | EV_DISPATCH, 0, 800, NULL); + kevent_add(ctx->kqfd, &kev, 4, EVFILT_TIMER, EV_ADD | EV_DISPATCH, 0, 800, NULL); /* Get one event */ kev.flags = EV_ADD | EV_CLEAR | EV_DISPATCH; kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); /* Confirm that the knote is disabled */ sleep(1); - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); /* Enable the knote and make sure no events are pending */ - kevent_add(kqfd, &kev, 4, EVFILT_TIMER, EV_ENABLE | EV_DISPATCH, 0, 800, NULL); - test_no_kevents(kqfd); + kevent_add(ctx->kqfd, &kev, 4, EVFILT_TIMER, EV_ENABLE | EV_DISPATCH, 0, 800, NULL); + test_no_kevents(ctx->kqfd); /* Get the next event */ sleep(1); kev.flags = EV_ADD | EV_CLEAR | EV_DISPATCH; kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); /* Remove the knote and ensure the event no longer fires */ - kevent_add(kqfd, &kev, 4, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, 4, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); sleep(1); - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); } #endif /* HAVE_EV_DISPATCH */ void -test_evfilt_timer(int _kqfd) +test_evfilt_timer(struct test_context *ctx) { - kqfd = _kqfd; - test(kevent_timer_add); - test(kevent_timer_del); - test(kevent_timer_get); - test(kevent_timer_oneshot); - test(kevent_timer_periodic); - test(kevent_timer_disable_and_enable); + test(kevent_timer_add, ctx); + test(kevent_timer_del, ctx); + test(kevent_timer_get, ctx); + test(kevent_timer_oneshot, ctx); + test(kevent_timer_periodic, ctx); + test(kevent_timer_disable_and_enable, ctx); #if HAVE_EV_DISPATCH - test(kevent_timer_dispatch); + test(kevent_timer_dispatch, ctx); #endif } diff --git a/vendor/libkqueue/test/user.c b/vendor/libkqueue/test/user.c index d24e9ef6d..65dcaa5b8 100644 --- a/vendor/libkqueue/test/user.c +++ b/vendor/libkqueue/test/user.c @@ -16,153 +16,155 @@ #include "common.h" -static int __thread kqfd; - static void -test_kevent_user_add_and_delete(void) +test_kevent_user_add_and_delete(struct test_context *ctx) { struct kevent kev; - kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL); - test_no_kevents(kqfd); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL); + test_no_kevents(ctx->kqfd); - kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_DELETE, 0, 0, NULL); - test_no_kevents(kqfd); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_DELETE, 0, 0, NULL); + test_no_kevents(ctx->kqfd); } static void -test_kevent_user_get(void) +test_kevent_user_get(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); /* Add the event, and then trigger it */ - kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, NULL); - kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; kev.flags = EV_CLEAR; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); } static void -test_kevent_user_get_hires(void) +test_kevent_user_get_hires(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); /* Add the event, and then trigger it */ - kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, NULL); - kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; kev.flags = EV_CLEAR; - kevent_cmp(&kev, kevent_get_hires(kqfd)); + kevent_get(&ret, ctx->kqfd); //FIXME: Shouldn't this be kevent_get_hires() ? + kevent_cmp(&kev, &ret); - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); } static void -test_kevent_user_disable_and_enable(void) +test_kevent_user_disable_and_enable(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); - kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL); - kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_DISABLE, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_DISABLE, 0, 0, NULL); /* Trigger the event, but since it is disabled, nothing will happen. */ - kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); - test_no_kevents(kqfd); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + test_no_kevents(ctx->kqfd); - kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ENABLE, 0, 0, NULL); - kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ENABLE, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); kev.flags = EV_CLEAR; kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); } static void -test_kevent_user_oneshot(void) +test_kevent_user_oneshot(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); - kevent_add(kqfd, &kev, 2, EVFILT_USER, EV_ADD | EV_ONESHOT, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, 2, EVFILT_USER, EV_ADD | EV_ONESHOT, 0, 0, NULL); puts(" -- event 1"); - kevent_add(kqfd, &kev, 2, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + kevent_add(ctx->kqfd, &kev, 2, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); kev.flags = EV_ONESHOT; kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); } #if HAVE_EV_DISPATCH void -test_kevent_user_dispatch(void) +test_kevent_user_dispatch(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); /* Add the event, and then trigger it */ - kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ADD | EV_CLEAR | EV_DISPATCH, 0, 0, NULL); - kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ADD | EV_CLEAR | EV_DISPATCH, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); /* Retrieve one event */ kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; kev.flags = EV_CLEAR; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); /* Confirm that the knote is disabled automatically */ - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); /* Re-enable the kevent */ /* FIXME- is EV_DISPATCH needed when rearming ? */ - kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ENABLE | EV_CLEAR | EV_DISPATCH, 0, 0, NULL); - test_no_kevents(kqfd); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ENABLE | EV_CLEAR | EV_DISPATCH, 0, 0, NULL); + test_no_kevents(ctx->kqfd); /* Trigger the event */ - kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; kev.flags = EV_CLEAR; - kevent_cmp(&kev, kevent_get(kqfd)); - test_no_kevents(kqfd); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); + test_no_kevents(ctx->kqfd); /* Delete the watch */ - kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_DELETE, 0, 0, NULL); - test_no_kevents(kqfd); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_DELETE, 0, 0, NULL); + test_no_kevents(ctx->kqfd); } #endif /* HAVE_EV_DISPATCH */ void -test_evfilt_user(int _kqfd) +test_evfilt_user(struct test_context *ctx) { - kqfd = _kqfd; - - test(kevent_user_add_and_delete); - test(kevent_user_get); - test(kevent_user_get_hires); - test(kevent_user_disable_and_enable); - test(kevent_user_oneshot); + test(kevent_user_add_and_delete, ctx); + test(kevent_user_get, ctx); + test(kevent_user_get_hires, ctx); + test(kevent_user_disable_and_enable, ctx); + test(kevent_user_oneshot, ctx); #if HAVE_EV_DISPATCH - test(kevent_user_dispatch); + test(kevent_user_dispatch, ctx); #endif /* TODO: try different fflags operations */ } diff --git a/vendor/libkqueue/test/vnode.c b/vendor/libkqueue/test/vnode.c index f61c63e5b..638b9b0a2 100644 --- a/vendor/libkqueue/test/vnode.c +++ b/vendor/libkqueue/test/vnode.c @@ -16,120 +16,117 @@ #include "common.h" -static int __thread kqfd; -static int __thread vnode_fd; -static char __thread testfile[1024]; - - /* Create an empty file */ static void -testfile_create(void) +testfile_create(const char *path) { int fd; - if ((fd = open(testfile, O_CREAT | O_WRONLY, 0600)) < 0) + if ((fd = open(path, O_CREAT | O_WRONLY, 0600)) < 0) die("open"); close(fd); } static void -testfile_touch(void) +testfile_touch(const char *path) { char buf[1024]; - snprintf(&buf[0], sizeof(buf), "touch %s", testfile); + snprintf(&buf[0], sizeof(buf), "touch %s", path); if (system(buf) != 0) die("system"); } static void -testfile_write(void) +testfile_write(const char *path) { char buf[1024]; - snprintf(&buf[0], sizeof(buf), "echo hi >> %s", testfile); + snprintf(&buf[0], sizeof(buf), "echo hi >> %s", path); if (system(buf) != 0) die("system"); } static void -testfile_rename(int step) +testfile_rename(const char *path, int step) { char buf[1024]; - snprintf(&buf[0], sizeof(buf), "%s.tmp", testfile); + snprintf(&buf[0], sizeof(buf), "%s.tmp", path); /* XXX-FIXME use of 'step' conceals a major memory corruption when the file is renamed twice. To replicate, remove "if step" conditional so two renames occur in this function. */ if (step == 0) { - if (rename(testfile,buf) != 0) + if (rename(path, buf) != 0) err(1,"rename"); } else { - if (rename(buf, testfile) != 0) + if (rename(buf, path) != 0) err(1,"rename"); } } void -test_kevent_vnode_add(void) +test_kevent_vnode_add(struct test_context *ctx) { struct kevent kev; - testfile_create(); + testfile_create(ctx->testfile); - vnode_fd = open(testfile, O_RDWR); - if (vnode_fd < 0) - err(1, "open of %s", testfile); + ctx->vnode_fd = open(ctx->testfile, O_RDWR); + if (ctx->vnode_fd < 0) + err(1, "open of %s", ctx->testfile); - kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD, + kevent_add(ctx->kqfd, &kev, ctx->vnode_fd, EVFILT_VNODE, EV_ADD, NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME | NOTE_DELETE, 0, NULL); } void -test_kevent_vnode_note_delete(void) +test_kevent_vnode_note_delete(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; - kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, NULL); + kevent_add(ctx->kqfd, &kev, ctx->vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, NULL); - if (unlink(testfile) < 0) + if (unlink(ctx->testfile) < 0) die("unlink"); - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); } void -test_kevent_vnode_note_write(void) +test_kevent_vnode_note_write(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; - kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_WRITE, 0, NULL); + kevent_add(ctx->kqfd, &kev, ctx->vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_WRITE, 0, NULL); - testfile_write(); + testfile_write(ctx->testfile); /* BSD kqueue adds NOTE_EXTEND even though it was not requested */ /* BSD kqueue removes EV_ENABLE */ kev.flags &= ~EV_ENABLE; // XXX-FIXME compatibility issue kev.fflags |= NOTE_EXTEND; // XXX-FIXME compatibility issue - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); } void -test_kevent_vnode_note_attrib(void) +test_kevent_vnode_note_attrib(struct test_context *ctx) { struct kevent kev; int nfds; - kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL); + kevent_add(ctx->kqfd, &kev, ctx->vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL); - testfile_touch(); + testfile_touch(ctx->testfile); - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + nfds = kevent(ctx->kqfd, NULL, 0, &kev, 1, NULL); if (nfds < 1) die("kevent"); - if (kev.ident != vnode_fd || + if (kev.ident != ctx->vnode_fd || kev.filter != EVFILT_VNODE || kev.fflags != NOTE_ATTRIB) err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", @@ -137,62 +134,62 @@ test_kevent_vnode_note_attrib(void) } void -test_kevent_vnode_note_rename(void) +test_kevent_vnode_note_rename(struct test_context *ctx) { struct kevent kev; int nfds; - kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_RENAME, 0, NULL); + kevent_add(ctx->kqfd, &kev, ctx->vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_RENAME, 0, NULL); - testfile_rename(0); + testfile_rename(ctx->testfile, 0); - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + nfds = kevent(ctx->kqfd, NULL, 0, &kev, 1, NULL); if (nfds < 1) die("kevent"); - if (kev.ident != vnode_fd || + if (kev.ident != ctx->vnode_fd || kev.filter != EVFILT_VNODE || kev.fflags != NOTE_RENAME) err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - testfile_rename(1); + testfile_rename(ctx->testfile, 1); - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); } void -test_kevent_vnode_del(void) +test_kevent_vnode_del(struct test_context *ctx) { struct kevent kev; - kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, ctx->vnode_fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL); } void -test_kevent_vnode_disable_and_enable(void) +test_kevent_vnode_disable_and_enable(struct test_context *ctx) { struct kevent kev; int nfds; - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); /* Add the watch and immediately disable it */ - kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL); + kevent_add(ctx->kqfd, &kev, ctx->vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL); kev.flags = EV_DISABLE; - kevent_update(kqfd, &kev); + kevent_update(ctx->kqfd, &kev); /* Confirm that the watch is disabled */ - testfile_touch(); - test_no_kevents(kqfd); + testfile_touch(ctx->testfile); + test_no_kevents(ctx->kqfd); /* Re-enable and check again */ kev.flags = EV_ENABLE; - kevent_update(kqfd, &kev); - testfile_touch(); - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + kevent_update(ctx->kqfd, &kev); + testfile_touch(ctx->testfile); + nfds = kevent(ctx->kqfd, NULL, 0, &kev, 1, NULL); if (nfds < 1) die("kevent"); - if (kev.ident != vnode_fd || + if (kev.ident != ctx->vnode_fd || kev.filter != EVFILT_VNODE || kev.fflags != NOTE_ATTRIB) err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", @@ -201,66 +198,65 @@ test_kevent_vnode_disable_and_enable(void) #if HAVE_EV_DISPATCH void -test_kevent_vnode_dispatch(void) +test_kevent_vnode_dispatch(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, ret; int nfds; - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); - kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_DISPATCH, NOTE_ATTRIB, 0, NULL); + kevent_add(ctx->kqfd, &kev, ctx->vnode_fd, EVFILT_VNODE, EV_ADD | EV_DISPATCH, NOTE_ATTRIB, 0, NULL); - testfile_touch(); + testfile_touch(ctx->testfile); - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); + nfds = kevent(ctx->kqfd, NULL, 0, &kev, 1, NULL); if (nfds < 1) die("kevent"); - if (kev.ident != vnode_fd || + if (kev.ident != ctx->vnode_fd || kev.filter != EVFILT_VNODE || kev.fflags != NOTE_ATTRIB) err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", test_id, (unsigned int)kev.ident, kev.filter, kev.flags); /* Confirm that the watch is disabled automatically */ - testfile_touch(); - test_no_kevents(kqfd); + testfile_touch(ctx->testfile); + test_no_kevents(ctx->kqfd); /* Re-enable the kevent */ /* FIXME- is EV_DISPATCH needed when rearming ? */ - kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ENABLE | EV_DISPATCH, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, ctx->vnode_fd, EVFILT_VNODE, EV_ENABLE | EV_DISPATCH, 0, 0, NULL); kev.flags = EV_ADD | EV_DISPATCH; /* FIXME: may not be portable */ kev.fflags = NOTE_ATTRIB; - testfile_touch(); - kevent_cmp(&kev, kevent_get(kqfd)); - test_no_kevents(kqfd); + testfile_touch(ctx->testfile); + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); + test_no_kevents(ctx->kqfd); /* Delete the watch */ - kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_DELETE, NOTE_ATTRIB, 0, NULL); + kevent_add(ctx->kqfd, &kev, ctx->vnode_fd, EVFILT_VNODE, EV_DELETE, NOTE_ATTRIB, 0, NULL); } #endif /* HAVE_EV_DISPATCH */ void -test_evfilt_vnode(int _kqfd) +test_evfilt_vnode(struct test_context *ctx) { - #if (defined(__sun) && !defined(HAVE_PORT_SOURCE_FILE)) puts("**NOTE** EVFILT_VNODE is not supported on this version of Solaris"); return; #endif - snprintf(testfile, sizeof(testfile), "/tmp/kqueue-test%d.tmp", + snprintf(ctx->testfile, sizeof(ctx->testfile), "/tmp/kqueue-test%d.tmp", testing_make_uid()); - kqfd = _kqfd; - test(kevent_vnode_add); - test(kevent_vnode_del); - test(kevent_vnode_disable_and_enable); + test(kevent_vnode_add, ctx); + test(kevent_vnode_del, ctx); + test(kevent_vnode_disable_and_enable, ctx); #if HAVE_EV_DISPATCH - test(kevent_vnode_dispatch); + test(kevent_vnode_dispatch, ctx); #endif - test(kevent_vnode_note_write); - test(kevent_vnode_note_attrib); - test(kevent_vnode_note_rename); - test(kevent_vnode_note_delete); - unlink(testfile); + test(kevent_vnode_note_write, ctx); + test(kevent_vnode_note_attrib, ctx); + test(kevent_vnode_note_rename, ctx); + test(kevent_vnode_note_delete, ctx); + unlink(ctx->testfile); } From 5acf1eeae69a0921f2c50fb045f813cfce9fb886 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 26 May 2011 03:45:28 +0000 Subject: [PATCH 0491/1120] Build a debug-enabled static library. Build two versions of kqtest with and without debugging enabled. Use static linking for kqtest and kqtest_debug. Add additional Makefile targets for profiling with Valgrind Enable gprof profiling in the debug targets. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@520 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile | 13 +++++++++++-- vendor/libkqueue/src/common/kevent.c | 1 + vendor/libkqueue/test/Makefile | 28 +++++++++++++++++++--------- vendor/libkqueue/test/config.inc | 2 +- vendor/libkqueue/test/main.c | 1 + 5 files changed, 33 insertions(+), 12 deletions(-) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile index a439a0516..6562e3245 100644 --- a/vendor/libkqueue/Makefile +++ b/vendor/libkqueue/Makefile @@ -22,7 +22,7 @@ include config.mk .PHONY :: install uninstall check dist dist-upload clean merge distclean fresh-build rpm edit cscope -all: $(PROGRAM).so.$(ABI_VERSION) $(PROGRAM)_debug.so $(PROGRAM).a +all: $(PROGRAM).so.$(ABI_VERSION) $(PROGRAM)_debug.so $(PROGRAM).a $(PROGRAM)_debug.a %.o: %.c $(DEPS) $(CC) -c -o $@ -I./include -I./src/common -DNDEBUG $(CFLAGS) $< @@ -34,6 +34,12 @@ $(PROGRAM).a: $(STRIP) $(PROGRAM).a rm *.o +$(PROGRAM)_debug.a: + rm -f *.o + $(CC) -c -I./include -I./src/common -DMAKE_STATIC=1 -pg -static $(CFLAGS) $(SOURCES) $(LDADD) + $(AR) rcs $(PROGRAM)_debug.a *.o + rm *.o + $(PROGRAM).so.$(ABI_VERSION): $(OBJS) $(CC) -o $@ -I./include -I./src/common -shared $(LDFLAGS) -DNDEBUG $(CFLAGS) $(SOURCES) $(LDADD) $(STRIP) $(PROGRAM).so.$(ABI_VERSION) @@ -69,9 +75,12 @@ uninstall: test/config.mk: cd test && ../configure -check: clean all test/config.mk +check: test/config.mk cd test && make check +profile: clean $(PROGRAM)_debug.a + cd test && ./kqtest + debug: clean all test/config.mk cd test && make debug diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 9a30b98b6..abd947285 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -255,6 +255,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, dbg_printf("--- kevent %u --- (nchanges = %d, nevents = %d)", myid, nchanges, nevents); } else { myid = 0; + (void) myid; } /* diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile index 30ec63801..975a71f50 100644 --- a/vendor/libkqueue/test/Makefile +++ b/vendor/libkqueue/test/Makefile @@ -14,7 +14,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -tests=kqtest lockstat static-lib-test +tests=kqtest kqtest_debug lockstat static-lib-test include config.mk @@ -24,28 +24,38 @@ lockstat: lockstat.c $(CC) -o lockstat $(CFLAGS) lockstat.c $(LDADD) kqtest: $(SOURCES) - $(CC) -rdynamic -o kqtest $(CFLAGS) $(SOURCES) $(LDADD) + $(CC) -pg -o kqtest -DMAKE_STATIC=1 $(CFLAGS) $(SOURCES) ../libkqueue.a -lpthread + +kqtest_debug: $(SOURCES) + $(CC) -pg -o kqtest_debug -DMAKE_STATIC=1 $(CFLAGS) $(SOURCES) ../libkqueue_debug.a -lpthread static-lib-test: $(SOURCES) $(CC) -o static-lib-test -DMAKE_STATIC=1 $(CFLAGS) $(SOURCES) ../libkqueue.a -lpthread check: kqtest - LD_LIBRARY_PATH="..:/usr/sfw/lib/64" PATH="$$PATH:.." ./kqtest $(KQTEST_OPTS) + ./kqtest $(KQTEST_OPTS) debug: kqtest - LD_LIBRARY_PATH="..:/usr/sfw/lib/64" PATH="$$PATH:.." gdb ./kqtest $(KQTEST_OPTS) + gdb ./kqtest $(KQTEST_OPTS) valgrind: kqtest - LD_LIBRARY_PATH="..:/usr/sfw/lib/64" \ valgrind --tool=memcheck --leak-check=full --show-reachable=yes --num-callers=20 --track-fds=yes ./kqtest helgrind: kqtest - LD_LIBRARY_PATH="..:/usr/sfw/lib/64" \ - valgrind --tool=helgrind ./kqtest + valgrind --tool=helgrind ./kqtest -c 25 -n 1 + +callgrind: kqtest + rm -f callgrind.* + valgrind --tool=callgrind --branch-sim=yes ./kqtest || true + kcachegrind callgrind.* cachegrind: kqtest - LD_LIBRARY_PATH="..:/usr/sfw/lib/64" \ - valgrind --tool=cachegrind --branch-sim=yes ./kqtest + rm -f cachegrind.* + valgrind --tool=cachegrind --branch-sim=yes ./kqtest || true + #CLI: + #cg_annotate cachegrind.* + #GUI: + kcachegrind check-installed: $(CC) -o kqtest $(CFLAGS) $(SOURCES) $(LDADD) -lkqueue diff --git a/vendor/libkqueue/test/config.inc b/vendor/libkqueue/test/config.inc index 72d30b716..cbaa960c0 100755 --- a/vendor/libkqueue/test/config.inc +++ b/vendor/libkqueue/test/config.inc @@ -17,7 +17,7 @@ pre_configure_hook() { then ldadd="$ldadd ../libkqueue.so" else - ldadd="$ldadd -lkqueue_debug -lpthread -lrt" + ldadd="$ldadd ../libkqueue_debug.a -lpthread -lrt" fi } diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 03cc49c03..96a0813ce 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -204,6 +204,7 @@ main(int argc, char **argv) struct unit_test tests[] = { { "socket", 1, test_evfilt_read }, #ifndef _WIN32 + // XXX-FIXME -- BROKEN ON LINUX WHEN RUN IN A SEPARATE THREAD { "signal", 0, test_evfilt_signal }, #endif #if FIXME From 449bf6bac45b01985552a3293f10f95c87d516c1 Mon Sep 17 00:00:00 2001 From: marius Date: Thu, 26 May 2011 19:17:33 +0000 Subject: [PATCH 0492/1120] + stdint.h compatibility when using VS 2008 * Fixed usage of knote_release macros git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@521 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/include/sys/event.h | 6 +- vendor/libkqueue/src/windows/stdint.h | 247 ++++++++++++++++++++++++++ vendor/libkqueue/src/windows/timer.c | 4 +- 3 files changed, 254 insertions(+), 3 deletions(-) create mode 100644 vendor/libkqueue/src/windows/stdint.h diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index 7fd7bf040..90f1a874e 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -36,7 +36,11 @@ #define intptr_t long #else #include -#include +#if _MSC_VER < 1600 +# include "../../src/windows/stdint.h" +#else +# include +#endif #define LIBKQUEUE 1 #endif diff --git a/vendor/libkqueue/src/windows/stdint.h b/vendor/libkqueue/src/windows/stdint.h new file mode 100644 index 000000000..d02608a59 --- /dev/null +++ b/vendor/libkqueue/src/windows/stdint.h @@ -0,0 +1,247 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#ifdef __cplusplus +extern "C" { +#endif +# include +#ifdef __cplusplus +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + + +#endif // _MSC_STDINT_H_ ] diff --git a/vendor/libkqueue/src/windows/timer.c b/vendor/libkqueue/src/windows/timer.c index e4105a4b2..acd46961e 100644 --- a/vendor/libkqueue/src/windows/timer.c +++ b/vendor/libkqueue/src/windows/timer.c @@ -45,7 +45,7 @@ ktimer_delete(struct filter *filt, struct knote *kn) } if( !(kn->kev.flags & EV_ONESHOT) ) - knote_release(filt, kn); + knote_release(kn); kn->data.handle = NULL; return (0); @@ -83,7 +83,7 @@ static VOID CALLBACK evfilt_timer_callback(void* param, BOOLEAN fired){ struct filter* filt; if( filter_lookup(&filt, kq, kn->kev.filter) ) dbg_perror("filter_lookup()"); - knote_release(filt, kn); + knote_release(kn); } } From 7c69faa4e63f6694ede9dae500e156ec239154ad Mon Sep 17 00:00:00 2001 From: marius Date: Fri, 27 May 2011 18:00:58 +0000 Subject: [PATCH 0493/1120] * Repair inclusion of stdint on non-windows platforms git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@522 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/include/sys/event.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index 90f1a874e..f28e12ef8 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -36,7 +36,7 @@ #define intptr_t long #else #include -#if _MSC_VER < 1600 +#if defined(_WIN32) && _MSC_VER < 1600 # include "../../src/windows/stdint.h" #else # include From fa6e7c953ab2ea6b28e9995fcad696cbd5864fb3 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 30 May 2011 14:59:08 +0000 Subject: [PATCH 0494/1120] Eliminate use of global variable "cur_test_id" git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@523 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/common.h | 14 ++++++++------ vendor/libkqueue/test/main.c | 10 +++++++--- vendor/libkqueue/test/test.c | 19 +++++++++---------- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 61006952e..1640f2274 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -65,6 +65,7 @@ struct unit_test { struct test_context { struct unit_test tests[50]; //TODO: use MAX_TESTS instead of magic number + char *cur_test_id; int iterations; int concurrency; int iteration; @@ -88,10 +89,11 @@ void test_evfilt_proc(struct test_context *); void test_evfilt_user(struct test_context *); #endif -#define test(f,ctx,...) do { \ - test_begin("test_"#f"()\t"__VA_ARGS__); \ - test_##f(ctx);\ - test_end(); \ +#define test(f,ctx,...) do { \ + assert(ctx != NULL); \ + test_begin(ctx, "test_"#f"()\t"__VA_ARGS__); \ + test_##f(ctx); \ + test_end(ctx); \ } while (/*CONSTCOND*/0) extern const char * kevent_to_str(struct kevent *); @@ -126,8 +128,8 @@ kevent_add(int kqfd, struct kevent *kev, void _test_no_kevents(int, const char *, int); /* From test.c */ -void test_begin(const char *); -void test_end(void); +void test_begin(struct test_context *, const char *); +void test_end(struct test_context *); void test_atexit(void); void testing_begin(void); void testing_end(void); diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 96a0813ce..c47971dd4 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -148,18 +148,22 @@ test_harness(struct unit_test tests[], int iterations, int concurrency) testing_begin(); - test(peer_close_detection, NULL); + ctx = calloc(1, sizeof(*ctx)); - test(kqueue, NULL); + test(peer_close_detection, ctx); + + test(kqueue, ctx); if ((kqfd = kqueue()) < 0) die("kqueue()"); - test(ev_receipt, NULL); + test(ev_receipt, ctx); /* TODO: this fails now, but would be good later test(kqueue_descriptor_is_pollable); */ + free(ctx); + n = 0; for (i = 0; i < iterations; i++) { for (j = 0; j < concurrency; j++) { diff --git a/vendor/libkqueue/test/test.c b/vendor/libkqueue/test/test.c index f935b1d9e..0e0ea8c26 100644 --- a/vendor/libkqueue/test/test.c +++ b/vendor/libkqueue/test/test.c @@ -24,7 +24,6 @@ static int testnum = 1; static int error_flag = 1; -static char * cur_test_id = NULL; /* FIXME: not portable beyond linux */ #ifndef _WIN32 @@ -48,7 +47,7 @@ static void testing_atexit(void) { if (error_flag) { - printf(" *** TEST FAILED: %s\n", cur_test_id); + printf(" *** TEST FAILED ***\n"); //TODO: print detailed log } else { printf("\n---\n" @@ -57,21 +56,21 @@ testing_atexit(void) } void -test_begin(const char *func) +test_begin(struct test_context *ctx, const char *func) { - if (cur_test_id) - free(cur_test_id); - cur_test_id = strdup(func); + if (ctx->cur_test_id) + free(ctx->cur_test_id); + ctx->cur_test_id = strdup(func); - printf("%d: %s\n", testnum++, cur_test_id); + printf("%d: %s\n", testnum++, ctx->cur_test_id); //TODO: redirect stdout/err to logfile } void -test_end(void) +test_end(struct test_context *ctx) { - free(cur_test_id); - cur_test_id = NULL; + free(ctx->cur_test_id); + ctx->cur_test_id = NULL; } void From 574c2371fefec8683d0ae87b674a2a306de0b868 Mon Sep 17 00:00:00 2001 From: marius Date: Mon, 13 Jun 2011 19:27:44 +0000 Subject: [PATCH 0495/1120] * Streamlined some variables to be of the same type regardless of the architecture used git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@524 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/knote.c | 2 +- vendor/libkqueue/src/common/private.h | 2 +- vendor/libkqueue/src/windows/platform.c | 2 +- vendor/libkqueue/src/windows/timer.c | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 76b8c00d2..1622e25b2 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -120,7 +120,7 @@ knote_delete(struct filter *filt, struct knote *kn) } struct knote * -knote_lookup(struct filter *filt, short ident) +knote_lookup(struct filter *filt, uintptr_t ident) { struct knote query; struct knote *ent = NULL; diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 161f58772..451b01bdc 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -185,7 +185,7 @@ extern const struct kqueue_vtable kqops; /* * knote internal API */ -struct knote * knote_lookup(struct filter *, short); +struct knote * knote_lookup(struct filter *, uintptr_t); //DEADWOOD: struct knote * knote_get_by_data(struct filter *filt, intptr_t); struct knote * knote_new(void); #define knote_retain(kn) atomic_inc(&kn->kn_ref) diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 6e60ed8b4..6744f755e 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -224,7 +224,7 @@ windows_get_descriptor_type(struct knote *kn) /* * Test if the descriptor is a socket. */ - if (fstat(kn->kev.ident, &sb) == 0) { + if (fstat( (int)kn->kev.ident, &sb) == 0) { dbg_printf("HANDLE %d appears to a be regular file", kn->kev.ident); kn->kn_flags |= KNFL_REGULAR_FILE; } else { diff --git a/vendor/libkqueue/src/windows/timer.c b/vendor/libkqueue/src/windows/timer.c index acd46961e..e0abfcb21 100644 --- a/vendor/libkqueue/src/windows/timer.c +++ b/vendor/libkqueue/src/windows/timer.c @@ -18,7 +18,7 @@ /* Convert milliseconds into negative increments of 100-nanoseconds */ static void -convert_msec_to_filetime(LARGE_INTEGER *dst, int src) +convert_msec_to_filetime(LARGE_INTEGER *dst, intptr_t src) { dst->QuadPart = -((int64_t) src * 1000 * 10); } @@ -130,7 +130,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) convert_msec_to_filetime(&liDueTime, kn->kev.data); // XXX-FIXME add completion routine to this call - if (!SetWaitableTimer(th, &liDueTime, (kn->kev.flags & EV_ONESHOT) ? 0 : kn->kev.data, NULL, NULL, FALSE)) { + if (!SetWaitableTimer(th, &liDueTime, (LONG)( (kn->kev.flags & EV_ONESHOT) ? 0 : kn->kev.data ), NULL, NULL, FALSE)) { dbg_lasterror("SetWaitableTimer()"); CloseHandle(th); return (-1); From cb2f86708550d2aa8c0b7f6c37a465ac894926f1 Mon Sep 17 00:00:00 2001 From: marius Date: Wed, 15 Jun 2011 19:46:39 +0000 Subject: [PATCH 0496/1120] Fixed a compiler warning on gcc introduced in r524 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@525 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/knote.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 1622e25b2..e81569b15 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -133,7 +133,7 @@ knote_lookup(struct filter *filt, uintptr_t ident) knote_lock(ent); pthread_rwlock_unlock(&filt->kf_knote_mtx); - dbg_printf("id=%d ent=%p", ident, ent); + dbg_printf("id=%lu ent=%p", ident, ent); return (ent); } From a4b6fba49ee107c0c707bc411c948d6bf8f2e738 Mon Sep 17 00:00:00 2001 From: marius Date: Tue, 21 Jun 2011 17:50:07 +0000 Subject: [PATCH 0497/1120] Fixed a compiler warning on 32bit linux introduced while streamlining the variables git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@526 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/knote.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index e81569b15..a0f501e20 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -133,7 +133,11 @@ knote_lookup(struct filter *filt, uintptr_t ident) knote_lock(ent); pthread_rwlock_unlock(&filt->kf_knote_mtx); +#ifdef __x86_64__ dbg_printf("id=%lu ent=%p", ident, ent); +#else + dbg_printf("id=%u ent=%p", ident, ent); +#endif return (ent); } From 2630df2dfac3c1da80581189ac0680cd1d63e0b7 Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 10 Feb 2012 01:25:35 +0000 Subject: [PATCH 0498/1120] Add support for concurrent tests. Test providing an invalid kqueue descriptor to kevent() git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@532 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/common.h | 2 ++ vendor/libkqueue/test/main.c | 30 +++++++++++++++++++++++------- vendor/libkqueue/test/timer.c | 12 ++++++++++++ 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 1640f2274..d7a37aaf9 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -60,6 +60,7 @@ struct test_context; struct unit_test { const char *ut_name; int ut_enabled; + int ut_concurrent; void (*ut_func)(struct test_context *); }; @@ -84,6 +85,7 @@ void test_evfilt_read(struct test_context *); void test_evfilt_signal(struct test_context *); void test_evfilt_vnode(struct test_context *); void test_evfilt_timer(struct test_context *); +void test_evfilt_timer_concurrent(struct test_context *); void test_evfilt_proc(struct test_context *); #if HAVE_EVFILT_USER void test_evfilt_user(struct test_context *); diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index c47971dd4..981862e26 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -97,6 +97,18 @@ test_kqueue(void *unused) die("close()"); } +void +test_kevent(void *unused) +{ + struct kevent kev; + + memset(&kev, 0, sizeof(kev)); + + /* Provide an invalid kqueue descriptor */ + if (kevent(-1, &kev, 1, NULL, 0, NULL) == 0) + die("invalid kq parameter"); +} + void test_ev_receipt(void *unused) { @@ -126,6 +138,8 @@ run_iteration(struct test_context *ctx) struct unit_test *test; for (test = &ctx->tests[0]; test->ut_name != NULL; test++) { + if (ctx->concurrency > 1 && test->ut_concurrent == 0) + continue; if (test->ut_enabled) test->ut_func(ctx); } @@ -153,6 +167,7 @@ test_harness(struct unit_test tests[], int iterations, int concurrency) test(peer_close_detection, ctx); test(kqueue, ctx); + test(kevent, ctx); if ((kqfd = kqueue()) < 0) die("kqueue()"); @@ -206,22 +221,23 @@ int main(int argc, char **argv) { struct unit_test tests[] = { - { "socket", 1, test_evfilt_read }, + { "socket", 1, 0, test_evfilt_read }, #ifndef _WIN32 // XXX-FIXME -- BROKEN ON LINUX WHEN RUN IN A SEPARATE THREAD - { "signal", 0, test_evfilt_signal }, + { "signal", 0, 0, test_evfilt_signal }, #endif #if FIXME - { "proc", 1, test_evfilt_proc }, + { "proc", 1, 0, test_evfilt_proc }, #endif - { "timer", 1, test_evfilt_timer }, + { "timer", 1, 0, test_evfilt_timer }, + { "timer_concurrent", 1, 1, test_evfilt_timer_concurrent }, #ifndef _WIN32 - { "vnode", 1, test_evfilt_vnode }, + { "vnode", 1, 0, test_evfilt_vnode }, #endif #if HAVE_EVFILT_USER - { "user", 1, test_evfilt_user }, + { "user", 1, 0, test_evfilt_user }, #endif - { NULL, 0, NULL }, + { NULL, 0, 0, NULL }, }; struct unit_test *test; int c, i, concurrency, iterations; diff --git a/vendor/libkqueue/test/timer.c b/vendor/libkqueue/test/timer.c index 79cd30822..00ce85833 100644 --- a/vendor/libkqueue/test/timer.c +++ b/vendor/libkqueue/test/timer.c @@ -168,3 +168,15 @@ test_evfilt_timer(struct test_context *ctx) test(kevent_timer_dispatch, ctx); #endif } + +void +test_evfilt_timer_concurrent(struct test_context *ctx) +{ + struct kevent kev, ret; + + kevent_add(ctx->kqfd, &kev, ctx->iteration, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 100, NULL); + kevent_get(&ret, ctx->kqfd); + /* Do not compare ret and kev, because it may be triggered by a + different thread's kevent stucture */ + +} From 7c500bf74eb566f09a040feb729c810a996a8820 Mon Sep 17 00:00:00 2001 From: marius Date: Thu, 23 Feb 2012 07:34:53 +0000 Subject: [PATCH 0499/1120] * Merged a bugfix from xdispatch within windows_kevent_wait causing wrong timeouts git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@536 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/windows/platform.c | 28 +++++++++++++++---------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 6744f755e..309a8d888 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -123,19 +123,25 @@ windows_kevent_wait(struct kqueue *kq, int no, const struct timespec *timeout) DWORD timeout_ms; BOOL success; - /* Convert timeout to milliseconds */ - /* NOTE: loss of precision for timeout values less than 1ms */ - if (timeout == NULL) { - timeout_ms = INFINITE; - } else { - timeout_ms = 0; - if (timeout->tv_sec > 0) - timeout_ms += ((DWORD)timeout->tv_sec) / 1000; - if (timeout->tv_sec > 0) - timeout_ms += timeout->tv_nsec / 1000000; - } + if (timeout == NULL) { + timeout_ms = INFINITE; + } else if ( timeout->tv_sec == 0 && timeout->tv_nsec < 1000000 ) { + /* do we need to try high precision timing? */ + // TODO: This is currently not possible on windows! + timeout_ms = 0; + } else { /* Convert timeout to milliseconds */ + timeout_ms = 0; + if (timeout->tv_sec > 0) + timeout_ms += ((DWORD)timeout->tv_sec) * 1000; + if (timeout->tv_nsec > 0) + timeout_ms += timeout->tv_nsec / 1000000; + } dbg_printf("waiting for events (timeout=%u ms)", (unsigned int) timeout_ms); +#if 0 + if(timeout_ms <= 0) + dbg_printf("Woop, not waiting !?"); +#endif memset(&iocp_buf, 0, sizeof(iocp_buf)); success = GetQueuedCompletionStatus(kq->kq_iocp, &iocp_buf.bytes, &iocp_buf.key, &iocp_buf.overlap, From 5f09213d3e781400eae9d11edcfa0a1bedc012ca Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 19 Apr 2012 19:33:00 +0000 Subject: [PATCH 0500/1120] Document the need to fix the "stub" functions git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@537 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/BUGS | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/vendor/libkqueue/BUGS b/vendor/libkqueue/BUGS index cb25a87f4..4e9e1ca56 100644 --- a/vendor/libkqueue/BUGS +++ b/vendor/libkqueue/BUGS @@ -23,3 +23,25 @@ [read.c:84]: Unexpected event:_test_no_kevents(): [ident=7, filter=-1, flags = 1 (EV_ADD), fflags = 0, data=0, udata=fffffd7fff08c6b4]: Error 0 + + * There are a number of stub functions that silently fail or succeed. + These need to be cleaned up; at a minimum, they should emit very loud + debugging output saying "FIXME -- UNIMPLEMENTED". + + $ grep STUB src/*/*.c + src/linux/proc.c: return (-1); /*STUB*/ + src/linux/proc.c: return (0); /* STUB */ + src/linux/proc.c: return (0); /* STUB */ + src/linux/proc.c: return (0); /* STUB */ + src/linux/proc.c: return (0); /* STUB */ + src/linux/proc.c: return (0); /* STUB */ + src/linux/read.c: return (-1); /* STUB */ + src/linux/timer.c: return (0); /* STUB */ + src/linux/vnode.c: return (-1); /* FIXME - STUB */ + src/linux/write.c: return (-1); /* STUB */ + src/posix/timer.c: return (-1); /* STUB */ + src/solaris/socket.c: return (-1); /* STUB */ + src/solaris/timer.c: return (-1); /* STUB */ + src/windows/read.c: return (-1); /* STUB */ + src/windows/timer.c: return (0); /* STUB */ + From 3b88ebe0813bd2d474b5b1526456e50ebad69524 Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 20 Apr 2012 18:18:30 +0000 Subject: [PATCH 0501/1120] Document the need to use deferred cancellation with specific cancellation points. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@540 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/BUGS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vendor/libkqueue/BUGS b/vendor/libkqueue/BUGS index 4e9e1ca56..ae6bf9e36 100644 --- a/vendor/libkqueue/BUGS +++ b/vendor/libkqueue/BUGS @@ -45,3 +45,9 @@ src/windows/read.c: return (-1); /* STUB */ src/windows/timer.c: return (0); /* STUB */ + * kqueue() should defer thread cancellation until the end. + + * kevent() should defer thread cancellation and call pthread_testcancel() + before and after the call to kevent_wait(). This may require changing the + way that EINTR is handled, to make sure that the EINTR is propagated up + the call stack to kevent(). From 6b9fcd0dd1aab23eec34cdfa97de1634f0af4063 Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 26 Oct 2012 01:42:30 +0000 Subject: [PATCH 0502/1120] Warn people not to use the trunk git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@562 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/TODO | 1 + vendor/libkqueue/src/common/kqueue.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/vendor/libkqueue/TODO b/vendor/libkqueue/TODO index 6ebb725fd..527f8731b 100644 --- a/vendor/libkqueue/TODO +++ b/vendor/libkqueue/TODO @@ -17,3 +17,4 @@ * Check other filters for the EV_DISPATCH bug that was fixed in r252. + * Merge the fix from r546 in the stable branch. diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 8e9b49ff2..195d8ec5a 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -114,6 +114,8 @@ kqueue(void) struct kqueue *kq; struct kqueue *tmp; +#error The libkqueue trunk is broken, please use the stable branch instead + kq = calloc(1, sizeof(*kq)); if (kq == NULL) return (-1); From 17f6ca40fb8120c2c64e8583f3dd9f5b28200475 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 25 Nov 2012 20:46:02 +0000 Subject: [PATCH 0503/1120] * Remove the SERIALIZE_KEVENT macro, and always protect kevent_copyin() and kevent_copyout() with a mutex. * Remove fine-grained locking at the knote level. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@585 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 13 +++++++++---- vendor/libkqueue/src/common/kevent.c | 12 ------------ vendor/libkqueue/src/common/knote.c | 18 +----------------- vendor/libkqueue/src/common/kqueue.c | 2 -- vendor/libkqueue/src/common/private.h | 18 ------------------ vendor/libkqueue/src/linux/platform.c | 3 --- vendor/libkqueue/src/solaris/platform.c | 7 ------- vendor/libkqueue/src/windows/platform.c | 6 +----- 8 files changed, 11 insertions(+), 68 deletions(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 4e82ae47f..bcdaec257 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,10 +1,15 @@ HEAD ------------------------------------------------------------------------ - * Add a counter that increments on each each kevent() call. When printing - debug information within kevent(), display the value of the counter. - This will be helpful when debugging a multithreaded program that may have - multiple kevent() calls executing in parallel. (Credit: Julien Blache) + * Remove the SERIALIZE_KEVENT macro, and always protect kevent_copyin() + and kevent_copyout() with a mutex. + + * Remove fine-grained locking at the knote level. + + * Add a counter that increments on each each kevent() call. When printing + debug information within kevent(), display the value of the counter. + This will be helpful when debugging a multithreaded program that may have + multiple kevent() calls executing in parallel. (Credit: Julien Blache) 2010-09-18 v1.0 r344 ------------------------------------------------------------------------ diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index abd947285..c8bb09e03 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -172,22 +172,18 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) if (src->flags & EV_DELETE) { rv = knote_delete(filt, kn); dbg_printf("knote_delete returned %d", rv); - /* NOTE: the knote lock was dropped by knote_delete() */ } else if (src->flags & EV_DISABLE) { kn->kev.flags |= EV_DISABLE; rv = filt->kn_disable(filt, kn); dbg_printf("kn_disable returned %d", rv); - knote_unlock(kn); } else if (src->flags & EV_ENABLE) { kn->kev.flags &= ~EV_DISABLE; rv = filt->kn_enable(filt, kn); dbg_printf("kn_enable returned %d", rv); - knote_unlock(kn); } else if (src->flags & EV_ADD || src->flags == 0 || src->flags & EV_RECEIPT) { kn->kev.udata = src->udata; rv = filt->kn_modify(filt, kn, src); dbg_printf("kn_modify returned %d", rv); - knote_unlock(kn); } return (rv); @@ -262,13 +258,9 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, * Process each kevent on the changelist. */ if (nchanges > 0) { -#if SERIALIZE_KEVENT kqueue_lock(kq); -#endif rv = kevent_copyin(kq, changelist, nchanges, eventlist, nevents); -#if SERIALIZE_KEVENT kqueue_unlock(kq); -#endif dbg_printf("(%u) changelist: rv=%d", myid, rv); if (rv < 0) goto out; @@ -289,13 +281,9 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, rv = kqops.kevent_wait(kq, nevents, timeout); dbg_printf("kqops.kevent_wait returned %d", rv); if (fastpath(rv > 0)) { -#if SERIALIZE_KEVENT kqueue_lock(kq); -#endif rv = kqops.kevent_copyout(kq, rv, eventlist, nevents); -#if SERIALIZE_KEVENT kqueue_unlock(kq); -#endif } else if (rv == 0) { /* Timeout reached */ } else { diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index a0f501e20..ff10c346f 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -46,7 +46,6 @@ knote_new(void) if (res == NULL) return (NULL); - tracing_mutex_init(&res->kn_mtx, NULL); //TODO: error checking res->kn_ref = 1; return (res); @@ -57,20 +56,15 @@ knote_release(struct knote *kn) { assert (kn->kn_ref > 0); - tracing_mutex_assert(&kn->kn_mtx, MTX_LOCKED); - if (atomic_dec(&kn->kn_ref) == 0) { if (kn->kn_flags & KNFL_KNOTE_DELETED) { dbg_printf("freeing knote at %p", kn); - knote_unlock(kn); - tracing_mutex_destroy(&kn->kn_mtx); free(kn); } else { dbg_puts("this should never happen"); } } else { dbg_printf("decrementing refcount of knote %p rc=%d", kn, kn->kn_ref); - knote_unlock(kn); } } @@ -88,24 +82,19 @@ knote_delete(struct filter *filt, struct knote *kn) struct knote query; struct knote *tmp; - tracing_mutex_assert(&kn->kn_mtx, MTX_LOCKED); - if (kn->kn_flags & KNFL_KNOTE_DELETED) { dbg_puts("ERROR: double deletion detected"); return (-1); } /* - * Drop the knote lock, and acquire both the knotelist write lock - * and the knote lock. Verify that the knote wasn't removed by another + * Verify that the knote wasn't removed by another * thread before we acquired the knotelist lock. */ query.kev.ident = kn->kev.ident; - knote_unlock(kn); pthread_rwlock_wrlock(&filt->kf_knote_mtx); tmp = RB_FIND(knt, &filt->kf_knote, &query); if (tmp == kn) { - knote_lock(kn); RB_REMOVE(knt, &filt->kf_knote, kn); } pthread_rwlock_unlock(&filt->kf_knote_mtx); @@ -129,8 +118,6 @@ knote_lookup(struct filter *filt, uintptr_t ident) pthread_rwlock_rdlock(&filt->kf_knote_mtx); ent = RB_FIND(knt, &filt->kf_knote, &query); - if (ent != NULL) - knote_lock(ent); pthread_rwlock_unlock(&filt->kf_knote_mtx); #ifdef __x86_64__ @@ -154,7 +141,6 @@ knote_get_by_data(struct filter *filt, intptr_t data) break; } if (kn != NULL) { - knote_lock(kn); knote_retain(kn); } pthread_rwlock_unlock(&filt->kf_knote_mtx); @@ -168,8 +154,6 @@ knote_disable(struct filter *filt, struct knote *kn) { assert(!(kn->kev.flags & EV_DISABLE)); - tracing_mutex_assert(&kn->kn_mtx, MTX_LOCKED); - filt->kn_disable(filt, kn); //TODO: Error checking KNOTE_DISABLE(kn); return (0); diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 195d8ec5a..8e9b49ff2 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -114,8 +114,6 @@ kqueue(void) struct kqueue *kq; struct kqueue *tmp; -#error The libkqueue trunk is broken, please use the stable branch instead - kq = calloc(1, sizeof(*kq)); if (kq == NULL) return (-1); diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 451b01bdc..9f5e8cb49 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -22,12 +22,6 @@ #include #include "tree.h" -/* If true, calls to kevent() will be serialized so that only a - single thread can copyin/copyout. This should go away once - fine-grained locking is fixed. -*/ -#define SERIALIZE_KEVENT 1 - /* Maximum events returnable in a single kevent() call */ #define MAX_KEVENT 512 @@ -86,7 +80,6 @@ struct knote { void *handle; /* Used by win32 filters */ } data; struct kqueue* kn_kq; - tracing_mutex_t kn_mtx; volatile uint32_t kn_ref; #if defined(KNOTE_PLATFORM_SPECIFIC) KNOTE_PLATFORM_SPECIFIC; @@ -194,17 +187,6 @@ void knote_insert(struct filter *, struct knote *); int knote_delete(struct filter *, struct knote *); int knote_init(void); int knote_disable(struct filter *, struct knote *); -void knote_lock(struct knote *); - -#define knote_lock(kn) do { \ - tracing_mutex_assert(&(kn)->kn_mtx, MTX_UNLOCKED); \ - tracing_mutex_lock(&(kn)->kn_mtx); \ -} while (0) - -#define knote_unlock(kn) do { \ - tracing_mutex_assert(&(kn)->kn_mtx, MTX_LOCKED); \ - tracing_mutex_unlock(&(kn)->kn_mtx); \ -} while (0) int filter_lookup(struct filter **, struct kqueue *, short); int filter_register_all(struct kqueue *); diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index e8f35ff84..056fb0ab7 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -157,7 +157,6 @@ linux_kevent_copyout(struct kqueue *kq, int nready, for (i = 0; i < nready; i++) { ev = &epevt[i]; kn = (struct knote *) ev->data.ptr; - knote_lock(kn); filt = &kq->kq_filt[~(kn->kev.filter)]; rv = filt->kf_copyout(eventlist, kn, ev); if (slowpath(rv < 0)) { @@ -174,8 +173,6 @@ linux_kevent_copyout(struct kqueue *kq, int nready, knote_disable(filt, kn); //FIXME: Error checking if (eventlist->flags & EV_ONESHOT) { knote_delete(filt, kn); //FIXME: Error checking - } else { - knote_unlock(kn); } /* If an empty kevent structure is returned, the event is discarded. */ diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index bbaa1a64a..e94562a99 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -158,8 +158,6 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, skip_event = 0; dbg_printf("event=%s", port_event_dump(evt)); - knote_lock(kn); - switch (evt->portev_source) { case PORT_SOURCE_FD: //XXX-FIXME WHAT ABOUT WRITE??? @@ -206,7 +204,6 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, if (rv < 0) { dbg_puts("kevent_copyout failed"); - knote_unlock(kn); return (-1); } @@ -220,10 +217,6 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, { knote_delete(filt, kn); //TODO: Error checking } - else - { - knote_unlock(kn); - } if (skip_event) skipped_events++; diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 309a8d888..43db11532 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -170,7 +170,6 @@ windows_kevent_copyout(struct kqueue *kq, int nready, //FIXME: not true for EVFILT_IOCP kn = (struct knote *) iocp_buf.overlap; - knote_lock(kn); filt = &kq->kq_filt[~(kn->kev.filter)]; rv = filt->kf_copyout(eventlist, kn, &iocp_buf); if (slowpath(rv < 0)) { @@ -187,11 +186,8 @@ windows_kevent_copyout(struct kqueue *kq, int nready, */ if (eventlist->flags & EV_DISPATCH) knote_disable(filt, kn); //TODO: Error checking - if (eventlist->flags & EV_ONESHOT) { + if (eventlist->flags & EV_ONESHOT) knote_delete(filt, kn); //TODO: Error checking - } else { - knote_unlock(kn); - } /* If an empty kevent structure is returned, the event is discarded. */ if (fastpath(eventlist->filter != 0)) { From ee78453eac44a5f8ba676c01a838fd13d0ac8054 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 25 Nov 2012 21:35:37 +0000 Subject: [PATCH 0504/1120] Avoid generating extra code if NDEBUG is defined git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@588 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kevent.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index c8bb09e03..f2903447e 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -234,10 +234,14 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout) { - static unsigned int _kevent_counter = 0; struct kqueue *kq; int rv = 0; - unsigned int myid; +#ifndef NDEBUG + static unsigned int _kevent_counter = 0; + unsigned int myid = 0; + + (void) myid; +#endif /* Convert the descriptor into an object pointer */ kq = kqueue_lookup(kqfd); @@ -246,13 +250,12 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, return (-1); } +#ifndef NDEBUG if (DEBUG_KQUEUE) { myid = atomic_inc(&_kevent_counter); dbg_printf("--- kevent %u --- (nchanges = %d, nevents = %d)", myid, nchanges, nevents); - } else { - myid = 0; - (void) myid; } +#endif /* * Process each kevent on the changelist. @@ -292,6 +295,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, } } +#ifndef NDEBUG if (DEBUG_KQUEUE) { int n; @@ -300,6 +304,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, dbg_printf("(%u) eventlist[%d] = %s", myid, n, kevent_dump(&eventlist[n])); } } +#endif out: dbg_printf("--- END kevent %u ret %d ---", myid, rv); From 74ee31b99d52cc5dcac0b0ce74da8bd6fea2c09d Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 25 Nov 2012 21:52:11 +0000 Subject: [PATCH 0505/1120] Merge c542 from the stable branch. Fixes a concurrency problem in posix_kevent_wait() git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@589 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/posix/kevent.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/posix/kevent.c b/vendor/libkqueue/src/posix/kevent.c index 6ebb62e14..722ec0ca3 100644 --- a/vendor/libkqueue/src/posix/kevent.c +++ b/vendor/libkqueue/src/posix/kevent.c @@ -26,11 +26,14 @@ posix_kevent_wait( struct kqueue *kq, const struct timespec *timeout) { - int n; + int n, nfds; + fd_set rfds; + + nfds = kq->kq_nfds; + rfds = kq->kq_fds; dbg_puts("waiting for events"); - kq->kq_rfds = kq->kq_fds; - n = pselect(kq->kq_nfds, &kq->kq_rfds, NULL , NULL, timeout, NULL); + n = pselect(nfds, &rfds, NULL , NULL, timeout, NULL); if (n < 0) { if (errno == EINTR) { dbg_puts("signal caught"); @@ -40,6 +43,8 @@ posix_kevent_wait( return (-1); } + kq->kq_rfds = rfds; + return (n); } From 08259d6c19f0be68131e328de248948cdf406454 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 25 Nov 2012 22:31:57 +0000 Subject: [PATCH 0506/1120] * Ensure that calling close() on a file descriptor will remove any kevents that reference the descriptor. [merged from ^/branches/stable@551] git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@590 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 3 +++ vendor/libkqueue/src/linux/vnode.c | 13 ++++++++++++- vendor/libkqueue/test/vnode.c | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index bcdaec257..576c529c3 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,6 +1,9 @@ HEAD ------------------------------------------------------------------------ + * Ensure that calling close() on a file descriptor will remove any + kevents that reference the descriptor. [merged from ^/branches/stable@551] + * Remove the SERIALIZE_KEVENT macro, and always protect kevent_copyin() and kevent_copyout() with a mutex. diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 69434675d..57ad0b833 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -100,7 +100,7 @@ add_watch(struct filter *filt, struct knote *kn) return (-1); /* Convert the fflags to the inotify mask */ - mask = 0; + mask = IN_CLOSE; if (kn->kev.fflags & NOTE_DELETE) mask |= IN_ATTRIB | IN_DELETE_SELF; if (kn->kev.fflags & NOTE_WRITE) @@ -179,6 +179,17 @@ evfilt_vnode_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) dbg_printf("inotify event: %s", inotify_event_dump(&evt)); if (evt.mask & IN_IGNORED) { /* TODO: possibly return error when fs is unmounted */ + dst->filter = 0; + return (0); + } + + /* Check if the watched file has been closed, and + XXX-this may not exactly match the kevent() behavior if multiple file de +scriptors reference the same file. + */ + if (evt.mask & IN_CLOSE_WRITE || evt.mask & IN_CLOSE_NOWRITE) { + src->kn_flags |= EV_ONESHOT; /* KLUDGE: causes the knote to be deleted */ + dst->filter = 0; /* KLUDGE: causes the event to be discarded */ return (0); } diff --git a/vendor/libkqueue/test/vnode.c b/vendor/libkqueue/test/vnode.c index 638b9b0a2..06db4a9ba 100644 --- a/vendor/libkqueue/test/vnode.c +++ b/vendor/libkqueue/test/vnode.c @@ -258,5 +258,7 @@ test_evfilt_vnode(struct test_context *ctx) test(kevent_vnode_note_attrib, ctx); test(kevent_vnode_note_rename, ctx); test(kevent_vnode_note_delete, ctx); + /* TODO: test r590 corner case where a descriptor is closed and + the associated knote is automatically freed. */ unlink(ctx->testfile); } From 93429de04a479490d4cfd416e8bde33fca1fc292 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 26 Nov 2012 02:32:45 +0000 Subject: [PATCH 0507/1120] Use pthread_once() instead of marking libkqueue_init() as a constructor. This gives the correct behavior for both static and dynamic libraries. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@591 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/BUGS | 3 +++ vendor/libkqueue/src/common/kqueue.c | 15 ++++++++++----- vendor/libkqueue/src/common/private.h | 2 -- vendor/libkqueue/src/posix/platform.h | 5 ----- vendor/libkqueue/src/windows/platform.c | 3 +-- vendor/libkqueue/src/windows/platform.h | 6 ------ 6 files changed, 14 insertions(+), 20 deletions(-) diff --git a/vendor/libkqueue/BUGS b/vendor/libkqueue/BUGS index ae6bf9e36..344267209 100644 --- a/vendor/libkqueue/BUGS +++ b/vendor/libkqueue/BUGS @@ -1,3 +1,6 @@ + * On Windows, you need to supply -DMAKE_STATIC in CFLAGS when building the + static library. This does not apply when using cmake. + * When passing a knote pointer to the kernel, the reference count of the knote structure should be incremented. Conversely, when the pointer has been returned from the kernel and the event unregistered from the diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 8e9b49ff2..426313571 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -27,6 +27,11 @@ int DEBUG_KQUEUE = 0; char *KQUEUE_DEBUG_IDENT = "KQ"; +#ifndef _WIN32 +pthread_mutex_t kq_mtx = PTHREAD_MUTEX_INITIALIZER; +pthread_once_t kq_is_initialized = PTHREAD_ONCE_INIT; +#endif + static unsigned int get_fd_limit(void) { @@ -51,10 +56,7 @@ get_fd_limit(void) static struct map *kqmap; -int CONSTRUCTOR -#ifdef MAKE_STATIC - VISIBLE -#endif +static void libkqueue_init(void) { #ifdef NDEBUG @@ -80,7 +82,6 @@ libkqueue_init(void) if (knote_init() < 0) abort(); dbg_puts("library initialization complete"); - return (0); } #if DEADWOOD @@ -114,6 +115,10 @@ kqueue(void) struct kqueue *kq; struct kqueue *tmp; + (void) pthread_mutex_lock(&kq_mtx); + (void) pthread_once(&kq_is_initialized, libkqueue_init); + (void) pthread_mutex_unlock(&kq_mtx); + kq = calloc(1, sizeof(*kq)); if (kq == NULL) return (-1); diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 9f5e8cb49..2abf96c5f 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -208,6 +208,4 @@ void *map_lookup(struct map *, int); void *map_delete(struct map *, int); void map_free(struct map *); -int CONSTRUCTOR libkqueue_init(void); - #endif /* ! _KQUEUE_PRIVATE_H */ diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index b1691719f..ef14e32d0 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -39,11 +39,6 @@ /* * GCC-compatible attributes */ -#ifdef MAKE_STATIC -# define CONSTRUCTOR -#else -# define CONSTRUCTOR __attribute__ ((constructor)) -#endif #define VISIBLE __attribute__((visibility("default"))) #define HIDDEN __attribute__((visibility("hidden"))) #define UNUSED __attribute__((unused)) diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 43db11532..8fb7cdd10 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -58,8 +58,7 @@ BOOL WINAPI DllMain( if (WSAStartup(MAKEWORD(2,2), NULL) != 0) return (FALSE); #endif - if (libkqueue_init() < 0) - return (FALSE); + libkqueue_init(); break; case DLL_PROCESS_DETACH: diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 904163d6a..3d098e3bf 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -99,12 +99,6 @@ int windows_filter_init(struct kqueue *, struct filter *); void windows_filter_free(struct kqueue *, struct filter *); int windows_get_descriptor_type(struct knote *); -/* Windows does not support this attribute. - DllMain() is the only available constructor function. - This means the constructor must be called from within DllMain(). - */ -#define CONSTRUCTOR - /* * GCC-compatible branch prediction macros */ From d795045c9eda2d0b3f2c4f16555b20c4a56b97a2 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 26 Nov 2012 02:42:53 +0000 Subject: [PATCH 0508/1120] Convert the build script to Makeconf git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@592 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/{Makefile => Makefile.OLD} | 0 vendor/libkqueue/configure | 388 ++------------------ 2 files changed, 33 insertions(+), 355 deletions(-) rename vendor/libkqueue/{Makefile => Makefile.OLD} (100%) diff --git a/vendor/libkqueue/Makefile b/vendor/libkqueue/Makefile.OLD similarity index 100% rename from vendor/libkqueue/Makefile rename to vendor/libkqueue/Makefile.OLD diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index c6860a847..d4a9095e1 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -1,368 +1,46 @@ #!/bin/sh # -# Copyright (c) 2009-2011 Mark Heily +# Bootstrap configuration script for Makeconf # -# Permission to use, copy, modify, and distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# Author: Mark Heily # -makeconf_version="$Revision: 10 $" - -c_exports="program version target api cflags" - -make_exports="program version target api distfile \ - prefix bindir sbindir libdir includedir mandir \ - cflags ldflags ldadd libdepends \ - sources objs deps mans headers extra_dist subdirs \ - abi_major abi_minor abi_version \ - cc cpp ld ln ar install diff strip" - -required_headers= -optional_headers= - -pre_configure_hook() { - return -} - -post_configure_hook() { - return -} - -export_to_make() { - for id in $* - do - - # Prepend $DESTDIR to installation directories - case "$id" in - prefix) - eval "$id=\"\\\$\\\$DESTDIR\$$id\"" - esac - - uc_id=`echo $id | $tr '[:lower:]' '[:upper:]'`; - eval "echo \"$uc_id=\"\$$id\"\" >> config.mk" - done -} - -export_to_c() { - for id in $* - do - uc_id=`echo $id | $tr '[:lower:]' '[:upper:]'`; - eval "echo \"#define $uc_id \\\"\$$id\\\"\" >> config.h" - done -} - -finalize() { - uc_id=`echo \"$1\" | $tr '[:lower:]' '[:upper:]'`; - eval "if [ \"\$$1\" = \"\" ] ; then $1=\"$2\" ; fi" -} - -process_argv() { - for arg in $* - do - if [ "$arg" = "--makeconf-version" ] ; then - echo $makeconf_version | sed 's/[^0-9.]//g' - exit 0 - fi - id=`echo "$arg" | sed 's/=.*//; s/^--//;'` - val=`echo "$arg" | sed 's/^.*=//'` - if [ "$val" = "" ] ; then val=1 ; fi - eval "$id=\"$val\"" - done -} - -process_env() { - test -n "$CC" && cc="$CC" - test -n "$CPP" && cpp="$CPP" - test -n "$CPPFLAGS" && cppflags="$CPPFLAGS" - test -n "$CFLAGS" && cflags="$CFLAGS" - test -n "$LD" && ld="$LD" - test -n "$LN" && ld="$LN" - test -n "$LDFLAGS" && ldflags="$LDFLAGS" - test -n "$AR" && ar="$AR" -} - -check_header() { - sym=`echo "have_$1" | sed 's,[./],_,g'` - uc_sym=`echo "$sym" | $tr '[:lower:]' '[:upper:]'`; - path=$1 - - printf "checking for $path.. " - if [ -f "/usr/include/$path" ] ; then - echo "yes" - echo "#define $uc_sym 1" >> config.h - eval "$sym=yes" - return 0 - else - echo "no" - echo "#undef $uc_sym" >> config.h - eval "$sym=no" - return 1 - fi -} - -# Determine the path to an executable binary -check_binary() { - id=$1 - shift - - for path in $* - do - test -f $path - if [ $? = 0 ] ; then - eval "$id=\"$path\"" - return - fi - done - - echo "not found" - return -} - -check_headers() { - for header in $* - do - check_header "$header" - done -} - -check_symbol() { - header=$1 - symbol=$2 - - uc_symbol=`echo "HAVE_$symbol" | $tr '[:lower:]' '[:upper:]' | sed 's,[./],_,g'` - lc_symbol=`echo "have_$symbol" | $tr '[:upper:]' '[:lower:]' | sed 's,[./],_,g'` - - if [ -f "$header" ] ; then - path="$header" - elif [ -f "/usr/include/$header" ] ; then - path="/usr/include/$header" - else - echo "*** ERROR: Cannot find <$header>" - exit 1 - fi - - printf "checking $header for $symbol.. " - if [ "`grep $symbol $path`" != "" ] ; then - eval "$lc_symbol=yes" - echo "#define $uc_symbol 1" >> config.h - echo "yes" - return 0 - else - eval "$lc_symbol=no" - echo "no" - echo "#undef $uc_symbol" >> config.h - return 1 - fi -} - -check_install() { - printf "checking for a BSD-compatible install.. " - if [ "`uname -s`" = "SunOS" ] ; then - default_install=/usr/ucb/install - else - default_install=/usr/bin/install - fi - finalize install "$default_install" - echo "$install" -} - -check_target() { - printf "checking operating system type.. " - default_target=`uname -s | $tr '[:upper:]' '[:lower:]'` - default_api="posix" - case "$default_target" in - sunos) - default_target="solaris" - ;; - "gnu/kfreebsd") - default_target="freebsd" - ;; - mingw*) - default_target="windows" - default_api="windows" - ;; - esac - finalize target "$default_target" - finalize api "$default_api" - echo "$api-$target" -} - -check_compiler() { - printf "checking for a C compiler.. " - check_binary default_cc "$cc" "`which $cc 2>/dev/null`" "/usr/bin/cc" "/usr/bin/gcc" "/usr/sfw/bin/gcc" "`which gcc 2>/dev/null`" - finalize cc "$default_cc" -# test -x "$cc" || err "Unable to locate a C compiler" - echo "$cc" -} - -check_linker() { - printf "checking for a suitable linker.. " - - # Workaround for "hidden symbol is referenced by DSO" linker error - # seen when compiling libdispatch. - # Appears to be a problem with GCC 4.0 and binutils - # - default_ld="$cc" - ldflags="-o $program.so.$abi_major.$abi_minor $ldflags" - - # FIXME: port to solaris - if [ "$target" = "linux" ] ; then - ldflags="$ldflags -Wl,-export-dynamic -Wl,-soname,$program.so.$abi_major" - fi - - if [ "$target" = "solaris" ] ; then - ldflags="$ldflags" - fi - - finalize ld "$default_ld" - echo "$ld" -} - -check_archiver() { - printf "checking for a suitable archiver.. " - if [ "`uname -s`" = "SunOS" -a "`uname -v | grep Nexenta`" = "" ] ; then - default_ar="/usr/sfw/bin/gar" - else - default_ar="/usr/bin/ar" - fi - finalize ar "$default_ar" - echo "$ar" +die() { + printf "\n*** ERROR: $1 ***\n\n$2\n\n" + exit 1 } -err() { - echo "*** ERROR *** $*" - rm -f config.mk $program.pc config.h - exit 1 -} - -check_diff() { - # TODO: Support non-GNU diff syntax - # TODO: Search for the command - printf "checking for a suitable diff(1) command.. " - finalize diff "diff -ruN -dEbwBp -x .svn -x .o -x config.h -x config.mk" - echo "found" -} - -check_strip() { - printf "checking for a suitable strip(1) command.. " - if [ "`uname -s`" = "SunOS" ] ; then - finalize strip "/usr/sfw/bin/gstrip --strip-unneeded" - else - finalize strip "/usr/bin/strip --strip-unneeded" - fi - echo "found" -} - -subst_vars() { - outfile=$1 - - if [ ! -f "${outfile}.in" ] ; then - return - fi - - echo "Creating $outfile" - rm -f $outfile - sed -e " - s,@@CWD@@,`pwd`,g; - s,@@PROGRAM@@,$program,g; - s,@@VERSION@@,$version,g; - s,@@PREFIX@@,$prefix,g; - s,@@LIBDIR@@,$libdir,g; - s,@@INCLUDEDIR@@,$includedir,g; - s,@@MANDIR@@,$mandir,g; - s,@@LIBDEPENDS@@,$libdepends,g; - s,@@PKG_SUMMARY@@,$pkg_summary,g; - s,@@RPM_DATE@@,`date +'%a %b %d %Y'`,g; - s,@@PKG_DESCRIPTION@@,$pkg_description,g; - s,@@LICENSE@@,$license,g; - s,@@AUTHOR@@,$author,g; - " < ${outfile}.in > $outfile - chmod 400 $outfile -} - -####################################################################### -# -# MAIN() -# -####################################################################### - -# Workaround for Solaris "Bad string" issue when LOCALE is undefined -tr="/usr/bin/tr" -test -f /usr/xpg4/bin/tr && tr="/usr/xpg4/bin/tr" - -. ./config.inc - -# Initialize the output files -# -for output_file in config.mk -do - rm -f $output_file - echo "# AUTOMATICALLY GENERATED -- DO NOT EDIT" > $output_file -done -if [ "$sources" != "" ] ; then - rm -f config.h - echo "/* AUTOMATICALLY GENERATED -- DO NOT EDIT */" > config.h +if [ "$RUBY" != "" ] ; then + ruby=$RUBY +else + ruby=`which ruby` fi -process_argv "$*" -process_env - -check_target -check_compiler -check_linker -check_archiver -check_install -check_diff -check_strip - -finalize program "$program" -finalize version "$version" -finalize abi_major "$abi_major" -finalize abi_minor "$abi_minor" -finalize abi_version "$abi_major.$abi_minor" -finalize prefix "/usr/local" -finalize bindir "\\\$(PREFIX)/bin" -finalize sbindir "\\\$(PREFIX)/sbin" -finalize libdir "\\\$(PREFIX)/lib" -finalize includedir "\\\$(PREFIX)/include" -finalize mandir "\\\$(PREFIX)/share/man" -finalize cflags "$cflags" -finalize libdepends "$libdepends" -finalize ldadd "" -finalize ldflags "" -finalize deps "" -finalize ln "`which ln`" -finalize distfile "$program-$version.tar.gz" - -pre_configure_hook - -for header in $required_headers -do - check_header "$header" || err "$header is required, but cannot be found." -done -check_headers $optional_headers - -post_configure_hook - -objs="`echo \"$sources\" | sed 's/\.c/\.o/g'`" +printf 'checking for ruby.. ' +if [ ! -x "$ruby" ] ; then + echo 'no' + die 'Ruby was not found' 'Please install Ruby from http://www.ruby-lang.org/' +fi -subst_vars "$program.pc" -subst_vars "$program.la" -subst_vars "rpm.spec" +if [ "$RUBYLIB" != "" ] ; then + echo "$ruby (RUBYLIB=$RUBYLIB)" + export RUBYLIB +else + echo $ruby +fi -if [ "$sources" != "" ] ; then - echo "Creating config.h" - export_to_c $c_exports +printf 'checking for makeconf.. ' +ruby -e "require 'makeconf'" > /dev/null 2>&1 +if [ $? -ne 0 ] ; then + if [ -x ./makeconf ] ; then + echo 'yes (using local copy)' + ruby="$ruby -I./makeconf" + else + echo 'no' + die 'Makeconf was not found' 'Please install Makeconf from https://rubygems.org/' + fi +else + echo 'yes' fi -echo "Creating config.mk" -export_to_make "$make_exports" +exec $ruby ./configure.rb $* From b334dbc835fda3566b5a5aba0203dfeaa0ef95f3 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 26 Nov 2012 02:56:10 +0000 Subject: [PATCH 0509/1120] Minor fixes for Android git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@593 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/private.h | 5 +++++ vendor/libkqueue/src/linux/platform.h | 10 ++++++++-- vendor/libkqueue/src/linux/vnode.c | 2 +- vendor/libkqueue/test/test.c | 4 ++-- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 2abf96c5f..1bb64b967 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -50,6 +50,11 @@ struct evfilt_data; #include "debug.h" +/* Workaround for Android */ +#ifndef EPOLLONESHOT +# define EPOLLONESHOT (1 << 30) +#endif + struct eventfd { int ef_id; #if defined(EVENTFD_PLATFORM_SPECIFIC) diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 732de4ccb..e533bc413 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -23,8 +23,12 @@ struct filter; #include #include #include -#include -#include +#if HAVE_SYS_SIGNALFD_H +# include +#endif +#if HAVE_SYS_TIMERFD_H +# include +#endif /* * Get the current thread ID @@ -33,7 +37,9 @@ struct filter; # include # include # include +#ifndef __ANDROID__ extern long int syscall (long int __sysno, ...); +#endif /* Convenience macros to access the epoll descriptor for the kqueue */ #define kqueue_epfd(kq) ((kq)->kq_id) diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 57ad0b833..4d5533859 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -77,7 +77,7 @@ get_one_event(struct inotify_event *dst, int inofd) break; } } - dbg_printf("read(2) from inotify wd: %zu bytes", n); + dbg_printf("read(2) from inotify wd: %ld bytes", (long) n); /* FIXME-TODO: if len > 0, read(len) */ if (dst->len != 0) diff --git a/vendor/libkqueue/test/test.c b/vendor/libkqueue/test/test.c index 0e0ea8c26..97017f392 100644 --- a/vendor/libkqueue/test/test.c +++ b/vendor/libkqueue/test/test.c @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifdef __linux__ +#if defined(__linux__) && !defined(__ANDROID__) #include #endif #include @@ -30,7 +30,7 @@ static int error_flag = 1; static void error_handler(int signum) { -#ifdef __linux__ +#if defined(__linux__) && !defined(__ANDROID__) void *buf[32]; /* FIXME: the symbols aren't printing */ From 25552d5c4db26876677f0a2406bda85236af965b Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 26 Nov 2012 03:46:31 +0000 Subject: [PATCH 0510/1120] More fixes for Android git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@594 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/knote.c | 1 - vendor/libkqueue/src/common/private.h | 6 +- vendor/libkqueue/src/linux/timer.c | 29 +++++++++ vendor/libkqueue/src/posix/signal.c | 32 +++++---- vendor/libkqueue/src/posix/timer.c | 93 ++++++++++++++++++--------- 5 files changed, 116 insertions(+), 45 deletions(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index ff10c346f..4dd255073 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -161,4 +161,3 @@ knote_disable(struct filter *filt, struct knote *kn) //TODO: knote_enable() - diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 1bb64b967..b4f75cb53 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -81,7 +81,7 @@ struct knote { off_t size; /* Used by vnode */ } vnode; timer_t timerid; - pthread_t tid; /* Used by posix/timer.c */ + struct sleepreq *sleepreq; /* Used by posix/timer.c */ void *handle; /* Used by win32 filters */ } data; struct kqueue* kn_kq; @@ -120,11 +120,10 @@ struct filter { struct eventfd kf_efd; /* Used by user.c */ -#if DEADWOOD //MOVE TO POSIX? int kf_pfd; /* fd to poll(2) for readiness */ int kf_wfd; /* fd to write when an event occurs */ -#endif + //----? struct evfilt_data *kf_data; /* filter-specific data */ RB_HEAD(knt, knote) kf_knote; @@ -192,6 +191,7 @@ void knote_insert(struct filter *, struct knote *); int knote_delete(struct filter *, struct knote *); int knote_init(void); int knote_disable(struct filter *, struct knote *); +#define knote_get_filter(knt) &((knt)->kn_kq->kq_filt[(knt)->kev.filter]) int filter_lookup(struct filter **, struct kqueue *, short); int filter_register_all(struct kqueue *); diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 90fe1323e..fb8337514 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -16,6 +16,35 @@ #include "private.h" +/* Android 4.0 does not have this header, but the kernel supports timerfds */ +#ifndef HAVE_SYS_TIMERFD_H + +#ifdef __ARM_ARCH_5__ +#define __NR_timerfd_create (__NR_SYSCALL_BASE+350) +#define __NR_timerfd_settime (__NR_SYSCALL_BASE+353) +#define __NR_timerfd_gettime (__NR_SYSCALL_BASE+354) +#else +#error Unsupported architecture, need to get the syscall numbers +#endif + +int timerfd_create(int clockid, int flags) +{ + return syscall(__NR_timerfd_create, clockid, flags); +} + +int timerfd_settime(int ufc, int flags, const struct itimerspec *utmr, + struct itimerspec *otmr) +{ + return syscall(__NR_timerfd_settime, ufc, flags, utmr, otmr); +} + +int timerfd_gettime(int ufc, struct itimerspec *otmr) +{ + return syscall(__NR_timerfd_gettime, ufc, otmr); +} + +#endif + #ifndef NDEBUG static char * itimerspec_dump(struct itimerspec *ts) diff --git a/vendor/libkqueue/src/posix/signal.c b/vendor/libkqueue/src/posix/signal.c index f55c12adc..babbc8974 100644 --- a/vendor/libkqueue/src/posix/signal.c +++ b/vendor/libkqueue/src/posix/signal.c @@ -41,22 +41,25 @@ struct sentry { static pthread_mutex_t sigtbl_mtx = PTHREAD_MUTEX_INITIALIZER; static struct sentry sigtbl[SIGNAL_MAX]; +/* XXX-FIXME this will not work with multiple kqueue objects. + Need a linked list? Or should signals be delivered to all kqueue objects? + */ +static struct eventfd * sig_eventfd; + static void signal_handler(int sig) { struct sentry *s = &sigtbl[sig]; - ssize_t n; dbg_printf("caught sig=%d", sig); atomic_inc(&s->s_cnt); #if defined(__sun__) - n = 0;//FIXME: workaround if (port_send(s->s_filt->kf_kqueue->kq_port, X_PORT_SOURCE_SIGNAL, &sigtbl[sig]) < 0) { return; //FIXME: errorhandling } #else - n = write(s->s_filt->kf_wfd, &sig, sizeof(sig));//FIXME:errhandling + kqops.eventfd_raise(sig_eventfd); #endif } @@ -111,13 +114,16 @@ ignore_signal(int sig) int evfilt_signal_init(struct filter *filt) { - return filter_socketpair(filt); + if (kqops.eventfd_init(&filt->kf_efd) < 0) + return (-1); + sig_eventfd = &filt->kf_efd; // XXX - does not work w/ multiple kqueues + return (0); } void evfilt_signal_destroy(struct filter *filt) { - close(filt->kf_pfd); + kqops.eventfd_close(&filt->kf_efd); } int @@ -138,6 +144,7 @@ int evfilt_signal_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { + (void) filt; kn->kev.flags = kev->flags | EV_CLEAR; return (0); } @@ -145,6 +152,7 @@ evfilt_signal_knote_modify(struct filter *filt, struct knote *kn, int evfilt_signal_knote_delete(struct filter *filt, struct knote *kn) { + (void) filt; return ignore_signal(kn->kev.ident); } @@ -157,18 +165,18 @@ evfilt_signal_knote_enable(struct filter *filt, struct knote *kn) int evfilt_signal_knote_disable(struct filter *filt, struct knote *kn) { + (void) filt; return ignore_signal(kn->kev.ident); } int -evfilt_signal_copyout(struct filter *filt, - struct kevent *dst, - int nevents) +evfilt_signal_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) { struct sentry *s; struct knote *kn; int sig; - ssize_t n; + + (void) src; #if defined(__sun__) port_event_t pe; @@ -176,9 +184,9 @@ evfilt_signal_copyout(struct filter *filt, port_event_dequeue(&pe, filt->kf_kqueue); s = (struct sentry *) pe.portev_user; sig = s - &sigtbl[0]; - n = 0; //FIXME: Workaround #else - n = read(filt->kf_pfd, &sig, sizeof(sig));//FIXME:errhandling + kqops.eventfd_lower(sig_eventfd); + sig = 1; //XXX-FIXME totally broken, workaround just to compile s = &sigtbl[sig]; #endif @@ -192,6 +200,7 @@ evfilt_signal_copyout(struct filter *filt, dst->fflags = 0; dst->data = 1; +#if DEADWOOD if (kn->kev.flags & EV_DISPATCH) { ignore_signal(kn->kev.ident); KNOTE_DISABLE(kn); @@ -199,6 +208,7 @@ evfilt_signal_copyout(struct filter *filt, ignore_signal(kn->kev.ident); knote_free(filt, kn); } +#endif return (1); } diff --git a/vendor/libkqueue/src/posix/timer.c b/vendor/libkqueue/src/posix/timer.c index f0f9bc438..a7e383d18 100644 --- a/vendor/libkqueue/src/posix/timer.c +++ b/vendor/libkqueue/src/posix/timer.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,8 @@ struct sleepreq { int wfd; /* fd to wake up when sleep is over */ uintptr_t ident; /* from kevent */ intptr_t interval; /* sleep time, in milliseconds */ + pthread_cond_t cond; + pthread_mutex_t mtx; struct sleepstat *stat; }; @@ -48,45 +51,59 @@ struct sleepinfo { static void * sleeper_thread(void *arg) { - struct sleepreq sr; + struct sleepreq *sr = (struct sleepreq *) arg; struct sleepinfo si; - struct timespec req, rem; + struct timeval now; + struct timespec req; sigset_t mask; ssize_t cnt; bool cts = true; /* Clear To Send */ char buf[1]; + int rv; +#if 0 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); - - /* Copyin the request */ - memcpy(&sr, arg, sizeof(sr)); - free(arg); +#endif /* Initialize the response */ - si.ident = sr.ident; + si.ident = sr->ident; si.counter = 0; - /* Convert milliseconds into seconds+nanoseconds */ - req.tv_sec = sr.interval / 1000; - req.tv_nsec = (sr.interval % 1000) * 1000000; - /* Block all signals */ sigfillset(&mask); (void) pthread_sigmask(SIG_BLOCK, &mask, NULL); for (;;) { + pthread_mutex_lock(&sr->mtx); + + /* Convert the timeout into an absolute time */ + /* Convert milliseconds into seconds+nanoseconds */ + gettimeofday(&now, NULL); + req.tv_sec = now.tv_sec + sr->interval / 1000; + req.tv_nsec = now.tv_usec + ((sr->interval % 1000) * 1000000); + /* Sleep */ - if (nanosleep(&req, &rem) < 0) { - //TODO: handle eintr, spurious wakeups - dbg_perror("nanosleep(2)"); + dbg_printf("sleeping for %ld ms", (unsigned long) sr->interval); + rv = pthread_cond_timedwait(&sr->cond, &sr->mtx, &req); + pthread_mutex_unlock(&sr->mtx); + if (rv == 0) { + /* _timer_delete() has requested that we terminate */ + dbg_puts("terminating sleeper thread"); + break; + } else if (rv != 0) { + dbg_printf("rv=%d %s", rv, strerror(rv)); + if (rv == EINTR) + abort(); //FIXME should not happen + + //ASSUME: rv == ETIMEDOUT } si.counter++; dbg_printf(" -------- sleep over (CTS=%d)----------", cts); /* Test if the previous wakeup has been acknowledged */ if (!cts) { - cnt = read(sr.wfd, &buf, 1); + cnt = read(sr->wfd, &buf, 1); if (cnt < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { ; @@ -104,11 +121,11 @@ sleeper_thread(void *arg) /* Wake up kevent waiters if they are ready */ if (cts) { - cnt = write(sr.wfd, &si, sizeof(si)); + cnt = write(sr->wfd, &si, sizeof(si)); if (cnt < 0) { - /* FIXME: handle EAGAIN and EINTR */ + /* FIXME: handle EAGAIN */ dbg_perror("write(2)"); - } else if (cnt < sizeof(si)) { + } else if ((size_t)cnt < sizeof(si)) { dbg_puts("FIXME: handle short write"); } cts = false; @@ -116,6 +133,7 @@ sleeper_thread(void *arg) } } + dbg_puts("sleeper thread exiting"); return (NULL); } @@ -123,6 +141,7 @@ static int _timer_create(struct filter *filt, struct knote *kn) { pthread_attr_t attr; + pthread_t tid; struct sleepreq *req; kn->kev.flags |= EV_CLEAR; @@ -135,10 +154,13 @@ _timer_create(struct filter *filt, struct knote *kn) req->wfd = filt->kf_wfd; req->ident = kn->kev.ident; req->interval = kn->kev.data; + kn->data.sleepreq = req; + pthread_cond_init(&req->cond, NULL); + pthread_mutex_init(&req->mtx, NULL); pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - if (pthread_create(&kn->data.tid, &attr, sleeper_thread, req) != 0) { + if (pthread_create(&tid, &attr, sleeper_thread, req) != 0) { dbg_perror("pthread_create"); pthread_attr_destroy(&attr); free(req); @@ -152,12 +174,14 @@ _timer_create(struct filter *filt, struct knote *kn) static int _timer_delete(struct knote *kn) { - if (pthread_cancel(kn->data.tid) != 0) { - /* Race condition: sleeper_thread exits before it is cancelled */ - if (errno == ENOENT) - return (0); - dbg_perror("pthread_cancel(3)"); - return (-1); + if (kn->data.sleepreq != NULL) { + dbg_puts("deleting timer"); + pthread_mutex_lock(&kn->data.sleepreq->mtx); //FIXME - error check + pthread_cond_signal(&kn->data.sleepreq->cond); //FIXME - error check + pthread_mutex_unlock(&kn->data.sleepreq->mtx); //FIXME - error check + pthread_cond_destroy(&kn->data.sleepreq->cond); //FIXME - error check + free(kn->data.sleepreq); + kn->data.sleepreq = NULL; } return (0); } @@ -193,21 +217,24 @@ evfilt_timer_destroy(struct filter *filt) } int -evfilt_timer_copyout(struct filter *filt, - struct kevent *dst, - int nevents) +evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) { + struct filter *filt; struct sleepinfo si; ssize_t cnt; struct knote *kn; + filt = knote_get_filter(src); + /* Read the ident */ cnt = read(filt->kf_pfd, &si, sizeof(si)); if (cnt < 0) { - /* FIXME: handle EAGAIN and EINTR */ + if (errno == EINTR) + return (-EINTR); + /* FIXME: handle EAGAIN */ dbg_printf("read(2): %s", strerror(errno)); return (-1); - } else if (cnt < sizeof(si)) { + } else if ((size_t)cnt < sizeof(si)) { dbg_puts("error: short read"); return (-1); } @@ -235,6 +262,7 @@ evfilt_timer_copyout(struct filter *filt, dst->data = si.counter; +#if DEADWOOD if (kn->kev.flags & EV_DISPATCH) { KNOTE_DISABLE(kn); _timer_delete(kn); @@ -242,6 +270,7 @@ evfilt_timer_copyout(struct filter *filt, _timer_delete(kn); knote_free(filt, kn); } +#endif return (1); } @@ -256,12 +285,16 @@ int evfilt_timer_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { + (void) filt; + (void) kn; + (void) kev; return (-1); /* STUB */ } int evfilt_timer_knote_delete(struct filter *filt, struct knote *kn) { + (void) filt; if (kn->kev.flags & EV_DISABLE) return (0); From a610c28999f09f521e853ab4e828ff1cfbad442d Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 26 Nov 2012 03:59:02 +0000 Subject: [PATCH 0511/1120] Final fixes for Android. The testsuite runs on Linux and Android now. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@595 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/private.h | 1 + vendor/libkqueue/src/linux/platform.h | 3 --- vendor/libkqueue/src/linux/signal.c | 6 ++++++ vendor/libkqueue/test/vnode.c | 12 ++++++++++-- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index b4f75cb53..0ec34e23c 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -20,6 +20,7 @@ #include #include #include +#include "config.h" #include "tree.h" /* Maximum events returnable in a single kevent() call */ diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index e533bc413..d0fa876e2 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -23,9 +23,6 @@ struct filter; #include #include #include -#if HAVE_SYS_SIGNALFD_H -# include -#endif #if HAVE_SYS_TIMERFD_H # include #endif diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index 341c176b2..425d06c81 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -16,6 +16,12 @@ #include "private.h" +#if HAVE_SYS_SIGNALFD_H +# include +#else +# error signalfd is required +#endif + static void signalfd_reset(int sigfd) { diff --git a/vendor/libkqueue/test/vnode.c b/vendor/libkqueue/test/vnode.c index 06db4a9ba..42dc30f8e 100644 --- a/vendor/libkqueue/test/vnode.c +++ b/vendor/libkqueue/test/vnode.c @@ -245,8 +245,16 @@ test_evfilt_vnode(struct test_context *ctx) return; #endif - snprintf(ctx->testfile, sizeof(ctx->testfile), "/tmp/kqueue-test%d.tmp", - testing_make_uid()); + char *tmpdir = getenv("TMPDIR"); + if (tmpdir == NULL) +#ifdef __ANDROID__ + tmpdir = "/data/local/tmp"; +#else + tmpdir = "/tmp"; +#endif + + snprintf(ctx->testfile, sizeof(ctx->testfile), "%s/kqueue-test%d.tmp", + tmpdir, testing_make_uid()); test(kevent_vnode_add, ctx); test(kevent_vnode_del, ctx); From ab8228df1d9b9eabc9cef2d89444cc1eda640f62 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 26 Nov 2012 23:42:56 +0000 Subject: [PATCH 0512/1120] Add missing file git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@596 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure.rb | 260 ++++++++++++++++++++++++++++++++++ 1 file changed, 260 insertions(+) create mode 100644 vendor/libkqueue/configure.rb diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb new file mode 100644 index 000000000..aeb9e7143 --- /dev/null +++ b/vendor/libkqueue/configure.rb @@ -0,0 +1,260 @@ +#!/usr/bin/env ruby +# +# Copyright (c) 2012 Mark Heily +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +require 'makeconf' + +# Determine the list of compiler flags +def get_cflags + cflags='-I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600'.split(/ /) + + if Platform.is_linux? + # TODO - note this as a GCC 4.X dependency + cflags.push ' -fvisibility=hidden' + end + if Platform.is_solaris? + cflags.push "-D__EXTENSIONS__" + end + cflags +end + +# Determine the list of source code files for libkqueue +def get_source_list(project) + src = %w{ + src/common/filter.c + src/common/knote.c + src/common/map.c + src/common/kevent.c + src/common/kqueue.c + } + + if Platform.is_solaris? + src.push 'src/solaris/signal.c', + 'src/solaris/timer.c', + 'src/solaris/platform.c', + 'src/solaris/user.c' + end + + if Platform.is_linux? or Platform.is_solaris? + src.push 'src/posix/platform.c' + end + + if Platform.is_linux? + src.push 'src/linux/platform.c', + 'src/linux/read.c', + 'src/linux/write.c', + 'src/linux/user.c', + 'src/linux/vnode.c' + + if project.check_header('sys/signalfd.h') + src.push 'src/linux/signal.c' + else + src.push 'src/posix/signal.c' + end + + src.push 'src/linux/timer.c' + end + + src +end + +# Generate the linker flags +def get_ldadd + ldadd = '' + + if Platform.is_linux? or Platform.is_solaris? + ldadd += ' -lpthread' + end + + if Platform.is_linux? + ldadd += ' -lrt' + end + + ldadd +end + +# +# MAIN() +# + +project = Project.new \ + :id => 'libkqueue', + :version => 2.0 + +kq = Library.new( + :id => 'libkqueue', + :cflags => get_cflags(), + :ldadd => get_ldadd(), + :sources => get_source_list(project) + ) + + +if Platform.is_linux? + project.check_decl 'EPOLLRDHUP', :include => 'sys/epoll.h' + + + project.check_header('sys/epoll.h') or throw 'epoll is required' + project.check_header('sys/inotify.h') or throw 'inotify is required' + project.check_header %w{ sys/signalfd.h sys/timerfd.h sys/eventfd.h } +end + +project.add(kq) + +project.add( + Test.new( + :id => 'kqtest', + :cflags => '-g -O0 -Wall -Werror -Iinclude', + :ldadd => "-lpthread -lrt", + :sources => %w{ + test/main.c + test/kevent.c + test/test.c + test/proc.c + test/read.c + test/signal.c + test/timer.c + test/vnode.c + test/user.c + }, + :ldadd => %w{libkqueue.a -lpthread -lrt} + ) + ) + + +mc = Makeconf.new() +mc.configure(project) + +__END__ +# +# BEGIN: old config.inc contents +# +program="libkqueue" +version="2.0a" +abi_major="0" +abi_minor="0" +abi_version="$abi_major.$abi_minor" +cflags="-Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600" +ldflags="" +sources="src/common/filter.c src/common/knote.c src/common/map.c + src/common/kevent.c src/common/kqueue.c" +libdepends="" +deps="src/common/private.h src/common/debug.h" +mans="kqueue.2" +headers="src/common/private.h" +extra_dist="*.in" +subdirs="src include test" + +# Package metadata +pkg_summary="Emulates the kqueue and kevent system calls" +pkg_description="Emulates the kqueue and kevent system calls" +license="BSD" +author="Mark Heily" + +pre_configure_hook() { + if [ "$debug" = "yes" ] ; then + cflags="$cflags -g3 -O0 -rdynamic" + fi + + if [ "$target" != "windows" ] ; then + cflags="$cflags -fpic" + fi + + optional_headers="err.h" + + libdepends=" -L$libdir" + if [ $target = "linux" ] ; then + + check_symbol sys/epoll.h EPOLLRDHUP + + # TODO - note this as a GCC 4.X dependency + cflags="$cflags -fvisibility=hidden" + + libdepends="$libdepends -lpthread -lrt" + required_headers="sys/epoll.h sys/inotify.h" + optional_headers="sys/signalfd.h sys/timerfd.h sys/eventfd.h" + fi + + if [ $target = "solaris" ] ; then + cflags="$cflags -m64" + ldflags="$ldflags -m64" + libdepends="$libdepends -lsocket -lnsl" + fi +} + +post_configure_hook() { + finalize target "$target" + + platform="src/posix/platform.c" + evfilt_signal="src/posix/signal.c" + evfilt_proc="src/$target/proc.c" + evfilt_socket="src/$target/socket.c" + evfilt_timer="src/posix/timer.c" + evfilt_user="src/posix/user.c" + evfilt_vnode="src/$target/vnode.c" + + if [ $target = "linux" ] ; then + evfilt_user="src/linux/user.c" + evfilt_socket="src/linux/read.c src/linux/write.c" + + #XXX-FIXME disabled + evfilt_proc="" + + if [ "$have_sys_signalfd_h" = "yes" ] ; then + evfilt_signal="src/linux/signal.c" + fi + if [ "$have_sys_timerfd_h" = "yes" ] ; then + evfilt_timer="src/linux/timer.c" + fi + platform="$platform src/linux/platform.c" + fi + + if [ $target = "solaris" ] ; then + cflags="$cflags -D__EXTENSIONS__" + platform="$platform src/solaris/platform.c" + evfilt_timer="src/solaris/timer.c" + evfilt_user="src/solaris/user.c" + evfilt_signal="src/solaris/signal.c" + evfilt_proc="" + evfilt_vnode="" + fi + + # FIXME: This will compile but not actually work + if [ $target = "freebsd" ] ; then + evfilt_signal="src/posix/signal.c" + evfilt_proc="" + evfilt_socket="" + evfilt_timer="" + evfilt_vnode="" + fi + + if [ $target = "windows" ] ; then + platform="src/windows/platform.c" + cflags="$cflags -march=i686 -lws2_32" + ldflags="$ldflags -march=i686" + ldadd="-lws2_32" + evfilt_proc="" + evfilt_signal="" + #evfilt_socket="src/windows/read.c src/linux/write.c" + evfilt_socket="src/windows/read.c" + evfilt_timer="src/windows/timer.c" + evfilt_user="src/windows/user.c" + evfilt_vnode="" + fi + + sources="$sources $platform + $evfilt_signal $evfilt_proc + $evfilt_socket $evfilt_timer $evfilt_user $evfilt_vnode" +} From d416d161f822e6308acb0abf8f944ba4b9227562 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 27 Nov 2012 00:00:26 +0000 Subject: [PATCH 0513/1120] Fix path to config.h git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@597 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index d7a37aaf9..7805c0819 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -48,7 +48,7 @@ #include #include #include -#include "config.h" +#include "../config.h" #else # include "../include/sys/event.h" # include "../src/windows/platform.h" From 323f639205624f62ef7674a8c1b4807bfbcb8449 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 27 Nov 2012 03:35:06 +0000 Subject: [PATCH 0514/1120] Use the local copy of makeconf if needed git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@598 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index aeb9e7143..66ec58046 100644 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -15,7 +15,12 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # +begin require 'makeconf' +rescue LoadError + $LOAD_PATH << "makeconf" + require 'makeconf' +end # Determine the list of compiler flags def get_cflags From 61702f7c2cede26e8487d7c2328e89bd0db631a3 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 27 Nov 2012 04:07:32 +0000 Subject: [PATCH 0515/1120] Do not call pthread_once() on Win32 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@599 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/common/kqueue.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 426313571..f619b861b 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -115,9 +115,11 @@ kqueue(void) struct kqueue *kq; struct kqueue *tmp; +#ifndef _WIN32 (void) pthread_mutex_lock(&kq_mtx); (void) pthread_once(&kq_is_initialized, libkqueue_init); (void) pthread_mutex_unlock(&kq_mtx); +#endif kq = calloc(1, sizeof(*kq)); if (kq == NULL) From 520e84fde56acd4626bf941ec3e1cb9f79cfec9b Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 27 Nov 2012 04:23:15 +0000 Subject: [PATCH 0516/1120] Add missing Win32 files git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@600 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index 66ec58046..96c883794 100644 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -73,6 +73,13 @@ def get_source_list(project) src.push 'src/linux/timer.c' end + if Platform.is_windows? + src.push 'src/windows/timer.c', + 'src/windows/platform.c', + 'src/windows/read.c', + 'src/windows/user.c' + end + src end From 7ad4e97056d3a150a504e1b263a8d689e91d536f Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 27 Nov 2012 04:31:43 +0000 Subject: [PATCH 0517/1120] Minor fixes for win32 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@601 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure.rb | 4 ++++ vendor/libkqueue/src/common/kqueue.c | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index 96c883794..ea0465d9e 100644 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -95,6 +95,10 @@ def get_ldadd ldadd += ' -lrt' end + if Platform.is_windows? + ldadd += ' ws2_32.lib' + end + ldadd end diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index f619b861b..782bff4da 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -56,7 +56,8 @@ get_fd_limit(void) static struct map *kqmap; -static void + +void libkqueue_init(void) { #ifdef NDEBUG From f6fcd485b9934fc50507114c4091cb30e51ef530 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 27 Nov 2012 04:49:44 +0000 Subject: [PATCH 0518/1120] More win32 test changes git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@602 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure.rb | 56 +++++++++++++++++++++++------------ vendor/libkqueue/test/main.c | 13 ++++++++ 2 files changed, 50 insertions(+), 19 deletions(-) diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index ea0465d9e..60451cb3c 100644 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -129,26 +129,44 @@ def get_ldadd project.add(kq) -project.add( - Test.new( - :id => 'kqtest', - :cflags => '-g -O0 -Wall -Werror -Iinclude', - :ldadd => "-lpthread -lrt", - :sources => %w{ - test/main.c - test/kevent.c - test/test.c - test/proc.c - test/read.c - test/signal.c - test/timer.c - test/vnode.c - test/user.c - }, - :ldadd => %w{libkqueue.a -lpthread -lrt} +if Platform.is_windows? + project.add( + Test.new( + :id => 'kqtest', + :cflags => '-g -O0 -Wall -Werror -Iinclude', + :sources => %w{ + test/main.c + test/kevent.c + test/test.c + test/read.c + test/timer.c + test/vnode.c + test/user.c + }, # NOTE: signal.c and proc.c are removed + :ldadd => %w{libkqueue.lib ws2_32.lib} + ) ) - ) - +else + project.add( + Test.new( + :id => 'kqtest', + :cflags => '-g -O0 -Wall -Werror -Iinclude', + :ldadd => "-lpthread -lrt", + :sources => %w{ + test/main.c + test/kevent.c + test/test.c + test/proc.c + test/read.c + test/signal.c + test/timer.c + test/vnode.c + test/user.c + }, + :ldadd => %w{libkqueue.a -lpthread -lrt} + ) + ) +end mc = Makeconf.new() mc.configure(project) diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 981862e26..61b44f3f7 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -192,13 +192,23 @@ test_harness(struct unit_test tests[], int iterations, int concurrency) ctx->iterations = iterations; ctx->concurrency = concurrency; +#ifdef _WIN32 + /* TODO: run in a separate thread */ + run_iteration(ctx); + rv = 0; +#else rv = pthread_create(&tid[j], NULL, (void * (*)(void *)) run_iteration, ctx); +#endif if (rv != 0) err(1, "pthread_create"); } +#ifdef _WIN32 + // TODO: join threads +#else for (j = 0; j < concurrency; j++) { pthread_join(tid[j], NULL); } +#endif } testing_end(); @@ -255,6 +265,8 @@ main(int argc, char **argv) err(1, "WSAStartup failed"); #endif +/* Windows does not provide a POSIX-compatible getopt */ +#ifndef _WIN32 iterations = 1; concurrency = 1; while ((c = getopt (argc, argv, "hc:n:")) != -1) { @@ -296,6 +308,7 @@ main(int argc, char **argv) printf("enabled test: %s\n", arg); } } +#endif test_harness(tests, iterations, concurrency); From 719e869eca6817e4824aa94cf93de1cb177fea7c Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 3 Dec 2012 02:31:11 +0000 Subject: [PATCH 0519/1120] Remove -I. from cflags, use shared library for kqtest git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@603 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index 60451cb3c..29df16034 100644 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -24,7 +24,7 @@ # Determine the list of compiler flags def get_cflags - cflags='-I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600'.split(/ /) + cflags='-I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600'.split(/ /) if Platform.is_linux? # TODO - note this as a GCC 4.X dependency @@ -133,7 +133,7 @@ def get_ldadd project.add( Test.new( :id => 'kqtest', - :cflags => '-g -O0 -Wall -Werror -Iinclude', + :cflags => '-g -O0 -Wall -Werror -Iinclude -Itest', :sources => %w{ test/main.c test/kevent.c @@ -150,8 +150,7 @@ def get_ldadd project.add( Test.new( :id => 'kqtest', - :cflags => '-g -O0 -Wall -Werror -Iinclude', - :ldadd => "-lpthread -lrt", + :cflags => '-g -O0 -Wall -Werror -I./include -I./test', :sources => %w{ test/main.c test/kevent.c @@ -163,7 +162,7 @@ def get_ldadd test/vnode.c test/user.c }, - :ldadd => %w{libkqueue.a -lpthread -lrt} + :ldadd => %w{-lpthread -lrt -lkqueue} ) ) end From ed5d4546d73f78702487110143bb5fc29cedcc5b Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 4 Dec 2012 02:54:17 +0000 Subject: [PATCH 0520/1120] Add support for Android git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@605 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index 29df16034..1ec139505 100644 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -129,6 +129,12 @@ def get_ldadd project.add(kq) +test_ldadd = get_ldadd() +if SystemType.host =~ /-androideabi$/ + test_ldadd += ' libkqueue.a' +else + test_ldadd += ' -lkqueue' +end if Platform.is_windows? project.add( Test.new( @@ -143,7 +149,7 @@ def get_ldadd test/vnode.c test/user.c }, # NOTE: signal.c and proc.c are removed - :ldadd => %w{libkqueue.lib ws2_32.lib} + :ldadd => test_ldadd.split(' ') ) ) else @@ -162,7 +168,7 @@ def get_ldadd test/vnode.c test/user.c }, - :ldadd => %w{-lpthread -lrt -lkqueue} + :ldadd => test_ldadd.split(' ') ) ) end From 26c77631c72ea79a78c448ca3c17596d626016db Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 5 Dec 2012 03:10:25 +0000 Subject: [PATCH 0521/1120] Install sys/event.h git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@607 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index 1ec139505..02730754b 100644 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -129,6 +129,12 @@ def get_ldadd project.add(kq) +project.add(Header.new( + :id => 'event.h', + :sources => 'include/sys/event.h', + :namespace => 'kqueue/sys', + )) + test_ldadd = get_ldadd() if SystemType.host =~ /-androideabi$/ test_ldadd += ' libkqueue.a' From a4f11060164e81fa8bdced207d08985b610b6731 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 9 Dec 2012 22:28:45 +0000 Subject: [PATCH 0522/1120] * Avoid calling getsockopt() on file descriptors that are not sockets. (Credit: Eric Wong) * Call epoll_wait after linux_kevent_wait_hires() (Credit: Eric Wong) * Detect regular files correctly (Credit: Eric Wong) git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@608 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 9 +++++++++ vendor/libkqueue/src/linux/platform.c | 24 ++++++++++++++---------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 576c529c3..01bf61587 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,6 +1,15 @@ HEAD ------------------------------------------------------------------------ + * Avoid calling getsockopt() on file descriptors that are not sockets. + (Credit: Eric Wong) + + * Call epoll_wait after linux_kevent_wait_hires() + (Credit: Eric Wong) + + * Detect regular files correctly + (Credit: Eric Wong) + * Ensure that calling close() on a file descriptor will remove any kevents that reference the descriptor. [merged from ^/branches/stable@551] diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 056fb0ab7..8f8ace262 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -123,22 +123,24 @@ linux_kevent_wait( /* Use pselect() if the timeout value is less than one millisecond. */ if (ts != NULL && ts->tv_sec == 0 && ts->tv_nsec < 1000000) { nret = linux_kevent_wait_hires(kq, ts); + if (nret <= 0) + return (nret); - /* Otherwise, use epoll_wait() directly */ + /* pselect() told us epoll_wait() should have ready events */ + timeout = 0; } else { - /* Convert timeout to the format used by epoll_wait() */ if (ts == NULL) timeout = -1; else timeout = (1000 * ts->tv_sec) + (ts->tv_nsec / 1000000); + } - dbg_puts("waiting for events"); - nret = epoll_wait(kqueue_epfd(kq), &epevt[0], nevents, timeout); - if (nret < 0) { - dbg_perror("epoll_wait"); - return (-1); - } + dbg_puts("waiting for events"); + nret = epoll_wait(kqueue_epfd(kq), &epevt[0], nevents, timeout); + if (nret < 0) { + dbg_perror("epoll_wait"); + return (-1); } return (nret); @@ -292,8 +294,7 @@ linux_get_descriptor_type(struct knote *kn) dbg_perror("fstat(2)"); return (-1); } - if (! S_ISSOCK(sb.st_mode)) { - //FIXME: could be a pipe, device file, or other non-regular file + if (S_ISREG(sb.st_mode)) { kn->kn_flags |= KNFL_REGULAR_FILE; dbg_printf("fd %d is a regular file\n", (int)kn->kev.ident); return (0); @@ -302,6 +303,9 @@ linux_get_descriptor_type(struct knote *kn) /* * Test if the socket is active or passive. */ + if (! S_ISSOCK(sb.st_mode)) + return (0); + slen = sizeof(lsock); lsock = 0; i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_ACCEPTCONN, (char *) &lsock, &slen); From 083cac285999cb371fe10c4e1226c0d84f990bcc Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 24 Dec 2012 17:19:37 +0000 Subject: [PATCH 0523/1120] * Optimize kevent() when it is called with a zero timeout. (Credit: Eric Wong) git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@609 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 3 +++ vendor/libkqueue/src/linux/platform.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 01bf61587..a5f904974 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,6 +1,9 @@ HEAD ------------------------------------------------------------------------ + * Optimize kevent() when it is called with a zero timeout. + (Credit: Eric Wong) + * Avoid calling getsockopt() on file descriptors that are not sockets. (Credit: Eric Wong) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 8f8ace262..cb118daf4 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -121,7 +121,7 @@ linux_kevent_wait( int timeout, nret; /* Use pselect() if the timeout value is less than one millisecond. */ - if (ts != NULL && ts->tv_sec == 0 && ts->tv_nsec < 1000000) { + if (ts != NULL && ts->tv_sec == 0 && ts->tv_nsec > 0 && ts->tv_nsec < 1000000) { nret = linux_kevent_wait_hires(kq, ts); if (nret <= 0) return (nret); From 8a133e80770eb980af7e3382c3751aed85b9cbfd Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 24 Dec 2012 23:37:59 +0000 Subject: [PATCH 0524/1120] * Use ppoll(2) where possible (Credit: Eric Wong) * Reenable some additional unit tests git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@610 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure.rb | 11 +++++++++++ vendor/libkqueue/src/linux/platform.c | 24 +++++++++++++++++++----- vendor/libkqueue/test/user.c | 2 +- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index 02730754b..e57ac8019 100644 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -120,6 +120,7 @@ def get_ldadd if Platform.is_linux? project.check_decl 'EPOLLRDHUP', :include => 'sys/epoll.h' + project.check_decl 'ppoll', :cflags => '#define _GNU_SOURCE', :include => '' project.check_header('sys/epoll.h') or throw 'epoll is required' @@ -179,6 +180,16 @@ def get_ldadd ) end +if project.check_header 'sys/event.h' + # TODO: test for non-standard kqueue things like EV_RECEIPT + # This will allow running the testsuite against the native +else + # Assume libkqueue + project.define 'HAVE_EVFILT_USER' + project.define 'HAVE_EV_RECEIPT' + project.define 'HAVE_EV_DISPATCH' +end + mc = Makeconf.new() mc.configure(project) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index cb118daf4..9494de970 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -14,6 +14,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +# define _GNU_SOURCE +# include #include "../common/private.h" //XXX-FIXME TEMP @@ -90,25 +92,37 @@ linux_kevent_wait_hires( struct kqueue *kq, const struct timespec *timeout) { - fd_set fds; int n; +#if HAVE_DECL_PPOLL + struct pollfd fds; + + dbg_printf("waiting for events (timeout=%ld sec %ld nsec)", + timeout->tv_sec, timeout->tv_nsec); + fds.fd = kqueue_epfd(kq); + fds.events = POLLIN; + + n = ppoll(&fds, 1, timeout, NULL); +#else int epfd; + fd_set fds; dbg_printf("waiting for events (timeout=%ld sec %ld nsec)", timeout->tv_sec, timeout->tv_nsec); + epfd = kqueue_epfd(kq); FD_ZERO(&fds); FD_SET(epfd, &fds); n = pselect(epfd + 1, &fds, NULL , NULL, timeout, NULL); +#endif + if (n < 0) { if (errno == EINTR) { dbg_puts("signal caught"); return (-1); } - dbg_perror("pselect(2)"); + dbg_perror("ppoll(2) or pselect(2)"); return (-1); } - return (n); } @@ -120,13 +134,13 @@ linux_kevent_wait( { int timeout, nret; - /* Use pselect() if the timeout value is less than one millisecond. */ + /* Use a high-resolution syscall if the timeout value is less than one millisecond. */ if (ts != NULL && ts->tv_sec == 0 && ts->tv_nsec > 0 && ts->tv_nsec < 1000000) { nret = linux_kevent_wait_hires(kq, ts); if (nret <= 0) return (nret); - /* pselect() told us epoll_wait() should have ready events */ + /* epoll_wait() should have ready events */ timeout = 0; } else { /* Convert timeout to the format used by epoll_wait() */ diff --git a/vendor/libkqueue/test/user.c b/vendor/libkqueue/test/user.c index 65dcaa5b8..3a142c70c 100644 --- a/vendor/libkqueue/test/user.c +++ b/vendor/libkqueue/test/user.c @@ -62,7 +62,7 @@ test_kevent_user_get_hires(struct test_context *ctx) kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; kev.flags = EV_CLEAR; - kevent_get(&ret, ctx->kqfd); //FIXME: Shouldn't this be kevent_get_hires() ? + kevent_get_hires(&ret, ctx->kqfd); kevent_cmp(&kev, &ret); test_no_kevents(ctx->kqfd); From 2a800c626599b0a43a70ef55067d7c1d9bb55ce1 Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 24 Dec 2012 23:39:25 +0000 Subject: [PATCH 0525/1120] add changelog git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@611 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index a5f904974..b020ab2e9 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,6 +1,9 @@ HEAD ------------------------------------------------------------------------ + * Use ppoll(2) where possible to improve scalability. + (Credit: Eric Wong) + * Optimize kevent() when it is called with a zero timeout. (Credit: Eric Wong) From 0365b2d748e40c85066a10a54391b96dfd942770 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 6 Jan 2013 17:28:12 +0000 Subject: [PATCH 0526/1120] Use ifdef instead of check_decl() where possible. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@612 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure.rb | 12 +----------- vendor/libkqueue/test/common.h | 3 +-- vendor/libkqueue/test/kevent.c | 4 ++-- vendor/libkqueue/test/main.c | 4 ++-- vendor/libkqueue/test/read.c | 6 +++--- vendor/libkqueue/test/signal.c | 6 +++--- vendor/libkqueue/test/timer.c | 6 +++--- vendor/libkqueue/test/user.c | 6 +++--- vendor/libkqueue/test/vnode.c | 6 +++--- 9 files changed, 21 insertions(+), 32 deletions(-) diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index e57ac8019..6c2c1747f 100644 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -120,7 +120,7 @@ def get_ldadd if Platform.is_linux? project.check_decl 'EPOLLRDHUP', :include => 'sys/epoll.h' - project.check_decl 'ppoll', :cflags => '#define _GNU_SOURCE', :include => '' + project.check_decl 'ppoll', :cflags => '#define _GNU_SOURCE', :include => 'poll.h' project.check_header('sys/epoll.h') or throw 'epoll is required' @@ -180,16 +180,6 @@ def get_ldadd ) end -if project.check_header 'sys/event.h' - # TODO: test for non-standard kqueue things like EV_RECEIPT - # This will allow running the testsuite against the native -else - # Assume libkqueue - project.define 'HAVE_EVFILT_USER' - project.define 'HAVE_EV_RECEIPT' - project.define 'HAVE_EV_DISPATCH' -end - mc = Makeconf.new() mc.configure(project) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 7805c0819..e05d8ab68 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -52,7 +52,6 @@ #else # include "../include/sys/event.h" # include "../src/windows/platform.h" -# define HAVE_EVFILT_USER 1 #endif struct test_context; @@ -87,7 +86,7 @@ void test_evfilt_vnode(struct test_context *); void test_evfilt_timer(struct test_context *); void test_evfilt_timer_concurrent(struct test_context *); void test_evfilt_proc(struct test_context *); -#if HAVE_EVFILT_USER +#ifdef EVFILT_USER void test_evfilt_user(struct test_context *); #endif diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index ff60932d4..e74f9ba2e 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -125,10 +125,10 @@ kevent_flags_dump(struct kevent *kev) KEVFL_DUMP(EV_CLEAR); KEVFL_DUMP(EV_EOF); KEVFL_DUMP(EV_ERROR); -#if HAVE_EV_DISPATCH +#ifdef EV_DISPATCH KEVFL_DUMP(EV_DISPATCH); #endif -#if HAVE_EV_RECEIPT +#ifdef EV_RECEIPT KEVFL_DUMP(EV_RECEIPT); #endif buf[strlen(buf) - 1] = ')'; diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 61b44f3f7..33d8c4250 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -117,7 +117,7 @@ test_ev_receipt(void *unused) if ((kq = kqueue()) < 0) die("kqueue()"); -#if HAVE_EV_RECEIPT +#ifdef EV_RECEIPT EV_SET(&kev, SIGUSR2, EVFILT_SIGNAL, EV_ADD | EV_RECEIPT, 0, 0, NULL); if (kevent(kq, &kev, 1, &kev, 1, NULL) < 0) @@ -244,7 +244,7 @@ main(int argc, char **argv) #ifndef _WIN32 { "vnode", 1, 0, test_evfilt_vnode }, #endif -#if HAVE_EVFILT_USER +#ifdef EVFILT_USER { "user", 1, 0, test_evfilt_user }, #endif { NULL, 0, 0, NULL }, diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index f88ebc420..59dc57f8b 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -289,7 +289,7 @@ test_kevent_socket_listen_backlog(struct test_context *ctx) test_no_kevents(ctx->kqfd); } -#if HAVE_EV_DISPATCH +#ifdef EV_DISPATCH void test_kevent_socket_dispatch(struct test_context *ctx) { @@ -321,7 +321,7 @@ test_kevent_socket_dispatch(struct test_context *ctx) kevent_socket_drain(ctx); } -#endif /* HAVE_EV_DISPATCH */ +#endif /* EV_DISPATCH */ #if BROKEN_ON_LINUX void @@ -431,7 +431,7 @@ test_evfilt_read(struct test_context *ctx) test(kevent_socket_disable_and_enable, ctx); test(kevent_socket_oneshot, ctx); test(kevent_socket_clear, ctx); -#if HAVE_EV_DISPATCH +#ifdef EV_DISPATCH test(kevent_socket_dispatch, ctx); #endif test(kevent_socket_listen_backlog, ctx); diff --git a/vendor/libkqueue/test/signal.c b/vendor/libkqueue/test/signal.c index d2513eaa9..23a0edb63 100644 --- a/vendor/libkqueue/test/signal.c +++ b/vendor/libkqueue/test/signal.c @@ -134,7 +134,7 @@ test_kevent_signal_modify(struct test_context *ctx) test_kevent_signal_del(ctx); } -#if HAVE_EV_DISPATCH +#ifdef EV_DISPATCH void test_kevent_signal_dispatch(struct test_context *ctx) { @@ -174,7 +174,7 @@ test_kevent_signal_dispatch(struct test_context *ctx) die("kill"); test_no_kevents(ctx->kqfd); } -#endif /* HAVE_EV_DISPATCH */ +#endif /* EV_DISPATCH */ void test_evfilt_signal(struct test_context *ctx) @@ -188,7 +188,7 @@ test_evfilt_signal(struct test_context *ctx) test(kevent_signal_enable, ctx); test(kevent_signal_oneshot, ctx); test(kevent_signal_modify, ctx); -#if HAVE_EV_DISPATCH +#ifdef EV_DISPATCH test(kevent_signal_dispatch, ctx); #endif } diff --git a/vendor/libkqueue/test/timer.c b/vendor/libkqueue/test/timer.c index 00ce85833..3ba56325c 100644 --- a/vendor/libkqueue/test/timer.c +++ b/vendor/libkqueue/test/timer.c @@ -117,7 +117,7 @@ test_kevent_timer_disable_and_enable(struct test_context *ctx) kevent_cmp(&kev, &ret); } -#if HAVE_EV_DISPATCH +#ifdef EV_DISPATCH void test_kevent_timer_dispatch(struct test_context *ctx) { @@ -153,7 +153,7 @@ test_kevent_timer_dispatch(struct test_context *ctx) sleep(1); test_no_kevents(ctx->kqfd); } -#endif /* HAVE_EV_DISPATCH */ +#endif /* EV_DISPATCH */ void test_evfilt_timer(struct test_context *ctx) @@ -164,7 +164,7 @@ test_evfilt_timer(struct test_context *ctx) test(kevent_timer_oneshot, ctx); test(kevent_timer_periodic, ctx); test(kevent_timer_disable_and_enable, ctx); -#if HAVE_EV_DISPATCH +#ifdef EV_DISPATCH test(kevent_timer_dispatch, ctx); #endif } diff --git a/vendor/libkqueue/test/user.c b/vendor/libkqueue/test/user.c index 3a142c70c..8724a1d7a 100644 --- a/vendor/libkqueue/test/user.c +++ b/vendor/libkqueue/test/user.c @@ -113,7 +113,7 @@ test_kevent_user_oneshot(struct test_context *ctx) test_no_kevents(ctx->kqfd); } -#if HAVE_EV_DISPATCH +#ifdef EV_DISPATCH void test_kevent_user_dispatch(struct test_context *ctx) { @@ -153,7 +153,7 @@ test_kevent_user_dispatch(struct test_context *ctx) kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_DELETE, 0, 0, NULL); test_no_kevents(ctx->kqfd); } -#endif /* HAVE_EV_DISPATCH */ +#endif /* EV_DISPATCH */ void test_evfilt_user(struct test_context *ctx) @@ -163,7 +163,7 @@ test_evfilt_user(struct test_context *ctx) test(kevent_user_get_hires, ctx); test(kevent_user_disable_and_enable, ctx); test(kevent_user_oneshot, ctx); -#if HAVE_EV_DISPATCH +#ifdef EV_DISPATCH test(kevent_user_dispatch, ctx); #endif /* TODO: try different fflags operations */ diff --git a/vendor/libkqueue/test/vnode.c b/vendor/libkqueue/test/vnode.c index 42dc30f8e..d4de569ff 100644 --- a/vendor/libkqueue/test/vnode.c +++ b/vendor/libkqueue/test/vnode.c @@ -196,7 +196,7 @@ test_kevent_vnode_disable_and_enable(struct test_context *ctx) test_id, (unsigned int)kev.ident, kev.filter, kev.flags); } -#if HAVE_EV_DISPATCH +#ifdef EV_DISPATCH void test_kevent_vnode_dispatch(struct test_context *ctx) { @@ -235,7 +235,7 @@ test_kevent_vnode_dispatch(struct test_context *ctx) /* Delete the watch */ kevent_add(ctx->kqfd, &kev, ctx->vnode_fd, EVFILT_VNODE, EV_DELETE, NOTE_ATTRIB, 0, NULL); } -#endif /* HAVE_EV_DISPATCH */ +#endif /* EV_DISPATCH */ void test_evfilt_vnode(struct test_context *ctx) @@ -259,7 +259,7 @@ test_evfilt_vnode(struct test_context *ctx) test(kevent_vnode_add, ctx); test(kevent_vnode_del, ctx); test(kevent_vnode_disable_and_enable, ctx); -#if HAVE_EV_DISPATCH +#ifdef EV_DISPATCH test(kevent_vnode_dispatch, ctx); #endif test(kevent_vnode_note_write, ctx); From 611934df9ede6164b5eed866ab190ef9fa6244c6 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 6 Jan 2013 17:29:36 +0000 Subject: [PATCH 0527/1120] restore missing check for sys/event.h git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@613 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index 6c2c1747f..fb46189a0 100644 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -118,6 +118,7 @@ def get_ldadd ) +project.check_header 'sys/event.h' if Platform.is_linux? project.check_decl 'EPOLLRDHUP', :include => 'sys/epoll.h' project.check_decl 'ppoll', :cflags => '#define _GNU_SOURCE', :include => 'poll.h' From 7acb642117f189b5d50770ac3fb90c509a0ef893 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 12 Jan 2013 02:51:53 +0000 Subject: [PATCH 0528/1120] Add the generated Makefile and configure script. This eliminates the requirement for having Makeconf and it's dependencies when building on certain platforms (Linux, at least). git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@614 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/GNUmakefile | 259 ++++++++++++++++++++++++++++++++++ vendor/libkqueue/configure | 115 ++++++++++----- vendor/libkqueue/configure.rb | 0 3 files changed, 339 insertions(+), 35 deletions(-) create mode 100644 vendor/libkqueue/GNUmakefile mode change 100644 => 100755 vendor/libkqueue/configure.rb diff --git a/vendor/libkqueue/GNUmakefile b/vendor/libkqueue/GNUmakefile new file mode 100644 index 000000000..8dc65aa42 --- /dev/null +++ b/vendor/libkqueue/GNUmakefile @@ -0,0 +1,259 @@ +# AUTOMATICALLY GENERATED -- DO NOT EDIT +BINDIR = $(EPREFIX)/bin +CC = cc +DATADIR = $(DATAROOTDIR) +DATAROOTDIR = $(PREFIX)/share +DOCDIR = $(DATAROOTDIR)/doc/$(PACKAGE) +EPREFIX = $(PREFIX) +INCLUDEDIR = $(PREFIX)/include +INFODIR = $(DATAROOTDIR)/info +INSTALL ?= /usr/bin/install +LD = cc +LIBDIR = $(EPREFIX)/lib +LIBEXECDIR = $(EPREFIX)/libexec +LOCALEDIR = $(DATAROOTDIR)/locale +LOCALSTATEDIR = $(PREFIX)/var +MANDIR = $(DATAROOTDIR)/man +OLDINCLUDEDIR = /usr/include +PKGDATADIR = $(DATADIR)/$(PACKAGE) +PKGINCLUDEDIR = $(INCLUDEDIR)/$(PACKAGE) +PKGLIBDIR = $(LIBDIR)/$(PACKAGE) +PREFIX = /usr/local +SBINDIR = $(EPREFIX)/sbin +SHAREDSTATEDIR = $(PREFIX)/com +SYSCONFDIR = $(PREFIX)/etc + + +# +# Detect the canonical system type of the system we are building on +# (build) and the system the package runs on (host) +# +BUILD_CPU=$(shell uname -m) +HOST_CPU=$(BUILD_CPU) +BUILD_VENDOR=unknown +HOST_VENDOR=$(BUILD_VENDOR) +BUILD_KERNEL=$(shell uname | tr '[A-Z]' '[a-z]') +HOST_KERNEL=$(BUILD_KERNEL) +BUILD_SYSTEM=gnu +HOST_SYSTEM=$(BUILD_SYSTEM) +BUILD_TYPE=$(BUILD_CPU)-$(BUILD_VENDOR)-$(BUILD_KERNEL)-$(BUILD_SYSTEM) +HOST_TYPE=$(HOST_CPU)-$(HOST_VENDOR)-$(HOST_KERNEL)-$(HOST_SYSTEM) + +# Allow variables to be overridden via a ./configure script that outputs config.mk +# FIXME -- requires GNU Make +-include config.mk + +default: all + +all: libkqueue.so libkqueue.a kqtest + +check: kqtest + ./kqtest + +clean: + rm -f *.rpm + rm -f libkqueue-2.0.tar.gz + rm -f src/common/filter.o + rm -f src/common/knote.o + rm -f src/common/map.o + rm -f src/common/kevent.o + rm -f src/common/kqueue.o + rm -f src/posix/platform.o + rm -f src/linux/platform.o + rm -f src/linux/read.o + rm -f src/linux/write.o + rm -f src/linux/user.o + rm -f src/linux/vnode.o + rm -f src/linux/signal.o + rm -f src/linux/timer.o + rm -f libkqueue.so + rm -f libkqueue.a + rm -f test/main.o + rm -f test/kevent.o + rm -f test/test.o + rm -f test/proc.o + rm -f test/read.o + rm -f test/signal.o + rm -f test/timer.o + rm -f test/vnode.o + rm -f test/user.o + rm -f kqtest + +config.h: + @echo "checking build system type... $(BUILD_TYPE)" + @echo "checking host system type... $(HOST_TYPE)" + @echo "/* AUTOMATICALLY GENERATED -- DO NOT EDIT */" > config.h.tmp + @date > config.log + @printf "checking whether EPOLLRDHUP is declared in sys/epoll.h... " | tee -a config.log + @( printf '#define _GNU_SOURCE\n#include \nint main() { EPOLLRDHUP; }' | $(CC) $(CFLAGS) -E -x c - ) >/dev/null 2>>config.log && ( echo '#define HAVE_DECL_EPOLLRDHUP 1' >> config.h.tmp ; echo 'yes' ) || (echo '#define HAVE_DECL_EPOLLRDHUP 0' >> config.h.tmp ; echo 'no' ) + @printf "checking whether ppoll is declared in poll.h... " | tee -a config.log + @( printf '#define _GNU_SOURCE\n#include \nint main() { ppoll; }' | $(CC) $(CFLAGS) -E -x c - ) >/dev/null 2>>config.log && ( echo '#define HAVE_DECL_PPOLL 1' >> config.h.tmp ; echo 'yes' ) || (echo '#define HAVE_DECL_PPOLL 0' >> config.h.tmp ; echo 'no' ) + @printf "checking for sys/epoll.h... " + @( echo '#include ' | $(CC) $(CFLAGS) -E -x c - ) >/dev/null 2>&1 && ( echo '#define HAVE_SYS_EPOLL_H 1' >> config.h.tmp ; echo 'yes' ) || (echo '/* #undef HAVE_SYS_EPOLL_H */' >> config.h.tmp ; echo 'no' ) + @printf "checking for sys/event.h... " + @( echo '#include ' | $(CC) $(CFLAGS) -E -x c - ) >/dev/null 2>&1 && ( echo '#define HAVE_SYS_EVENT_H 1' >> config.h.tmp ; echo 'yes' ) || (echo '/* #undef HAVE_SYS_EVENT_H */' >> config.h.tmp ; echo 'no' ) + @printf "checking for sys/eventfd.h... " + @( echo '#include ' | $(CC) $(CFLAGS) -E -x c - ) >/dev/null 2>&1 && ( echo '#define HAVE_SYS_EVENTFD_H 1' >> config.h.tmp ; echo 'yes' ) || (echo '/* #undef HAVE_SYS_EVENTFD_H */' >> config.h.tmp ; echo 'no' ) + @printf "checking for sys/inotify.h... " + @( echo '#include ' | $(CC) $(CFLAGS) -E -x c - ) >/dev/null 2>&1 && ( echo '#define HAVE_SYS_INOTIFY_H 1' >> config.h.tmp ; echo 'yes' ) || (echo '/* #undef HAVE_SYS_INOTIFY_H */' >> config.h.tmp ; echo 'no' ) + @printf "checking for sys/signalfd.h... " + @( echo '#include ' | $(CC) $(CFLAGS) -E -x c - ) >/dev/null 2>&1 && ( echo '#define HAVE_SYS_SIGNALFD_H 1' >> config.h.tmp ; echo 'yes' ) || (echo '/* #undef HAVE_SYS_SIGNALFD_H */' >> config.h.tmp ; echo 'no' ) + @printf "checking for sys/timerfd.h... " + @( echo '#include ' | $(CC) $(CFLAGS) -E -x c - ) >/dev/null 2>&1 && ( echo '#define HAVE_SYS_TIMERFD_H 1' >> config.h.tmp ; echo 'yes' ) || (echo '/* #undef HAVE_SYS_TIMERFD_H */' >> config.h.tmp ; echo 'no' ) + @rm -f conftest.c conftest.o + @echo "creating config.h" + @mv config.h.tmp config.h + +dist: libkqueue-2.0.tar.gz + +distclean: clean + rm -f GNUmakefile + rm -f libkqueue-2.0.tar.gz + rm -f config.h + rm -f config.yaml + rm -f rpm.spec + +distdir: + umask 22 ; mkdir -p '$(distdir)/src/common' + umask 22 ; mkdir -p '$(distdir)/src/common/../posix' + umask 22 ; mkdir -p '$(distdir)/src/common/../posix/../../include/sys' + umask 22 ; mkdir -p '$(distdir)/src/common/../linux' + umask 22 ; mkdir -p '$(distdir)/src/posix' + umask 22 ; mkdir -p '$(distdir)/src/posix/../common' + umask 22 ; mkdir -p '$(distdir)/src/posix/../common/../posix' + umask 22 ; mkdir -p '$(distdir)/src/posix/../common/../posix/../../include/sys' + umask 22 ; mkdir -p '$(distdir)/src/posix/../common/../linux' + umask 22 ; mkdir -p '$(distdir)/src/linux' + umask 22 ; mkdir -p '$(distdir)/src/linux/../common' + umask 22 ; mkdir -p '$(distdir)/src/linux/../common/../posix' + umask 22 ; mkdir -p '$(distdir)/src/linux/../common/../posix/../../include/sys' + umask 22 ; mkdir -p '$(distdir)/src/linux/../common/../linux' + umask 22 ; mkdir -p '$(distdir)/include/sys' + umask 22 ; mkdir -p '$(distdir)/test' + umask 22 ; mkdir -p '$(distdir)/test/..' + cp -RL src/common/filter.c src/common/private.h src/common/tree.h src/common/debug.h src/common/knote.c src/common/alloc.h src/common/map.c src/common/kevent.c src/common/kqueue.c $(distdir)/src/common + cp -RL config.h GNUmakefile configure configure.rb $(distdir) + cp -RL src/common/../posix/platform.h $(distdir)/src/common/../posix + cp -RL src/common/../posix/../../include/sys/event.h $(distdir)/src/common/../posix/../../include/sys + cp -RL src/common/../linux/platform.h $(distdir)/src/common/../linux + cp -RL src/posix/platform.c $(distdir)/src/posix + cp -RL src/posix/../common/private.h src/posix/../common/tree.h src/posix/../common/debug.h $(distdir)/src/posix/../common + cp -RL src/posix/../common/../posix/platform.h $(distdir)/src/posix/../common/../posix + cp -RL src/posix/../common/../posix/../../include/sys/event.h $(distdir)/src/posix/../common/../posix/../../include/sys + cp -RL src/posix/../common/../linux/platform.h $(distdir)/src/posix/../common/../linux + cp -RL src/linux/platform.c src/linux/read.c src/linux/write.c src/linux/user.c src/linux/vnode.c src/linux/signal.c src/linux/timer.c $(distdir)/src/linux + cp -RL src/linux/../common/private.h src/linux/../common/tree.h src/linux/../common/debug.h $(distdir)/src/linux/../common + cp -RL src/linux/../common/../posix/platform.h $(distdir)/src/linux/../common/../posix + cp -RL src/linux/../common/../posix/../../include/sys/event.h $(distdir)/src/linux/../common/../posix/../../include/sys + cp -RL src/linux/../common/../linux/platform.h $(distdir)/src/linux/../common/../linux + cp -RL include/sys/event.h $(distdir)/include/sys + cp -RL test/main.c test/common.h test/kevent.c test/test.c test/proc.c test/read.c test/signal.c test/timer.c test/vnode.c test/user.c $(distdir)/test + cp -RL test/../config.h $(distdir)/test/.. + +install: + /usr/bin/test -e $(DESTDIR)$(LIBDIR) || $(INSTALL) -d -m 755 $(DESTDIR)$(LIBDIR) + $(INSTALL) -m 0644 libkqueue.so $(DESTDIR)$(LIBDIR)/libkqueue.so.0.0 + /usr/bin/test -e $(DESTDIR)$(INCLUDEDIR)/kqueue/sys || $(INSTALL) -d -m 755 $(DESTDIR)$(INCLUDEDIR)/kqueue/sys + $(INSTALL) -m 644 include/sys/event.h $(DESTDIR)$(INCLUDEDIR)/kqueue/sys + +kqtest: test/main.o test/kevent.o test/test.o test/proc.o test/read.o test/signal.o test/timer.o test/vnode.o test/user.o + $(LD) -o kqtest -L . -Wl,-rpath,. -L . $(LDFLAGS) test/main.o test/kevent.o test/test.o test/proc.o test/read.o test/signal.o test/timer.o test/vnode.o test/user.o -lpthread -lrt -lkqueue $(LDADD) + +libkqueue-2.0.tar.gz: + rm -rf libkqueue-2.0 + mkdir libkqueue-2.0 + $(MAKE) distdir distdir=libkqueue-2.0 + rm -rf libkqueue-2.0.tar libkqueue-2.0.tar.gz + tar cf libkqueue-2.0.tar libkqueue-2.0 + gzip libkqueue-2.0.tar + rm -rf libkqueue-2.0 + +libkqueue.a: src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o +ifneq ($(DISABLE_STATIC),1) + ar cru libkqueue.a src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o + ranlib libkqueue.a +endif + +libkqueue.so: src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o + $(LD) -o libkqueue.so -shared -fPIC -L . $(LDFLAGS) src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o -lpthread -lrt $(LDADD) + +package: clean libkqueue-2.0.tar.gz + rm -rf rpm *.rpm + mkdir -p rpm/BUILD rpm/RPMS rpm/SOURCES rpm/SPECS rpm/SRPMS + mkdir -p rpm/RPMS/i386 rpm/RPMS/x86_64 + cp libkqueue-2.0.tar.gz rpm/SOURCES + rpmbuild --define "_topdir `pwd`/rpm" -bs rpm.spec + cp rpm.spec rpm/SPECS/rpm.spec + rpmbuild --define "_topdir `pwd`/rpm" -bb ./rpm/SPECS/rpm.spec + mv ./rpm/SRPMS/* ./rpm/RPMS/*/*.rpm . + rm -rf rpm + +src/common/filter.o: src/common/filter.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/filter.o -fPIC -DPIC $(CFLAGS) -c src/common/filter.c + +src/common/kevent.o: src/common/kevent.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/kevent.o -fPIC -DPIC $(CFLAGS) -c src/common/kevent.c + +src/common/knote.o: src/common/knote.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h src/common/alloc.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/knote.o -fPIC -DPIC $(CFLAGS) -c src/common/knote.c + +src/common/kqueue.o: src/common/kqueue.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/kqueue.o -fPIC -DPIC $(CFLAGS) -c src/common/kqueue.c + +src/common/map.o: src/common/map.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/map.o -fPIC -DPIC $(CFLAGS) -c src/common/map.c + +src/linux/platform.o: src/linux/platform.c src/linux/../common/private.h config.h src/linux/../common/tree.h src/linux/../common/../posix/platform.h src/linux/../common/../posix/../../include/sys/event.h src/linux/../common/../linux/platform.h src/linux/../common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/platform.o -fPIC -DPIC $(CFLAGS) -c src/linux/platform.c + +src/linux/read.o: src/linux/read.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/read.o -fPIC -DPIC $(CFLAGS) -c src/linux/read.c + +src/linux/signal.o: src/linux/signal.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/signal.o -fPIC -DPIC $(CFLAGS) -c src/linux/signal.c + +src/linux/timer.o: src/linux/timer.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/timer.o -fPIC -DPIC $(CFLAGS) -c src/linux/timer.c + +src/linux/user.o: src/linux/user.c include/sys/event.h src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/user.o -fPIC -DPIC $(CFLAGS) -c src/linux/user.c + +src/linux/vnode.o: src/linux/vnode.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/vnode.o -fPIC -DPIC $(CFLAGS) -c src/linux/vnode.c + +src/linux/write.o: src/linux/write.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/write.o -fPIC -DPIC $(CFLAGS) -c src/linux/write.c + +src/posix/platform.o: src/posix/platform.c src/posix/../common/private.h config.h src/posix/../common/tree.h src/posix/../common/../posix/platform.h src/posix/../common/../posix/../../include/sys/event.h src/posix/../common/../linux/platform.h src/posix/../common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/posix/platform.o -fPIC -DPIC $(CFLAGS) -c src/posix/platform.c + +test/kevent.o: test/kevent.c test/common.h include/sys/event.h test/../config.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/kevent.o $(CFLAGS) -c test/kevent.c + +test/main.o: test/main.c test/common.h include/sys/event.h test/../config.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/main.o $(CFLAGS) -c test/main.c + +test/proc.o: test/proc.c test/common.h include/sys/event.h test/../config.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/proc.o $(CFLAGS) -c test/proc.c + +test/read.o: test/read.c test/common.h include/sys/event.h test/../config.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/read.o $(CFLAGS) -c test/read.c + +test/signal.o: test/signal.c test/common.h include/sys/event.h test/../config.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/signal.o $(CFLAGS) -c test/signal.c + +test/test.o: test/test.c test/common.h include/sys/event.h test/../config.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/test.o $(CFLAGS) -c test/test.c + +test/timer.o: test/timer.c test/common.h include/sys/event.h test/../config.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/timer.o $(CFLAGS) -c test/timer.c + +test/user.o: test/user.c test/common.h include/sys/event.h test/../config.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/user.o $(CFLAGS) -c test/user.c + +test/vnode.o: test/vnode.c test/common.h include/sys/event.h test/../config.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/vnode.o $(CFLAGS) -c test/vnode.c + +uninstall: + rm -f $(DESTDIR)$(LIBDIR)/libkqueue.so + rm -f $(DESTDIR)$(INCLUDEDIR)/kqueue/sys/include/sys/event.h diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index d4a9095e1..7c523a792 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -1,46 +1,91 @@ #!/bin/sh # -# Bootstrap configuration script for Makeconf +# Copyright (c) 2013 Mark Heily # -# Author: Mark Heily +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # + +usage() { +cat << "EOF" +Usage: configure [options] -die() { - printf "\n*** ERROR: $1 ***\n\n$2\n\n" - exit 1 -} +Installation options: + --bindir [DIRECTORY] TODO describe this [$(EPREFIX)/bin] + --datadir [DIRECTORY] TODO describe this [$(DATAROOTDIR)] + --datarootdir [DIRECTORY] TODO describe this [$(PREFIX)/share] + --docdir [DIRECTORY] TODO describe this [$(DATAROOTDIR)/doc/$(PACKAGE)] + --eprefix [DIRECTORY] TODO describe this [$(PREFIX)] + --includedir [DIRECTORY] TODO describe this [$(PREFIX)/include] + --infodir [DIRECTORY] TODO describe this [$(DATAROOTDIR)/info] + --libdir [DIRECTORY] TODO describe this [$(EPREFIX)/lib] + --libexecdir [DIRECTORY] TODO describe this [$(EPREFIX)/libexec] + --localedir [DIRECTORY] TODO describe this [$(DATAROOTDIR)/locale] + --localstatedir [DIRECTORY] TODO describe this [$(PREFIX)/var] + --mandir [DIRECTORY] TODO describe this [$(DATAROOTDIR)/man] + --oldincludedir [DIRECTORY] TODO describe this [/usr/include] + --pkgdatadir [DIRECTORY] TODO describe this [$(DATADIR)/$(PACKAGE)] + --pkgincludedir [DIRECTORY] TODO describe this [$(INCLUDEDIR)/$(PACKAGE)] + --pkglibdir [DIRECTORY] TODO describe this [$(LIBDIR)/$(PACKAGE)] + --prefix [DIRECTORY] TODO describe this [/usr/local] + --sbindir [DIRECTORY] TODO describe this [$(EPREFIX)/sbin] + --sharedstatedir [DIRECTORY] TODO describe this [$(PREFIX)/com] + --sysconfdir [DIRECTORY] TODO describe this [$(PREFIX)/etc] + +Project options: -if [ "$RUBY" != "" ] ; then - ruby=$RUBY -else - ruby=`which ruby` -fi +System types: + --build BUILD set the system type for building + --host HOST cross-compile programs to run on a different system type + --target TARGET build a compiler for cross-compiling -printf 'checking for ruby.. ' -if [ ! -x "$ruby" ] ; then - echo 'no' - die 'Ruby was not found' 'Please install Ruby from http://www.ruby-lang.org/' -fi +Optional Features: -if [ "$RUBYLIB" != "" ] ; then - echo "$ruby (RUBYLIB=$RUBYLIB)" - export RUBYLIB -else - echo $ruby -fi +Common options: + --disable-static Disable generation of static libraries + --disable-option-checking + -h, --help Show this message + -V, --version Display version information and exit +EOF +} -printf 'checking for makeconf.. ' -ruby -e "require 'makeconf'" > /dev/null 2>&1 -if [ $? -ne 0 ] ; then - if [ -x ./makeconf ] ; then - echo 'yes (using local copy)' - ruby="$ruby -I./makeconf" - else - echo 'no' - die 'Makeconf was not found' 'Please install Makeconf from https://rubygems.org/' +echo "# Automatically generated by ./configure -- do not edit" > config.mk +for arg in $* +do + if [ `echo "$arg" | grep "^--"` = "$arg" ] ; then + key=`echo $arg | sed "s/^--//; s/=.*//"` + val=`echo $arg | sed "s/.*=//"` + uc_key=`echo "$key" | tr "a-z" "A-Z" | tr "-" "_"` + echo key=$key -- val=$val + case $key in + "help") + usage + exit 1 + ;; + bindir|datadir|datarootdir|docdir|eprefix|includedir|infodir|libdir|libexecdir|localedir|localstatedir|mandir|pkgdatadir|pkgincludedir|pkglibdir|prefix|sbindir|sharedstatedir|sysconfdir) + echo "$uc_key=$val" >> config.mk + ;; + disable-static) + echo "$uc_key=1" >> config.mk + ;; + disable-option-checking) + # Not implemented, this behavior is the default (for now) + ;; + *) + echo "Warning: unrecognized option: $arg" + ;; + esac fi -else - echo 'yes' -fi +done -exec $ruby ./configure.rb $* +rm -f config.h +make config.h diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb old mode 100644 new mode 100755 From 439604a9b8d9d49358609404b13eeee6ba500e2f Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 13 Jan 2013 05:18:44 +0000 Subject: [PATCH 0529/1120] update configure script git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@615 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/GNUmakefile | 2 ++ vendor/libkqueue/configure | 61 ++++++++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/GNUmakefile b/vendor/libkqueue/GNUmakefile index 8dc65aa42..23bf7d587 100644 --- a/vendor/libkqueue/GNUmakefile +++ b/vendor/libkqueue/GNUmakefile @@ -155,6 +155,8 @@ install: $(INSTALL) -m 0644 libkqueue.so $(DESTDIR)$(LIBDIR)/libkqueue.so.0.0 /usr/bin/test -e $(DESTDIR)$(INCLUDEDIR)/kqueue/sys || $(INSTALL) -d -m 755 $(DESTDIR)$(INCLUDEDIR)/kqueue/sys $(INSTALL) -m 644 include/sys/event.h $(DESTDIR)$(INCLUDEDIR)/kqueue/sys + rm -f $(DESTDIR)$(LIBDIR)/libkqueue.so + ln -s libkqueue.so.0.0 $(DESTDIR)$(LIBDIR)/libkqueue.so kqtest: test/main.o test/kevent.o test/test.o test/proc.o test/read.o test/signal.o test/timer.o test/vnode.o test/user.o $(LD) -o kqtest -L . -Wl,-rpath,. -L . $(LDFLAGS) test/main.o test/kevent.o test/test.o test/proc.o test/read.o test/signal.o test/timer.o test/vnode.o test/user.o -lpthread -lrt -lkqueue $(LDADD) diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index 7c523a792..be815129e 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -58,6 +58,11 @@ Common options: EOF } +err() { + echo "*** ERROR *** $*" + exit 1 +} + echo "# Automatically generated by ./configure -- do not edit" > config.mk for arg in $* do @@ -65,21 +70,34 @@ do key=`echo $arg | sed "s/^--//; s/=.*//"` val=`echo $arg | sed "s/.*=//"` uc_key=`echo "$key" | tr "a-z" "A-Z" | tr "-" "_"` - echo key=$key -- val=$val case $key in "help") usage exit 1 ;; - bindir|datadir|datarootdir|docdir|eprefix|includedir|infodir|libdir|libexecdir|localedir|localstatedir|mandir|pkgdatadir|pkgincludedir|pkglibdir|prefix|sbindir|sharedstatedir|sysconfdir) + bindir|datadir|datarootdir|docdir|includedir|infodir|libdir|libexecdir|localedir|localstatedir|mandir|pkgdatadir|pkgincludedir|pkglibdir|prefix|sbindir|sharedstatedir|sysconfdir) echo "$uc_key=$val" >> config.mk ;; + exec-prefix) + echo "EPREFIX=$val" >> config.mk + ;; + program-prefix) + if [ "$val" != "" ] ; then err "FIXME - not implemented" ; fi + ;; disable-static) echo "$uc_key=1" >> config.mk ;; + build|host) + # TODO: we should split this up, and override the other Makeconf + # variables like *_VENDOR, *_ARCH, *_CPU, *_KERNEL, *_SYSTEM + echo "$uc_key=$val" >> config.mk + ;; disable-option-checking) # Not implemented, this behavior is the default (for now) ;; + disable-dependency-tracking) + # Not implemented, dependency tracking is done in Ruby (for now) + ;; *) echo "Warning: unrecognized option: $arg" ;; @@ -87,5 +105,42 @@ do fi done +printf "checking for a C compiler... " +for cmd in cc gcc gcc4 clang +do + $cmd --version >/dev/null 2>&1 + if [ $? -eq 0 ] ; then cc="$cmd" ; break ; fi +done +if [ -n "$CC" ] ; then cc="$CC" ; fi +if [ -n "$cc" ] ; then + echo "$cc" + echo "CC=$cc" >> config.mk + if [ "$cc" != "cc" ] ; then echo "LD=$cc" >> config.mk ; fi + if [ -n "$CFLAGS" ] ; then echo "CFLAGS=$CFLAGS" >> config.mk ; fi +else + echo "not found" + err "Please install a compiler and add it to your PATH" +fi + +printf "checking for a usable make command... " +for cmd in make gmake +do + $cmd --version >/dev/null 2>&1 + if [ $? -eq 0 ] ; then make="$cmd" ; break ; fi +done +if [ -n "$make" ] ; then + echo "yes" + echo "MAKE=$make" >> config.mk +else + echo "not found" + err "Please install GNU Make and add it to your PATH as either make or gmake" +fi + +# Allow additional variables from the environment to override the defaults +# +test -n "$LD" && echo "LD=$LD" >> config.mk +test -n "$LDFLAGS" && echo "LDFLAGS=$LDFLAGS" >> config.mk +# TODO: need to add Makefile support for: LIBS, CPP, CPPFLAGS + rm -f config.h -make config.h +$make config.h From b98d7a39e0fe065dfd8e06a28dd11835768b63b8 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 13 Jan 2013 15:56:56 +0000 Subject: [PATCH 0530/1120] Install the manpages git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@616 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/GNUmakefile | 6 +++++- vendor/libkqueue/configure.rb | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/GNUmakefile b/vendor/libkqueue/GNUmakefile index 23bf7d587..d579a238d 100644 --- a/vendor/libkqueue/GNUmakefile +++ b/vendor/libkqueue/GNUmakefile @@ -132,7 +132,7 @@ distdir: umask 22 ; mkdir -p '$(distdir)/test' umask 22 ; mkdir -p '$(distdir)/test/..' cp -RL src/common/filter.c src/common/private.h src/common/tree.h src/common/debug.h src/common/knote.c src/common/alloc.h src/common/map.c src/common/kevent.c src/common/kqueue.c $(distdir)/src/common - cp -RL config.h GNUmakefile configure configure.rb $(distdir) + cp -RL config.h GNUmakefile kqueue.2 configure configure.rb $(distdir) cp -RL src/common/../posix/platform.h $(distdir)/src/common/../posix cp -RL src/common/../posix/../../include/sys/event.h $(distdir)/src/common/../posix/../../include/sys cp -RL src/common/../linux/platform.h $(distdir)/src/common/../linux @@ -155,8 +155,11 @@ install: $(INSTALL) -m 0644 libkqueue.so $(DESTDIR)$(LIBDIR)/libkqueue.so.0.0 /usr/bin/test -e $(DESTDIR)$(INCLUDEDIR)/kqueue/sys || $(INSTALL) -d -m 755 $(DESTDIR)$(INCLUDEDIR)/kqueue/sys $(INSTALL) -m 644 include/sys/event.h $(DESTDIR)$(INCLUDEDIR)/kqueue/sys + /usr/bin/test -e $(DESTDIR)$(MANDIR)/man2 || $(INSTALL) -d -m 755 $(DESTDIR)$(MANDIR)/man2 + $(INSTALL) -m 644 kqueue.2 $(DESTDIR)$(MANDIR)/man2 rm -f $(DESTDIR)$(LIBDIR)/libkqueue.so ln -s libkqueue.so.0.0 $(DESTDIR)$(LIBDIR)/libkqueue.so + ln -s kqueue.2 $(DESTDIR)$(MANDIR)/man2/kevent.2 kqtest: test/main.o test/kevent.o test/test.o test/proc.o test/read.o test/signal.o test/timer.o test/vnode.o test/user.o $(LD) -o kqtest -L . -Wl,-rpath,. -L . $(LDFLAGS) test/main.o test/kevent.o test/test.o test/proc.o test/read.o test/signal.o test/timer.o test/vnode.o test/user.o -lpthread -lrt -lkqueue $(LDADD) @@ -259,3 +262,4 @@ test/vnode.o: test/vnode.c test/common.h include/sys/event.h test/../config.h GN uninstall: rm -f $(DESTDIR)$(LIBDIR)/libkqueue.so rm -f $(DESTDIR)$(INCLUDEDIR)/kqueue/sys/include/sys/event.h + rm -f $(DESTDIR)$(MANDIR)/man2/kqueue.2 diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index fb46189a0..6b126c00e 100755 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -137,6 +137,8 @@ def get_ldadd :namespace => 'kqueue/sys', )) +project.add(Manual.new('kqueue.2', :alias => 'kevent.2')) + test_ldadd = get_ldadd() if SystemType.host =~ /-androideabi$/ test_ldadd += ' libkqueue.a' From b4d223d684a3866b43de662af4e2e1f673838123 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 19 Jan 2013 01:16:06 +0000 Subject: [PATCH 0531/1120] Add libkqueue.pc git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@617 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/GNUmakefile | 13 +++++++++++-- vendor/libkqueue/configure | 3 ++- vendor/libkqueue/configure.rb | 10 ++++++++++ vendor/libkqueue/libkqueue.pc.in | 13 ------------- 4 files changed, 23 insertions(+), 16 deletions(-) delete mode 100644 vendor/libkqueue/libkqueue.pc.in diff --git a/vendor/libkqueue/GNUmakefile b/vendor/libkqueue/GNUmakefile index d579a238d..3568efc49 100644 --- a/vendor/libkqueue/GNUmakefile +++ b/vendor/libkqueue/GNUmakefile @@ -15,6 +15,7 @@ LOCALEDIR = $(DATAROOTDIR)/locale LOCALSTATEDIR = $(PREFIX)/var MANDIR = $(DATAROOTDIR)/man OLDINCLUDEDIR = /usr/include +PKGCONFIGDIR = $(LIBDIR)/pkgconfig PKGDATADIR = $(DATADIR)/$(PACKAGE) PKGINCLUDEDIR = $(INCLUDEDIR)/$(PACKAGE) PKGLIBDIR = $(LIBDIR)/$(PACKAGE) @@ -45,7 +46,7 @@ HOST_TYPE=$(HOST_CPU)-$(HOST_VENDOR)-$(HOST_KERNEL)-$(HOST_SYSTEM) default: all -all: libkqueue.so libkqueue.a kqtest +all: libkqueue.so libkqueue.a kqtest libkqueue.pc check: kqtest ./kqtest @@ -132,7 +133,7 @@ distdir: umask 22 ; mkdir -p '$(distdir)/test' umask 22 ; mkdir -p '$(distdir)/test/..' cp -RL src/common/filter.c src/common/private.h src/common/tree.h src/common/debug.h src/common/knote.c src/common/alloc.h src/common/map.c src/common/kevent.c src/common/kqueue.c $(distdir)/src/common - cp -RL config.h GNUmakefile kqueue.2 configure configure.rb $(distdir) + cp -RL config.h GNUmakefile kqueue.2 libkqueue.pc.in configure configure.rb $(distdir) cp -RL src/common/../posix/platform.h $(distdir)/src/common/../posix cp -RL src/common/../posix/../../include/sys/event.h $(distdir)/src/common/../posix/../../include/sys cp -RL src/common/../linux/platform.h $(distdir)/src/common/../linux @@ -157,6 +158,8 @@ install: $(INSTALL) -m 644 include/sys/event.h $(DESTDIR)$(INCLUDEDIR)/kqueue/sys /usr/bin/test -e $(DESTDIR)$(MANDIR)/man2 || $(INSTALL) -d -m 755 $(DESTDIR)$(MANDIR)/man2 $(INSTALL) -m 644 kqueue.2 $(DESTDIR)$(MANDIR)/man2 + /usr/bin/test -e $(DESTDIR)$(PKGCONFIGDIR) || $(INSTALL) -d -m 755 $(DESTDIR)$(PKGCONFIGDIR) + $(INSTALL) -m 644 libkqueue.pc $(DESTDIR)$(PKGCONFIGDIR) rm -f $(DESTDIR)$(LIBDIR)/libkqueue.so ln -s libkqueue.so.0.0 $(DESTDIR)$(LIBDIR)/libkqueue.so ln -s kqueue.2 $(DESTDIR)$(MANDIR)/man2/kevent.2 @@ -179,6 +182,11 @@ ifneq ($(DISABLE_STATIC),1) ranlib libkqueue.a endif +libkqueue.pc: config.h + @echo 'creating libkqueue.pc' + @printf "prefix=$(PREFIX)\nexec_prefix=$(EPREFIX)\nlibdir=$(LIBDIR)\nincludedir=$(INCLUDEDIR)\n" > libkqueue.pc + @cat libkqueue.pc.in >> libkqueue.pc + libkqueue.so: src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o $(LD) -o libkqueue.so -shared -fPIC -L . $(LDFLAGS) src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o -lpthread -lrt $(LDADD) @@ -263,3 +271,4 @@ uninstall: rm -f $(DESTDIR)$(LIBDIR)/libkqueue.so rm -f $(DESTDIR)$(INCLUDEDIR)/kqueue/sys/include/sys/event.h rm -f $(DESTDIR)$(MANDIR)/man2/kqueue.2 + rm -f $(DESTDIR)$(PKGCONFIGDIR)/libkqueue.pc diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index be815129e..5c3d15b4d 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -33,6 +33,7 @@ Installation options: --localstatedir [DIRECTORY] TODO describe this [$(PREFIX)/var] --mandir [DIRECTORY] TODO describe this [$(DATAROOTDIR)/man] --oldincludedir [DIRECTORY] TODO describe this [/usr/include] + --pkgconfigdir [DIRECTORY] where to install pkg-config files [$(LIBDIR)/pkgconfig] --pkgdatadir [DIRECTORY] TODO describe this [$(DATADIR)/$(PACKAGE)] --pkgincludedir [DIRECTORY] TODO describe this [$(INCLUDEDIR)/$(PACKAGE)] --pkglibdir [DIRECTORY] TODO describe this [$(LIBDIR)/$(PACKAGE)] @@ -75,7 +76,7 @@ do usage exit 1 ;; - bindir|datadir|datarootdir|docdir|includedir|infodir|libdir|libexecdir|localedir|localstatedir|mandir|pkgdatadir|pkgincludedir|pkglibdir|prefix|sbindir|sharedstatedir|sysconfdir) + bindir|datadir|datarootdir|docdir|includedir|infodir|libdir|libexecdir|localedir|localstatedir|mandir|pkgconfigdir|pkgdatadir|pkgincludedir|pkglibdir|prefix|sbindir|sharedstatedir|sysconfdir) echo "$uc_key=$val" >> config.mk ;; exec-prefix) diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index 6b126c00e..38b383e92 100755 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -183,6 +183,16 @@ def get_ldadd ) end + +project.add(PkgConfig.new( + :name => 'libkqueue', + :description => 'Emulates FreeBSD kqueue(2) on other platforms', + :requires => '', + :libs => '-lkqueue', + :libs_private => '-lpthread', + :export_cflags => '-I${includedir}/kqueue', + )) + mc = Makeconf.new() mc.configure(project) diff --git a/vendor/libkqueue/libkqueue.pc.in b/vendor/libkqueue/libkqueue.pc.in deleted file mode 100644 index c9622a063..000000000 --- a/vendor/libkqueue/libkqueue.pc.in +++ /dev/null @@ -1,13 +0,0 @@ -prefix=@@PREFIX@@ -exec_prefix=${prefix} -libdir=@@LIBDIR@@ -includedir=@@INCLUDEDIR@@ - -Name: @@PROGRAM@@ -Description: Emulates FreeBSD kqueue(2) on other platforms -Version: @@VERSION@@ -Requires: -Libs: @@LIBDEPENDS@@ -lkqueue -Libs.private: @@LIBDEPENDS@@ -Cflags: -I${includedir}/kqueue - From 0c9722e83bf57df0f6448c0f551cff254b93dea4 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 19 Jan 2013 01:17:16 +0000 Subject: [PATCH 0532/1120] restore missing file git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@618 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/libkqueue.pc.in | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 vendor/libkqueue/libkqueue.pc.in diff --git a/vendor/libkqueue/libkqueue.pc.in b/vendor/libkqueue/libkqueue.pc.in new file mode 100644 index 000000000..362f0493e --- /dev/null +++ b/vendor/libkqueue/libkqueue.pc.in @@ -0,0 +1,8 @@ + +Name: libkqueue +Description: Emulates FreeBSD kqueue(2) on other platforms +Version: 0.1 +Requires: +Libs: -lkqueue +Libs.private: -lpthread +Cflags: -I${includedir}/kqueue From 7d465a7357e869ce6adf3f5f40e6f67772587737 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 22 Jan 2013 01:06:27 +0000 Subject: [PATCH 0533/1120] Partial support for older Linux kernels without eventfd support git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@619 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/linux/platform.c | 10 ++++++++++ vendor/libkqueue/src/linux/platform.h | 4 +++- vendor/libkqueue/src/linux/read.c | 8 ++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 9494de970..f80f05e2e 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -34,11 +34,19 @@ const struct kqueue_vtable kqops = { linux_kevent_copyout, NULL, NULL, +#if HAVE_SYS_EVENTFD_H linux_eventfd_init, linux_eventfd_close, linux_eventfd_raise, linux_eventfd_lower, linux_eventfd_descriptor +#else + posix_eventfd_init, + posix_eventfd_close, + posix_eventfd_raise, + posix_eventfd_lower, + posix_eventfd_descriptor +#endif }; int @@ -204,6 +212,7 @@ linux_kevent_copyout(struct kqueue *kq, int nready, return (nret); } +#if HAVE_SYS_EVENTFD_H int linux_eventfd_init(struct eventfd *e) { @@ -293,6 +302,7 @@ linux_eventfd_descriptor(struct eventfd *e) { return (e->ef_id); } +#endif /* HAVE_SYS_EVENTFD_H */ int linux_get_descriptor_type(struct knote *kn) diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index d0fa876e2..475fd276f 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -22,7 +22,9 @@ struct filter; #include #include #include -#include +#if HAVE_SYS_EVENTFD_H +# include +#endif #if HAVE_SYS_TIMERFD_H # include #endif diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index 7ec4f0cfa..f976e328a 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -165,6 +165,7 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) int evfd; kn->kn_epollfd = filter_epfd(filt); +#if HAVE_SYS_EVENTFD_H evfd = eventfd(0, 0); if (evfd < 0) { dbg_perror("eventfd(2)"); @@ -175,6 +176,13 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) (void) close(evfd); return (-1); } +#else + evfd = open("/dev/zero", O_RDONLY); + if (evfd < 0) { + dbg_perror("eventfd(2)"); + return (-1); + } +#endif kn->kdata.kn_eventfd = evfd; if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_eventfd, &ev) < 0) { From 00a62196ea25d8c661a5cd055c183fd8dc2f2ac8 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 22 Jan 2013 01:56:43 +0000 Subject: [PATCH 0534/1120] attempt to use posix/user.c for RHEL 5 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@620 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure.rb | 3 ++ vendor/libkqueue/src/common/private.h | 9 ++++ vendor/libkqueue/src/linux/platform.c | 21 +++++++++ vendor/libkqueue/src/linux/user.c | 30 +++++------- vendor/libkqueue/src/posix/user.c | 66 +++++++++++---------------- 5 files changed, 71 insertions(+), 58 deletions(-) diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index 38b383e92..31b524a7d 100755 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -64,6 +64,9 @@ def get_source_list(project) 'src/linux/user.c', 'src/linux/vnode.c' + # FIXME: needed for RHEL5 + #src.push 'src/posix/user.c' + if project.check_header('sys/signalfd.h') src.push 'src/linux/signal.c' else diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 0ec34e23c..c36a5b5cd 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -214,4 +214,13 @@ void *map_lookup(struct map *, int); void *map_delete(struct map *, int); void map_free(struct map *); +int posix_evfilt_user_init(struct filter *); +void posix_evfilt_user_destroy(struct filter *); +int posix_evfilt_user_copyout(struct kevent *, struct knote *, void *ptr UNUSED); +int posix_evfilt_user_knote_create(struct filter *, struct knote *); +int posix_evfilt_user_knote_modify(struct filter *, struct knote *, const struct kevent *); +int posix_evfilt_user_knote_delete(struct filter *, struct knote *); +int posix_evfilt_user_knote_enable(struct filter *, struct knote *); +int posix_evfilt_user_knote_disable(struct filter *, struct knote *); + #endif /* ! _KQUEUE_PRIVATE_H */ diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index f80f05e2e..30d5d55ef 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -21,6 +21,27 @@ //XXX-FIXME TEMP const struct filter evfilt_proc = EVFILT_NOTIMPL; +const struct filter evfilt_user = { + EVFILT_USER, + NULL, + NULL, +#if HAVE_SYS_EVENTFD_H + linux_evfilt_user_copyout, + linux_evfilt_user_knote_create, + linux_evfilt_user_knote_modify, + linux_evfilt_user_knote_delete, + linux_evfilt_user_knote_enable, + linux_evfilt_user_knote_disable, +#else + posix_evfilt_user_copyout, + posix_evfilt_user_knote_create, + posix_evfilt_user_knote_modify, + posix_evfilt_user_knote_delete, + posix_evfilt_user_knote_enable, + posix_evfilt_user_knote_disable, +#endif +}; + /* * Per-thread epoll event buffer used to ferry data between * kevent_wait() and kevent_copyout(). diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index 48f61819b..47dc4d4cf 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -29,6 +29,8 @@ #include "sys/event.h" #include "private.h" +#if HAVE_SYS_EVENTFD_H + /* NOTE: copy+pasted from linux_eventfd_raise() */ static int eventfd_raise(int evfd) @@ -90,7 +92,7 @@ eventfd_lower(int evfd) } int -evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) +linux_evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) { memcpy(dst, &src->kev, sizeof(*dst)); dst->fflags &= ~NOTE_FFCTRLMASK; //FIXME: Not sure if needed @@ -114,7 +116,7 @@ evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) } int -evfilt_user_knote_create(struct filter *filt, struct knote *kn) +linux_evfilt_user_knote_create(struct filter *filt, struct knote *kn) { struct epoll_event ev; int evfd; @@ -145,7 +147,7 @@ evfilt_user_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_user_knote_modify(struct filter *filt UNUSED, struct knote *kn, +linux_evfilt_user_knote_modify(struct filter *filt UNUSED, struct knote *kn, const struct kevent *kev) { unsigned int ffctrl; @@ -185,7 +187,7 @@ evfilt_user_knote_modify(struct filter *filt UNUSED, struct knote *kn, } int -evfilt_user_knote_delete(struct filter *filt, struct knote *kn) +linux_evfilt_user_knote_delete(struct filter *filt, struct knote *kn) { if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_DEL, kn->kdata.kn_eventfd, NULL) < 0) { @@ -203,27 +205,17 @@ evfilt_user_knote_delete(struct filter *filt, struct knote *kn) } int -evfilt_user_knote_enable(struct filter *filt, struct knote *kn) +linux_evfilt_user_knote_enable(struct filter *filt, struct knote *kn) { /* FIXME: what happens if NOTE_TRIGGER is in fflags? should the event fire? */ - return evfilt_user_knote_create(filt, kn); + return linux_evfilt_user_knote_create(filt, kn); } int -evfilt_user_knote_disable(struct filter *filt, struct knote *kn) +linux_evfilt_user_knote_disable(struct filter *filt, struct knote *kn) { - return evfilt_user_knote_delete(filt, kn); + return linux_evfilt_user_knote_delete(filt, kn); } -const struct filter evfilt_user = { - EVFILT_USER, - NULL, - NULL, - evfilt_user_copyout, - evfilt_user_knote_create, - evfilt_user_knote_modify, - evfilt_user_knote_delete, - evfilt_user_knote_enable, - evfilt_user_knote_disable, -}; +#endif /* HAVE_SYS_EVENTFD_H */ diff --git a/vendor/libkqueue/src/posix/user.c b/vendor/libkqueue/src/posix/user.c index 89b50eade..fe29bb84e 100644 --- a/vendor/libkqueue/src/posix/user.c +++ b/vendor/libkqueue/src/posix/user.c @@ -30,7 +30,7 @@ #include "private.h" int -evfilt_user_init(struct filter *filt) +posix_evfilt_user_init(struct filter *filt) { if (kqops.eventfd_init(&filt->kf_efd) < 0) return (-1); @@ -41,56 +41,40 @@ evfilt_user_init(struct filter *filt) } void -evfilt_user_destroy(struct filter *filt) +posix_evfilt_user_destroy(struct filter *filt) { kqops.eventfd_close(&filt->kf_efd); return; } int -evfilt_user_copyout(struct filter *filt, - struct kevent *dst, - int maxevents) +posix_evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) { + memcpy(dst, &src->kev, sizeof(*dst)); struct knote *kn; int nevents = 0; - for (kn = knote_dequeue(filt); kn != NULL; kn = knote_dequeue(filt)) { - memcpy(dst, &kn->kev, sizeof(*dst)); - dst->fflags &= ~NOTE_FFCTRLMASK; //FIXME: Not sure if needed - dst->fflags &= ~NOTE_TRIGGER; - if (kn->kev.flags & EV_ADD) { - /* NOTE: True on FreeBSD but not consistent behavior with - other filters. */ - dst->flags &= ~EV_ADD; - } - if (kn->kev.flags & EV_CLEAR) - kn->kev.fflags &= ~NOTE_TRIGGER; - if (kn->kev.flags & (EV_DISPATCH | EV_CLEAR | EV_ONESHOT)) - kqops.eventfd_lower(&filt->kf_efd); - if (kn->kev.flags & EV_DISPATCH) { - KNOTE_DISABLE(kn); - kn->kev.fflags &= ~NOTE_TRIGGER; - } else if (kn->kev.flags & EV_ONESHOT) { - knote_free(filt, kn); - } - - dst++; - if (++nevents == maxevents) - break; + dst->fflags &= ~NOTE_FFCTRLMASK; //FIXME: Not sure if needed + dst->fflags &= ~NOTE_TRIGGER; + if (src->kev.flags & EV_ADD) { + /* NOTE: True on FreeBSD but not consistent behavior with + other filters. */ + dst->flags &= ~EV_ADD; } - - /* This should normally never happen but is here for debugging */ - if (nevents == 0) { - dbg_puts("spurious wakeup"); - kqops.eventfd_lower(&filt->kf_efd); + if (src->kev.flags & EV_CLEAR) + src->kev.fflags &= ~NOTE_TRIGGER; + if (src->kev.flags & (EV_DISPATCH | EV_CLEAR | EV_ONESHOT)) { + kqops.eventfd_raise(&src->kdata.kn_eventfd); } - return (nevents); + if (src->kev.flags & EV_DISPATCH) + src->kev.fflags &= ~NOTE_TRIGGER; + + return (0); } int -evfilt_user_knote_create(struct filter *filt, struct knote *kn) +posix_evfilt_user_knote_create(struct filter *filt, struct knote *kn) { #if TODO u_int ffctrl; @@ -106,7 +90,7 @@ evfilt_user_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_user_knote_modify(struct filter *filt, struct knote *kn, +posix_evfilt_user_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { unsigned int ffctrl; @@ -146,13 +130,13 @@ evfilt_user_knote_modify(struct filter *filt, struct knote *kn, } int -evfilt_user_knote_delete(struct filter *filt, struct knote *kn) +posix_evfilt_user_knote_delete(struct filter *filt, struct knote *kn) { return (0); } int -evfilt_user_knote_enable(struct filter *filt, struct knote *kn) +posix_evfilt_user_knote_enable(struct filter *filt, struct knote *kn) { /* FIXME: what happens if NOTE_TRIGGER is in fflags? should the event fire? */ @@ -160,11 +144,13 @@ evfilt_user_knote_enable(struct filter *filt, struct knote *kn) } int -evfilt_user_knote_disable(struct filter *filt, struct knote *kn) +posix_evfilt_user_knote_disable(struct filter *filt, struct knote *kn) { return (0); } +/* FIXME: this conflicts with the struct in linux/platform.c + const struct filter evfilt_user = { EVFILT_USER, evfilt_user_init, @@ -176,3 +162,5 @@ const struct filter evfilt_user = { evfilt_user_knote_enable, evfilt_user_knote_disable, }; + +*/ From 1818c875f69311208f92971d98ec69f124d897c8 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 22 Jan 2013 02:08:13 +0000 Subject: [PATCH 0535/1120] Try using syscall(3) on RHEL5 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@621 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/linux/platform.c | 21 --------------------- vendor/libkqueue/src/linux/platform.h | 1 + vendor/libkqueue/src/linux/user.c | 21 +++++++++++++++++---- 3 files changed, 18 insertions(+), 25 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 30d5d55ef..f80f05e2e 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -21,27 +21,6 @@ //XXX-FIXME TEMP const struct filter evfilt_proc = EVFILT_NOTIMPL; -const struct filter evfilt_user = { - EVFILT_USER, - NULL, - NULL, -#if HAVE_SYS_EVENTFD_H - linux_evfilt_user_copyout, - linux_evfilt_user_knote_create, - linux_evfilt_user_knote_modify, - linux_evfilt_user_knote_delete, - linux_evfilt_user_knote_enable, - linux_evfilt_user_knote_disable, -#else - posix_evfilt_user_copyout, - posix_evfilt_user_knote_create, - posix_evfilt_user_knote_modify, - posix_evfilt_user_knote_delete, - posix_evfilt_user_knote_enable, - posix_evfilt_user_knote_disable, -#endif -}; - /* * Per-thread epoll event buffer used to ferry data between * kevent_wait() and kevent_copyout(). diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 475fd276f..213198323 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -19,6 +19,7 @@ struct filter; +#include #include #include #include diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index 47dc4d4cf..66a6a8d43 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -29,8 +29,6 @@ #include "sys/event.h" #include "private.h" -#if HAVE_SYS_EVENTFD_H - /* NOTE: copy+pasted from linux_eventfd_raise() */ static int eventfd_raise(int evfd) @@ -122,7 +120,12 @@ linux_evfilt_user_knote_create(struct filter *filt, struct knote *kn) int evfd; /* Create an eventfd */ - if ((evfd = eventfd(0, 0)) < 0) { +#if HAVE_SYS_EVENTFD_H + evfd = eventfd(0, 0); +#else + evfd = syscall(SYS_eventfd, 0, 0); +#endif + if (evfd < 0) { dbg_perror("eventfd"); goto errout; } @@ -218,4 +221,14 @@ linux_evfilt_user_knote_disable(struct filter *filt, struct knote *kn) return linux_evfilt_user_knote_delete(filt, kn); } -#endif /* HAVE_SYS_EVENTFD_H */ +const struct filter evfilt_user = { + EVFILT_USER, + NULL, + NULL, + linux_evfilt_user_copyout, + linux_evfilt_user_knote_create, + linux_evfilt_user_knote_modify, + linux_evfilt_user_knote_delete, + linux_evfilt_user_knote_enable, + linux_evfilt_user_knote_disable, +}; From c0940785730206c0d2052ac9ae0782fbbb4248d2 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 22 Jan 2013 02:14:24 +0000 Subject: [PATCH 0536/1120] Support signalfd on RHEL 5 via syscall() git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@622 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/linux/signal.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index 425d06c81..6177271ad 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -19,7 +19,28 @@ #if HAVE_SYS_SIGNALFD_H # include #else -# error signalfd is required +#define signalfd(a,b,c) syscall(SYS_signalfd, (a), (b), (c)) +#define SFD_NONBLOCK 04000 +struct signalfd_siginfo +{ + uint32_t ssi_signo; + int32_t ssi_errno; + int32_t ssi_code; + uint32_t ssi_pid; + uint32_t ssi_uid; + int32_t ssi_fd; + uint32_t ssi_tid; + uint32_t ssi_band; + uint32_t ssi_overrun; + uint32_t ssi_trapno; + int32_t ssi_status; + int32_t ssi_int; + uint64_t ssi_ptr; + uint64_t ssi_utime; + uint64_t ssi_stime; + uint64_t ssi_addr; + uint8_t __pad[48]; +}; #endif static void @@ -69,6 +90,7 @@ signalfd_create(int epfd, void *ptr, int signum) sigemptyset(&sigmask); sigaddset(&sigmask, signum); sigfd = signalfd(-1, &sigmask, flags); + /* WORKAROUND: Flags are broken on kernels older than Linux 2.6.27 */ if (sigfd < 0 && errno == EINVAL && flags != 0) { flags = 0; From be675374c58a08d5d62c99ecb03a758bb0e6a45a Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 22 Jan 2013 02:17:50 +0000 Subject: [PATCH 0537/1120] improve portability of timerfd() syscall wrappers git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@623 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/linux/timer.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index fb8337514..0181602f4 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -16,31 +16,24 @@ #include "private.h" -/* Android 4.0 does not have this header, but the kernel supports timerfds */ #ifndef HAVE_SYS_TIMERFD_H -#ifdef __ARM_ARCH_5__ -#define __NR_timerfd_create (__NR_SYSCALL_BASE+350) -#define __NR_timerfd_settime (__NR_SYSCALL_BASE+353) -#define __NR_timerfd_gettime (__NR_SYSCALL_BASE+354) -#else -#error Unsupported architecture, need to get the syscall numbers -#endif +#include int timerfd_create(int clockid, int flags) { - return syscall(__NR_timerfd_create, clockid, flags); + return syscall(SYS_timerfd_create, clockid, flags); } int timerfd_settime(int ufc, int flags, const struct itimerspec *utmr, struct itimerspec *otmr) { - return syscall(__NR_timerfd_settime, ufc, flags, utmr, otmr); + return syscall(SYS_timerfd_settime, ufc, flags, utmr, otmr); } int timerfd_gettime(int ufc, struct itimerspec *otmr) { - return syscall(__NR_timerfd_gettime, ufc, otmr); + return syscall(SYS_timerfd_gettime, ufc, otmr); } #endif From 27bd3737f63c8ef12b6da4196f410c5b681faa23 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 22 Jan 2013 02:27:59 +0000 Subject: [PATCH 0538/1120] Use magic numbers because of missing SYS_timerfd_* functions git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@624 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/linux/timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 0181602f4..f9627d4c2 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -28,12 +28,12 @@ int timerfd_create(int clockid, int flags) int timerfd_settime(int ufc, int flags, const struct itimerspec *utmr, struct itimerspec *otmr) { - return syscall(SYS_timerfd_settime, ufc, flags, utmr, otmr); + return syscall(SYS_timerfd_create + 1, ufc, flags, utmr, otmr); } int timerfd_gettime(int ufc, struct itimerspec *otmr) { - return syscall(SYS_timerfd_gettime, ufc, otmr); + return syscall(SYS_timerfd_create + 2, ufc, otmr); } #endif From 1e812ff79c688335658628693a9f9be0bca08828 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 23 Jan 2013 02:00:55 +0000 Subject: [PATCH 0539/1120] Revert the /dev/zero code path, and use syscall(SYS_eventfd) instead git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@625 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/linux/platform.c | 13 ++----------- vendor/libkqueue/src/linux/platform.h | 10 ++++++++++ vendor/libkqueue/src/linux/read.c | 9 +-------- vendor/libkqueue/src/linux/user.c | 4 ---- 4 files changed, 13 insertions(+), 23 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index f80f05e2e..fe6868c64 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -34,19 +34,11 @@ const struct kqueue_vtable kqops = { linux_kevent_copyout, NULL, NULL, -#if HAVE_SYS_EVENTFD_H linux_eventfd_init, linux_eventfd_close, linux_eventfd_raise, linux_eventfd_lower, linux_eventfd_descriptor -#else - posix_eventfd_init, - posix_eventfd_close, - posix_eventfd_raise, - posix_eventfd_lower, - posix_eventfd_descriptor -#endif }; int @@ -212,13 +204,13 @@ linux_kevent_copyout(struct kqueue *kq, int nready, return (nret); } -#if HAVE_SYS_EVENTFD_H int linux_eventfd_init(struct eventfd *e) { int evfd; - if ((evfd = eventfd(0, 0)) < 0) { + evfd = syscall(SYS_eventfd, 0, 0); + if (evfd < 0) { dbg_perror("eventfd"); return (-1); } @@ -302,7 +294,6 @@ linux_eventfd_descriptor(struct eventfd *e) { return (e->ef_id); } -#endif /* HAVE_SYS_EVENTFD_H */ int linux_get_descriptor_type(struct knote *kn) diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 213198323..b534d3e03 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -25,6 +25,16 @@ struct filter; #include #if HAVE_SYS_EVENTFD_H # include +#else +# include +# define eventfd(a,b) syscall(SYS_eventfd, (a), (b)) + + static inline int eventfd_write(int fd, uint64_t val) { + if (write(fd, &val, sizeof(val)) < (ssize_t) sizeof(val)) + return (-1); + else + return (0); + } #endif #if HAVE_SYS_TIMERFD_H # include diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index f976e328a..21026313a 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -165,7 +165,6 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) int evfd; kn->kn_epollfd = filter_epfd(filt); -#if HAVE_SYS_EVENTFD_H evfd = eventfd(0, 0); if (evfd < 0) { dbg_perror("eventfd(2)"); @@ -176,13 +175,7 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) (void) close(evfd); return (-1); } -#else - evfd = open("/dev/zero", O_RDONLY); - if (evfd < 0) { - dbg_perror("eventfd(2)"); - return (-1); - } -#endif + kn->kdata.kn_eventfd = evfd; if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_eventfd, &ev) < 0) { diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index 66a6a8d43..e3bc28a74 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -120,11 +120,7 @@ linux_evfilt_user_knote_create(struct filter *filt, struct knote *kn) int evfd; /* Create an eventfd */ -#if HAVE_SYS_EVENTFD_H evfd = eventfd(0, 0); -#else - evfd = syscall(SYS_eventfd, 0, 0); -#endif if (evfd < 0) { dbg_perror("eventfd"); goto errout; From fc0b81d39dabae2f5afb4d05517d4cfe82a4ab58 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 24 Jan 2013 00:08:03 +0000 Subject: [PATCH 0540/1120] Fix regressions on Android. Tested OK on Android, Debian, and Debian without eventfd()/timerfd()/signalfd() git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@626 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/linux/platform.c | 2 +- vendor/libkqueue/src/linux/platform.h | 4 +--- vendor/libkqueue/src/linux/timer.c | 29 ++++++++++++++++++++++++--- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index fe6868c64..e97eacc51 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -209,7 +209,7 @@ linux_eventfd_init(struct eventfd *e) { int evfd; - evfd = syscall(SYS_eventfd, 0, 0); + evfd = eventfd(0, 0); if (evfd < 0) { dbg_perror("eventfd"); return (-1); diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index b534d3e03..c6077fdcb 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -19,14 +19,13 @@ struct filter; -#include +#include #include #include #include #if HAVE_SYS_EVENTFD_H # include #else -# include # define eventfd(a,b) syscall(SYS_eventfd, (a), (b)) static inline int eventfd_write(int fd, uint64_t val) { @@ -45,7 +44,6 @@ struct filter; */ # define _GNU_SOURCE # include -# include # include #ifndef __ANDROID__ extern long int syscall (long int __sysno, ...); diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index f9627d4c2..9a65e0007 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -18,7 +18,30 @@ #ifndef HAVE_SYS_TIMERFD_H -#include +/* Android 4.0 does not have this header, but the kernel supports timerfds */ +#ifndef SYS_timerfd_create +#ifdef __ARM_ARCH_5__ +#define __NR_timerfd_create (__NR_SYSCALL_BASE+350) +#define __NR_timerfd_settime (__NR_SYSCALL_BASE+353) +#define __NR_timerfd_gettime (__NR_SYSCALL_BASE+354) +#else +#error Unsupported architecture, need to get the syscall numbers +#endif + +#define SYS_timerfd_create __NR_timerfd_create +#define SYS_timerfd_settime __NR_timerfd_settime +#define SYS_timerfd_gettime __NR_timerfd_gettime +#endif /* ! SYS_timerfd_create */ + +/* XXX-FIXME + These are horrible hacks that are only known to be true on RHEL 5 x86. + */ +#ifndef SYS_timerfd_settime +#define SYS_timerfd_settime (SYS_timerfd_create + 1) +#endif +#ifndef SYS_timerfd_gettime +#define SYS_timerfd_gettime (SYS_timerfd_create + 2) +#endif int timerfd_create(int clockid, int flags) { @@ -28,12 +51,12 @@ int timerfd_create(int clockid, int flags) int timerfd_settime(int ufc, int flags, const struct itimerspec *utmr, struct itimerspec *otmr) { - return syscall(SYS_timerfd_create + 1, ufc, flags, utmr, otmr); + return syscall(SYS_timerfd_settime, ufc, flags, utmr, otmr); } int timerfd_gettime(int ufc, struct itimerspec *otmr) { - return syscall(SYS_timerfd_create + 2, ufc, otmr); + return syscall(SYS_timerfd_gettime, ufc, otmr); } #endif From 850f53560898c06c24db8955e35fa13aeb1116a7 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 24 Jan 2013 00:16:54 +0000 Subject: [PATCH 0541/1120] Add an INSTALL file git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@627 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/INSTALL | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 vendor/libkqueue/INSTALL diff --git a/vendor/libkqueue/INSTALL b/vendor/libkqueue/INSTALL new file mode 100644 index 000000000..a7c251e46 --- /dev/null +++ b/vendor/libkqueue/INSTALL @@ -0,0 +1,19 @@ +INSTALLATION INSTRUCTIONS +--- + +To building on Android, run something like this: + + ruby ./configure.rb --host=arm-linux-androideabi \ + --with-ndk=/opt/android-ndk-r8c \ + --with-sdk=/opt/android-sdks + make + +For building on Linux or Solaris, run: + + ./configure + make + make install + +TODO -- Need to document for Windows + + From d927471b10be396029acdfe02667bea3c66147dd Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 24 Jan 2013 02:00:41 +0000 Subject: [PATCH 0542/1120] try something different git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@628 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/GNUmakefile | 4 +++- vendor/libkqueue/configure | 3 ++- vendor/libkqueue/configure.rb | 1 + vendor/libkqueue/include/sys/event.h | 2 +- vendor/libkqueue/src/common/debug.h | 2 +- vendor/libkqueue/src/common/private.h | 4 ++++ 6 files changed, 12 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/GNUmakefile b/vendor/libkqueue/GNUmakefile index 3568efc49..8e1615296 100644 --- a/vendor/libkqueue/GNUmakefile +++ b/vendor/libkqueue/GNUmakefile @@ -162,6 +162,8 @@ install: $(INSTALL) -m 644 libkqueue.pc $(DESTDIR)$(PKGCONFIGDIR) rm -f $(DESTDIR)$(LIBDIR)/libkqueue.so ln -s libkqueue.so.0.0 $(DESTDIR)$(LIBDIR)/libkqueue.so + rm -f $(DESTDIR)$(LIBDIR)/libkqueue.so.0 + ln -s libkqueue.so.0.0 $(DESTDIR)$(LIBDIR)/libkqueue.so.0 ln -s kqueue.2 $(DESTDIR)$(MANDIR)/man2/kevent.2 kqtest: test/main.o test/kevent.o test/test.o test/proc.o test/read.o test/signal.o test/timer.o test/vnode.o test/user.o @@ -188,7 +190,7 @@ libkqueue.pc: config.h @cat libkqueue.pc.in >> libkqueue.pc libkqueue.so: src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o - $(LD) -o libkqueue.so -shared -fPIC -L . $(LDFLAGS) src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o -lpthread -lrt $(LDADD) + $(LD) -o libkqueue.so -shared -fPIC -L . -Wl,-soname,libkqueue.so.0 $(LDFLAGS) src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o -lpthread -lrt $(LDADD) package: clean libkqueue-2.0.tar.gz rm -rf rpm *.rpm diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index 5c3d15b4d..b88f06edf 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -92,6 +92,7 @@ do # TODO: we should split this up, and override the other Makeconf # variables like *_VENDOR, *_ARCH, *_CPU, *_KERNEL, *_SYSTEM echo "$uc_key=$val" >> config.mk + eval "${key}_system_type=\"$val\"" ;; disable-option-checking) # Not implemented, this behavior is the default (for now) @@ -107,7 +108,7 @@ do done printf "checking for a C compiler... " -for cmd in cc gcc gcc4 clang +for cmd in ${host_system_type}-cc cc gcc gcc4 clang do $cmd --version >/dev/null 2>&1 if [ $? -eq 0 ] ; then cc="$cmd" ; break ; fi diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index 31b524a7d..a7a3d4da1 100755 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -198,6 +198,7 @@ def get_ldadd mc = Makeconf.new() mc.configure(project) + throw Platform.is_windows? __END__ # diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index f28e12ef8..610ab4493 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -36,7 +36,7 @@ #define intptr_t long #else #include -#if defined(_WIN32) && _MSC_VER < 1600 +#if defined(_WIN32) && _MSC_VER < 1600 && !defined(__MINGW32__) # include "../../src/windows/stdint.h" #else # include diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index 1d1aa4f95..fa5e8815e 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -20,7 +20,7 @@ #include #include #ifdef _WIN32 -# include +# include #else # include #endif diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index c36a5b5cd..d56adf4da 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -214,6 +214,8 @@ void *map_lookup(struct map *, int); void *map_delete(struct map *, int); void map_free(struct map *); +/* DEADWOOD: No longer needed due to the un-smerging of POSIX and Linux + int posix_evfilt_user_init(struct filter *); void posix_evfilt_user_destroy(struct filter *); int posix_evfilt_user_copyout(struct kevent *, struct knote *, void *ptr UNUSED); @@ -223,4 +225,6 @@ int posix_evfilt_user_knote_delete(struct filter *, struct knote *); int posix_evfilt_user_knote_enable(struct filter *, struct knote *); int posix_evfilt_user_knote_disable(struct filter *, struct knote *); +*/ + #endif /* ! _KQUEUE_PRIVATE_H */ From f18824eaf524e2c1e614f27f3d8d9eb0e4d28792 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 24 Jan 2013 02:40:19 +0000 Subject: [PATCH 0543/1120] Minor tweaks for cross-compiling to Win32 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@629 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/GNUmakefile | 118 +++++++++--------------- vendor/libkqueue/configure | 28 ++++++ vendor/libkqueue/configure.rb | 52 ++--------- vendor/libkqueue/src/windows/platform.h | 15 +-- vendor/libkqueue/test/main.c | 4 +- 5 files changed, 86 insertions(+), 131 deletions(-) diff --git a/vendor/libkqueue/GNUmakefile b/vendor/libkqueue/GNUmakefile index 8e1615296..404f31f6b 100644 --- a/vendor/libkqueue/GNUmakefile +++ b/vendor/libkqueue/GNUmakefile @@ -59,22 +59,16 @@ clean: rm -f src/common/map.o rm -f src/common/kevent.o rm -f src/common/kqueue.o - rm -f src/posix/platform.o - rm -f src/linux/platform.o - rm -f src/linux/read.o - rm -f src/linux/write.o - rm -f src/linux/user.o - rm -f src/linux/vnode.o - rm -f src/linux/signal.o - rm -f src/linux/timer.o + rm -f src/windows/timer.o + rm -f src/windows/platform.o + rm -f src/windows/read.o + rm -f src/windows/user.o rm -f libkqueue.so rm -f libkqueue.a rm -f test/main.o rm -f test/kevent.o rm -f test/test.o - rm -f test/proc.o rm -f test/read.o - rm -f test/signal.o rm -f test/timer.o rm -f test/vnode.o rm -f test/user.o @@ -119,16 +113,11 @@ distdir: umask 22 ; mkdir -p '$(distdir)/src/common/../posix' umask 22 ; mkdir -p '$(distdir)/src/common/../posix/../../include/sys' umask 22 ; mkdir -p '$(distdir)/src/common/../linux' - umask 22 ; mkdir -p '$(distdir)/src/posix' - umask 22 ; mkdir -p '$(distdir)/src/posix/../common' - umask 22 ; mkdir -p '$(distdir)/src/posix/../common/../posix' - umask 22 ; mkdir -p '$(distdir)/src/posix/../common/../posix/../../include/sys' - umask 22 ; mkdir -p '$(distdir)/src/posix/../common/../linux' - umask 22 ; mkdir -p '$(distdir)/src/linux' - umask 22 ; mkdir -p '$(distdir)/src/linux/../common' - umask 22 ; mkdir -p '$(distdir)/src/linux/../common/../posix' - umask 22 ; mkdir -p '$(distdir)/src/linux/../common/../posix/../../include/sys' - umask 22 ; mkdir -p '$(distdir)/src/linux/../common/../linux' + umask 22 ; mkdir -p '$(distdir)/src/windows' + umask 22 ; mkdir -p '$(distdir)/src/windows/../common' + umask 22 ; mkdir -p '$(distdir)/src/windows/../common/../posix' + umask 22 ; mkdir -p '$(distdir)/src/windows/../common/../posix/../../include/sys' + umask 22 ; mkdir -p '$(distdir)/src/windows/../common/../linux' umask 22 ; mkdir -p '$(distdir)/include/sys' umask 22 ; mkdir -p '$(distdir)/test' umask 22 ; mkdir -p '$(distdir)/test/..' @@ -137,18 +126,13 @@ distdir: cp -RL src/common/../posix/platform.h $(distdir)/src/common/../posix cp -RL src/common/../posix/../../include/sys/event.h $(distdir)/src/common/../posix/../../include/sys cp -RL src/common/../linux/platform.h $(distdir)/src/common/../linux - cp -RL src/posix/platform.c $(distdir)/src/posix - cp -RL src/posix/../common/private.h src/posix/../common/tree.h src/posix/../common/debug.h $(distdir)/src/posix/../common - cp -RL src/posix/../common/../posix/platform.h $(distdir)/src/posix/../common/../posix - cp -RL src/posix/../common/../posix/../../include/sys/event.h $(distdir)/src/posix/../common/../posix/../../include/sys - cp -RL src/posix/../common/../linux/platform.h $(distdir)/src/posix/../common/../linux - cp -RL src/linux/platform.c src/linux/read.c src/linux/write.c src/linux/user.c src/linux/vnode.c src/linux/signal.c src/linux/timer.c $(distdir)/src/linux - cp -RL src/linux/../common/private.h src/linux/../common/tree.h src/linux/../common/debug.h $(distdir)/src/linux/../common - cp -RL src/linux/../common/../posix/platform.h $(distdir)/src/linux/../common/../posix - cp -RL src/linux/../common/../posix/../../include/sys/event.h $(distdir)/src/linux/../common/../posix/../../include/sys - cp -RL src/linux/../common/../linux/platform.h $(distdir)/src/linux/../common/../linux + cp -RL src/windows/timer.c src/windows/platform.c src/windows/read.c src/windows/user.c $(distdir)/src/windows + cp -RL src/windows/../common/private.h src/windows/../common/tree.h src/windows/../common/debug.h $(distdir)/src/windows/../common + cp -RL src/windows/../common/../posix/platform.h $(distdir)/src/windows/../common/../posix + cp -RL src/windows/../common/../posix/../../include/sys/event.h $(distdir)/src/windows/../common/../posix/../../include/sys + cp -RL src/windows/../common/../linux/platform.h $(distdir)/src/windows/../common/../linux cp -RL include/sys/event.h $(distdir)/include/sys - cp -RL test/main.c test/common.h test/kevent.c test/test.c test/proc.c test/read.c test/signal.c test/timer.c test/vnode.c test/user.c $(distdir)/test + cp -RL test/main.c test/common.h test/kevent.c test/test.c test/read.c test/timer.c test/vnode.c test/user.c $(distdir)/test cp -RL test/../config.h $(distdir)/test/.. install: @@ -166,8 +150,8 @@ install: ln -s libkqueue.so.0.0 $(DESTDIR)$(LIBDIR)/libkqueue.so.0 ln -s kqueue.2 $(DESTDIR)$(MANDIR)/man2/kevent.2 -kqtest: test/main.o test/kevent.o test/test.o test/proc.o test/read.o test/signal.o test/timer.o test/vnode.o test/user.o - $(LD) -o kqtest -L . -Wl,-rpath,. -L . $(LDFLAGS) test/main.o test/kevent.o test/test.o test/proc.o test/read.o test/signal.o test/timer.o test/vnode.o test/user.o -lpthread -lrt -lkqueue $(LDADD) +kqtest: test/main.o test/kevent.o test/test.o test/read.o test/timer.o test/vnode.o test/user.o + $(LD) -o kqtest -L . -Wl,-rpath,. -L . $(LDFLAGS) test/main.o test/kevent.o test/test.o test/read.o test/timer.o test/vnode.o test/user.o -march=i686 -lws2_32 -lkqueue $(LDADD) libkqueue-2.0.tar.gz: rm -rf libkqueue-2.0 @@ -178,10 +162,10 @@ libkqueue-2.0.tar.gz: gzip libkqueue-2.0.tar rm -rf libkqueue-2.0 -libkqueue.a: src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o +libkqueue.a: src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/windows/timer.o src/windows/platform.o src/windows/read.o src/windows/user.o ifneq ($(DISABLE_STATIC),1) - ar cru libkqueue.a src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o - ranlib libkqueue.a + $(AR) cru libkqueue.a src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/windows/timer.o src/windows/platform.o src/windows/read.o src/windows/user.o + $(RANLIB) libkqueue.a endif libkqueue.pc: config.h @@ -189,8 +173,8 @@ libkqueue.pc: config.h @printf "prefix=$(PREFIX)\nexec_prefix=$(EPREFIX)\nlibdir=$(LIBDIR)\nincludedir=$(INCLUDEDIR)\n" > libkqueue.pc @cat libkqueue.pc.in >> libkqueue.pc -libkqueue.so: src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o - $(LD) -o libkqueue.so -shared -fPIC -L . -Wl,-soname,libkqueue.so.0 $(LDFLAGS) src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o -lpthread -lrt $(LDADD) +libkqueue.so: src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/windows/timer.o src/windows/platform.o src/windows/read.o src/windows/user.o + $(LD) -o libkqueue.so -shared -fPIC -L . -Wl,-soname,libkqueue.so.0 $(LDFLAGS) src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/windows/timer.o src/windows/platform.o src/windows/read.o src/windows/user.o -march=i686 -lws2_32 $(LDADD) package: clean libkqueue-2.0.tar.gz rm -rf rpm *.rpm @@ -204,70 +188,52 @@ package: clean libkqueue-2.0.tar.gz rm -rf rpm src/common/filter.o: src/common/filter.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/filter.o -fPIC -DPIC $(CFLAGS) -c src/common/filter.c + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -o src/common/filter.o -fPIC -DPIC $(CFLAGS) -c src/common/filter.c src/common/kevent.o: src/common/kevent.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/kevent.o -fPIC -DPIC $(CFLAGS) -c src/common/kevent.c + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -o src/common/kevent.o -fPIC -DPIC $(CFLAGS) -c src/common/kevent.c src/common/knote.o: src/common/knote.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h src/common/alloc.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/knote.o -fPIC -DPIC $(CFLAGS) -c src/common/knote.c + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -o src/common/knote.o -fPIC -DPIC $(CFLAGS) -c src/common/knote.c src/common/kqueue.o: src/common/kqueue.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/kqueue.o -fPIC -DPIC $(CFLAGS) -c src/common/kqueue.c + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -o src/common/kqueue.o -fPIC -DPIC $(CFLAGS) -c src/common/kqueue.c src/common/map.o: src/common/map.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/map.o -fPIC -DPIC $(CFLAGS) -c src/common/map.c + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -o src/common/map.o -fPIC -DPIC $(CFLAGS) -c src/common/map.c -src/linux/platform.o: src/linux/platform.c src/linux/../common/private.h config.h src/linux/../common/tree.h src/linux/../common/../posix/platform.h src/linux/../common/../posix/../../include/sys/event.h src/linux/../common/../linux/platform.h src/linux/../common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/platform.o -fPIC -DPIC $(CFLAGS) -c src/linux/platform.c +src/windows/platform.o: src/windows/platform.c src/windows/../common/private.h config.h src/windows/../common/tree.h src/windows/../common/../posix/platform.h src/windows/../common/../posix/../../include/sys/event.h src/windows/../common/../linux/platform.h src/windows/../common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -o src/windows/platform.o -fPIC -DPIC $(CFLAGS) -c src/windows/platform.c -src/linux/read.o: src/linux/read.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/read.o -fPIC -DPIC $(CFLAGS) -c src/linux/read.c +src/windows/read.o: src/windows/read.c src/windows/../common/private.h config.h src/windows/../common/tree.h src/windows/../common/../posix/platform.h src/windows/../common/../posix/../../include/sys/event.h src/windows/../common/../linux/platform.h src/windows/../common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -o src/windows/read.o -fPIC -DPIC $(CFLAGS) -c src/windows/read.c -src/linux/signal.o: src/linux/signal.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/signal.o -fPIC -DPIC $(CFLAGS) -c src/linux/signal.c +src/windows/timer.o: src/windows/timer.c src/windows/../common/private.h config.h src/windows/../common/tree.h src/windows/../common/../posix/platform.h src/windows/../common/../posix/../../include/sys/event.h src/windows/../common/../linux/platform.h src/windows/../common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -o src/windows/timer.o -fPIC -DPIC $(CFLAGS) -c src/windows/timer.c -src/linux/timer.o: src/linux/timer.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/timer.o -fPIC -DPIC $(CFLAGS) -c src/linux/timer.c - -src/linux/user.o: src/linux/user.c include/sys/event.h src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/user.o -fPIC -DPIC $(CFLAGS) -c src/linux/user.c - -src/linux/vnode.o: src/linux/vnode.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/vnode.o -fPIC -DPIC $(CFLAGS) -c src/linux/vnode.c - -src/linux/write.o: src/linux/write.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/write.o -fPIC -DPIC $(CFLAGS) -c src/linux/write.c - -src/posix/platform.o: src/posix/platform.c src/posix/../common/private.h config.h src/posix/../common/tree.h src/posix/../common/../posix/platform.h src/posix/../common/../posix/../../include/sys/event.h src/posix/../common/../linux/platform.h src/posix/../common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/posix/platform.o -fPIC -DPIC $(CFLAGS) -c src/posix/platform.c +src/windows/user.o: src/windows/user.c src/windows/../common/private.h config.h src/windows/../common/tree.h src/windows/../common/../posix/platform.h src/windows/../common/../posix/../../include/sys/event.h src/windows/../common/../linux/platform.h src/windows/../common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -o src/windows/user.o -fPIC -DPIC $(CFLAGS) -c src/windows/user.c test/kevent.o: test/kevent.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/kevent.o $(CFLAGS) -c test/kevent.c + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Iinclude -Itest -g -O0 -o test/kevent.o $(CFLAGS) -c test/kevent.c test/main.o: test/main.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/main.o $(CFLAGS) -c test/main.c - -test/proc.o: test/proc.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/proc.o $(CFLAGS) -c test/proc.c + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Iinclude -Itest -g -O0 -o test/main.o $(CFLAGS) -c test/main.c test/read.o: test/read.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/read.o $(CFLAGS) -c test/read.c - -test/signal.o: test/signal.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/signal.o $(CFLAGS) -c test/signal.c + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Iinclude -Itest -g -O0 -o test/read.o $(CFLAGS) -c test/read.c test/test.o: test/test.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/test.o $(CFLAGS) -c test/test.c + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Iinclude -Itest -g -O0 -o test/test.o $(CFLAGS) -c test/test.c test/timer.o: test/timer.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/timer.o $(CFLAGS) -c test/timer.c + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Iinclude -Itest -g -O0 -o test/timer.o $(CFLAGS) -c test/timer.c test/user.o: test/user.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/user.o $(CFLAGS) -c test/user.c + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Iinclude -Itest -g -O0 -o test/user.o $(CFLAGS) -c test/user.c test/vnode.o: test/vnode.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/vnode.o $(CFLAGS) -c test/vnode.c + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Iinclude -Itest -g -O0 -o test/vnode.o $(CFLAGS) -c test/vnode.c uninstall: rm -f $(DESTDIR)$(LIBDIR)/libkqueue.so diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index b88f06edf..1d0610def 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -124,6 +124,34 @@ else err "Please install a compiler and add it to your PATH" fi +printf "checking for ar.. " +for ar in ${host_system_type}-ar ar gar +do + $ar --version >/dev/null 2>&1 + if [ $? -eq 0 ] ; then ar="$ar" ; break ; fi +done +if [ -n "$ar" ] ; then + echo "$ar" + echo "AR=$ar" >> config.mk +else + echo "not found" + err "Please install an archiver and add it to your PATH" +fi + +printf "checking for ranlib.. " +for ranlib in ${host_system_type}-ranlib ranlib +do + $ar --version >/dev/null 2>&1 + if [ $? -eq 0 ] ; then ranlib="$ranlib" ; break ; fi +done +if [ -n "$ranlib" ] ; then + echo "$ranlib" + echo "RANLIB=$ranlib" >> config.mk +else + echo "not found" + err "Please install ranlib and add it to your PATH" +fi + printf "checking for a usable make command... " for cmd in make gmake do diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index a7a3d4da1..f90185ec7 100755 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -24,13 +24,13 @@ # Determine the list of compiler flags def get_cflags - cflags='-I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600'.split(/ /) + cflags='-I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600'.split(/ /) - if Platform.is_linux? + if false # TODO - note this as a GCC 4.X dependency cflags.push ' -fvisibility=hidden' end - if Platform.is_solaris? + if false cflags.push "-D__EXTENSIONS__" end cflags @@ -46,18 +46,18 @@ def get_source_list(project) src/common/kqueue.c } - if Platform.is_solaris? + if false src.push 'src/solaris/signal.c', 'src/solaris/timer.c', 'src/solaris/platform.c', 'src/solaris/user.c' end - if Platform.is_linux? or Platform.is_solaris? + if false src.push 'src/posix/platform.c' end - if Platform.is_linux? + if false src.push 'src/linux/platform.c', 'src/linux/read.c', 'src/linux/write.c', @@ -76,7 +76,7 @@ def get_source_list(project) src.push 'src/linux/timer.c' end - if Platform.is_windows? + if true src.push 'src/windows/timer.c', 'src/windows/platform.c', 'src/windows/read.c', @@ -90,17 +90,7 @@ def get_source_list(project) def get_ldadd ldadd = '' - if Platform.is_linux? or Platform.is_solaris? - ldadd += ' -lpthread' - end - - if Platform.is_linux? - ldadd += ' -lrt' - end - - if Platform.is_windows? ldadd += ' ws2_32.lib' - end ldadd end @@ -109,6 +99,8 @@ def get_ldadd # MAIN() # +mc = Makeconf.new() + project = Project.new \ :id => 'libkqueue', :version => 2.0 @@ -148,11 +140,10 @@ def get_ldadd else test_ldadd += ' -lkqueue' end -if Platform.is_windows? project.add( Test.new( :id => 'kqtest', - :cflags => '-g -O0 -Wall -Werror -Iinclude -Itest', + :cflags => '-g -O0 -Wall -Iinclude -Itest', :sources => %w{ test/main.c test/kevent.c @@ -165,27 +156,6 @@ def get_ldadd :ldadd => test_ldadd.split(' ') ) ) -else - project.add( - Test.new( - :id => 'kqtest', - :cflags => '-g -O0 -Wall -Werror -I./include -I./test', - :sources => %w{ - test/main.c - test/kevent.c - test/test.c - test/proc.c - test/read.c - test/signal.c - test/timer.c - test/vnode.c - test/user.c - }, - :ldadd => test_ldadd.split(' ') - ) - ) -end - project.add(PkgConfig.new( :name => 'libkqueue', @@ -196,9 +166,7 @@ def get_ldadd :export_cflags => '-I${includedir}/kqueue', )) -mc = Makeconf.new() mc.configure(project) - throw Platform.is_windows? __END__ # diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 3d098e3bf..a9c98c19a 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -46,17 +46,10 @@ /* * Atomic integer operations */ -#ifdef __GNUC__ -# define atomic_inc(p) __sync_add_and_fetch((p), 1) -# define atomic_dec(p) __sync_sub_and_fetch((p), 1) -# define atomic_cas(p, v0, v1) __sync_val_compare_and_swap((p), (v0), (v1)) -# define atomic_ptr_cas(p, v0, v1) __sync_val_compare_and_swap((p), (v0), (v1)) -#else -# define atomic_inc InterlockedIncrement -# define atomic_dec InterlockedDecrement -# define atomic_cas(p, oval, nval) InterlockedCompareExchange(p, nval, oval) -# define atomic_ptr_cas(p, oval, nval) InterlockedCompareExchangePointer(p, nval, oval) -#endif +#define atomic_inc InterlockedIncrement +#define atomic_dec InterlockedDecrement +#define atomic_cas(p, oval, nval) InterlockedCompareExchange(p, nval, oval) +#define atomic_ptr_cas(p, oval, nval) InterlockedCompareExchangePointer(p, nval, oval) /* * Additional members of struct kqueue diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 33d8c4250..e1a5e039f 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -117,7 +117,7 @@ test_ev_receipt(void *unused) if ((kq = kqueue()) < 0) die("kqueue()"); -#ifdef EV_RECEIPT +#if defined(EV_RECEIPT) && !defined(_WIN32) EV_SET(&kev, SIGUSR2, EVFILT_SIGNAL, EV_ADD | EV_RECEIPT, 0, 0, NULL); if (kevent(kq, &kev, 1, &kev, 1, NULL) < 0) @@ -128,7 +128,7 @@ test_ev_receipt(void *unused) close(kq); #else memset(&kev, 0, sizeof(kev)); - puts("Skipped -- EV_RECEIPT is not available"); + puts("Skipped -- EV_RECEIPT is not available or running on Win32"); #endif } From 210f51b455df1112d560340e2b746586865beafe Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 25 Jan 2013 02:43:43 +0000 Subject: [PATCH 0544/1120] Fixes for _WIN32. Eliminates the use of MAKE_STATIC and the DllMain constructor. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@630 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/CMakeLists.txt | 1 - vendor/libkqueue/src/common/kqueue.c | 27 +++++++++++++++++++--- vendor/libkqueue/src/windows/platform.c | 30 ------------------------- vendor/libkqueue/test/main.c | 11 ++++----- 4 files changed, 28 insertions(+), 41 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 9da5ccfac..dfc32de10 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -86,7 +86,6 @@ include_directories( option(STATIC_KQUEUE "Enable to build libkqueue as static lib" OFF) if(STATIC_KQUEUE) message("-- building libkqueue as static lib") - add_definitions(-DMAKE_STATIC) add_library(kqueue STATIC ${SRC} ${INCL}) else() add_library(kqueue SHARED ${SRC} ${INCL}) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 782bff4da..c05f4e12b 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -27,7 +27,10 @@ int DEBUG_KQUEUE = 0; char *KQUEUE_DEBUG_IDENT = "KQ"; -#ifndef _WIN32 +#ifdef _WIN32 +static LONG kq_init_begin = 0; +static int kq_init_complete = 0; +#else pthread_mutex_t kq_mtx = PTHREAD_MUTEX_INITIALIZER; pthread_once_t kq_is_initialized = PTHREAD_ONCE_INIT; #endif @@ -56,7 +59,6 @@ get_fd_limit(void) static struct map *kqmap; - void libkqueue_init(void) { @@ -66,6 +68,14 @@ libkqueue_init(void) char *s = getenv("KQUEUE_DEBUG"); if (s != NULL && strlen(s) > 0) { DEBUG_KQUEUE = 1; + +#ifdef _WIN32 + /* Initialize the Winsock library */ + WSADATA wsaData; + if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) + abort(); +#endif + # if defined(_WIN32) && !defined(__GNUC__) /* Enable heap surveillance */ { @@ -83,6 +93,9 @@ libkqueue_init(void) if (knote_init() < 0) abort(); dbg_puts("library initialization complete"); +#ifdef _WIN32 + kq_init_complete = 1; +#endif } #if DEADWOOD @@ -116,7 +129,15 @@ kqueue(void) struct kqueue *kq; struct kqueue *tmp; -#ifndef _WIN32 +#ifdef _WIN32 + if (InterlockedCompareExchange(&kq_init_begin, 0, 1) == 0) { + libkqueue_init(); + } else { + while (kq_init_complete == 0) { + sleep(1); + } + } +#else (void) pthread_mutex_lock(&kq_mtx); (void) pthread_once(&kq_is_initialized, libkqueue_init); (void) pthread_mutex_unlock(&kq_mtx); diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 8fb7cdd10..1f8c04e6c 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -43,36 +43,6 @@ const struct kqueue_vtable kqops = { windows_filter_free, }; -#ifndef MAKE_STATIC - -BOOL WINAPI DllMain( - HINSTANCE self, - DWORD reason, - LPVOID unused) -{ - switch (reason) { - case DLL_PROCESS_ATTACH: - -#if XXX - //move to EVFILT_READ? - if (WSAStartup(MAKEWORD(2,2), NULL) != 0) - return (FALSE); -#endif - libkqueue_init(); - break; - - case DLL_PROCESS_DETACH: -#if XXX - WSACleanup(); -#endif - break; - } - - return (TRUE); -} - -#endif - int windows_kqueue_init(struct kqueue *kq) { diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index e1a5e039f..110d64ae9 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -188,7 +188,7 @@ test_harness(struct unit_test tests[], int iterations, int concurrency) abort(); ctx->iteration = n++; ctx->kqfd = kqfd; - memcpy(&ctx->tests, tests, sizeof(ctx->tests)); //FIXME: invalid read + memcpy(&ctx->tests, tests, sizeof(*tests)); ctx->iterations = iterations; ctx->concurrency = concurrency; @@ -254,10 +254,6 @@ main(int argc, char **argv) char *arg; int match; -#ifdef MAKE_STATIC - libkqueue_init(); -#endif - #ifdef _WIN32 /* Initialize the Winsock library */ WSADATA wsaData; @@ -265,10 +261,11 @@ main(int argc, char **argv) err(1, "WSAStartup failed"); #endif -/* Windows does not provide a POSIX-compatible getopt */ -#ifndef _WIN32 iterations = 1; concurrency = 1; + +/* Windows does not provide a POSIX-compatible getopt */ +#ifndef _WIN32 while ((c = getopt (argc, argv, "hc:n:")) != -1) { switch (c) { case 'c': From 0f7977fb64d2bb5d7910d5bcfeb273374b3c6c90 Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 25 Jan 2013 02:48:07 +0000 Subject: [PATCH 0545/1120] Revert accidental checkin of win32-specific script git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@631 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/configure.rb | 51 ++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index f90185ec7..31b524a7d 100755 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -24,13 +24,13 @@ # Determine the list of compiler flags def get_cflags - cflags='-I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600'.split(/ /) + cflags='-I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600'.split(/ /) - if false + if Platform.is_linux? # TODO - note this as a GCC 4.X dependency cflags.push ' -fvisibility=hidden' end - if false + if Platform.is_solaris? cflags.push "-D__EXTENSIONS__" end cflags @@ -46,18 +46,18 @@ def get_source_list(project) src/common/kqueue.c } - if false + if Platform.is_solaris? src.push 'src/solaris/signal.c', 'src/solaris/timer.c', 'src/solaris/platform.c', 'src/solaris/user.c' end - if false + if Platform.is_linux? or Platform.is_solaris? src.push 'src/posix/platform.c' end - if false + if Platform.is_linux? src.push 'src/linux/platform.c', 'src/linux/read.c', 'src/linux/write.c', @@ -76,7 +76,7 @@ def get_source_list(project) src.push 'src/linux/timer.c' end - if true + if Platform.is_windows? src.push 'src/windows/timer.c', 'src/windows/platform.c', 'src/windows/read.c', @@ -90,7 +90,17 @@ def get_source_list(project) def get_ldadd ldadd = '' + if Platform.is_linux? or Platform.is_solaris? + ldadd += ' -lpthread' + end + + if Platform.is_linux? + ldadd += ' -lrt' + end + + if Platform.is_windows? ldadd += ' ws2_32.lib' + end ldadd end @@ -99,8 +109,6 @@ def get_ldadd # MAIN() # -mc = Makeconf.new() - project = Project.new \ :id => 'libkqueue', :version => 2.0 @@ -140,10 +148,11 @@ def get_ldadd else test_ldadd += ' -lkqueue' end +if Platform.is_windows? project.add( Test.new( :id => 'kqtest', - :cflags => '-g -O0 -Wall -Iinclude -Itest', + :cflags => '-g -O0 -Wall -Werror -Iinclude -Itest', :sources => %w{ test/main.c test/kevent.c @@ -156,6 +165,27 @@ def get_ldadd :ldadd => test_ldadd.split(' ') ) ) +else + project.add( + Test.new( + :id => 'kqtest', + :cflags => '-g -O0 -Wall -Werror -I./include -I./test', + :sources => %w{ + test/main.c + test/kevent.c + test/test.c + test/proc.c + test/read.c + test/signal.c + test/timer.c + test/vnode.c + test/user.c + }, + :ldadd => test_ldadd.split(' ') + ) + ) +end + project.add(PkgConfig.new( :name => 'libkqueue', @@ -166,6 +196,7 @@ def get_ldadd :export_cflags => '-I${includedir}/kqueue', )) +mc = Makeconf.new() mc.configure(project) __END__ From 73557907bc9b3f9f73164c1eca0044db87c14237 Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 25 Jan 2013 02:59:35 +0000 Subject: [PATCH 0546/1120] Remove concurrency, re-enable signal tests git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@632 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/common.h | 6 +-- vendor/libkqueue/test/main.c | 79 ++++++++++------------------------ vendor/libkqueue/test/timer.c | 12 ------ 3 files changed, 25 insertions(+), 72 deletions(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index e05d8ab68..d447fe140 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -59,15 +59,14 @@ struct test_context; struct unit_test { const char *ut_name; int ut_enabled; - int ut_concurrent; void (*ut_func)(struct test_context *); }; +#define MAX_TESTS 50 struct test_context { - struct unit_test tests[50]; //TODO: use MAX_TESTS instead of magic number + struct unit_test tests[MAX_TESTS]; char *cur_test_id; int iterations; - int concurrency; int iteration; int kqfd; @@ -84,7 +83,6 @@ void test_evfilt_read(struct test_context *); void test_evfilt_signal(struct test_context *); void test_evfilt_vnode(struct test_context *); void test_evfilt_timer(struct test_context *); -void test_evfilt_timer_concurrent(struct test_context *); void test_evfilt_proc(struct test_context *); #ifdef EVFILT_USER void test_evfilt_user(struct test_context *); diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 110d64ae9..7680c1f3d 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -138,8 +138,6 @@ run_iteration(struct test_context *ctx) struct unit_test *test; for (test = &ctx->tests[0]; test->ut_name != NULL; test++) { - if (ctx->concurrency > 1 && test->ut_concurrent == 0) - continue; if (test->ut_enabled) test->ut_func(ctx); } @@ -147,18 +145,12 @@ run_iteration(struct test_context *ctx) } void -test_harness(struct unit_test tests[], int iterations, int concurrency) +test_harness(struct unit_test tests[MAX_TESTS], int iterations) { - int i, j, n, kqfd; - pthread_t tid[MAX_THREADS]; + int i, n, kqfd; struct test_context *ctx; - int rv; - if (concurrency >= MAX_THREADS) - errx(1, "Too many threads"); - - printf("Running %d iterations using %d worker threads\n", - iterations, concurrency); + printf("Running %d iterations\n", iterations); testing_begin(); @@ -181,34 +173,15 @@ test_harness(struct unit_test tests[], int iterations, int concurrency) n = 0; for (i = 0; i < iterations; i++) { - for (j = 0; j < concurrency; j++) { - /* Create a unique context object for each thread */ - ctx = calloc(1, sizeof(*ctx)); - if (ctx == NULL) - abort(); - ctx->iteration = n++; - ctx->kqfd = kqfd; - memcpy(&ctx->tests, tests, sizeof(*tests)); - ctx->iterations = iterations; - ctx->concurrency = concurrency; - -#ifdef _WIN32 - /* TODO: run in a separate thread */ - run_iteration(ctx); - rv = 0; -#else - rv = pthread_create(&tid[j], NULL, (void * (*)(void *)) run_iteration, ctx); -#endif - if (rv != 0) - err(1, "pthread_create"); - } -#ifdef _WIN32 - // TODO: join threads -#else - for (j = 0; j < concurrency; j++) { - pthread_join(tid[j], NULL); - } -#endif + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) + abort(); + ctx->iteration = n++; + ctx->kqfd = kqfd; + memcpy(&ctx->tests, tests, sizeof(ctx->tests)); + ctx->iterations = iterations; + + run_iteration(ctx); } testing_end(); @@ -221,7 +194,6 @@ usage(void) printf("usage:\n" " -h This message\n" " -n Number of iterations (default: 1)\n" - " -c Number of threads running concurrently (default: 1)\n" "\n\n" ); exit(1); @@ -230,27 +202,26 @@ usage(void) int main(int argc, char **argv) { - struct unit_test tests[] = { - { "socket", 1, 0, test_evfilt_read }, + struct unit_test tests[MAX_TESTS] = { + { "socket", 1, test_evfilt_read }, #ifndef _WIN32 // XXX-FIXME -- BROKEN ON LINUX WHEN RUN IN A SEPARATE THREAD - { "signal", 0, 0, test_evfilt_signal }, + { "signal", 1, test_evfilt_signal }, #endif #if FIXME - { "proc", 1, 0, test_evfilt_proc }, + { "proc", 1, test_evfilt_proc }, #endif - { "timer", 1, 0, test_evfilt_timer }, - { "timer_concurrent", 1, 1, test_evfilt_timer_concurrent }, + { "timer", 1, test_evfilt_timer }, #ifndef _WIN32 - { "vnode", 1, 0, test_evfilt_vnode }, + { "vnode", 1, test_evfilt_vnode }, #endif #ifdef EVFILT_USER - { "user", 1, 0, test_evfilt_user }, + { "user", 1, test_evfilt_user }, #endif - { NULL, 0, 0, NULL }, + { NULL, 0, NULL }, }; struct unit_test *test; - int c, i, concurrency, iterations; + int c, i, iterations; char *arg; int match; @@ -262,15 +233,11 @@ main(int argc, char **argv) #endif iterations = 1; - concurrency = 1; /* Windows does not provide a POSIX-compatible getopt */ #ifndef _WIN32 - while ((c = getopt (argc, argv, "hc:n:")) != -1) { + while ((c = getopt (argc, argv, "hn:")) != -1) { switch (c) { - case 'c': - concurrency = atoi(optarg); - break; case 'h': usage(); break; @@ -307,7 +274,7 @@ main(int argc, char **argv) } #endif - test_harness(tests, iterations, concurrency); + test_harness(tests, iterations); return (0); } diff --git a/vendor/libkqueue/test/timer.c b/vendor/libkqueue/test/timer.c index 3ba56325c..e838a00e4 100644 --- a/vendor/libkqueue/test/timer.c +++ b/vendor/libkqueue/test/timer.c @@ -168,15 +168,3 @@ test_evfilt_timer(struct test_context *ctx) test(kevent_timer_dispatch, ctx); #endif } - -void -test_evfilt_timer_concurrent(struct test_context *ctx) -{ - struct kevent kev, ret; - - kevent_add(ctx->kqfd, &kev, ctx->iteration, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 100, NULL); - kevent_get(&ret, ctx->kqfd); - /* Do not compare ret and kev, because it may be triggered by a - different thread's kevent stucture */ - -} From c291d500842716ea0433d595b57405e46b03423f Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 1 Feb 2013 01:58:52 +0000 Subject: [PATCH 0547/1120] disable signal test on android git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@633 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 7680c1f3d..3403a7491 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -204,7 +204,7 @@ main(int argc, char **argv) { struct unit_test tests[MAX_TESTS] = { { "socket", 1, test_evfilt_read }, -#ifndef _WIN32 +#if !defined(_WIN32) && !defined(__ANDROID__) // XXX-FIXME -- BROKEN ON LINUX WHEN RUN IN A SEPARATE THREAD { "signal", 1, test_evfilt_signal }, #endif From bcbbed2e72b75569ddaf52a20dc1eab30b122dd2 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 5 Feb 2013 01:41:02 +0000 Subject: [PATCH 0548/1120] Fix regression with Ruby 1.8 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@634 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/GNUmakefile | 122 ++++++++++++++++++++++------------ vendor/libkqueue/configure.rb | 4 +- 2 files changed, 80 insertions(+), 46 deletions(-) diff --git a/vendor/libkqueue/GNUmakefile b/vendor/libkqueue/GNUmakefile index 404f31f6b..c70ae9b12 100644 --- a/vendor/libkqueue/GNUmakefile +++ b/vendor/libkqueue/GNUmakefile @@ -59,16 +59,22 @@ clean: rm -f src/common/map.o rm -f src/common/kevent.o rm -f src/common/kqueue.o - rm -f src/windows/timer.o - rm -f src/windows/platform.o - rm -f src/windows/read.o - rm -f src/windows/user.o + rm -f src/posix/platform.o + rm -f src/linux/platform.o + rm -f src/linux/read.o + rm -f src/linux/write.o + rm -f src/linux/user.o + rm -f src/linux/vnode.o + rm -f src/linux/signal.o + rm -f src/linux/timer.o rm -f libkqueue.so rm -f libkqueue.a rm -f test/main.o rm -f test/kevent.o rm -f test/test.o + rm -f test/proc.o rm -f test/read.o + rm -f test/signal.o rm -f test/timer.o rm -f test/vnode.o rm -f test/user.o @@ -113,26 +119,36 @@ distdir: umask 22 ; mkdir -p '$(distdir)/src/common/../posix' umask 22 ; mkdir -p '$(distdir)/src/common/../posix/../../include/sys' umask 22 ; mkdir -p '$(distdir)/src/common/../linux' - umask 22 ; mkdir -p '$(distdir)/src/windows' - umask 22 ; mkdir -p '$(distdir)/src/windows/../common' - umask 22 ; mkdir -p '$(distdir)/src/windows/../common/../posix' - umask 22 ; mkdir -p '$(distdir)/src/windows/../common/../posix/../../include/sys' - umask 22 ; mkdir -p '$(distdir)/src/windows/../common/../linux' + umask 22 ; mkdir -p '$(distdir)/src/posix' + umask 22 ; mkdir -p '$(distdir)/src/posix/../common' + umask 22 ; mkdir -p '$(distdir)/src/posix/../common/../posix' + umask 22 ; mkdir -p '$(distdir)/src/posix/../common/../posix/../../include/sys' + umask 22 ; mkdir -p '$(distdir)/src/posix/../common/../linux' + umask 22 ; mkdir -p '$(distdir)/src/linux' + umask 22 ; mkdir -p '$(distdir)/src/linux/../common' + umask 22 ; mkdir -p '$(distdir)/src/linux/../common/../posix' + umask 22 ; mkdir -p '$(distdir)/src/linux/../common/../posix/../../include/sys' + umask 22 ; mkdir -p '$(distdir)/src/linux/../common/../linux' umask 22 ; mkdir -p '$(distdir)/include/sys' umask 22 ; mkdir -p '$(distdir)/test' umask 22 ; mkdir -p '$(distdir)/test/..' - cp -RL src/common/filter.c src/common/private.h src/common/tree.h src/common/debug.h src/common/knote.c src/common/alloc.h src/common/map.c src/common/kevent.c src/common/kqueue.c $(distdir)/src/common - cp -RL config.h GNUmakefile kqueue.2 libkqueue.pc.in configure configure.rb $(distdir) - cp -RL src/common/../posix/platform.h $(distdir)/src/common/../posix cp -RL src/common/../posix/../../include/sys/event.h $(distdir)/src/common/../posix/../../include/sys + cp -RL src/linux/../common/private.h src/linux/../common/tree.h src/linux/../common/debug.h $(distdir)/src/linux/../common cp -RL src/common/../linux/platform.h $(distdir)/src/common/../linux - cp -RL src/windows/timer.c src/windows/platform.c src/windows/read.c src/windows/user.c $(distdir)/src/windows - cp -RL src/windows/../common/private.h src/windows/../common/tree.h src/windows/../common/debug.h $(distdir)/src/windows/../common - cp -RL src/windows/../common/../posix/platform.h $(distdir)/src/windows/../common/../posix - cp -RL src/windows/../common/../posix/../../include/sys/event.h $(distdir)/src/windows/../common/../posix/../../include/sys - cp -RL src/windows/../common/../linux/platform.h $(distdir)/src/windows/../common/../linux + cp -RL src/common/../posix/platform.h $(distdir)/src/common/../posix + cp -RL src/posix/../common/../linux/platform.h $(distdir)/src/posix/../common/../linux + cp -RL src/common/filter.c src/common/private.h src/common/tree.h src/common/debug.h src/common/knote.c src/common/alloc.h src/common/map.c src/common/kevent.c src/common/kqueue.c $(distdir)/src/common + cp -RL src/linux/../common/../posix/platform.h $(distdir)/src/linux/../common/../posix + cp -RL src/posix/platform.c $(distdir)/src/posix cp -RL include/sys/event.h $(distdir)/include/sys - cp -RL test/main.c test/common.h test/kevent.c test/test.c test/read.c test/timer.c test/vnode.c test/user.c $(distdir)/test + cp -RL config.h GNUmakefile kqueue.2 libkqueue.pc.in configure configure.rb $(distdir) + cp -RL src/linux/../common/../posix/../../include/sys/event.h $(distdir)/src/linux/../common/../posix/../../include/sys + cp -RL src/posix/../common/../posix/platform.h $(distdir)/src/posix/../common/../posix + cp -RL src/linux/../common/../linux/platform.h $(distdir)/src/linux/../common/../linux + cp -RL src/posix/../common/private.h src/posix/../common/tree.h src/posix/../common/debug.h $(distdir)/src/posix/../common + cp -RL test/main.c test/common.h test/kevent.c test/test.c test/proc.c test/read.c test/signal.c test/timer.c test/vnode.c test/user.c $(distdir)/test + cp -RL src/posix/../common/../posix/../../include/sys/event.h $(distdir)/src/posix/../common/../posix/../../include/sys + cp -RL src/linux/platform.c src/linux/read.c src/linux/write.c src/linux/user.c src/linux/vnode.c src/linux/signal.c src/linux/timer.c $(distdir)/src/linux cp -RL test/../config.h $(distdir)/test/.. install: @@ -150,8 +166,8 @@ install: ln -s libkqueue.so.0.0 $(DESTDIR)$(LIBDIR)/libkqueue.so.0 ln -s kqueue.2 $(DESTDIR)$(MANDIR)/man2/kevent.2 -kqtest: test/main.o test/kevent.o test/test.o test/read.o test/timer.o test/vnode.o test/user.o - $(LD) -o kqtest -L . -Wl,-rpath,. -L . $(LDFLAGS) test/main.o test/kevent.o test/test.o test/read.o test/timer.o test/vnode.o test/user.o -march=i686 -lws2_32 -lkqueue $(LDADD) +kqtest: test/main.o test/kevent.o test/test.o test/proc.o test/read.o test/signal.o test/timer.o test/vnode.o test/user.o + $(LD) -o kqtest -L . -Wl,-rpath,. -L . $(LDFLAGS) test/main.o test/kevent.o test/test.o test/proc.o test/read.o test/signal.o test/timer.o test/vnode.o test/user.o -lpthread -lrt -lkqueue $(LDADD) libkqueue-2.0.tar.gz: rm -rf libkqueue-2.0 @@ -162,9 +178,9 @@ libkqueue-2.0.tar.gz: gzip libkqueue-2.0.tar rm -rf libkqueue-2.0 -libkqueue.a: src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/windows/timer.o src/windows/platform.o src/windows/read.o src/windows/user.o +libkqueue.a: src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o ifneq ($(DISABLE_STATIC),1) - $(AR) cru libkqueue.a src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/windows/timer.o src/windows/platform.o src/windows/read.o src/windows/user.o + $(AR) cru libkqueue.a src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o $(RANLIB) libkqueue.a endif @@ -173,8 +189,8 @@ libkqueue.pc: config.h @printf "prefix=$(PREFIX)\nexec_prefix=$(EPREFIX)\nlibdir=$(LIBDIR)\nincludedir=$(INCLUDEDIR)\n" > libkqueue.pc @cat libkqueue.pc.in >> libkqueue.pc -libkqueue.so: src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/windows/timer.o src/windows/platform.o src/windows/read.o src/windows/user.o - $(LD) -o libkqueue.so -shared -fPIC -L . -Wl,-soname,libkqueue.so.0 $(LDFLAGS) src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/windows/timer.o src/windows/platform.o src/windows/read.o src/windows/user.o -march=i686 -lws2_32 $(LDADD) +libkqueue.so: src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o + $(LD) -o libkqueue.so -shared -fPIC -L . -Wl,-soname,libkqueue.so.0 $(LDFLAGS) src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o -lpthread -lrt $(LDADD) package: clean libkqueue-2.0.tar.gz rm -rf rpm *.rpm @@ -188,52 +204,70 @@ package: clean libkqueue-2.0.tar.gz rm -rf rpm src/common/filter.o: src/common/filter.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -o src/common/filter.o -fPIC -DPIC $(CFLAGS) -c src/common/filter.c + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/filter.o -fPIC -DPIC $(CFLAGS) -c src/common/filter.c src/common/kevent.o: src/common/kevent.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -o src/common/kevent.o -fPIC -DPIC $(CFLAGS) -c src/common/kevent.c + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/kevent.o -fPIC -DPIC $(CFLAGS) -c src/common/kevent.c src/common/knote.o: src/common/knote.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h src/common/alloc.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -o src/common/knote.o -fPIC -DPIC $(CFLAGS) -c src/common/knote.c + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/knote.o -fPIC -DPIC $(CFLAGS) -c src/common/knote.c src/common/kqueue.o: src/common/kqueue.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -o src/common/kqueue.o -fPIC -DPIC $(CFLAGS) -c src/common/kqueue.c + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/kqueue.o -fPIC -DPIC $(CFLAGS) -c src/common/kqueue.c src/common/map.o: src/common/map.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -o src/common/map.o -fPIC -DPIC $(CFLAGS) -c src/common/map.c + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/map.o -fPIC -DPIC $(CFLAGS) -c src/common/map.c -src/windows/platform.o: src/windows/platform.c src/windows/../common/private.h config.h src/windows/../common/tree.h src/windows/../common/../posix/platform.h src/windows/../common/../posix/../../include/sys/event.h src/windows/../common/../linux/platform.h src/windows/../common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -o src/windows/platform.o -fPIC -DPIC $(CFLAGS) -c src/windows/platform.c +src/linux/platform.o: src/linux/platform.c src/linux/../common/private.h config.h src/linux/../common/tree.h src/linux/../common/../posix/platform.h src/linux/../common/../posix/../../include/sys/event.h src/linux/../common/../linux/platform.h src/linux/../common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/platform.o -fPIC -DPIC $(CFLAGS) -c src/linux/platform.c -src/windows/read.o: src/windows/read.c src/windows/../common/private.h config.h src/windows/../common/tree.h src/windows/../common/../posix/platform.h src/windows/../common/../posix/../../include/sys/event.h src/windows/../common/../linux/platform.h src/windows/../common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -o src/windows/read.o -fPIC -DPIC $(CFLAGS) -c src/windows/read.c +src/linux/read.o: src/linux/read.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/read.o -fPIC -DPIC $(CFLAGS) -c src/linux/read.c -src/windows/timer.o: src/windows/timer.c src/windows/../common/private.h config.h src/windows/../common/tree.h src/windows/../common/../posix/platform.h src/windows/../common/../posix/../../include/sys/event.h src/windows/../common/../linux/platform.h src/windows/../common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -o src/windows/timer.o -fPIC -DPIC $(CFLAGS) -c src/windows/timer.c +src/linux/signal.o: src/linux/signal.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/signal.o -fPIC -DPIC $(CFLAGS) -c src/linux/signal.c -src/windows/user.o: src/windows/user.c src/windows/../common/private.h config.h src/windows/../common/tree.h src/windows/../common/../posix/platform.h src/windows/../common/../posix/../../include/sys/event.h src/windows/../common/../linux/platform.h src/windows/../common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -o src/windows/user.o -fPIC -DPIC $(CFLAGS) -c src/windows/user.c +src/linux/timer.o: src/linux/timer.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/timer.o -fPIC -DPIC $(CFLAGS) -c src/linux/timer.c + +src/linux/user.o: src/linux/user.c include/sys/event.h src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/user.o -fPIC -DPIC $(CFLAGS) -c src/linux/user.c + +src/linux/vnode.o: src/linux/vnode.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/vnode.o -fPIC -DPIC $(CFLAGS) -c src/linux/vnode.c + +src/linux/write.o: src/linux/write.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/write.o -fPIC -DPIC $(CFLAGS) -c src/linux/write.c + +src/posix/platform.o: src/posix/platform.c src/posix/../common/private.h config.h src/posix/../common/tree.h src/posix/../common/../posix/platform.h src/posix/../common/../posix/../../include/sys/event.h src/posix/../common/../linux/platform.h src/posix/../common/debug.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/posix/platform.o -fPIC -DPIC $(CFLAGS) -c src/posix/platform.c test/kevent.o: test/kevent.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Iinclude -Itest -g -O0 -o test/kevent.o $(CFLAGS) -c test/kevent.c + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/kevent.o $(CFLAGS) -c test/kevent.c test/main.o: test/main.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Iinclude -Itest -g -O0 -o test/main.o $(CFLAGS) -c test/main.c + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/main.o $(CFLAGS) -c test/main.c + +test/proc.o: test/proc.c test/common.h include/sys/event.h test/../config.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/proc.o $(CFLAGS) -c test/proc.c test/read.o: test/read.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Iinclude -Itest -g -O0 -o test/read.o $(CFLAGS) -c test/read.c + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/read.o $(CFLAGS) -c test/read.c + +test/signal.o: test/signal.c test/common.h include/sys/event.h test/../config.h GNUmakefile + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/signal.o $(CFLAGS) -c test/signal.c test/test.o: test/test.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Iinclude -Itest -g -O0 -o test/test.o $(CFLAGS) -c test/test.c + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/test.o $(CFLAGS) -c test/test.c test/timer.o: test/timer.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Iinclude -Itest -g -O0 -o test/timer.o $(CFLAGS) -c test/timer.c + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/timer.o $(CFLAGS) -c test/timer.c test/user.o: test/user.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Iinclude -Itest -g -O0 -o test/user.o $(CFLAGS) -c test/user.c + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/user.o $(CFLAGS) -c test/user.c test/vnode.o: test/vnode.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Iinclude -Itest -g -O0 -o test/vnode.o $(CFLAGS) -c test/vnode.c + $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/vnode.o $(CFLAGS) -c test/vnode.c uninstall: rm -f $(DESTDIR)$(LIBDIR)/libkqueue.so diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index 31b524a7d..40d96b001 100755 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -137,7 +137,7 @@ def get_ldadd project.add(Header.new( :id => 'event.h', :sources => 'include/sys/event.h', - :namespace => 'kqueue/sys', + :namespace => 'kqueue/sys' )) project.add(Manual.new('kqueue.2', :alias => 'kevent.2')) @@ -193,7 +193,7 @@ def get_ldadd :requires => '', :libs => '-lkqueue', :libs_private => '-lpthread', - :export_cflags => '-I${includedir}/kqueue', + :export_cflags => '-I${includedir}/kqueue' )) mc = Makeconf.new() From 9a47e246075eef40775c7095e070057cb321c590 Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 8 Mar 2013 02:33:05 +0000 Subject: [PATCH 0549/1120] Regenerate GNUmakefile git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@635 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/GNUmakefile | 20 ++++++++++---------- vendor/libkqueue/configure | 24 +++++++++++++++++++++++- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/vendor/libkqueue/GNUmakefile b/vendor/libkqueue/GNUmakefile index c70ae9b12..be6f1f99e 100644 --- a/vendor/libkqueue/GNUmakefile +++ b/vendor/libkqueue/GNUmakefile @@ -132,23 +132,23 @@ distdir: umask 22 ; mkdir -p '$(distdir)/include/sys' umask 22 ; mkdir -p '$(distdir)/test' umask 22 ; mkdir -p '$(distdir)/test/..' + cp -RL src/common/filter.c src/common/private.h src/common/tree.h src/common/debug.h src/common/knote.c src/common/alloc.h src/common/map.c src/common/kevent.c src/common/kqueue.c $(distdir)/src/common + cp -RL config.h GNUmakefile kqueue.2 libkqueue.pc.in configure configure.rb $(distdir) + cp -RL src/common/../posix/platform.h $(distdir)/src/common/../posix cp -RL src/common/../posix/../../include/sys/event.h $(distdir)/src/common/../posix/../../include/sys - cp -RL src/linux/../common/private.h src/linux/../common/tree.h src/linux/../common/debug.h $(distdir)/src/linux/../common cp -RL src/common/../linux/platform.h $(distdir)/src/common/../linux - cp -RL src/common/../posix/platform.h $(distdir)/src/common/../posix + cp -RL src/posix/platform.c $(distdir)/src/posix + cp -RL src/posix/../common/private.h src/posix/../common/tree.h src/posix/../common/debug.h $(distdir)/src/posix/../common + cp -RL src/posix/../common/../posix/platform.h $(distdir)/src/posix/../common/../posix + cp -RL src/posix/../common/../posix/../../include/sys/event.h $(distdir)/src/posix/../common/../posix/../../include/sys cp -RL src/posix/../common/../linux/platform.h $(distdir)/src/posix/../common/../linux - cp -RL src/common/filter.c src/common/private.h src/common/tree.h src/common/debug.h src/common/knote.c src/common/alloc.h src/common/map.c src/common/kevent.c src/common/kqueue.c $(distdir)/src/common + cp -RL src/linux/platform.c src/linux/read.c src/linux/write.c src/linux/user.c src/linux/vnode.c src/linux/signal.c src/linux/timer.c $(distdir)/src/linux + cp -RL src/linux/../common/private.h src/linux/../common/tree.h src/linux/../common/debug.h $(distdir)/src/linux/../common cp -RL src/linux/../common/../posix/platform.h $(distdir)/src/linux/../common/../posix - cp -RL src/posix/platform.c $(distdir)/src/posix - cp -RL include/sys/event.h $(distdir)/include/sys - cp -RL config.h GNUmakefile kqueue.2 libkqueue.pc.in configure configure.rb $(distdir) cp -RL src/linux/../common/../posix/../../include/sys/event.h $(distdir)/src/linux/../common/../posix/../../include/sys - cp -RL src/posix/../common/../posix/platform.h $(distdir)/src/posix/../common/../posix cp -RL src/linux/../common/../linux/platform.h $(distdir)/src/linux/../common/../linux - cp -RL src/posix/../common/private.h src/posix/../common/tree.h src/posix/../common/debug.h $(distdir)/src/posix/../common + cp -RL include/sys/event.h $(distdir)/include/sys cp -RL test/main.c test/common.h test/kevent.c test/test.c test/proc.c test/read.c test/signal.c test/timer.c test/vnode.c test/user.c $(distdir)/test - cp -RL src/posix/../common/../posix/../../include/sys/event.h $(distdir)/src/posix/../common/../posix/../../include/sys - cp -RL src/linux/platform.c src/linux/read.c src/linux/write.c src/linux/user.c src/linux/vnode.c src/linux/signal.c src/linux/timer.c $(distdir)/src/linux cp -RL test/../config.h $(distdir)/test/.. install: diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure index 1d0610def..3de909985 100755 --- a/vendor/libkqueue/configure +++ b/vendor/libkqueue/configure @@ -64,11 +64,21 @@ err() { exit 1 } +require_var() { + key=$1 + eval "val=\$$key" + if [ "$val" = "" ] ; then + echo "ERROR: you must provide --$2 as a command line option" + exit 1 + fi +} + + echo "# Automatically generated by ./configure -- do not edit" > config.mk for arg in $* do if [ `echo "$arg" | grep "^--"` = "$arg" ] ; then - key=`echo $arg | sed "s/^--//; s/=.*//"` + key=`echo $arg | sed "s/^--//; s/=.*//; s/^with-//;"` val=`echo $arg | sed "s/.*=//"` uc_key=`echo "$key" | tr "a-z" "A-Z" | tr "-" "_"` case $key in @@ -100,6 +110,11 @@ do disable-dependency-tracking) # Not implemented, dependency tracking is done in Ruby (for now) ;; + # Android-specific variables + ndk|sdk) + echo "$uc_key=$val" >> config.mk + eval "$key=\"$val\"" + ;; *) echo "Warning: unrecognized option: $arg" ;; @@ -107,6 +122,13 @@ do fi done +# Android-specific options +if [ "`echo ${host_system_type} | grep androideabi`" != "" ] ; then + exec ./configure.rb $* +# require_var ndk with-ndk +# require_var sdk with-sdk +fi + printf "checking for a C compiler... " for cmd in ${host_system_type}-cc cc gcc gcc4 clang do From 75f1b13825ddd93d747c19fbd6e13fcf7a9ef7f2 Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 8 Mar 2013 02:37:03 +0000 Subject: [PATCH 0550/1120] Remove manpage symlink before recreating it git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@636 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/GNUmakefile | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/GNUmakefile b/vendor/libkqueue/GNUmakefile index be6f1f99e..bf20bb5d6 100644 --- a/vendor/libkqueue/GNUmakefile +++ b/vendor/libkqueue/GNUmakefile @@ -164,6 +164,7 @@ install: ln -s libkqueue.so.0.0 $(DESTDIR)$(LIBDIR)/libkqueue.so rm -f $(DESTDIR)$(LIBDIR)/libkqueue.so.0 ln -s libkqueue.so.0.0 $(DESTDIR)$(LIBDIR)/libkqueue.so.0 + rm -f $(DESTDIR)$(MANDIR)/man2/kevent.2 ln -s kqueue.2 $(DESTDIR)$(MANDIR)/man2/kevent.2 kqtest: test/main.o test/kevent.o test/test.o test/proc.o test/read.o test/signal.o test/timer.o test/vnode.o test/user.o From 66cd785318a7d41e222124fcb92ea50a6f3eda2e Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 13 Apr 2013 01:39:04 +0000 Subject: [PATCH 0551/1120] Change how we check for the ARM achitecture for Android git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@637 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/src/linux/timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 9a65e0007..96e39171f 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -20,7 +20,7 @@ /* Android 4.0 does not have this header, but the kernel supports timerfds */ #ifndef SYS_timerfd_create -#ifdef __ARM_ARCH_5__ +#ifdef __ARM_EABI__ #define __NR_timerfd_create (__NR_SYSCALL_BASE+350) #define __NR_timerfd_settime (__NR_SYSCALL_BASE+353) #define __NR_timerfd_gettime (__NR_SYSCALL_BASE+354) From aea320e874920bea24ac2891837345ddddeaaf87 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 30 Apr 2013 02:08:26 +0000 Subject: [PATCH 0552/1120] Make kqtest statically linked git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@638 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/GNUmakefile | 4 +++- vendor/libkqueue/configure.rb | 6 +----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/GNUmakefile b/vendor/libkqueue/GNUmakefile index bf20bb5d6..a40c6dd75 100644 --- a/vendor/libkqueue/GNUmakefile +++ b/vendor/libkqueue/GNUmakefile @@ -1,4 +1,5 @@ # AUTOMATICALLY GENERATED -- DO NOT EDIT +AR = ar BINDIR = $(EPREFIX)/bin CC = cc DATADIR = $(DATAROOTDIR) @@ -20,6 +21,7 @@ PKGDATADIR = $(DATADIR)/$(PACKAGE) PKGINCLUDEDIR = $(INCLUDEDIR)/$(PACKAGE) PKGLIBDIR = $(LIBDIR)/$(PACKAGE) PREFIX = /usr/local +RANLIB = ranlib SBINDIR = $(EPREFIX)/sbin SHAREDSTATEDIR = $(PREFIX)/com SYSCONFDIR = $(PREFIX)/etc @@ -168,7 +170,7 @@ install: ln -s kqueue.2 $(DESTDIR)$(MANDIR)/man2/kevent.2 kqtest: test/main.o test/kevent.o test/test.o test/proc.o test/read.o test/signal.o test/timer.o test/vnode.o test/user.o - $(LD) -o kqtest -L . -Wl,-rpath,. -L . $(LDFLAGS) test/main.o test/kevent.o test/test.o test/proc.o test/read.o test/signal.o test/timer.o test/vnode.o test/user.o -lpthread -lrt -lkqueue $(LDADD) + $(LD) -o kqtest -L . -Wl,-rpath,. -L . $(LDFLAGS) test/main.o test/kevent.o test/test.o test/proc.o test/read.o test/signal.o test/timer.o test/vnode.o test/user.o libkqueue.a -lpthread -lrt $(LDADD) libkqueue-2.0.tar.gz: rm -rf libkqueue-2.0 diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index 40d96b001..37caf27cd 100755 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -143,11 +143,7 @@ def get_ldadd project.add(Manual.new('kqueue.2', :alias => 'kevent.2')) test_ldadd = get_ldadd() -if SystemType.host =~ /-androideabi$/ - test_ldadd += ' libkqueue.a' -else - test_ldadd += ' -lkqueue' -end +test_ldadd += ' libkqueue.a' if Platform.is_windows? project.add( Test.new( From 839b60ea9eda1b68c98db4424c6d198b9e4dfe50 Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 30 Apr 2013 02:15:04 +0000 Subject: [PATCH 0553/1120] Release 2.0 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@639 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index b020ab2e9..8f358cde7 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,4 +1,4 @@ -HEAD +2013-04-29 v2.0 r639 ------------------------------------------------------------------------ * Use ppoll(2) where possible to improve scalability. From dd831ab63164ebd97934c8a5fa8f6c83a58f453c Mon Sep 17 00:00:00 2001 From: eradman Date: Thu, 2 May 2013 12:30:44 +0000 Subject: [PATCH 0554/1120] Port libkqueue spec file from libkqueue/1.x maintenance branch. Patch to GNUmakefile is a temporary fix since it's generated by Makeconf. ok mheily git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@641 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/COPYING | 42 ++++++++++++++++ vendor/libkqueue/GNUmakefile | 11 ++--- vendor/libkqueue/libkqueue.spec | 86 +++++++++++++++++++++++++++++++++ vendor/libkqueue/rpm.spec.in | 77 ----------------------------- 4 files changed, 133 insertions(+), 83 deletions(-) create mode 100644 vendor/libkqueue/COPYING create mode 100644 vendor/libkqueue/libkqueue.spec delete mode 100644 vendor/libkqueue/rpm.spec.in diff --git a/vendor/libkqueue/COPYING b/vendor/libkqueue/COPYING new file mode 100644 index 000000000..102e6eb88 --- /dev/null +++ b/vendor/libkqueue/COPYING @@ -0,0 +1,42 @@ +== all source == + +Copyright (c) 2009 Mark Heily + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +== event.h == + +Copyright (c) 1999,2000,2001 Jonathan Lemon +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + diff --git a/vendor/libkqueue/GNUmakefile b/vendor/libkqueue/GNUmakefile index a40c6dd75..32b75a4d3 100644 --- a/vendor/libkqueue/GNUmakefile +++ b/vendor/libkqueue/GNUmakefile @@ -114,9 +114,8 @@ distclean: clean rm -f libkqueue-2.0.tar.gz rm -f config.h rm -f config.yaml - rm -f rpm.spec -distdir: +distdir: config.h umask 22 ; mkdir -p '$(distdir)/src/common' umask 22 ; mkdir -p '$(distdir)/src/common/../posix' umask 22 ; mkdir -p '$(distdir)/src/common/../posix/../../include/sys' @@ -135,7 +134,7 @@ distdir: umask 22 ; mkdir -p '$(distdir)/test' umask 22 ; mkdir -p '$(distdir)/test/..' cp -RL src/common/filter.c src/common/private.h src/common/tree.h src/common/debug.h src/common/knote.c src/common/alloc.h src/common/map.c src/common/kevent.c src/common/kqueue.c $(distdir)/src/common - cp -RL config.h GNUmakefile kqueue.2 libkqueue.pc.in configure configure.rb $(distdir) + cp -RL config.h COPYING GNUmakefile kqueue.2 libkqueue.pc.in configure configure.rb $(distdir) cp -RL src/common/../posix/platform.h $(distdir)/src/common/../posix cp -RL src/common/../posix/../../include/sys/event.h $(distdir)/src/common/../posix/../../include/sys cp -RL src/common/../linux/platform.h $(distdir)/src/common/../linux @@ -200,9 +199,9 @@ package: clean libkqueue-2.0.tar.gz mkdir -p rpm/BUILD rpm/RPMS rpm/SOURCES rpm/SPECS rpm/SRPMS mkdir -p rpm/RPMS/i386 rpm/RPMS/x86_64 cp libkqueue-2.0.tar.gz rpm/SOURCES - rpmbuild --define "_topdir `pwd`/rpm" -bs rpm.spec - cp rpm.spec rpm/SPECS/rpm.spec - rpmbuild --define "_topdir `pwd`/rpm" -bb ./rpm/SPECS/rpm.spec + rpmbuild --define "_topdir `pwd`/rpm" -bs libkqueue.spec + cp libkqueue.spec rpm/SPECS/libkqueue.spec + rpmbuild --define "_topdir `pwd`/rpm" -bb ./rpm/SPECS/libkqueue.spec mv ./rpm/SRPMS/* ./rpm/RPMS/*/*.rpm . rm -rf rpm diff --git a/vendor/libkqueue/libkqueue.spec b/vendor/libkqueue/libkqueue.spec new file mode 100644 index 000000000..f29049950 --- /dev/null +++ b/vendor/libkqueue/libkqueue.spec @@ -0,0 +1,86 @@ +Name: libkqueue +Summary: Userspace implementation of the kqueue event notification mechanism +Version: 2.0 +Release: 1 +# The entire source code is MIT, event.h which is BSD (2-clause) +License: MIT and BSD +Group: System Environment/Libraries +URL: http://mark.heily.com/project/libkqueue +Source0: http://static.eradman.com/src/%{name}-%{version}.tar.gz +Provides: libkqueue.so.0 + +%description +A user space implementation of the kqueue(2) kernel event notification +mechanism. libkqueue acts as a translator between the kevent structure and the +native kernel facilities. + +%package devel +Group: Development/Libraries +Summary: Development files for %{name}-%{version} +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description devel +%{summary} + +%prep +%setup -q + +# %%{configure} sets --target 'x86_64-redhat-linux-gnu' instead of 'linux' +%build +CFLAGS="%{optflags} -fpic" %{_configure} --prefix=%{_prefix} --libdir=%{_libdir} +make + +%install +%{make_install} + +%check +make check + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files +%doc COPYING +%{_libdir}/libkqueue.so.* + +%files devel +%dir %{_includedir}/kqueue +%dir %{_includedir}/kqueue/sys +%{_libdir}/libkqueue.so +%{_includedir}/kqueue/sys/event.h +%{_libdir}/pkgconfig/libkqueue.pc +%{_mandir}/man2/kqueue.2.* +%{_mandir}/man2/kevent.2.* + +%changelog +* Wed May 01 2013 Eric Radman - 2.0-1 +- Adapt to libkqueue 2.0 + +* Thu Apr 04 2013 Eric Radman - 1.0.1-6 +- Set CFLAGS using optflags since we're using a custom configure +- Shorten summary + +* Wed Apr 03 2013 Eric Radman - 1.0.1-5 +- Use %% to avoid warning about special character in comment +- Remove defattr + +* Fri Jan 18 2013 Eric Radman - 1.0.1-4 +- Configure respects CFLAGS and LDFLAGS. Also pass --libdir to the configure script + +* Sat Jan 12 2013 Eric Radman - 1.0.1-3 +- Add license text for event.h +- Use the dir macro for the include directories +- Remove static package, exclude .a file, and make sure new directories are owned by the RPM + +* Thu Jan 03 2013 Eric Radman - 1.0.1-3 +- Configure respects CFLAGS and LDFLAGS. Also pass --libdir= to the configure script instead of setting LIB + +* Mon Dec 31 2012 Eric Radman - 1.0.1-2 +- Do not set the buildroot (F-10 does not require it) +- Do not manually clean (F-13) + +* Thu Dec 27 2012 Eric Radman - 1.0.1-1 +- Initial build with separate -devel package. Based on work done by Mark Heily, + Aditya Patawari and John Haxby + diff --git a/vendor/libkqueue/rpm.spec.in b/vendor/libkqueue/rpm.spec.in deleted file mode 100644 index d889ee4a9..000000000 --- a/vendor/libkqueue/rpm.spec.in +++ /dev/null @@ -1,77 +0,0 @@ -# -# Copyright (c) 2009-2010 Mark Heily -# -# Permission to use, copy, modify, and distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -Name: @@PROGRAM@@ -Summary: @@PKG_SUMMARY@@ -Version: @@VERSION@@ -Release: 1 -License: @@LICENSE@@ -Vendor: @@AUTHOR@@ -Group: System Environment/Libraries -Source0: %{name}-%version.tar.gz - -BuildRequires: glibc-devel - -%description -@@PKG_DESCRIPTION@@ - -%package devel -Summary: Header files, libraries and development documentation for %{name} -Group: Development/Libraries -Requires: %{name} = %{version}-%{release} - -%description devel -This package contains the header files, static libraries and development -documentation for %{name}. If you like to develop programs using %{name}, -you will need to install %{name}-devel. - -%prep -%setup -q -n @@PROGRAM@@-@@VERSION@@ - -%build -./configure --prefix=/usr --libdir=%{_libdir} -make - -%install -make DESTDIR=%{buildroot} install -gzip -f $RPM_BUILD_ROOT/usr/share/man/man2/kqueue.2 -gzip -f $RPM_BUILD_ROOT/usr/share/man/man2/kevent.2 - -%clean -[ %{buildroot} != "/" ] && rm -rf %{buildroot} - -%post -p /sbin/ldconfig -%postun -p /sbin/ldconfig - -%files -%defattr(-,root,root) - -%{_libdir}/*.so.* - -%files devel -%defattr(-,root,root) - -%{_libdir}/*.so -/usr/include/kqueue/sys/event.h -%{_libdir}/pkgconfig/libkqueue.pc -/usr/share/man/man2/kqueue.2.gz -/usr/share/man/man2/kevent.2.gz -%exclude %{_libdir}/*.la -%exclude %{_libdir}/*.a - -%changelog -* @@RPM_DATE@@ Mark Heily - @@VERSION@@-1 -- automatically generated spec file From 0b0cbbe3812cfbdf4a51b2b080b5ac251976fefc Mon Sep 17 00:00:00 2001 From: eradman Date: Thu, 2 May 2013 14:41:39 +0000 Subject: [PATCH 0555/1120] Use official source file from sf.net instead of my public WIP folder git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@642 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/libkqueue.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/libkqueue.spec b/vendor/libkqueue/libkqueue.spec index f29049950..0f16cd3f7 100644 --- a/vendor/libkqueue/libkqueue.spec +++ b/vendor/libkqueue/libkqueue.spec @@ -5,8 +5,8 @@ Release: 1 # The entire source code is MIT, event.h which is BSD (2-clause) License: MIT and BSD Group: System Environment/Libraries -URL: http://mark.heily.com/project/libkqueue -Source0: http://static.eradman.com/src/%{name}-%{version}.tar.gz +URL: http://sourceforge.net/p/libkqueue/wiki/Home/ +Source0: http://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.gz Provides: libkqueue.so.0 %description From 5b9ac08099c502164a9d90432e9d0660eec85b3e Mon Sep 17 00:00:00 2001 From: eradman Date: Wed, 8 May 2013 12:50:01 +0000 Subject: [PATCH 0556/1120] Rename COPYING to LICENSE to match libpwq/ git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@643 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/GNUmakefile | 2 +- vendor/libkqueue/{COPYING => LICENSE} | 0 vendor/libkqueue/libkqueue.spec | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename vendor/libkqueue/{COPYING => LICENSE} (100%) diff --git a/vendor/libkqueue/GNUmakefile b/vendor/libkqueue/GNUmakefile index 32b75a4d3..639576a6d 100644 --- a/vendor/libkqueue/GNUmakefile +++ b/vendor/libkqueue/GNUmakefile @@ -134,7 +134,7 @@ distdir: config.h umask 22 ; mkdir -p '$(distdir)/test' umask 22 ; mkdir -p '$(distdir)/test/..' cp -RL src/common/filter.c src/common/private.h src/common/tree.h src/common/debug.h src/common/knote.c src/common/alloc.h src/common/map.c src/common/kevent.c src/common/kqueue.c $(distdir)/src/common - cp -RL config.h COPYING GNUmakefile kqueue.2 libkqueue.pc.in configure configure.rb $(distdir) + cp -RL config.h LICENSE GNUmakefile kqueue.2 libkqueue.pc.in configure configure.rb $(distdir) cp -RL src/common/../posix/platform.h $(distdir)/src/common/../posix cp -RL src/common/../posix/../../include/sys/event.h $(distdir)/src/common/../posix/../../include/sys cp -RL src/common/../linux/platform.h $(distdir)/src/common/../linux diff --git a/vendor/libkqueue/COPYING b/vendor/libkqueue/LICENSE similarity index 100% rename from vendor/libkqueue/COPYING rename to vendor/libkqueue/LICENSE diff --git a/vendor/libkqueue/libkqueue.spec b/vendor/libkqueue/libkqueue.spec index 0f16cd3f7..61e7f29b4 100644 --- a/vendor/libkqueue/libkqueue.spec +++ b/vendor/libkqueue/libkqueue.spec @@ -41,7 +41,7 @@ make check %postun -p /sbin/ldconfig %files -%doc COPYING +%doc LICENSE %{_libdir}/libkqueue.so.* %files devel From 4cd6412ab46b587bc07b689c4d147345b684f4ab Mon Sep 17 00:00:00 2001 From: eradman Date: Wed, 8 May 2013 13:21:24 +0000 Subject: [PATCH 0557/1120] Small cleanup for 2.0 release: remove Makefile.OLD it's available in the stable branch git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@644 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/Makefile.OLD | 179 ---------------------------------- 1 file changed, 179 deletions(-) delete mode 100644 vendor/libkqueue/Makefile.OLD diff --git a/vendor/libkqueue/Makefile.OLD b/vendor/libkqueue/Makefile.OLD deleted file mode 100644 index 6562e3245..000000000 --- a/vendor/libkqueue/Makefile.OLD +++ /dev/null @@ -1,179 +0,0 @@ -# -# Copyright (c) 2009 Mark Heily -# -# Permission to use, copy, modify, and distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -REPOSITORY=svn+ssh://mark.heily.com/$$HOME/svn/$(PROGRAM) -DIST=heily.com:$$HOME/public_html/$(PROGRAM)/dist -DISTFILE=$(PROGRAM)-$(VERSION).tar.gz - -include config.mk - -.PHONY :: install uninstall check dist dist-upload clean merge distclean fresh-build rpm edit cscope - -all: $(PROGRAM).so.$(ABI_VERSION) $(PROGRAM)_debug.so $(PROGRAM).a $(PROGRAM)_debug.a - -%.o: %.c $(DEPS) - $(CC) -c -o $@ -I./include -I./src/common -DNDEBUG $(CFLAGS) $< - -$(PROGRAM).a: - rm -f *.o - $(CC) -c -I./include -I./src/common -DNDEBUG -DMAKE_STATIC=1 -static $(CFLAGS) $(SOURCES) $(LDADD) - $(AR) rcs $(PROGRAM).a *.o - $(STRIP) $(PROGRAM).a - rm *.o - -$(PROGRAM)_debug.a: - rm -f *.o - $(CC) -c -I./include -I./src/common -DMAKE_STATIC=1 -pg -static $(CFLAGS) $(SOURCES) $(LDADD) - $(AR) rcs $(PROGRAM)_debug.a *.o - rm *.o - -$(PROGRAM).so.$(ABI_VERSION): $(OBJS) - $(CC) -o $@ -I./include -I./src/common -shared $(LDFLAGS) -DNDEBUG $(CFLAGS) $(SOURCES) $(LDADD) - $(STRIP) $(PROGRAM).so.$(ABI_VERSION) - $(LN) -sf $(PROGRAM).so.$(ABI_VERSION) $(PROGRAM).so.$(ABI_MAJOR) - $(LN) -sf $(PROGRAM).so.$(ABI_VERSION) $(PROGRAM).so - -$(PROGRAM)_debug.so: - $(CC) -o $@ -I./include -I./src/common -shared -rdynamic $(CFLAGS) -g3 -O0 $(SOURCES) $(LDADD) - -install: all - $(INSTALL) -d -m 755 $(INCLUDEDIR)/kqueue/sys - $(INSTALL) -m 644 include/sys/event.h $(INCLUDEDIR)/kqueue/sys/event.h - $(INSTALL) -d -m 755 $(LIBDIR) - $(INSTALL) -m 644 $(PROGRAM).so.$(ABI_VERSION) $(LIBDIR) - $(INSTALL) -m 644 $(PROGRAM).so.$(ABI_MAJOR) $(LIBDIR) - $(LN) -sf $(PROGRAM).so.$(ABI_VERSION) $(LIBDIR)/$(PROGRAM).so.$(ABI_MAJOR) - $(LN) -sf $(PROGRAM).so.$(ABI_VERSION) $(LIBDIR)/$(PROGRAM).so - $(INSTALL) -m 644 $(PROGRAM)_debug.so $(LIBDIR) - $(INSTALL) -d -m 755 $(LIBDIR)/pkgconfig - $(INSTALL) -m 644 libkqueue.pc $(LIBDIR)/pkgconfig - $(INSTALL) -d -m 755 $(MANDIR)/man2 - $(INSTALL) -m 644 kqueue.2 $(MANDIR)/man2/kqueue.2 - $(INSTALL) -m 644 kqueue.2 $(MANDIR)/man2/kevent.2 - -uninstall: - rm -f $(INCLUDEDIR)/kqueue/sys/event.h - rm -f $(LIBDIR)/libkqueue.so - rm -f $(LIBDIR)/pkgconfig/libkqueue.pc - rm -f $(MANDIR)/man2/kqueue.2 - rm -f $(MANDIR)/man2/kevent.2 - rmdir $(INCLUDEDIR)/kqueue/sys $(INCLUDEDIR)/kqueue - -test/config.mk: - cd test && ../configure - -check: test/config.mk - cd test && make check - -profile: clean $(PROGRAM)_debug.a - cd test && ./kqtest - -debug: clean all test/config.mk - cd test && make debug - -debug-check: clean test/config.mk - cd test && KQUEUE_DEBUG=yes make check - -$(DISTFILE): $(SOURCES) $(HEADERS) - mkdir $(PROGRAM)-$(VERSION) - cp Makefile ChangeLog configure config.inc \ - $(MANS) $(EXTRA_DIST) \ - $(PROGRAM)-$(VERSION) - cp -R $(SUBDIRS) $(PROGRAM)-$(VERSION) - rm -rf `find $(PROGRAM)-$(VERSION) -type d -name .svn -o -name .libs` - cd $(PROGRAM)-$(VERSION) && ./configure && cd test && ./configure && cd .. && make distclean - tar zcf $(PROGRAM)-$(VERSION).tar.gz $(PROGRAM)-$(VERSION) - rm -rf $(PROGRAM)-$(VERSION) - -dist: - rm -f $(DISTFILE) - make $(DISTFILE) - -dist-upload: $(DISTFILE) - scp $(DISTFILE) $(DIST) - -clean: - rm -f tags *.a *.so *.so.* *.so.*.* - find src -name '*.o' -exec rm {} \; - rm -rf pkg - cd test && make clean || true - -distclean: clean - rm -f *.tar.gz config.mk config.h $(PROGRAM).pc $(PROGRAM).la rpm.spec - rm -rf $(PROGRAM)-$(VERSION) 2>/dev/null || true - -fresh-build: - rm -rf /tmp/$(PROGRAM)-testbuild - svn co svn://mark.heily.com/libkqueue/trunk /tmp/$(PROGRAM)-testbuild - cd /tmp/$(PROGRAM)-testbuild && ./configure && make check - rm -rf /tmp/$(PROGRAM)-testbuild - -merge: - svn diff $(REPOSITORY)/branches/stable $(REPOSITORY)/trunk | gvim - - @printf "Merge changes from the trunk to the stable branch [y/N]? " - @read x && test "$$x" = "y" - echo "ok" - -tags: $(SOURCES) $(HEADERS) - ctags $(SOURCES) $(HEADERS) - -edit: tags - $(EDITOR) $(SOURCES) $(HEADERS) - -cscope: tags - cscope $(SOURCES) $(HEADERS) - -# Creates an ~/rpmbuild tree -rpmbuild: - mkdir -p $$HOME/rpmbuild - cd $$HOME/rpmbuild && mkdir -p BUILD RPMS SOURCES SPECS SRPMS - grep _topdir $$HOME/.rpmmacros || \ - echo "%_topdir %(echo $$HOME/rpmbuild)" >> $$HOME/.rpmmacros - -rpm: rpmbuild clean $(DISTFILE) - mkdir -p pkg - cp $(DISTFILE) $$HOME/rpmbuild/SOURCES - rpmbuild -bb rpm.spec - find $$HOME/rpmbuild -name '$(PROGRAM)-$(VERSION)*.rpm' -exec mv {} ./pkg \; - -deb: clean $(DISTFILE) - mkdir pkg && cd pkg ; \ - tar zxf ../$(DISTFILE) ; \ - cp ../$(DISTFILE) $(PROGRAM)_$(VERSION).orig.tar.gz ; \ - cp -R ../ports/debian $(PROGRAM)-$(VERSION) ; \ - rm -rf `find $(PROGRAM)-$(VERSION)/debian -type d -name .svn` ; \ - perl -pi -e 's/\@\@VERSION\@\@/$(VERSION)/' $(PROGRAM)-$(VERSION)/debian/changelog ; \ - cd $(PROGRAM)-$(VERSION) && dpkg-buildpackage -uc -us - lintian -i pkg/*.deb - @printf "\nThe following packages have been created:\n" - @find ./pkg -name '*.deb' | sed 's/^/ /' - -debug-install: - ./configure --prefix=/usr --debug=yes - make clean && make && sudo make install - -diff: - if [ "`pwd | grep /trunk`" != "" ] ; then \ - (cd .. ; $(DIFF) branches/stable trunk | less) ; \ - fi - if [ "`pwd | grep /branches/stable`" != "" ] ; then \ - (cd ../.. ; $(DIFF) branches/stable trunk | less) ; \ - fi - -# Used for testing on a Solaris guest VM -# -solaris-test: - make dist && scp -P 2222 libkqueue-$(VERSION).tar.gz localhost:/tmp && ssh -p 2222 localhost ". .profile ; cd /tmp ; rm -rf libkqueue-$(VERSION) ; gtar zxvf libkqueue-$(VERSION).tar.gz && cd libkqueue-$(VERSION) && ./configure && make && make check" From f7fdc9de69dde59c6f07bda26df2fb7a14f98474 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 9 May 2013 01:35:56 +0000 Subject: [PATCH 0558/1120] Replace manual changes to GNUmakefile with the new code generated by Makeconf git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@645 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/GNUmakefile | 11 ++++++----- vendor/libkqueue/configure.rb | 2 ++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/GNUmakefile b/vendor/libkqueue/GNUmakefile index 639576a6d..04ce9b157 100644 --- a/vendor/libkqueue/GNUmakefile +++ b/vendor/libkqueue/GNUmakefile @@ -115,7 +115,7 @@ distclean: clean rm -f config.h rm -f config.yaml -distdir: config.h +distdir: config.h umask 22 ; mkdir -p '$(distdir)/src/common' umask 22 ; mkdir -p '$(distdir)/src/common/../posix' umask 22 ; mkdir -p '$(distdir)/src/common/../posix/../../include/sys' @@ -133,8 +133,8 @@ distdir: config.h umask 22 ; mkdir -p '$(distdir)/include/sys' umask 22 ; mkdir -p '$(distdir)/test' umask 22 ; mkdir -p '$(distdir)/test/..' + cp -RL libkqueue.spec config.h GNUmakefile kqueue.2 libkqueue.pc.in configure configure.rb LICENSE $(distdir) cp -RL src/common/filter.c src/common/private.h src/common/tree.h src/common/debug.h src/common/knote.c src/common/alloc.h src/common/map.c src/common/kevent.c src/common/kqueue.c $(distdir)/src/common - cp -RL config.h LICENSE GNUmakefile kqueue.2 libkqueue.pc.in configure configure.rb $(distdir) cp -RL src/common/../posix/platform.h $(distdir)/src/common/../posix cp -RL src/common/../posix/../../include/sys/event.h $(distdir)/src/common/../posix/../../include/sys cp -RL src/common/../linux/platform.h $(distdir)/src/common/../linux @@ -197,11 +197,12 @@ libkqueue.so: src/common/filter.o src/common/knote.o src/common/map.o src/common package: clean libkqueue-2.0.tar.gz rm -rf rpm *.rpm mkdir -p rpm/BUILD rpm/RPMS rpm/SOURCES rpm/SPECS rpm/SRPMS - mkdir -p rpm/RPMS/i386 rpm/RPMS/x86_64 + mkdir -p rpm/RPMS/`uname -m` cp libkqueue-2.0.tar.gz rpm/SOURCES - rpmbuild --define "_topdir `pwd`/rpm" -bs libkqueue.spec cp libkqueue.spec rpm/SPECS/libkqueue.spec - rpmbuild --define "_topdir `pwd`/rpm" -bb ./rpm/SPECS/libkqueue.spec + perl -pi -e 's/Version:.*/Version: 2.0/' rpm/SPECS/libkqueue.spec + rpmbuild --define "_topdir `pwd`/rpm" -bs rpm/SPECS/libkqueue.spec + rpmbuild --define "_topdir `pwd`/rpm" -bb rpm/SPECS/libkqueue.spec mv ./rpm/SRPMS/* ./rpm/RPMS/*/*.rpm . rm -rf rpm diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index 37caf27cd..b5660601f 100755 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -192,6 +192,8 @@ def get_ldadd :export_cflags => '-I${includedir}/kqueue' )) +project.packager.add 'libkqueue.spec' + mc = Makeconf.new() mc.configure(project) From d02255ab4a9c034725140d3d9acc1fa8ed8f48fb Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 9 May 2013 01:43:36 +0000 Subject: [PATCH 0559/1120] Release version 2.0.1 git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@646 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 6 ++++++ vendor/libkqueue/GNUmakefile | 28 ++++++++++++++-------------- vendor/libkqueue/configure.rb | 2 +- vendor/libkqueue/libkqueue.spec | 5 ++++- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 8f358cde7..70952be80 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,3 +1,9 @@ +2013-05-08 v2.0.1 r646 +------------------------------------------------------------------------ + + * Improvements to the RPM package spec + (Credit: Eric Wong) + 2013-04-29 v2.0 r639 ------------------------------------------------------------------------ diff --git a/vendor/libkqueue/GNUmakefile b/vendor/libkqueue/GNUmakefile index 04ce9b157..e7b0d9cf2 100644 --- a/vendor/libkqueue/GNUmakefile +++ b/vendor/libkqueue/GNUmakefile @@ -55,7 +55,7 @@ check: kqtest clean: rm -f *.rpm - rm -f libkqueue-2.0.tar.gz + rm -f libkqueue-2.0.1.tar.gz rm -f src/common/filter.o rm -f src/common/knote.o rm -f src/common/map.o @@ -107,11 +107,11 @@ config.h: @echo "creating config.h" @mv config.h.tmp config.h -dist: libkqueue-2.0.tar.gz +dist: libkqueue-2.0.1.tar.gz distclean: clean rm -f GNUmakefile - rm -f libkqueue-2.0.tar.gz + rm -f libkqueue-2.0.1.tar.gz rm -f config.h rm -f config.yaml @@ -171,14 +171,14 @@ install: kqtest: test/main.o test/kevent.o test/test.o test/proc.o test/read.o test/signal.o test/timer.o test/vnode.o test/user.o $(LD) -o kqtest -L . -Wl,-rpath,. -L . $(LDFLAGS) test/main.o test/kevent.o test/test.o test/proc.o test/read.o test/signal.o test/timer.o test/vnode.o test/user.o libkqueue.a -lpthread -lrt $(LDADD) -libkqueue-2.0.tar.gz: - rm -rf libkqueue-2.0 - mkdir libkqueue-2.0 - $(MAKE) distdir distdir=libkqueue-2.0 - rm -rf libkqueue-2.0.tar libkqueue-2.0.tar.gz - tar cf libkqueue-2.0.tar libkqueue-2.0 - gzip libkqueue-2.0.tar - rm -rf libkqueue-2.0 +libkqueue-2.0.1.tar.gz: + rm -rf libkqueue-2.0.1 + mkdir libkqueue-2.0.1 + $(MAKE) distdir distdir=libkqueue-2.0.1 + rm -rf libkqueue-2.0.1.tar libkqueue-2.0.1.tar.gz + tar cf libkqueue-2.0.1.tar libkqueue-2.0.1 + gzip libkqueue-2.0.1.tar + rm -rf libkqueue-2.0.1 libkqueue.a: src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o ifneq ($(DISABLE_STATIC),1) @@ -194,13 +194,13 @@ libkqueue.pc: config.h libkqueue.so: src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o $(LD) -o libkqueue.so -shared -fPIC -L . -Wl,-soname,libkqueue.so.0 $(LDFLAGS) src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o -lpthread -lrt $(LDADD) -package: clean libkqueue-2.0.tar.gz +package: clean libkqueue-2.0.1.tar.gz rm -rf rpm *.rpm mkdir -p rpm/BUILD rpm/RPMS rpm/SOURCES rpm/SPECS rpm/SRPMS mkdir -p rpm/RPMS/`uname -m` - cp libkqueue-2.0.tar.gz rpm/SOURCES + cp libkqueue-2.0.1.tar.gz rpm/SOURCES cp libkqueue.spec rpm/SPECS/libkqueue.spec - perl -pi -e 's/Version:.*/Version: 2.0/' rpm/SPECS/libkqueue.spec + perl -pi -e 's/^Version:.*/Version: 2.0.1/' rpm/SPECS/libkqueue.spec rpmbuild --define "_topdir `pwd`/rpm" -bs rpm/SPECS/libkqueue.spec rpmbuild --define "_topdir `pwd`/rpm" -bb rpm/SPECS/libkqueue.spec mv ./rpm/SRPMS/* ./rpm/RPMS/*/*.rpm . diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb index b5660601f..2fc7e9b0e 100755 --- a/vendor/libkqueue/configure.rb +++ b/vendor/libkqueue/configure.rb @@ -111,7 +111,7 @@ def get_ldadd project = Project.new \ :id => 'libkqueue', - :version => 2.0 + :version => '2.0.1' kq = Library.new( :id => 'libkqueue', diff --git a/vendor/libkqueue/libkqueue.spec b/vendor/libkqueue/libkqueue.spec index 61e7f29b4..36a581acc 100644 --- a/vendor/libkqueue/libkqueue.spec +++ b/vendor/libkqueue/libkqueue.spec @@ -1,6 +1,6 @@ Name: libkqueue Summary: Userspace implementation of the kqueue event notification mechanism -Version: 2.0 +Version: 2.0.1 Release: 1 # The entire source code is MIT, event.h which is BSD (2-clause) License: MIT and BSD @@ -54,6 +54,9 @@ make check %{_mandir}/man2/kevent.2.* %changelog +* Wed May 08 2013 Mark Heily - 2.0.1-1 +- New upstream release + * Wed May 01 2013 Eric Radman - 2.0-1 - Adapt to libkqueue 2.0 From 60f14800f7309e2c23b322cc42990cb3114ecdf4 Mon Sep 17 00:00:00 2001 From: eradman Date: Sat, 1 Jun 2013 21:45:01 +0000 Subject: [PATCH 0560/1120] Integrate INSTALL with a new README file that includes very breif release history. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@648 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/INSTALL | 19 ----------- vendor/libkqueue/README.md | 64 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 19 deletions(-) delete mode 100644 vendor/libkqueue/INSTALL create mode 100644 vendor/libkqueue/README.md diff --git a/vendor/libkqueue/INSTALL b/vendor/libkqueue/INSTALL deleted file mode 100644 index a7c251e46..000000000 --- a/vendor/libkqueue/INSTALL +++ /dev/null @@ -1,19 +0,0 @@ -INSTALLATION INSTRUCTIONS ---- - -To building on Android, run something like this: - - ruby ./configure.rb --host=arm-linux-androideabi \ - --with-ndk=/opt/android-ndk-r8c \ - --with-sdk=/opt/android-sdks - make - -For building on Linux or Solaris, run: - - ./configure - make - make install - -TODO -- Need to document for Windows - - diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md new file mode 100644 index 000000000..2d2f5acaf --- /dev/null +++ b/vendor/libkqueue/README.md @@ -0,0 +1,64 @@ +libkqueue +========= + +A user space implementation of the kqueue(2) kernel event notification mechanism +libkqueue acts as a translator between the kevent structure and the native +kernel facilities on Linux, Android, Solaris, and Windows. + +Supported Event Types +--------------------- + +* vnode +* socket +* proc +* user +* timer + +Installation - Linux, Solaris +----------------------------- + + ./configure + make + make install + +Installation - Red Hat +---------------------- + + ./configure + make package + rpm -i *.rpm + +Installation - Android +---------------------- + + ruby ./configure.rb --host=arm-linux-androideabi \ + --with-ndk=/opt/android-ndk-r8c \ + --with-sdk=/opt/android-sdks + make + +Running Unit Tests +------------------ + + ./configure + make + make check + +Building Applications +--------------------- + + CFLAGS += -I/usr/include/kqueue + LDFLAGS += -lkqueue + +Tutorials & Examples +-------------------- + +[Kqueues for Fun and Profit](http://doc.geoffgarside.co.uk/kqueue) + +[Handling TCP Connections with Kqueue Event Notification](http://eradman.com/posts//kqueue-tcp.html) + +Releases History +---------------- + +2.0 add support for Android _2013-04-29_ + +1.0 stable relesae for Linux, Solaris, and Windows _2010-09-18_ From 40909639081e4330653a96d6ac201a4e984b78f3 Mon Sep 17 00:00:00 2001 From: eradman Date: Tue, 4 Jun 2013 14:14:36 +0000 Subject: [PATCH 0561/1120] Adapt test_kevent_user_multi_trigger_merged() from the 1.0 branch. It appears that 2.0-current does not suffer from the same problem. Tests pass on Debian 6.0/i386. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@649 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/TODO | 1 - vendor/libkqueue/test/user.c | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/TODO b/vendor/libkqueue/TODO index 527f8731b..6ebb725fd 100644 --- a/vendor/libkqueue/TODO +++ b/vendor/libkqueue/TODO @@ -17,4 +17,3 @@ * Check other filters for the EV_DISPATCH bug that was fixed in r252. - * Merge the fix from r546 in the stable branch. diff --git a/vendor/libkqueue/test/user.c b/vendor/libkqueue/test/user.c index 8724a1d7a..54a526fe2 100644 --- a/vendor/libkqueue/test/user.c +++ b/vendor/libkqueue/test/user.c @@ -113,6 +113,28 @@ test_kevent_user_oneshot(struct test_context *ctx) test_no_kevents(ctx->kqfd); } +static void +test_kevent_user_multi_trigger_merged(struct test_context *ctx) +{ + struct kevent kev, ret; + int i; + + test_no_kevents(ctx->kqfd); + + kevent_add(ctx->kqfd, &kev, 2, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, NULL); + + for (i = 0; i < 10; i++) + kevent_add(ctx->kqfd, &kev, 2, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + + kev.flags = EV_CLEAR; + kev.fflags &= ~NOTE_FFCTRLMASK; + kev.fflags &= ~NOTE_TRIGGER; + kevent_get(&ret, ctx->kqfd); + kevent_cmp(&kev, &ret); + + test_no_kevents(ctx->kqfd); +} + #ifdef EV_DISPATCH void test_kevent_user_dispatch(struct test_context *ctx) @@ -163,6 +185,7 @@ test_evfilt_user(struct test_context *ctx) test(kevent_user_get_hires, ctx); test(kevent_user_disable_and_enable, ctx); test(kevent_user_oneshot, ctx); + test(kevent_user_multi_trigger_merged, ctx); #ifdef EV_DISPATCH test(kevent_user_dispatch, ctx); #endif From 345c4a0171c8038dc62665eb2de29f6617f3dcd1 Mon Sep 17 00:00:00 2001 From: eradman Date: Tue, 4 Jun 2013 14:22:34 +0000 Subject: [PATCH 0562/1120] Remove extra print statement from test_kevent_user_oneshot() git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@650 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/user.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/vendor/libkqueue/test/user.c b/vendor/libkqueue/test/user.c index 54a526fe2..2f35cdcff 100644 --- a/vendor/libkqueue/test/user.c +++ b/vendor/libkqueue/test/user.c @@ -100,8 +100,6 @@ test_kevent_user_oneshot(struct test_context *ctx) test_no_kevents(ctx->kqfd); kevent_add(ctx->kqfd, &kev, 2, EVFILT_USER, EV_ADD | EV_ONESHOT, 0, 0, NULL); - - puts(" -- event 1"); kevent_add(ctx->kqfd, &kev, 2, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); kev.flags = EV_ONESHOT; From a6263cb14156335366306dd1e4593f4eae818c93 Mon Sep 17 00:00:00 2001 From: eradman Date: Tue, 4 Jun 2013 16:28:46 +0000 Subject: [PATCH 0563/1120] cast off_t as (unsigned long) so that tests build on MacOS 10.8. MacOS and FreeBSD should both serve as a useful reference for the correctness of the tests. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@651 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/read.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 59dc57f8b..7d397dba1 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -398,7 +398,7 @@ test_kevent_regular_file(struct test_context *ctx) ret.data--; if ((curpos = lseek(fd, ret.data, SEEK_SET)) != ret.data) { printf("seek to %u failed with rv=%lu\n", - (unsigned int) ret.data, curpos); + (unsigned int) ret.data, (unsigned long) curpos); abort(); } @@ -407,7 +407,7 @@ test_kevent_regular_file(struct test_context *ctx) ret.data = curpos + 1; if ((curpos = lseek(fd, ret.data, SEEK_SET)) != ret.data) { printf("seek to %u failed with rv=%lu\n", - (unsigned int) ret.data, curpos); + (unsigned int) ret.data, (unsigned long) curpos); abort(); } From 3db08dac8f4f6ff46cca194b409ed0f0c41ce56b Mon Sep 17 00:00:00 2001 From: eradman Date: Tue, 11 Jun 2013 14:45:42 +0000 Subject: [PATCH 0564/1120] Minor imporovements to test runner: * kqtest help message includes the names of test suites that can be run * no need to test for EV_RECEIPT since it's always defined in our local copy of event.h * include netdb.h to enable builds on *BSD. git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@652 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/test/common.h | 1 + vendor/libkqueue/test/main.c | 15 ++++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index d447fe140..a34b09e46 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -49,6 +49,7 @@ #include #include #include "../config.h" +#include #else # include "../include/sys/event.h" # include "../src/windows/platform.h" diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 3403a7491..3161bef93 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -117,8 +117,7 @@ test_ev_receipt(void *unused) if ((kq = kqueue()) < 0) die("kqueue()"); -#if defined(EV_RECEIPT) && !defined(_WIN32) - +#if !defined(_WIN32) EV_SET(&kev, SIGUSR2, EVFILT_SIGNAL, EV_ADD | EV_RECEIPT, 0, 0, NULL); if (kevent(kq, &kev, 1, &kev, 1, NULL) < 0) die("kevent"); @@ -191,11 +190,13 @@ test_harness(struct unit_test tests[MAX_TESTS], int iterations) void usage(void) { - printf("usage:\n" - " -h This message\n" - " -n Number of iterations (default: 1)\n" - "\n\n" - ); + printf("usage: [-hn] [testclass ...]\n" + " -h This message\n" + " -n Number of iterations (default: 1)\n" + " testclass Tests suites to run: [socket signal timer vnode user]\n" + " All tests are run by default\n" + "\n" + ); exit(1); } From d8efa9c26d93c89acd2227b48032b95f3c042c92 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 13 Oct 2013 16:31:51 +0000 Subject: [PATCH 0565/1120] Mockup of kqueue/lite.h git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@653 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/include/lite.h | 68 +++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 vendor/libkqueue/include/lite.h diff --git a/vendor/libkqueue/include/lite.h b/vendor/libkqueue/include/lite.h new file mode 100644 index 000000000..0ec54279a --- /dev/null +++ b/vendor/libkqueue/include/lite.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2013 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _KQUEUE_LITE_H +#define _KQUEUE_LITE_H + +#if defined(__FreeBSD__) || defined( +#define USE_KQUEUE +#elif defined(__linux__) +#define USE_EPOLL +#else +#error Unsupported operating system type +#endif + +/* Define an object that represents the event descriptor */ +struct event_source { +#if USE_KQUEUE + int kqfd; /* kqueue */ +#elif USE_EPOLL + /* Linux has a separate file descriptor for each event type. */ + int epfd; /* epoll */ + int inofd; /* inotify */ + int timefd; /* timerfd */ + int sigfd; /* signalfd */ +#endif +}; + +/* Initialize the event descriptor */ +static inline int +event_source_init(struct event_source *ev) +{ +#if USE_KQUEUE + // ev = kqueue() +#elif USE_EPOLL + // ev = epoll_create + // inofd = inotify_create + // timefd = timerfd_create + // sigfd = sigfd_create + // add inofd, timed, sigfd, to ev +#endif + return (0); +} + +// TODO: event_listen() +// TODO: event_get() + +/* Avoid polluting the namespace of the calling program */ +#ifdef USE_KQUEUE +#undef USE_KQUEUE +#endif +#ifdef USE_EPOLL +#undef USE_EPOLL +#endif + +#endif /* ! _KQUEUE_LITE_H */ From 0cd4656f6e233d11f4d76804ab578eef7c10192c Mon Sep 17 00:00:00 2001 From: mheily Date: Mon, 14 Oct 2013 02:50:25 +0000 Subject: [PATCH 0566/1120] More work on kqueue-lite git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@654 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/include/Makefile | 5 + vendor/libkqueue/include/lite.h | 206 ++++++++++++++++++++++++--- vendor/libkqueue/include/test-lite.c | 10 ++ 3 files changed, 201 insertions(+), 20 deletions(-) create mode 100644 vendor/libkqueue/include/Makefile create mode 100644 vendor/libkqueue/include/test-lite.c diff --git a/vendor/libkqueue/include/Makefile b/vendor/libkqueue/include/Makefile new file mode 100644 index 000000000..d8ef537d8 --- /dev/null +++ b/vendor/libkqueue/include/Makefile @@ -0,0 +1,5 @@ +test-lite: test-lite.c lite.h + gcc -g -O0 -Wall -Werror -o test-lite test-lite.c + +check: test-lite + ./test-lite diff --git a/vendor/libkqueue/include/lite.h b/vendor/libkqueue/include/lite.h index 0ec54279a..ce68d7984 100644 --- a/vendor/libkqueue/include/lite.h +++ b/vendor/libkqueue/include/lite.h @@ -17,45 +17,211 @@ #ifndef _KQUEUE_LITE_H #define _KQUEUE_LITE_H -#if defined(__FreeBSD__) || defined( +/* Determine what type of kernel event system to use. */ +#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) #define USE_KQUEUE #elif defined(__linux__) #define USE_EPOLL +#include +#include +#include +#include +#include +#include #else #error Unsupported operating system type #endif -/* Define an object that represents the event descriptor */ -struct event_source { -#if USE_KQUEUE - int kqfd; /* kqueue */ -#elif USE_EPOLL - /* Linux has a separate file descriptor for each event type. */ +/* Equilavent to the list of kevent filters */ +typedef enum { + SOURCE_READ, + SOURCE_WRITE, + SOURCE_VNODE, + SOURCE_SIGNAL, + SOURCE_TIMER +} kevent_source_t; + +/* Equivalent to 'struct kevent' */ +typedef struct { + uintptr_t ident; /* identifier for this event */ + short filter; /* filter for event */ + unsigned short flags; + unsigned int fflags; + intptr_t data; + void *udata; /* opaque user data identifier */ +} kevent_t; + +/* kqueue_t - the event descriptor */ +#if defined(USE_KQUEUE) +typedef int kqueue_t; +#elif defined(USE_EPOLL) +typedef struct { int epfd; /* epoll */ int inofd; /* inotify */ int timefd; /* timerfd */ int sigfd; /* signalfd */ + sigset_t sigmask; + pthread_mutex_t kq_mtx; +} kqueue_t; #endif -}; /* Initialize the event descriptor */ static inline int -event_source_init(struct event_source *ev) +kq_init(kqueue_t *kq) +{ +#if defined(USE_KQUEUE) + *kq = kqueue(); + + return (*kq); +#elif defined(USE_EPOLL) + if (pthread_mutex_init(&kq->kq_mtx, NULL) != 0) + return (-1); + kq->epfd = epoll_create(10); + sigemptyset(&kq->sigmask); + + return (kq->epfd); +#endif +} + +/* Add a new item to the list of events to be monitored */ +static inline int +kq_add(kqueue_t *kq, const kevent_t *ev) { -#if USE_KQUEUE - // ev = kqueue() -#elif USE_EPOLL - // ev = epoll_create - // inofd = inotify_create - // timefd = timerfd_create - // sigfd = sigfd_create - // add inofd, timed, sigfd, to ev + int rv = 0; +#if defined(USE_KQUEUE) + //TODO +#elif defined(USE_EPOLL) + struct epoll_event epev; + kevent_t *evcopy; + int sigfd; + + /* Save a copy of the kevent so kq_wait() can use it later */ + evcopy = malloc(sizeof(*evcopy)); + if (evcopy == NULL) + return (-1); + memcpy (evcopy, ev, sizeof(*evcopy)); + + switch (ev->ident) { + case SOURCE_READ: + epev.events = EPOLLIN; + epev.data.ptr = evcopy; + rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); + + case SOURCE_WRITE: + epev.events = EPOLLOUT; + epev.data.ptr = evcopy; + rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); + + case SOURCE_VNODE: + //TODO: create an inotifyfd, create an epollfd, add the inotifyfd to the epollfd, set epollfd.data.ptr = evcopy, add epollfd to kq->epfd. + rv = -1; + break; + + case SOURCE_SIGNAL: + pthread_mutex_lock(&kq->kq_mtx); + sigaddset(&kq->sigmask, ev->ident); + sigfd = signalfd(kq->sigfd, &kq->sigmask, 0); + pthread_mutex_unlock(&kq->kq_mtx); + if (sigfd < 0) { + rv = -1; + } else { + rv = 0; + } + break; + + case SOURCE_TIMER: + //TODO + rv = -1; + break; + + default: + rv = -1; + return (-1); + } + +// if (rv < 0) +// free(evcopy); #endif - return (0); + return (rv); } -// TODO: event_listen() -// TODO: event_get() +/* Delete an item from the list of events to be monitored */ +static inline int +kq_remove(kqueue_t *kq, const kevent_t *ev) +{ + int rv = 0; + int sigfd; +#if defined(USE_KQUEUE) + //TODO +#elif defined(USE_EPOLL) + struct epoll_event epev; + + switch (ev->ident) { + case SOURCE_READ: + case SOURCE_WRITE: + rv = epoll_ctl(kq->epfd, EPOLL_CTL_DEL, ev->ident, &epev); + break; + + case SOURCE_VNODE: + //TODO + break; + + case SOURCE_SIGNAL: + pthread_mutex_lock(&kq->kq_mtx); + sigdelset(&kq->sigmask, ev->ident); + sigfd = signalfd(kq->sigfd, &kq->sigmask, 0); + pthread_mutex_unlock(&kq->kq_mtx); + if (sigfd < 0) { + rv = -1; + } else { + rv = 0; + } + break; + + case SOURCE_TIMER: + //TODO + break; + + default: + rv = 0; + break; + } +#endif + return (rv); +} + +/* Wait for an event */ +static inline int +kq_wait(kqueue_t *kq, kevent_t *ev, const struct timespec *timeout) +{ + int rv = 0; +#if defined(USE_KQUEUE) + //TODO +#elif defined(USE_EPOLL) + struct epoll_event epev; + int eptimeout; + + /* Convert timeout to the format used by epoll_wait() */ + if (timeout == NULL) + eptimeout = -1; + else + eptimeout = (1000 * timeout->tv_sec) + (timeout->tv_nsec / 1000000); + + rv = epoll_wait(kq->epfd, &epev, 1, eptimeout); + //FIXME: handle timeout + if (rv > 0) { + if (epev.data.fd == kq->sigfd) { + // FIXME: data.fd isn't actually set :( + // Special case: a signal was received + // ... + } else { + // Normal case: data.ptr is a kevent_t (see evcopy from above) + // ... + } + } +#endif + return (rv == 1 ? 0 : -1); +} /* Avoid polluting the namespace of the calling program */ #ifdef USE_KQUEUE diff --git a/vendor/libkqueue/include/test-lite.c b/vendor/libkqueue/include/test-lite.c new file mode 100644 index 000000000..5ffa7a499 --- /dev/null +++ b/vendor/libkqueue/include/test-lite.c @@ -0,0 +1,10 @@ +#include "./lite.h" + +#include +#include +#include + +int main() { + puts("ok"); + exit(0); +} From b4f95b07df3b5d66ae33905114aa3f44072db8e0 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 16 Oct 2013 23:51:15 +0000 Subject: [PATCH 0567/1120] Move kqlite to a separate directory git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@655 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/kqlite/Makefile | 5 + vendor/libkqueue/kqlite/lite.h | 234 ++++++++++++++++++++++++++++ vendor/libkqueue/kqlite/test-lite.c | 10 ++ 3 files changed, 249 insertions(+) create mode 100644 vendor/libkqueue/kqlite/Makefile create mode 100644 vendor/libkqueue/kqlite/lite.h create mode 100644 vendor/libkqueue/kqlite/test-lite.c diff --git a/vendor/libkqueue/kqlite/Makefile b/vendor/libkqueue/kqlite/Makefile new file mode 100644 index 000000000..d8ef537d8 --- /dev/null +++ b/vendor/libkqueue/kqlite/Makefile @@ -0,0 +1,5 @@ +test-lite: test-lite.c lite.h + gcc -g -O0 -Wall -Werror -o test-lite test-lite.c + +check: test-lite + ./test-lite diff --git a/vendor/libkqueue/kqlite/lite.h b/vendor/libkqueue/kqlite/lite.h new file mode 100644 index 000000000..ce68d7984 --- /dev/null +++ b/vendor/libkqueue/kqlite/lite.h @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2013 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _KQUEUE_LITE_H +#define _KQUEUE_LITE_H + +/* Determine what type of kernel event system to use. */ +#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) +#define USE_KQUEUE +#elif defined(__linux__) +#define USE_EPOLL +#include +#include +#include +#include +#include +#include +#else +#error Unsupported operating system type +#endif + +/* Equilavent to the list of kevent filters */ +typedef enum { + SOURCE_READ, + SOURCE_WRITE, + SOURCE_VNODE, + SOURCE_SIGNAL, + SOURCE_TIMER +} kevent_source_t; + +/* Equivalent to 'struct kevent' */ +typedef struct { + uintptr_t ident; /* identifier for this event */ + short filter; /* filter for event */ + unsigned short flags; + unsigned int fflags; + intptr_t data; + void *udata; /* opaque user data identifier */ +} kevent_t; + +/* kqueue_t - the event descriptor */ +#if defined(USE_KQUEUE) +typedef int kqueue_t; +#elif defined(USE_EPOLL) +typedef struct { + int epfd; /* epoll */ + int inofd; /* inotify */ + int timefd; /* timerfd */ + int sigfd; /* signalfd */ + sigset_t sigmask; + pthread_mutex_t kq_mtx; +} kqueue_t; +#endif + +/* Initialize the event descriptor */ +static inline int +kq_init(kqueue_t *kq) +{ +#if defined(USE_KQUEUE) + *kq = kqueue(); + + return (*kq); +#elif defined(USE_EPOLL) + if (pthread_mutex_init(&kq->kq_mtx, NULL) != 0) + return (-1); + kq->epfd = epoll_create(10); + sigemptyset(&kq->sigmask); + + return (kq->epfd); +#endif +} + +/* Add a new item to the list of events to be monitored */ +static inline int +kq_add(kqueue_t *kq, const kevent_t *ev) +{ + int rv = 0; +#if defined(USE_KQUEUE) + //TODO +#elif defined(USE_EPOLL) + struct epoll_event epev; + kevent_t *evcopy; + int sigfd; + + /* Save a copy of the kevent so kq_wait() can use it later */ + evcopy = malloc(sizeof(*evcopy)); + if (evcopy == NULL) + return (-1); + memcpy (evcopy, ev, sizeof(*evcopy)); + + switch (ev->ident) { + case SOURCE_READ: + epev.events = EPOLLIN; + epev.data.ptr = evcopy; + rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); + + case SOURCE_WRITE: + epev.events = EPOLLOUT; + epev.data.ptr = evcopy; + rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); + + case SOURCE_VNODE: + //TODO: create an inotifyfd, create an epollfd, add the inotifyfd to the epollfd, set epollfd.data.ptr = evcopy, add epollfd to kq->epfd. + rv = -1; + break; + + case SOURCE_SIGNAL: + pthread_mutex_lock(&kq->kq_mtx); + sigaddset(&kq->sigmask, ev->ident); + sigfd = signalfd(kq->sigfd, &kq->sigmask, 0); + pthread_mutex_unlock(&kq->kq_mtx); + if (sigfd < 0) { + rv = -1; + } else { + rv = 0; + } + break; + + case SOURCE_TIMER: + //TODO + rv = -1; + break; + + default: + rv = -1; + return (-1); + } + +// if (rv < 0) +// free(evcopy); +#endif + return (rv); +} + +/* Delete an item from the list of events to be monitored */ +static inline int +kq_remove(kqueue_t *kq, const kevent_t *ev) +{ + int rv = 0; + int sigfd; +#if defined(USE_KQUEUE) + //TODO +#elif defined(USE_EPOLL) + struct epoll_event epev; + + switch (ev->ident) { + case SOURCE_READ: + case SOURCE_WRITE: + rv = epoll_ctl(kq->epfd, EPOLL_CTL_DEL, ev->ident, &epev); + break; + + case SOURCE_VNODE: + //TODO + break; + + case SOURCE_SIGNAL: + pthread_mutex_lock(&kq->kq_mtx); + sigdelset(&kq->sigmask, ev->ident); + sigfd = signalfd(kq->sigfd, &kq->sigmask, 0); + pthread_mutex_unlock(&kq->kq_mtx); + if (sigfd < 0) { + rv = -1; + } else { + rv = 0; + } + break; + + case SOURCE_TIMER: + //TODO + break; + + default: + rv = 0; + break; + } +#endif + return (rv); +} + +/* Wait for an event */ +static inline int +kq_wait(kqueue_t *kq, kevent_t *ev, const struct timespec *timeout) +{ + int rv = 0; +#if defined(USE_KQUEUE) + //TODO +#elif defined(USE_EPOLL) + struct epoll_event epev; + int eptimeout; + + /* Convert timeout to the format used by epoll_wait() */ + if (timeout == NULL) + eptimeout = -1; + else + eptimeout = (1000 * timeout->tv_sec) + (timeout->tv_nsec / 1000000); + + rv = epoll_wait(kq->epfd, &epev, 1, eptimeout); + //FIXME: handle timeout + if (rv > 0) { + if (epev.data.fd == kq->sigfd) { + // FIXME: data.fd isn't actually set :( + // Special case: a signal was received + // ... + } else { + // Normal case: data.ptr is a kevent_t (see evcopy from above) + // ... + } + } +#endif + return (rv == 1 ? 0 : -1); +} + +/* Avoid polluting the namespace of the calling program */ +#ifdef USE_KQUEUE +#undef USE_KQUEUE +#endif +#ifdef USE_EPOLL +#undef USE_EPOLL +#endif + +#endif /* ! _KQUEUE_LITE_H */ diff --git a/vendor/libkqueue/kqlite/test-lite.c b/vendor/libkqueue/kqlite/test-lite.c new file mode 100644 index 000000000..5ffa7a499 --- /dev/null +++ b/vendor/libkqueue/kqlite/test-lite.c @@ -0,0 +1,10 @@ +#include "./lite.h" + +#include +#include +#include + +int main() { + puts("ok"); + exit(0); +} From 8c97d7b8578c623ee2ef7d7b76ce1cb428772f51 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 16 Oct 2013 23:53:19 +0000 Subject: [PATCH 0568/1120] remove kqlite git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@656 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/include/Makefile | 5 - vendor/libkqueue/include/lite.h | 234 --------------------------- vendor/libkqueue/include/test-lite.c | 10 -- 3 files changed, 249 deletions(-) delete mode 100644 vendor/libkqueue/include/Makefile delete mode 100644 vendor/libkqueue/include/lite.h delete mode 100644 vendor/libkqueue/include/test-lite.c diff --git a/vendor/libkqueue/include/Makefile b/vendor/libkqueue/include/Makefile deleted file mode 100644 index d8ef537d8..000000000 --- a/vendor/libkqueue/include/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -test-lite: test-lite.c lite.h - gcc -g -O0 -Wall -Werror -o test-lite test-lite.c - -check: test-lite - ./test-lite diff --git a/vendor/libkqueue/include/lite.h b/vendor/libkqueue/include/lite.h deleted file mode 100644 index ce68d7984..000000000 --- a/vendor/libkqueue/include/lite.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2013 Mark Heily - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _KQUEUE_LITE_H -#define _KQUEUE_LITE_H - -/* Determine what type of kernel event system to use. */ -#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) -#define USE_KQUEUE -#elif defined(__linux__) -#define USE_EPOLL -#include -#include -#include -#include -#include -#include -#else -#error Unsupported operating system type -#endif - -/* Equilavent to the list of kevent filters */ -typedef enum { - SOURCE_READ, - SOURCE_WRITE, - SOURCE_VNODE, - SOURCE_SIGNAL, - SOURCE_TIMER -} kevent_source_t; - -/* Equivalent to 'struct kevent' */ -typedef struct { - uintptr_t ident; /* identifier for this event */ - short filter; /* filter for event */ - unsigned short flags; - unsigned int fflags; - intptr_t data; - void *udata; /* opaque user data identifier */ -} kevent_t; - -/* kqueue_t - the event descriptor */ -#if defined(USE_KQUEUE) -typedef int kqueue_t; -#elif defined(USE_EPOLL) -typedef struct { - int epfd; /* epoll */ - int inofd; /* inotify */ - int timefd; /* timerfd */ - int sigfd; /* signalfd */ - sigset_t sigmask; - pthread_mutex_t kq_mtx; -} kqueue_t; -#endif - -/* Initialize the event descriptor */ -static inline int -kq_init(kqueue_t *kq) -{ -#if defined(USE_KQUEUE) - *kq = kqueue(); - - return (*kq); -#elif defined(USE_EPOLL) - if (pthread_mutex_init(&kq->kq_mtx, NULL) != 0) - return (-1); - kq->epfd = epoll_create(10); - sigemptyset(&kq->sigmask); - - return (kq->epfd); -#endif -} - -/* Add a new item to the list of events to be monitored */ -static inline int -kq_add(kqueue_t *kq, const kevent_t *ev) -{ - int rv = 0; -#if defined(USE_KQUEUE) - //TODO -#elif defined(USE_EPOLL) - struct epoll_event epev; - kevent_t *evcopy; - int sigfd; - - /* Save a copy of the kevent so kq_wait() can use it later */ - evcopy = malloc(sizeof(*evcopy)); - if (evcopy == NULL) - return (-1); - memcpy (evcopy, ev, sizeof(*evcopy)); - - switch (ev->ident) { - case SOURCE_READ: - epev.events = EPOLLIN; - epev.data.ptr = evcopy; - rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); - - case SOURCE_WRITE: - epev.events = EPOLLOUT; - epev.data.ptr = evcopy; - rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); - - case SOURCE_VNODE: - //TODO: create an inotifyfd, create an epollfd, add the inotifyfd to the epollfd, set epollfd.data.ptr = evcopy, add epollfd to kq->epfd. - rv = -1; - break; - - case SOURCE_SIGNAL: - pthread_mutex_lock(&kq->kq_mtx); - sigaddset(&kq->sigmask, ev->ident); - sigfd = signalfd(kq->sigfd, &kq->sigmask, 0); - pthread_mutex_unlock(&kq->kq_mtx); - if (sigfd < 0) { - rv = -1; - } else { - rv = 0; - } - break; - - case SOURCE_TIMER: - //TODO - rv = -1; - break; - - default: - rv = -1; - return (-1); - } - -// if (rv < 0) -// free(evcopy); -#endif - return (rv); -} - -/* Delete an item from the list of events to be monitored */ -static inline int -kq_remove(kqueue_t *kq, const kevent_t *ev) -{ - int rv = 0; - int sigfd; -#if defined(USE_KQUEUE) - //TODO -#elif defined(USE_EPOLL) - struct epoll_event epev; - - switch (ev->ident) { - case SOURCE_READ: - case SOURCE_WRITE: - rv = epoll_ctl(kq->epfd, EPOLL_CTL_DEL, ev->ident, &epev); - break; - - case SOURCE_VNODE: - //TODO - break; - - case SOURCE_SIGNAL: - pthread_mutex_lock(&kq->kq_mtx); - sigdelset(&kq->sigmask, ev->ident); - sigfd = signalfd(kq->sigfd, &kq->sigmask, 0); - pthread_mutex_unlock(&kq->kq_mtx); - if (sigfd < 0) { - rv = -1; - } else { - rv = 0; - } - break; - - case SOURCE_TIMER: - //TODO - break; - - default: - rv = 0; - break; - } -#endif - return (rv); -} - -/* Wait for an event */ -static inline int -kq_wait(kqueue_t *kq, kevent_t *ev, const struct timespec *timeout) -{ - int rv = 0; -#if defined(USE_KQUEUE) - //TODO -#elif defined(USE_EPOLL) - struct epoll_event epev; - int eptimeout; - - /* Convert timeout to the format used by epoll_wait() */ - if (timeout == NULL) - eptimeout = -1; - else - eptimeout = (1000 * timeout->tv_sec) + (timeout->tv_nsec / 1000000); - - rv = epoll_wait(kq->epfd, &epev, 1, eptimeout); - //FIXME: handle timeout - if (rv > 0) { - if (epev.data.fd == kq->sigfd) { - // FIXME: data.fd isn't actually set :( - // Special case: a signal was received - // ... - } else { - // Normal case: data.ptr is a kevent_t (see evcopy from above) - // ... - } - } -#endif - return (rv == 1 ? 0 : -1); -} - -/* Avoid polluting the namespace of the calling program */ -#ifdef USE_KQUEUE -#undef USE_KQUEUE -#endif -#ifdef USE_EPOLL -#undef USE_EPOLL -#endif - -#endif /* ! _KQUEUE_LITE_H */ diff --git a/vendor/libkqueue/include/test-lite.c b/vendor/libkqueue/include/test-lite.c deleted file mode 100644 index 5ffa7a499..000000000 --- a/vendor/libkqueue/include/test-lite.c +++ /dev/null @@ -1,10 +0,0 @@ -#include "./lite.h" - -#include -#include -#include - -int main() { - puts("ok"); - exit(0); -} From 70a62e9d1811d816794466fa3fe89d06632c8be6 Mon Sep 17 00:00:00 2001 From: mheily Date: Thu, 17 Oct 2013 00:05:57 +0000 Subject: [PATCH 0569/1120] Move code out of lite.h git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@657 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/kqlite/Makefile | 4 +- vendor/libkqueue/kqlite/kqlite.c | 203 +++++++++++++++++++++++++++++++ vendor/libkqueue/kqlite/lite.h | 191 ++--------------------------- 3 files changed, 212 insertions(+), 186 deletions(-) create mode 100644 vendor/libkqueue/kqlite/kqlite.c diff --git a/vendor/libkqueue/kqlite/Makefile b/vendor/libkqueue/kqlite/Makefile index d8ef537d8..ef468edcb 100644 --- a/vendor/libkqueue/kqlite/Makefile +++ b/vendor/libkqueue/kqlite/Makefile @@ -1,5 +1,5 @@ -test-lite: test-lite.c lite.h - gcc -g -O0 -Wall -Werror -o test-lite test-lite.c +test-lite: test-lite.c kqlite.c lite.h + gcc -g -O0 -Wall -Werror -o test-lite test-lite.c kqlite.c check: test-lite ./test-lite diff --git a/vendor/libkqueue/kqlite/kqlite.c b/vendor/libkqueue/kqlite/kqlite.c new file mode 100644 index 000000000..4e549aea3 --- /dev/null +++ b/vendor/libkqueue/kqlite/kqlite.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2013 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "./lite.h" + +/* Determine what type of kernel event system to use. */ +#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) +#define USE_KQUEUE +#elif defined(__linux__) +#define USE_EPOLL +#include +#include +#include +#include +#include +#include +#else +#error Unsupported operating system type +#endif + +#if defined(USE_KQUEUE) +typedef int kqueue_t; +#elif defined(USE_EPOLL) +struct kqueue { + int epfd; /* epoll */ + int inofd; /* inotify */ + int timefd; /* timerfd */ + int sigfd; /* signalfd */ + sigset_t sigmask; + pthread_mutex_t kq_mtx; +}; +#endif + +/* Initialize the event descriptor */ +int +kq_init(kqueue_t kq) +{ +#if defined(USE_KQUEUE) + kq = kqueue(); + + return (kq); +#elif defined(USE_EPOLL) + if (pthread_mutex_init(&kq->kq_mtx, NULL) != 0) + return (-1); + kq->epfd = epoll_create(10); + sigemptyset(&kq->sigmask); + + return (kq->epfd); +#endif +} + +/* Add a new item to the list of events to be monitored */ +int +kq_add(kqueue_t kq, const kevent_t *ev) +{ + int rv = 0; +#if defined(USE_KQUEUE) + //TODO +#elif defined(USE_EPOLL) + struct epoll_event epev; + kevent_t *evcopy; + int sigfd; + + /* Save a copy of the kevent so kq_wait() can use it later */ + evcopy = malloc(sizeof(*evcopy)); + if (evcopy == NULL) + return (-1); + memcpy (evcopy, ev, sizeof(*evcopy)); + + switch (ev->ident) { + case SOURCE_READ: + epev.events = EPOLLIN; + epev.data.ptr = evcopy; + rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); + + case SOURCE_WRITE: + epev.events = EPOLLOUT; + epev.data.ptr = evcopy; + rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); + + case SOURCE_VNODE: + //TODO: create an inotifyfd, create an epollfd, add the inotifyfd to the epollfd, set epollfd.data.ptr = evcopy, add epollfd to kq->epfd. + rv = -1; + break; + + case SOURCE_SIGNAL: + pthread_mutex_lock(&kq->kq_mtx); + sigaddset(&kq->sigmask, ev->ident); + sigfd = signalfd(kq->sigfd, &kq->sigmask, 0); + pthread_mutex_unlock(&kq->kq_mtx); + if (sigfd < 0) { + rv = -1; + } else { + rv = 0; + } + break; + + case SOURCE_TIMER: + //TODO + rv = -1; + break; + + default: + rv = -1; + return (-1); + } + +// if (rv < 0) +// free(evcopy); +#endif + return (rv); +} + +/* Delete an item from the list of events to be monitored */ +int +kq_remove(kqueue_t kq, const kevent_t *ev) +{ + int rv = 0; + int sigfd; +#if defined(USE_KQUEUE) + //TODO +#elif defined(USE_EPOLL) + struct epoll_event epev; + + switch (ev->ident) { + case SOURCE_READ: + case SOURCE_WRITE: + rv = epoll_ctl(kq->epfd, EPOLL_CTL_DEL, ev->ident, &epev); + break; + + case SOURCE_VNODE: + //TODO + break; + + case SOURCE_SIGNAL: + pthread_mutex_lock(&kq->kq_mtx); + sigdelset(&kq->sigmask, ev->ident); + sigfd = signalfd(kq->sigfd, &kq->sigmask, 0); + pthread_mutex_unlock(&kq->kq_mtx); + if (sigfd < 0) { + rv = -1; + } else { + rv = 0; + } + break; + + case SOURCE_TIMER: + //TODO + break; + + default: + rv = 0; + break; + } +#endif + return (rv); +} + +/* Wait for an event */ +int +kq_wait(kqueue_t kq, kevent_t *ev, const struct timespec *timeout) +{ + int rv = 0; +#if defined(USE_KQUEUE) + //TODO +#elif defined(USE_EPOLL) + struct epoll_event epev; + int eptimeout; + + /* Convert timeout to the format used by epoll_wait() */ + if (timeout == NULL) + eptimeout = -1; + else + eptimeout = (1000 * timeout->tv_sec) + (timeout->tv_nsec / 1000000); + + rv = epoll_wait(kq->epfd, &epev, 1, eptimeout); + //FIXME: handle timeout + if (rv > 0) { + if (epev.data.fd == kq->sigfd) { + // FIXME: data.fd isn't actually set :( + // Special case: a signal was received + // ... + } else { + // Normal case: data.ptr is a kevent_t (see evcopy from above) + // ... + } + } +#endif + return (rv == 1 ? 0 : -1); +} diff --git a/vendor/libkqueue/kqlite/lite.h b/vendor/libkqueue/kqlite/lite.h index ce68d7984..0eff3464d 100644 --- a/vendor/libkqueue/kqlite/lite.h +++ b/vendor/libkqueue/kqlite/lite.h @@ -17,20 +17,8 @@ #ifndef _KQUEUE_LITE_H #define _KQUEUE_LITE_H -/* Determine what type of kernel event system to use. */ -#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) -#define USE_KQUEUE -#elif defined(__linux__) -#define USE_EPOLL -#include -#include -#include -#include -#include -#include -#else -#error Unsupported operating system type -#endif +#include +#include /* Equilavent to the list of kevent filters */ typedef enum { @@ -52,183 +40,18 @@ typedef struct { } kevent_t; /* kqueue_t - the event descriptor */ -#if defined(USE_KQUEUE) -typedef int kqueue_t; -#elif defined(USE_EPOLL) -typedef struct { - int epfd; /* epoll */ - int inofd; /* inotify */ - int timefd; /* timerfd */ - int sigfd; /* signalfd */ - sigset_t sigmask; - pthread_mutex_t kq_mtx; -} kqueue_t; -#endif +typedef struct kqueue *kqueue_t; /* Initialize the event descriptor */ -static inline int -kq_init(kqueue_t *kq) -{ -#if defined(USE_KQUEUE) - *kq = kqueue(); - - return (*kq); -#elif defined(USE_EPOLL) - if (pthread_mutex_init(&kq->kq_mtx, NULL) != 0) - return (-1); - kq->epfd = epoll_create(10); - sigemptyset(&kq->sigmask); - - return (kq->epfd); -#endif -} +int kq_init(kqueue_t kq); /* Add a new item to the list of events to be monitored */ -static inline int -kq_add(kqueue_t *kq, const kevent_t *ev) -{ - int rv = 0; -#if defined(USE_KQUEUE) - //TODO -#elif defined(USE_EPOLL) - struct epoll_event epev; - kevent_t *evcopy; - int sigfd; - - /* Save a copy of the kevent so kq_wait() can use it later */ - evcopy = malloc(sizeof(*evcopy)); - if (evcopy == NULL) - return (-1); - memcpy (evcopy, ev, sizeof(*evcopy)); - - switch (ev->ident) { - case SOURCE_READ: - epev.events = EPOLLIN; - epev.data.ptr = evcopy; - rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); - - case SOURCE_WRITE: - epev.events = EPOLLOUT; - epev.data.ptr = evcopy; - rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); - - case SOURCE_VNODE: - //TODO: create an inotifyfd, create an epollfd, add the inotifyfd to the epollfd, set epollfd.data.ptr = evcopy, add epollfd to kq->epfd. - rv = -1; - break; - - case SOURCE_SIGNAL: - pthread_mutex_lock(&kq->kq_mtx); - sigaddset(&kq->sigmask, ev->ident); - sigfd = signalfd(kq->sigfd, &kq->sigmask, 0); - pthread_mutex_unlock(&kq->kq_mtx); - if (sigfd < 0) { - rv = -1; - } else { - rv = 0; - } - break; - - case SOURCE_TIMER: - //TODO - rv = -1; - break; - - default: - rv = -1; - return (-1); - } - -// if (rv < 0) -// free(evcopy); -#endif - return (rv); -} +int kq_add(kqueue_t kq, const kevent_t *ev); /* Delete an item from the list of events to be monitored */ -static inline int -kq_remove(kqueue_t *kq, const kevent_t *ev) -{ - int rv = 0; - int sigfd; -#if defined(USE_KQUEUE) - //TODO -#elif defined(USE_EPOLL) - struct epoll_event epev; - - switch (ev->ident) { - case SOURCE_READ: - case SOURCE_WRITE: - rv = epoll_ctl(kq->epfd, EPOLL_CTL_DEL, ev->ident, &epev); - break; - - case SOURCE_VNODE: - //TODO - break; - - case SOURCE_SIGNAL: - pthread_mutex_lock(&kq->kq_mtx); - sigdelset(&kq->sigmask, ev->ident); - sigfd = signalfd(kq->sigfd, &kq->sigmask, 0); - pthread_mutex_unlock(&kq->kq_mtx); - if (sigfd < 0) { - rv = -1; - } else { - rv = 0; - } - break; - - case SOURCE_TIMER: - //TODO - break; - - default: - rv = 0; - break; - } -#endif - return (rv); -} +int kq_remove(kqueue_t kq, const kevent_t *ev); /* Wait for an event */ -static inline int -kq_wait(kqueue_t *kq, kevent_t *ev, const struct timespec *timeout) -{ - int rv = 0; -#if defined(USE_KQUEUE) - //TODO -#elif defined(USE_EPOLL) - struct epoll_event epev; - int eptimeout; - - /* Convert timeout to the format used by epoll_wait() */ - if (timeout == NULL) - eptimeout = -1; - else - eptimeout = (1000 * timeout->tv_sec) + (timeout->tv_nsec / 1000000); - - rv = epoll_wait(kq->epfd, &epev, 1, eptimeout); - //FIXME: handle timeout - if (rv > 0) { - if (epev.data.fd == kq->sigfd) { - // FIXME: data.fd isn't actually set :( - // Special case: a signal was received - // ... - } else { - // Normal case: data.ptr is a kevent_t (see evcopy from above) - // ... - } - } -#endif - return (rv == 1 ? 0 : -1); -} - -/* Avoid polluting the namespace of the calling program */ -#ifdef USE_KQUEUE -#undef USE_KQUEUE -#endif -#ifdef USE_EPOLL -#undef USE_EPOLL -#endif +int kq_wait(kqueue_t kq, kevent_t *ev, const struct timespec *timeout); #endif /* ! _KQUEUE_LITE_H */ From 60637faebab6f2bc8a6389434b9f7a14b920bd5a Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 18 Oct 2013 00:03:02 +0000 Subject: [PATCH 0570/1120] More work on kqlite git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@658 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/kqlite/README | 26 +++++ vendor/libkqueue/kqlite/kqlite.c | 154 +++++++++++++++++-------- vendor/libkqueue/kqlite/lite.h | 172 ++++++++++++++++++++++------ vendor/libkqueue/kqlite/test-lite.c | 5 + 4 files changed, 271 insertions(+), 86 deletions(-) create mode 100644 vendor/libkqueue/kqlite/README diff --git a/vendor/libkqueue/kqlite/README b/vendor/libkqueue/kqlite/README new file mode 100644 index 000000000..6611597b9 --- /dev/null +++ b/vendor/libkqueue/kqlite/README @@ -0,0 +1,26 @@ +kqlite has the following goals: + + * be lightweight and efficient + * provide a strict subset of the functionality of kqueue(2) and kevent(2) + * closely resemble the kqueue API, but not guarantee 100% compatibility + * support modern POSIX operating systems + +It should be possible to switch between kqlite and the full libkqueue +using a few preprocessor macros: + + #if LIBKQUEUE + #define kqueue_t int + #define kq_init kqueue + #define kq_event kevent + #define kq_free close + #endif + +Here are the differences between kqlite and kqueue: + + * Function names are different: + + kqueue() == kq_init() + kevent() == kq_event() + close() == kq_free() + + * kqueue() returns an int, while kq_init returns an opaque kqueue_t type. diff --git a/vendor/libkqueue/kqlite/kqlite.c b/vendor/libkqueue/kqlite/kqlite.c index 4e549aea3..4263baf54 100644 --- a/vendor/libkqueue/kqlite/kqlite.c +++ b/vendor/libkqueue/kqlite/kqlite.c @@ -16,9 +16,12 @@ #include "./lite.h" +#include + /* Determine what type of kernel event system to use. */ #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) #define USE_KQUEUE +#include #elif defined(__linux__) #define USE_EPOLL #include @@ -31,47 +34,88 @@ #error Unsupported operating system type #endif + +/* Linux supports a subset of these filters. */ +#if defined(USE_EPOLL) +#define EVFILT_READ (0) +#define EVFILT_WRITE (1) +#define EVFILT_VNODE (2) +#define EVFILT_SIGNAL (3) +#define EVFILT_TIMER (4) +#define EVFILT_SYSCOUNT (5) +#endif + +struct kqueue { #if defined(USE_KQUEUE) -typedef int kqueue_t; + int kqfd; /* kqueue(2) descriptor */ #elif defined(USE_EPOLL) -struct kqueue { int epfd; /* epoll */ - int inofd; /* inotify */ - int timefd; /* timerfd */ - int sigfd; /* signalfd */ + int wfd[EVFILT_SYSCOUNT]; /* an event wait descriptor for each EVFILT_* */ sigset_t sigmask; pthread_mutex_t kq_mtx; -}; +#else +#error Undefined event system #endif +}; /* Initialize the event descriptor */ -int -kq_init(kqueue_t kq) +kqueue_t +kq_init(void) { -#if defined(USE_KQUEUE) - kq = kqueue(); + struct kqueue *kq; - return (kq); + if ((kq = malloc(sizeof(*kq))) == NULL) + return (NULL); + +#if defined(USE_KQUEUE) + kq->kqfd = kqueue(); + if (kq->kqfd < 0) { + free(kq); + return (NULL); + } + #elif defined(USE_EPOLL) if (pthread_mutex_init(&kq->kq_mtx, NULL) != 0) - return (-1); + goto errout; kq->epfd = epoll_create(10); + if (kq->epfd < 0) + goto errout; sigemptyset(&kq->sigmask); + kq->wfd[EVFILT_SIGNAL] = signalfd(-1, &kq->sigmask, 0); + + // FIXME: check that all members of kq->wfd are valid + + return (kq); - return (kq->epfd); +errout: + free(kq); + if (kq->epfd >= 0) close(kq->epfd); + //FIXME: something like: if (kq->wfd[EVFILT_SIGNAL] >= 0) free(kq->epfd); + return (NULL); #endif } -/* Add a new item to the list of events to be monitored */ -int -kq_add(kqueue_t kq, const kevent_t *ev) +void +kq_free(kqueue_t kq) { - int rv = 0; #if defined(USE_KQUEUE) - //TODO + close(kq.kqfd); + #elif defined(USE_EPOLL) + close(kq->epfd); +#endif + free(kq); +} + +#if defined(USE_EPOLL) + +/* Add a new item to the list of events to be monitored */ +static inline int +kq_add(kqueue_t kq, const struct kevent *ev) +{ + int rv = 0; struct epoll_event epev; - kevent_t *evcopy; + struct kevent *evcopy; int sigfd; /* Save a copy of the kevent so kq_wait() can use it later */ @@ -81,25 +125,25 @@ kq_add(kqueue_t kq, const kevent_t *ev) memcpy (evcopy, ev, sizeof(*evcopy)); switch (ev->ident) { - case SOURCE_READ: + case EVFILT_READ: epev.events = EPOLLIN; epev.data.ptr = evcopy; rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); - case SOURCE_WRITE: + case EVFILT_WRITE: epev.events = EPOLLOUT; epev.data.ptr = evcopy; rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); - case SOURCE_VNODE: + case EVFILT_VNODE: //TODO: create an inotifyfd, create an epollfd, add the inotifyfd to the epollfd, set epollfd.data.ptr = evcopy, add epollfd to kq->epfd. rv = -1; break; - case SOURCE_SIGNAL: + case EVFILT_SIGNAL: pthread_mutex_lock(&kq->kq_mtx); sigaddset(&kq->sigmask, ev->ident); - sigfd = signalfd(kq->sigfd, &kq->sigmask, 0); + sigfd = signalfd(kq->wfd[EVFILT_SIGNAL], &kq->sigmask, 0); pthread_mutex_unlock(&kq->kq_mtx); if (sigfd < 0) { rv = -1; @@ -108,7 +152,7 @@ kq_add(kqueue_t kq, const kevent_t *ev) } break; - case SOURCE_TIMER: + case EVFILT_TIMER: //TODO rv = -1; break; @@ -120,35 +164,31 @@ kq_add(kqueue_t kq, const kevent_t *ev) // if (rv < 0) // free(evcopy); -#endif return (rv); } /* Delete an item from the list of events to be monitored */ -int -kq_remove(kqueue_t kq, const kevent_t *ev) +static int +kq_delete(kqueue_t kq, const struct kevent *ev) { int rv = 0; int sigfd; -#if defined(USE_KQUEUE) - //TODO -#elif defined(USE_EPOLL) struct epoll_event epev; switch (ev->ident) { - case SOURCE_READ: - case SOURCE_WRITE: + case EVFILT_READ: + case EVFILT_WRITE: rv = epoll_ctl(kq->epfd, EPOLL_CTL_DEL, ev->ident, &epev); break; - case SOURCE_VNODE: + case EVFILT_VNODE: //TODO break; - case SOURCE_SIGNAL: + case EVFILT_SIGNAL: pthread_mutex_lock(&kq->kq_mtx); sigdelset(&kq->sigmask, ev->ident); - sigfd = signalfd(kq->sigfd, &kq->sigmask, 0); + sigfd = signalfd(kq->wfd[EVFILT_SIGNAL], &kq->sigmask, 0); pthread_mutex_unlock(&kq->kq_mtx); if (sigfd < 0) { rv = -1; @@ -157,7 +197,7 @@ kq_remove(kqueue_t kq, const kevent_t *ev) } break; - case SOURCE_TIMER: + case EVFILT_TIMER: //TODO break; @@ -165,20 +205,37 @@ kq_remove(kqueue_t kq, const kevent_t *ev) rv = 0; break; } -#endif return (rv); } -/* Wait for an event */ -int -kq_wait(kqueue_t kq, kevent_t *ev, const struct timespec *timeout) +#endif /* defined(USE_EPOLL) */ + +/* Equivalent to kevent() */ +int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, + struct kevent *eventlist, int nevents, + const struct timespec *timeout) { int rv = 0; + #if defined(USE_KQUEUE) - //TODO + return kevent(kq->kqfd, changelist, nchanges, eventlist, nevents, timeout); + #elif defined(USE_EPOLL) struct epoll_event epev; - int eptimeout; + int i, eptimeout; + + /* Process each item on the changelist */ + for (i = 0; i < nchanges; i++) { + if (changelist[i].flags & EV_ADD) { + rv = kq_add(kq, &changelist[i]); + } else if (changelist[i].flags & EV_DELETE) { + rv = kq_delete(kq, &changelist[i]); + } else { + rv = -1; + } + if (rv < 0) + return (-1); + } /* Convert timeout to the format used by epoll_wait() */ if (timeout == NULL) @@ -189,15 +246,16 @@ kq_wait(kqueue_t kq, kevent_t *ev, const struct timespec *timeout) rv = epoll_wait(kq->epfd, &epev, 1, eptimeout); //FIXME: handle timeout if (rv > 0) { - if (epev.data.fd == kq->sigfd) { + //if (epev.data.fd == kq->sigfd) { // FIXME: data.fd isn't actually set :( // Special case: a signal was received // ... - } else { - // Normal case: data.ptr is a kevent_t (see evcopy from above) + //} else { + // Normal case: data.ptr is a struct kevent (see evcopy from above) // ... - } + //} } -#endif + return (rv == 1 ? 0 : -1); +#endif } diff --git a/vendor/libkqueue/kqlite/lite.h b/vendor/libkqueue/kqlite/lite.h index 0eff3464d..5e8a4d529 100644 --- a/vendor/libkqueue/kqlite/lite.h +++ b/vendor/libkqueue/kqlite/lite.h @@ -1,57 +1,153 @@ -/* +/*- * Copyright (c) 2013 Mark Heily + * Copyright (c) 1999,2000,2001 Jonathan Lemon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * $FreeBSD SVN Revision 197533$ */ #ifndef _KQUEUE_LITE_H #define _KQUEUE_LITE_H -#include +#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) +#include +#else + #include +#include +#include + +#define EV_SET(kevp_, a, b, c, d, e, f) do { \ + struct kevent *kevp = (kevp_); \ + (kevp)->ident = (a); \ + (kevp)->filter = (b); \ + (kevp)->flags = (c); \ + (kevp)->fflags = (d); \ + (kevp)->data = (e); \ + (kevp)->udata = (f); \ +} while(0) + +struct kevent { + uintptr_t ident; /* identifier for this event */ + short filter; /* filter for event */ + unsigned short flags; + unsigned int fflags; + intptr_t data; + void *udata; /* opaque user data identifier */ +}; -/* Equilavent to the list of kevent filters */ -typedef enum { - SOURCE_READ, - SOURCE_WRITE, - SOURCE_VNODE, - SOURCE_SIGNAL, - SOURCE_TIMER -} kevent_source_t; - -/* Equivalent to 'struct kevent' */ -typedef struct { - uintptr_t ident; /* identifier for this event */ - short filter; /* filter for event */ - unsigned short flags; - unsigned int fflags; - intptr_t data; - void *udata; /* opaque user data identifier */ -} kevent_t; +/* actions */ +#define EV_ADD 0x0001 /* add event to kq (implies enable) */ +#define EV_DELETE 0x0002 /* delete event from kq */ +#define EV_ENABLE 0x0004 /* enable event */ +#define EV_DISABLE 0x0008 /* disable event (not reported) */ + +/* flags */ +#define EV_ONESHOT 0x0010 /* only report one occurrence */ +#define EV_CLEAR 0x0020 /* clear event state after reporting */ +#define EV_RECEIPT 0x0040 /* force EV_ERROR on success, data=0 */ +#define EV_DISPATCH 0x0080 /* disable event after reporting */ + +#define EV_SYSFLAGS 0xF000 /* reserved by system */ +#define EV_FLAG1 0x2000 /* filter-specific flag */ + +/* returned values */ +#define EV_EOF 0x8000 /* EOF detected */ +#define EV_ERROR 0x4000 /* error, data contains errno */ + + /* + * data/hint flags/masks for EVFILT_USER + * + * On input, the top two bits of fflags specifies how the lower twenty four + * bits should be applied to the stored value of fflags. + * + * On output, the top two bits will always be set to NOTE_FFNOP and the + * remaining twenty four bits will contain the stored fflags value. + */ +#define NOTE_FFNOP 0x00000000 /* ignore input fflags */ +#define NOTE_FFAND 0x40000000 /* AND fflags */ +#define NOTE_FFOR 0x80000000 /* OR fflags */ +#define NOTE_FFCOPY 0xc0000000 /* copy fflags */ +#define NOTE_FFCTRLMASK 0xc0000000 /* masks for operations */ +#define NOTE_FFLAGSMASK 0x00ffffff + +#define NOTE_TRIGGER 0x01000000 /* Cause the event to be + triggered for output. */ + +/* + * data/hint flags for EVFILT_{READ|WRITE} + */ +#define NOTE_LOWAT 0x0001 /* low water mark */ +#undef NOTE_LOWAT /* Not supported on Linux */ + +/* + * data/hint flags for EVFILT_VNODE + */ +#define NOTE_DELETE 0x0001 /* vnode was removed */ +#define NOTE_WRITE 0x0002 /* data contents changed */ +#define NOTE_EXTEND 0x0004 /* size increased */ +#define NOTE_ATTRIB 0x0008 /* attributes changed */ +#define NOTE_LINK 0x0010 /* link count changed */ +#define NOTE_RENAME 0x0020 /* vnode was renamed */ +#define NOTE_REVOKE 0x0040 /* vnode access was revoked */ +#undef NOTE_REVOKE /* Not supported on Linux */ + +/* + * data/hint flags for EVFILT_PROC + */ +#define NOTE_EXIT 0x80000000 /* process exited */ +#define NOTE_FORK 0x40000000 /* process forked */ +#define NOTE_EXEC 0x20000000 /* process exec'd */ +#define NOTE_PCTRLMASK 0xf0000000 /* mask for hint bits */ +#define NOTE_PDATAMASK 0x000fffff /* mask for pid */ + +/* additional flags for EVFILT_PROC */ +#define NOTE_TRACK 0x00000001 /* follow across forks */ +#define NOTE_TRACKERR 0x00000002 /* could not track child */ +#define NOTE_CHILD 0x00000004 /* am a child process */ + +/* + * data/hint flags for EVFILT_NETDEV + */ +#define NOTE_LINKUP 0x0001 /* link is up */ +#define NOTE_LINKDOWN 0x0002 /* link is down */ +#define NOTE_LINKINV 0x0004 /* link state is invalid */ + +#endif /* defined(__FreeBSD__) etc.. */ /* kqueue_t - the event descriptor */ typedef struct kqueue *kqueue_t; /* Initialize the event descriptor */ -int kq_init(kqueue_t kq); - -/* Add a new item to the list of events to be monitored */ -int kq_add(kqueue_t kq, const kevent_t *ev); +kqueue_t kq_init(); -/* Delete an item from the list of events to be monitored */ -int kq_remove(kqueue_t kq, const kevent_t *ev); +/* Free the event descriptor */ +void kq_free(kqueue_t kq); -/* Wait for an event */ -int kq_wait(kqueue_t kq, kevent_t *ev, const struct timespec *timeout); +/* Equivalent to kevent() */ +int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, + struct kevent *eventlist, int nevents, + const struct timespec *timeout); #endif /* ! _KQUEUE_LITE_H */ diff --git a/vendor/libkqueue/kqlite/test-lite.c b/vendor/libkqueue/kqlite/test-lite.c index 5ffa7a499..14c8b4ba2 100644 --- a/vendor/libkqueue/kqlite/test-lite.c +++ b/vendor/libkqueue/kqlite/test-lite.c @@ -5,6 +5,11 @@ #include int main() { + kqueue_t kq; + + kq = kq_init(); + kq_free(kq); + puts("ok"); exit(0); } From 5e77075beda335ad95ec992f93ec1ac00952fdb8 Mon Sep 17 00:00:00 2001 From: mheily Date: Fri, 18 Oct 2013 01:27:07 +0000 Subject: [PATCH 0571/1120] Checkpoint for more kqlite work git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@659 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/kqlite/kqlite.c | 108 +++++++++++--- vendor/libkqueue/kqlite/utarray.h | 232 ++++++++++++++++++++++++++++++ 2 files changed, 320 insertions(+), 20 deletions(-) create mode 100644 vendor/libkqueue/kqlite/utarray.h diff --git a/vendor/libkqueue/kqlite/kqlite.c b/vendor/libkqueue/kqlite/kqlite.c index 4263baf54..7bfd90ae1 100644 --- a/vendor/libkqueue/kqlite/kqlite.c +++ b/vendor/libkqueue/kqlite/kqlite.c @@ -15,6 +15,12 @@ */ #include "./lite.h" +#include "./utarray.h" + +/* The maximum number of events that can be returned in + a single kq_event() call + */ +#define EPEV_BUF_MAX 512 #include @@ -52,12 +58,29 @@ struct kqueue { int epfd; /* epoll */ int wfd[EVFILT_SYSCOUNT]; /* an event wait descriptor for each EVFILT_* */ sigset_t sigmask; + UT_array *kev; /* All of the active kevents */ pthread_mutex_t kq_mtx; #else #error Undefined event system #endif }; +static inline void +kq_lock(kqueue_t kq) +{ + if (pthread_mutex_lock(&kq->kq_mtx) != 0) + abort(); +} + +static inline void +kq_unlock(kqueue_t kq) +{ + if (pthread_mutex_unlock(&kq->kq_mtx) != 0) + abort(); +} + +UT_icd kevent_icd = { sizeof(struct kevent), NULL, NULL, NULL }; + /* Initialize the event descriptor */ kqueue_t kq_init(void) @@ -83,6 +106,8 @@ kq_init(void) sigemptyset(&kq->sigmask); kq->wfd[EVFILT_SIGNAL] = signalfd(-1, &kq->sigmask, 0); + utarray_new(kq->kev, &kevent_icd); + // FIXME: check that all members of kq->wfd are valid return (kq); @@ -103,6 +128,8 @@ kq_free(kqueue_t kq) #elif defined(USE_EPOLL) close(kq->epfd); + utarray_free(kq->kev); + //FIXME: there are a more things to do #endif free(kq); } @@ -118,21 +145,25 @@ kq_add(kqueue_t kq, const struct kevent *ev) struct kevent *evcopy; int sigfd; - /* Save a copy of the kevent so kq_wait() can use it later */ + /* Save a copy of the kevent so kq_event() can use it after + the event occurs. + */ evcopy = malloc(sizeof(*evcopy)); if (evcopy == NULL) return (-1); memcpy (evcopy, ev, sizeof(*evcopy)); + kq_lock(kq); + utarray_push_back(kq->kev, evcopy); + epev.data.u32 = utarray_len(kq->kev); + kq_unlock(kq); switch (ev->ident) { case EVFILT_READ: epev.events = EPOLLIN; - epev.data.ptr = evcopy; rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); case EVFILT_WRITE: epev.events = EPOLLOUT; - epev.data.ptr = evcopy; rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); case EVFILT_VNODE: @@ -141,10 +172,10 @@ kq_add(kqueue_t kq, const struct kevent *ev) break; case EVFILT_SIGNAL: - pthread_mutex_lock(&kq->kq_mtx); + kq_lock(kq); sigaddset(&kq->sigmask, ev->ident); sigfd = signalfd(kq->wfd[EVFILT_SIGNAL], &kq->sigmask, 0); - pthread_mutex_unlock(&kq->kq_mtx); + kq_unlock(kq); if (sigfd < 0) { rv = -1; } else { @@ -186,10 +217,10 @@ kq_delete(kqueue_t kq, const struct kevent *ev) break; case EVFILT_SIGNAL: - pthread_mutex_lock(&kq->kq_mtx); + kq_lock(kq); sigdelset(&kq->sigmask, ev->ident); sigfd = signalfd(kq->wfd[EVFILT_SIGNAL], &kq->sigmask, 0); - pthread_mutex_unlock(&kq->kq_mtx); + kq_unlock(kq); if (sigfd < 0) { rv = -1; } else { @@ -216,12 +247,15 @@ int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, const struct timespec *timeout) { int rv = 0; + struct kevent *kevp, *dst; #if defined(USE_KQUEUE) return kevent(kq->kqfd, changelist, nchanges, eventlist, nevents, timeout); #elif defined(USE_EPOLL) - struct epoll_event epev; + struct epoll_event epev_buf[EPEV_BUF_MAX]; + struct epoll_event *epev; + size_t epev_wait_max, epev_cnt; int i, eptimeout; /* Process each item on the changelist */ @@ -243,18 +277,52 @@ int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, else eptimeout = (1000 * timeout->tv_sec) + (timeout->tv_nsec / 1000000); - rv = epoll_wait(kq->epfd, &epev, 1, eptimeout); - //FIXME: handle timeout - if (rv > 0) { - //if (epev.data.fd == kq->sigfd) { - // FIXME: data.fd isn't actually set :( - // Special case: a signal was received - // ... - //} else { - // Normal case: data.ptr is a struct kevent (see evcopy from above) - // ... - //} - } + /* Wait for events and put them into a buffer */ + if (nevents > EPEV_BUF_MAX) { + epev_wait_max = EPEV_BUF_MAX; + } else { + epev_wait_max = nevents; + } + epev_cnt = epoll_wait(kq->epfd, (struct epoll_event *) &epev_buf, epev_wait_max, eptimeout); + if (epev_cnt < 0) { + return (-1); //FIXME: handle timeout + } + + /* Determine what events have occurred and copy the result to the caller */ + for (i = 0; i < epev_cnt; i++) { + dst = &eventlist[i]; + epev = &epev_buf[i]; + + /* + epev->data.u32 is an index into kq->kev that stores + a copy of the kevent structure. + */ + kevp = (struct kevent *) utarray_eltptr(kq->kev, epev->data.u32); + + /* Some filters require an extra level of indirection to get at + the real kevent. */ + switch (kevp->ident) { + case EVFILT_SIGNAL: + //TODO + break; + + case EVFILT_VNODE: + //TODO + break; + + case EVFILT_TIMER: + //TODO + break; + + case EVFILT_READ: + case EVFILT_WRITE: + memcpy(dst, kevp, sizeof(*dst)); + break; + + default: + abort(); + } + } return (rv == 1 ? 0 : -1); #endif diff --git a/vendor/libkqueue/kqlite/utarray.h b/vendor/libkqueue/kqlite/utarray.h new file mode 100644 index 000000000..3bb87f097 --- /dev/null +++ b/vendor/libkqueue/kqlite/utarray.h @@ -0,0 +1,232 @@ +/* +Copyright (c) 2008-2013, Troy D. Hanson http://troydhanson.github.com/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* a dynamic array implementation using macros + */ +#ifndef UTARRAY_H +#define UTARRAY_H + +#define UTARRAY_VERSION 1.9.8 + +#ifdef __GNUC__ +#define _UNUSED_ __attribute__ ((__unused__)) +#else +#define _UNUSED_ +#endif + +#include /* size_t */ +#include /* memset, etc */ +#include /* exit */ + +#define oom() exit(-1) + +typedef void (ctor_f)(void *dst, const void *src); +typedef void (dtor_f)(void *elt); +typedef void (init_f)(void *elt); +typedef struct { + size_t sz; + init_f *init; + ctor_f *copy; + dtor_f *dtor; +} UT_icd; + +typedef struct { + unsigned i,n;/* i: index of next available slot, n: num slots */ + UT_icd icd; /* initializer, copy and destructor functions */ + char *d; /* n slots of size icd->sz*/ +} UT_array; + +#define utarray_init(a,_icd) do { \ + memset(a,0,sizeof(UT_array)); \ + (a)->icd=*_icd; \ +} while(0) + +#define utarray_done(a) do { \ + if ((a)->n) { \ + if ((a)->icd.dtor) { \ + size_t _ut_i; \ + for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ + (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \ + } \ + } \ + free((a)->d); \ + } \ + (a)->n=0; \ +} while(0) + +#define utarray_new(a,_icd) do { \ + a=(UT_array*)malloc(sizeof(UT_array)); \ + utarray_init(a,_icd); \ +} while(0) + +#define utarray_free(a) do { \ + utarray_done(a); \ + free(a); \ +} while(0) + +#define utarray_reserve(a,by) do { \ + if (((a)->i+by) > ((a)->n)) { \ + while(((a)->i+by) > ((a)->n)) { (a)->n = ((a)->n ? (2*(a)->n) : 8); } \ + if ( ((a)->d=(char*)realloc((a)->d, (a)->n*(a)->icd.sz)) == NULL) oom(); \ + } \ +} while(0) + +#define utarray_push_back(a,p) do { \ + utarray_reserve(a,1); \ + if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,(a)->i++), p); } \ + else { memcpy(_utarray_eltptr(a,(a)->i++), p, (a)->icd.sz); }; \ +} while(0) + +#define utarray_pop_back(a) do { \ + if ((a)->icd.dtor) { (a)->icd.dtor( _utarray_eltptr(a,--((a)->i))); } \ + else { (a)->i--; } \ +} while(0) + +#define utarray_extend_back(a) do { \ + utarray_reserve(a,1); \ + if ((a)->icd.init) { (a)->icd.init(_utarray_eltptr(a,(a)->i)); } \ + else { memset(_utarray_eltptr(a,(a)->i),0,(a)->icd.sz); } \ + (a)->i++; \ +} while(0) + +#define utarray_len(a) ((a)->i) + +#define utarray_eltptr(a,j) (((j) < (a)->i) ? _utarray_eltptr(a,j) : NULL) +#define _utarray_eltptr(a,j) ((char*)((a)->d + ((a)->icd.sz*(j) ))) + +#define utarray_insert(a,p,j) do { \ + if (j > (a)->i) utarray_resize(a,j); \ + utarray_reserve(a,1); \ + if ((j) < (a)->i) { \ + memmove( _utarray_eltptr(a,(j)+1), _utarray_eltptr(a,j), \ + ((a)->i - (j))*((a)->icd.sz)); \ + } \ + if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,j), p); } \ + else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); }; \ + (a)->i++; \ +} while(0) + +#define utarray_inserta(a,w,j) do { \ + if (utarray_len(w) == 0) break; \ + if (j > (a)->i) utarray_resize(a,j); \ + utarray_reserve(a,utarray_len(w)); \ + if ((j) < (a)->i) { \ + memmove(_utarray_eltptr(a,(j)+utarray_len(w)), \ + _utarray_eltptr(a,j), \ + ((a)->i - (j))*((a)->icd.sz)); \ + } \ + if ((a)->icd.copy) { \ + size_t _ut_i; \ + for(_ut_i=0;_ut_i<(w)->i;_ut_i++) { \ + (a)->icd.copy(_utarray_eltptr(a,j+_ut_i), _utarray_eltptr(w,_ut_i)); \ + } \ + } else { \ + memcpy(_utarray_eltptr(a,j), _utarray_eltptr(w,0), \ + utarray_len(w)*((a)->icd.sz)); \ + } \ + (a)->i += utarray_len(w); \ +} while(0) + +#define utarray_resize(dst,num) do { \ + size_t _ut_i; \ + if (dst->i > (size_t)(num)) { \ + if ((dst)->icd.dtor) { \ + for(_ut_i=num; _ut_i < dst->i; _ut_i++) { \ + (dst)->icd.dtor(utarray_eltptr(dst,_ut_i)); \ + } \ + } \ + } else if (dst->i < (size_t)(num)) { \ + utarray_reserve(dst,num-dst->i); \ + if ((dst)->icd.init) { \ + for(_ut_i=dst->i; _ut_i < num; _ut_i++) { \ + (dst)->icd.init(utarray_eltptr(dst,_ut_i)); \ + } \ + } else { \ + memset(_utarray_eltptr(dst,dst->i),0,(dst)->icd.sz*(num-dst->i)); \ + } \ + } \ + dst->i = num; \ +} while(0) + +#define utarray_concat(dst,src) do { \ + utarray_inserta((dst),(src),utarray_len(dst)); \ +} while(0) + +#define utarray_erase(a,pos,len) do { \ + if ((a)->icd.dtor) { \ + size_t _ut_i; \ + for(_ut_i=0; _ut_i < len; _ut_i++) { \ + (a)->icd.dtor(utarray_eltptr((a),pos+_ut_i)); \ + } \ + } \ + if ((a)->i > (pos+len)) { \ + memmove( _utarray_eltptr((a),pos), _utarray_eltptr((a),pos+len), \ + (((a)->i)-(pos+len))*((a)->icd.sz)); \ + } \ + (a)->i -= (len); \ +} while(0) + +#define utarray_renew(a,u) do { \ + if (a) utarray_clear(a); \ + else utarray_new((a),(u)); \ +} while(0) + +#define utarray_clear(a) do { \ + if ((a)->i > 0) { \ + if ((a)->icd.dtor) { \ + size_t _ut_i; \ + for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ + (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \ + } \ + } \ + (a)->i = 0; \ + } \ +} while(0) + +#define utarray_sort(a,cmp) do { \ + qsort((a)->d, (a)->i, (a)->icd.sz, cmp); \ +} while(0) + +#define utarray_find(a,v,cmp) bsearch((v),(a)->d,(a)->i,(a)->icd.sz,cmp) + +#define utarray_front(a) (((a)->i) ? (_utarray_eltptr(a,0)) : NULL) +#define utarray_next(a,e) (((e)==NULL) ? utarray_front(a) : ((((a)->i) > (utarray_eltidx(a,e)+1)) ? _utarray_eltptr(a,utarray_eltidx(a,e)+1) : NULL)) +#define utarray_prev(a,e) (((e)==NULL) ? utarray_back(a) : ((utarray_eltidx(a,e) > 0) ? _utarray_eltptr(a,utarray_eltidx(a,e)-1) : NULL)) +#define utarray_back(a) (((a)->i) ? (_utarray_eltptr(a,(a)->i-1)) : NULL) +#define utarray_eltidx(a,e) (((char*)(e) >= (char*)((a)->d)) ? (((char*)(e) - (char*)((a)->d))/(ssize_t)(a)->icd.sz) : -1) + +/* last we pre-define a few icd for common utarrays of ints and strings */ +static void utarray_str_cpy(void *dst, const void *src) { + char **_src = (char**)src, **_dst = (char**)dst; + *_dst = (*_src == NULL) ? NULL : strdup(*_src); +} +static void utarray_str_dtor(void *elt) { + char **eltc = (char**)elt; + if (*eltc) free(*eltc); +} +static const UT_icd ut_str_icd _UNUSED_ = {sizeof(char*),NULL,utarray_str_cpy,utarray_str_dtor}; +static const UT_icd ut_int_icd _UNUSED_ = {sizeof(int),NULL,NULL,NULL}; +static const UT_icd ut_ptr_icd _UNUSED_ = {sizeof(void*),NULL,NULL,NULL}; + + +#endif /* UTARRAY_H */ From 9893edebf30b3f98b2dc826c804f8c998919a3bf Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 22 Oct 2013 00:52:07 +0000 Subject: [PATCH 0572/1120] kqlite: new function kq_dispatch() git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@660 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/kqlite/Makefile | 2 +- vendor/libkqueue/kqlite/kqlite.c | 84 ++++++++++++++++++++++++++++---- vendor/libkqueue/kqlite/lite.h | 3 ++ 3 files changed, 78 insertions(+), 11 deletions(-) diff --git a/vendor/libkqueue/kqlite/Makefile b/vendor/libkqueue/kqlite/Makefile index ef468edcb..fe651cb47 100644 --- a/vendor/libkqueue/kqlite/Makefile +++ b/vendor/libkqueue/kqlite/Makefile @@ -1,5 +1,5 @@ test-lite: test-lite.c kqlite.c lite.h - gcc -g -O0 -Wall -Werror -o test-lite test-lite.c kqlite.c + gcc -g -O0 -Wall -Werror -fopenmp -o test-lite test-lite.c kqlite.c check: test-lite ./test-lite diff --git a/vendor/libkqueue/kqlite/kqlite.c b/vendor/libkqueue/kqlite/kqlite.c index 7bfd90ae1..3140dc753 100644 --- a/vendor/libkqueue/kqlite/kqlite.c +++ b/vendor/libkqueue/kqlite/kqlite.c @@ -13,6 +13,10 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifdef _OPENMP +#include +#endif /* _OPENMP */ #include "./lite.h" #include "./utarray.h" @@ -32,6 +36,7 @@ #define USE_EPOLL #include #include +#include #include #include #include @@ -55,8 +60,9 @@ struct kqueue { #if defined(USE_KQUEUE) int kqfd; /* kqueue(2) descriptor */ #elif defined(USE_EPOLL) - int epfd; /* epoll */ - int wfd[EVFILT_SYSCOUNT]; /* an event wait descriptor for each EVFILT_* */ + int epfd; /* epoll */ + int inofd; /* inotify */ + int sigfd; /* signalfd */ sigset_t sigmask; UT_array *kev; /* All of the active kevents */ pthread_mutex_t kq_mtx; @@ -87,10 +93,10 @@ kq_init(void) { struct kqueue *kq; +#if defined(USE_KQUEUE) if ((kq = malloc(sizeof(*kq))) == NULL) return (NULL); -#if defined(USE_KQUEUE) kq->kqfd = kqueue(); if (kq->kqfd < 0) { free(kq); @@ -98,15 +104,47 @@ kq_init(void) } #elif defined(USE_EPOLL) + struct epoll_event epev; + struct kevent *kev; + + if ((kq = malloc(sizeof(*kq))) == NULL) + return (NULL); + if (pthread_mutex_init(&kq->kq_mtx, NULL) != 0) goto errout; + + /* Create an index of kevents to allow lookups from epev.data.u32 */ + utarray_new(kq->kev, &kevent_icd); + + /* Initialize all the event descriptors */ + sigemptyset(&kq->sigmask); + kq->sigfd = signalfd(-1, &kq->sigmask, 0); + kq->inofd = inotify_init(); kq->epfd = epoll_create(10); - if (kq->epfd < 0) + if (kq->sigfd < 0 || kq->inofd < 0 || kq->epfd < 0) goto errout; - sigemptyset(&kq->sigmask); - kq->wfd[EVFILT_SIGNAL] = signalfd(-1, &kq->sigmask, 0); - utarray_new(kq->kev, &kevent_icd); + /* Add the signalfd descriptor to the epollset */ + if ((kev = malloc(sizeof(*kev))) == NULL) + goto errout; + EV_SET(kev, 0, EVFILT_SIGNAL, 0, 0, 0, NULL); + epev.events = EPOLLIN; + epev.data.u32 = 0; + utarray_push_back(kq->kev, kev); + if (epoll_ctl(kq->epfd, EPOLL_CTL_ADD, kq->sigfd, &epev) < 0) + goto errout; + + /* Add the inotify descriptor to the epollset */ + if ((kev = malloc(sizeof(*kev))) == NULL) + goto errout; + EV_SET(kev, 0, EVFILT_VNODE, 0, 0, 0, NULL); + epev.events = EPOLLIN; + epev.data.u32 = 1; + utarray_push_back(kq->kev, kev); + if (epoll_ctl(kq->epfd, EPOLL_CTL_ADD, kq->inofd, &epev) < 0) + goto errout; + + //TODO: consider applying FD_CLOEXEC to all descriptors // FIXME: check that all members of kq->wfd are valid @@ -167,14 +205,15 @@ kq_add(kqueue_t kq, const struct kevent *ev) rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); case EVFILT_VNODE: - //TODO: create an inotifyfd, create an epollfd, add the inotifyfd to the epollfd, set epollfd.data.ptr = evcopy, add epollfd to kq->epfd. + epev.events = EPOLLIN; + rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); rv = -1; break; case EVFILT_SIGNAL: kq_lock(kq); sigaddset(&kq->sigmask, ev->ident); - sigfd = signalfd(kq->wfd[EVFILT_SIGNAL], &kq->sigmask, 0); + sigfd = signalfd(kq->sigfd, &kq->sigmask, 0); kq_unlock(kq); if (sigfd < 0) { rv = -1; @@ -219,7 +258,7 @@ kq_delete(kqueue_t kq, const struct kevent *ev) case EVFILT_SIGNAL: kq_lock(kq); sigdelset(&kq->sigmask, ev->ident); - sigfd = signalfd(kq->wfd[EVFILT_SIGNAL], &kq->sigmask, 0); + sigfd = signalfd(kq->sigfd, &kq->sigmask, 0); kq_unlock(kq); if (sigfd < 0) { rv = -1; @@ -327,3 +366,28 @@ int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, return (rv == 1 ? 0 : -1); #endif } + +/* + * EXPERIMENTAL dispatching API + */ +void +kq_dispatch(kqueue_t kq, void (*cb)(kqueue_t, struct kevent)) +{ + const int maxevents = 64; /* Should be more like 2xNCPU */ + struct kevent events[maxevents]; + ssize_t nevents; + int i; + + for (;;) { + nevents = kq_event(kq, NULL, 0, (struct kevent *) &events, maxevents, NULL); + if (nevents < 0) + abort(); + #pragma omp parallel + { + for (i = 0; i < nevents; i++) { + #pragma omp single nowait + (*cb)(kq, events[i]); + } + } + } +} diff --git a/vendor/libkqueue/kqlite/lite.h b/vendor/libkqueue/kqlite/lite.h index 5e8a4d529..45b232ad9 100644 --- a/vendor/libkqueue/kqlite/lite.h +++ b/vendor/libkqueue/kqlite/lite.h @@ -150,4 +150,7 @@ int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); +/* Dispatch kevents using multiple threads */ +void kq_dispatch(kqueue_t, void (*)(kqueue_t, struct kevent)); + #endif /* ! _KQUEUE_LITE_H */ From f55a74178d722583f09b13fd7bd7b51d9d42401d Mon Sep 17 00:00:00 2001 From: mheily Date: Tue, 22 Oct 2013 01:42:22 +0000 Subject: [PATCH 0573/1120] kqlite: checkpoint git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@661 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/kqlite/kqlite.c | 104 +++++++++++++++++++++------- vendor/libkqueue/kqlite/lite.h | 8 +++ vendor/libkqueue/kqlite/test-lite.c | 20 ++++++ 3 files changed, 108 insertions(+), 24 deletions(-) diff --git a/vendor/libkqueue/kqlite/kqlite.c b/vendor/libkqueue/kqlite/kqlite.c index 3140dc753..4e747e778 100644 --- a/vendor/libkqueue/kqlite/kqlite.c +++ b/vendor/libkqueue/kqlite/kqlite.c @@ -14,6 +14,10 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include + + #ifdef _OPENMP #include #endif /* _OPENMP */ @@ -28,6 +32,11 @@ #include +/* Debugging macros */ +#define dbg_puts(s) dbg_printf("%s", (s)) +#define dbg_printf(fmt,...) fprintf(stderr, "kq [%d]: %s(): "fmt"\n", \ + 0 /*TODO: thread id */, __func__, __VA_ARGS__) + /* Determine what type of kernel event system to use. */ #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) #define USE_KQUEUE @@ -41,21 +50,12 @@ #include #include #include + +static char * epoll_event_to_str(struct epoll_event *); #else #error Unsupported operating system type #endif - -/* Linux supports a subset of these filters. */ -#if defined(USE_EPOLL) -#define EVFILT_READ (0) -#define EVFILT_WRITE (1) -#define EVFILT_VNODE (2) -#define EVFILT_SIGNAL (3) -#define EVFILT_TIMER (4) -#define EVFILT_SYSCOUNT (5) -#endif - struct kqueue { #if defined(USE_KQUEUE) int kqfd; /* kqueue(2) descriptor */ @@ -63,6 +63,7 @@ struct kqueue { int epfd; /* epoll */ int inofd; /* inotify */ int sigfd; /* signalfd */ + UT_array *sighandler; /* All of the active kevents for EVFILT_SIGNAL */ sigset_t sigmask; UT_array *kev; /* All of the active kevents */ pthread_mutex_t kq_mtx; @@ -115,6 +116,7 @@ kq_init(void) /* Create an index of kevents to allow lookups from epev.data.u32 */ utarray_new(kq->kev, &kevent_icd); + utarray_new(kq->sighandler, &kevent_icd); /* Initialize all the event descriptors */ sigemptyset(&kq->sigmask); @@ -127,22 +129,24 @@ kq_init(void) /* Add the signalfd descriptor to the epollset */ if ((kev = malloc(sizeof(*kev))) == NULL) goto errout; - EV_SET(kev, 0, EVFILT_SIGNAL, 0, 0, 0, NULL); + EV_SET(kev, EVFILT_SIGNAL, EVFILT_SIGNAL, 0, 0, 0, NULL); epev.events = EPOLLIN; - epev.data.u32 = 0; + epev.data.u32 = EVFILT_SIGNAL; utarray_push_back(kq->kev, kev); if (epoll_ctl(kq->epfd, EPOLL_CTL_ADD, kq->sigfd, &epev) < 0) goto errout; /* Add the inotify descriptor to the epollset */ + /* if ((kev = malloc(sizeof(*kev))) == NULL) goto errout; - EV_SET(kev, 0, EVFILT_VNODE, 0, 0, 0, NULL); + EV_SET(kev, EVFILT_VNODE, EVFILT_VNODE, 0, 0, 0, NULL); epev.events = EPOLLIN; epev.data.u32 = 1; utarray_push_back(kq->kev, kev); if (epoll_ctl(kq->epfd, EPOLL_CTL_ADD, kq->inofd, &epev) < 0) goto errout; + */ //TODO: consider applying FD_CLOEXEC to all descriptors @@ -195,7 +199,7 @@ kq_add(kqueue_t kq, const struct kevent *ev) epev.data.u32 = utarray_len(kq->kev); kq_unlock(kq); - switch (ev->ident) { + switch (ev->filter) { case EVFILT_READ: epev.events = EPOLLIN; rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); @@ -220,6 +224,7 @@ kq_add(kqueue_t kq, const struct kevent *ev) } else { rv = 0; } + dbg_printf("added signal %d, rv = %d", (int)ev->ident, rv); break; case EVFILT_TIMER: @@ -232,6 +237,7 @@ kq_add(kqueue_t kq, const struct kevent *ev) return (-1); } + dbg_printf("done. rv = %d", rv); // if (rv < 0) // free(evcopy); return (rv); @@ -280,6 +286,25 @@ kq_delete(kqueue_t kq, const struct kevent *ev) #endif /* defined(USE_EPOLL) */ +/* Read a signal from the signalfd */ +static inline int +_get_signal(struct kevent *dst, kqueue_t kq) +{ + struct kevent *kev; + struct signalfd_siginfo sig; + ssize_t n; + + n = read(kq->sigfd, &sig, sizeof(sig)); + if (n < 0 || n != sizeof(sig)) { + abort(); + } + + kev = (struct kevent *) utarray_eltptr(kq->sighandler, sig.ssi_signo); + memcpy(dst, kev, sizeof(*dst)); + + return (0); +} + /* Equivalent to kevent() */ int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, @@ -322,27 +347,30 @@ int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, } else { epev_wait_max = nevents; } - epev_cnt = epoll_wait(kq->epfd, (struct epoll_event *) &epev_buf, epev_wait_max, eptimeout); + epev_cnt = epoll_wait(kq->epfd, (struct epoll_event *) &epev_buf[0], epev_wait_max, eptimeout); if (epev_cnt < 0) { return (-1); //FIXME: handle timeout } + else if (epev_cnt == 0) { + dbg_puts("timed out"); + } + + dbg_puts("whee -- got event"); /* Determine what events have occurred and copy the result to the caller */ for (i = 0; i < epev_cnt; i++) { dst = &eventlist[i]; epev = &epev_buf[i]; - /* - epev->data.u32 is an index into kq->kev that stores - a copy of the kevent structure. - */ + dbg_printf("got event: %s", epoll_event_to_str(epev)); + abort(); + + //FIXME: old design: kevp = (struct kevent *) utarray_eltptr(kq->kev, epev->data.u32); - /* Some filters require an extra level of indirection to get at - the real kevent. */ - switch (kevp->ident) { + switch (epev->data.u32) { case EVFILT_SIGNAL: - //TODO + (void)_get_signal(dst, kq);//FIXME: errorhandle break; case EVFILT_VNODE: @@ -391,3 +419,31 @@ kq_dispatch(kqueue_t kq, void (*cb)(kqueue_t, struct kevent)) } } } + +#if defined(USE_EPOLL) +static char * +epoll_event_to_str(struct epoll_event *evt) +{ + static __thread char buf[128]; + + if (evt == NULL) + return "(null)"; + +#define EPEVT_DUMP(attrib) \ + if (evt->events & attrib) \ + strcat(&buf[0], #attrib" "); + + snprintf(&buf[0], 128, " { data = %p, events = ", evt->data.ptr); + EPEVT_DUMP(EPOLLIN); + EPEVT_DUMP(EPOLLOUT); +#if defined(HAVE_EPOLLRDHUP) + EPEVT_DUMP(EPOLLRDHUP); +#endif + EPEVT_DUMP(EPOLLONESHOT); + EPEVT_DUMP(EPOLLET); + strcat(&buf[0], "}\n"); + + return (&buf[0]); +#undef EPEVT_DUMP +} +#endif diff --git a/vendor/libkqueue/kqlite/lite.h b/vendor/libkqueue/kqlite/lite.h index 45b232ad9..2e368cd6e 100644 --- a/vendor/libkqueue/kqlite/lite.h +++ b/vendor/libkqueue/kqlite/lite.h @@ -134,6 +134,14 @@ struct kevent { #define NOTE_LINKDOWN 0x0002 /* link is down */ #define NOTE_LINKINV 0x0004 /* link state is invalid */ +/* Linux supports a subset of these filters. */ +#define EVFILT_READ (0) +#define EVFILT_WRITE (1) +#define EVFILT_VNODE (2) +#define EVFILT_SIGNAL (3) +#define EVFILT_TIMER (4) +#define EVFILT_SYSCOUNT (5) + #endif /* defined(__FreeBSD__) etc.. */ /* kqueue_t - the event descriptor */ diff --git a/vendor/libkqueue/kqlite/test-lite.c b/vendor/libkqueue/kqlite/test-lite.c index 14c8b4ba2..5b214341f 100644 --- a/vendor/libkqueue/kqlite/test-lite.c +++ b/vendor/libkqueue/kqlite/test-lite.c @@ -2,12 +2,32 @@ #include #include +#include #include +void install_sighandler(kqueue_t kq) { + struct kevent kev; + + signal(SIGUSR1, SIG_IGN); + + EV_SET(&kev, SIGINT, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, NULL); + kq_event(kq, &kev, 1, 0, 0, NULL); + puts("installed SIGUSR1 handler"); + + if (kill(getpid(), SIGUSR1) < 0) + abort(); + + /* wait for the event */ + puts("waiting for SIGUSR1"); + kq_event(kq, NULL, 0, &kev, 1, NULL); + puts ("got it"); +} + int main() { kqueue_t kq; kq = kq_init(); + install_sighandler(kq); kq_free(kq); puts("ok"); From a8b10e82ee12855ffdfc2444b37d89d3a55cf274 Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 26 Oct 2013 02:11:00 +0000 Subject: [PATCH 0574/1120] kqlite: checkpoint git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@662 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/kqlite/Makefile | 2 +- vendor/libkqueue/kqlite/kqlite.c | 142 ++++++++++++++++++++-------- vendor/libkqueue/kqlite/test-lite.c | 34 ++++++- 3 files changed, 135 insertions(+), 43 deletions(-) diff --git a/vendor/libkqueue/kqlite/Makefile b/vendor/libkqueue/kqlite/Makefile index fe651cb47..ca87913d0 100644 --- a/vendor/libkqueue/kqlite/Makefile +++ b/vendor/libkqueue/kqlite/Makefile @@ -1,5 +1,5 @@ test-lite: test-lite.c kqlite.c lite.h - gcc -g -O0 -Wall -Werror -fopenmp -o test-lite test-lite.c kqlite.c + gcc -D_GNU_SOURCE=1 -g -O0 -std=c99 -Wall -Werror -fopenmp -o test-lite test-lite.c kqlite.c check: test-lite ./test-lite diff --git a/vendor/libkqueue/kqlite/kqlite.c b/vendor/libkqueue/kqlite/kqlite.c index 4e747e778..09a34abda 100644 --- a/vendor/libkqueue/kqlite/kqlite.c +++ b/vendor/libkqueue/kqlite/kqlite.c @@ -14,10 +14,11 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include #include #include - #ifdef _OPENMP #include #endif /* _OPENMP */ @@ -63,15 +64,31 @@ struct kqueue { int epfd; /* epoll */ int inofd; /* inotify */ int sigfd; /* signalfd */ - UT_array *sighandler; /* All of the active kevents for EVFILT_SIGNAL */ + int readfd, writefd; /* epoll descriptors for EVFILT_READ & EVFILT_WRITE */ sigset_t sigmask; - UT_array *kev; /* All of the active kevents */ + /* All of the active knotes for each filter. The index in the array matches + the 'ident' parameter of the 'struct kevent' in the knote. + */ + UT_array *knote[EVFILT_SYSCOUNT]; pthread_mutex_t kq_mtx; #else #error Undefined event system #endif }; +/* A knote is used to store information about a kevent while it is + being monitored. Once it fires, information from the knote is returned + to the caller. + */ +struct knote { + struct kevent kev; + union { + int timerfd; /* Each EVFILT_TIMER kevent has a timerfd */ + int inofd; /* Each EVFILT_VNODE kevent has an inotify fd */ + } aux; + int deleted; /* When EV_DELETE is used, it marks the knote deleted instead of freeing the object. This helps with threadsafety by ensuring that threads don't try to access a freed object. It doesn't help with memory usage, as the memory is never reclaimed. */ +}; + static inline void kq_lock(kqueue_t kq) { @@ -86,7 +103,7 @@ kq_unlock(kqueue_t kq) abort(); } -UT_icd kevent_icd = { sizeof(struct kevent), NULL, NULL, NULL }; +UT_icd knote_icd = { sizeof(struct knote), NULL, NULL, NULL }; /* Initialize the event descriptor */ kqueue_t @@ -106,7 +123,6 @@ kq_init(void) #elif defined(USE_EPOLL) struct epoll_event epev; - struct kevent *kev; if ((kq = malloc(sizeof(*kq))) == NULL) return (NULL); @@ -115,27 +131,40 @@ kq_init(void) goto errout; /* Create an index of kevents to allow lookups from epev.data.u32 */ - utarray_new(kq->kev, &kevent_icd); - utarray_new(kq->sighandler, &kevent_icd); + + for (int i = 0; i < EVFILT_SYSCOUNT; i++) + utarray_new(kq->knote[i], &knote_icd); /* Initialize all the event descriptors */ sigemptyset(&kq->sigmask); + kq->sigfd = kq->inofd = kq->epfd = kq->readfd = kq->writefd = -1; kq->sigfd = signalfd(-1, &kq->sigmask, 0); kq->inofd = inotify_init(); kq->epfd = epoll_create(10); - if (kq->sigfd < 0 || kq->inofd < 0 || kq->epfd < 0) + kq->readfd = epoll_create(10); + kq->writefd = epoll_create(10); + if (kq->sigfd < 0 || kq->inofd < 0 || kq->epfd < 0 + || kq->readfd < 0 || kq->writefd < 0) goto errout; /* Add the signalfd descriptor to the epollset */ - if ((kev = malloc(sizeof(*kev))) == NULL) - goto errout; - EV_SET(kev, EVFILT_SIGNAL, EVFILT_SIGNAL, 0, 0, 0, NULL); epev.events = EPOLLIN; epev.data.u32 = EVFILT_SIGNAL; - utarray_push_back(kq->kev, kev); if (epoll_ctl(kq->epfd, EPOLL_CTL_ADD, kq->sigfd, &epev) < 0) goto errout; + /* Add the readfd descriptor to the epollset */ + epev.events = EPOLLIN; + epev.data.u32 = EVFILT_READ; + if (epoll_ctl(kq->epfd, EPOLL_CTL_ADD, kq->readfd, &epev) < 0) + goto errout; + + /* Add the writefd descriptor to the epollset */ + epev.events = EPOLLIN; + epev.data.u32 = EVFILT_WRITE; + if (epoll_ctl(kq->epfd, EPOLL_CTL_ADD, kq->writefd, &epev) < 0) + goto errout; + /* Add the inotify descriptor to the epollset */ /* if ((kev = malloc(sizeof(*kev))) == NULL) @@ -157,6 +186,9 @@ kq_init(void) errout: free(kq); if (kq->epfd >= 0) close(kq->epfd); + if (kq->readfd >= 0) close(kq->readfd); + if (kq->writefd >= 0) close(kq->writefd); + if (kq->sigfd >= 0) close(kq->sigfd); //FIXME: something like: if (kq->wfd[EVFILT_SIGNAL] >= 0) free(kq->epfd); return (NULL); #endif @@ -170,7 +202,9 @@ kq_free(kqueue_t kq) #elif defined(USE_EPOLL) close(kq->epfd); - utarray_free(kq->kev); + //FIXME: need to free each individual knote + for (int i = 0; i < EVFILT_SYSCOUNT; i++) + utarray_free(kq->knote[i]); //FIXME: there are a more things to do #endif free(kq); @@ -178,35 +212,62 @@ kq_free(kqueue_t kq) #if defined(USE_EPOLL) +/* Create a knote object */ +static int +knote_add(kqueue_t kq, const struct kevent *kev) +{ + struct knote *kn; + + assert(kev->filter < EVFILT_SYSCOUNT); + + kn = malloc(sizeof(*kn)); + if (kn == NULL) + return (-1); + memcpy (&kn->kev, kev, sizeof(kn->kev)); + + kq_lock(kq); + utarray_insert(kq->knote[kev->filter], kn, kev->ident); + kq_unlock(kq); + + return (0); +} + +/* Lookup a 'struct kevent' that was previously stored in a knote object */ +static struct knote * +knote_lookup(kqueue_t kq, short filter, uint32_t ident) +{ + struct knote *p; + + kq_lock(kq); + p = (struct knote *) utarray_eltptr(kq->knote[filter], ident); + //TODO: refcounting + kq_unlock(kq); + + return (p); +} + /* Add a new item to the list of events to be monitored */ static inline int kq_add(kqueue_t kq, const struct kevent *ev) { int rv = 0; struct epoll_event epev; - struct kevent *evcopy; int sigfd; - /* Save a copy of the kevent so kq_event() can use it after - the event occurs. - */ - evcopy = malloc(sizeof(*evcopy)); - if (evcopy == NULL) - return (-1); - memcpy (evcopy, ev, sizeof(*evcopy)); - kq_lock(kq); - utarray_push_back(kq->kev, evcopy); - epev.data.u32 = utarray_len(kq->kev); - kq_unlock(kq); + epev.data.u32 = ev->filter; + if (knote_add(kq, ev) < 0) + abort(); //TODO: errorhandle switch (ev->filter) { case EVFILT_READ: epev.events = EPOLLIN; - rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); + rv = epoll_ctl(kq->readfd, EPOLL_CTL_ADD, ev->ident, &epev); + break; case EVFILT_WRITE: epev.events = EPOLLOUT; - rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); + rv = epoll_ctl(kq->writefd, EPOLL_CTL_ADD, ev->ident, &epev); + break; case EVFILT_VNODE: epev.events = EPOLLIN; @@ -237,6 +298,10 @@ kq_add(kqueue_t kq, const struct kevent *ev) return (-1); } + if (rv < 0) { + dbg_printf("failed; errno = %s", strerror(errno)); + } + dbg_printf("done. rv = %d", rv); // if (rv < 0) // free(evcopy); @@ -290,7 +355,7 @@ kq_delete(kqueue_t kq, const struct kevent *ev) static inline int _get_signal(struct kevent *dst, kqueue_t kq) { - struct kevent *kev; + struct knote *kn; struct signalfd_siginfo sig; ssize_t n; @@ -299,8 +364,8 @@ _get_signal(struct kevent *dst, kqueue_t kq) abort(); } - kev = (struct kevent *) utarray_eltptr(kq->sighandler, sig.ssi_signo); - memcpy(dst, kev, sizeof(*dst)); + kn = knote_lookup(kq, EVFILT_SIGNAL, sig.ssi_signo); + memcpy(dst, &kn->kev, sizeof(*dst)); return (0); } @@ -311,7 +376,8 @@ int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, const struct timespec *timeout) { int rv = 0; - struct kevent *kevp, *dst; + struct kevent *dst; + //struct knote *kn; #if defined(USE_KQUEUE) return kevent(kq->kqfd, changelist, nchanges, eventlist, nevents, timeout); @@ -319,8 +385,8 @@ int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, #elif defined(USE_EPOLL) struct epoll_event epev_buf[EPEV_BUF_MAX]; struct epoll_event *epev; - size_t epev_wait_max, epev_cnt; - int i, eptimeout; + size_t epev_wait_max; + int i, epev_cnt, eptimeout; /* Process each item on the changelist */ for (i = 0; i < nchanges; i++) { @@ -347,7 +413,7 @@ int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, } else { epev_wait_max = nevents; } - epev_cnt = epoll_wait(kq->epfd, (struct epoll_event *) &epev_buf[0], epev_wait_max, eptimeout); + epev_cnt = epoll_wait(kq->epfd, &epev_buf[0], epev_wait_max, eptimeout); if (epev_cnt < 0) { return (-1); //FIXME: handle timeout } @@ -355,7 +421,7 @@ int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, dbg_puts("timed out"); } - dbg_puts("whee -- got event"); + dbg_printf("whee -- got %d event(s)", epev_cnt); /* Determine what events have occurred and copy the result to the caller */ for (i = 0; i < epev_cnt; i++) { @@ -363,10 +429,6 @@ int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, epev = &epev_buf[i]; dbg_printf("got event: %s", epoll_event_to_str(epev)); - abort(); - - //FIXME: old design: - kevp = (struct kevent *) utarray_eltptr(kq->kev, epev->data.u32); switch (epev->data.u32) { case EVFILT_SIGNAL: @@ -383,7 +445,7 @@ int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, case EVFILT_READ: case EVFILT_WRITE: - memcpy(dst, kevp, sizeof(*dst)); + //memcpy(dst, kevp, sizeof(*dst)); break; default: diff --git a/vendor/libkqueue/kqlite/test-lite.c b/vendor/libkqueue/kqlite/test-lite.c index 5b214341f..378bab854 100644 --- a/vendor/libkqueue/kqlite/test-lite.c +++ b/vendor/libkqueue/kqlite/test-lite.c @@ -1,16 +1,45 @@ #include "./lite.h" +#include #include #include #include +#include +#include #include + +void test_evfilt_write(kqueue_t kq) { + struct kevent kev; + int sockfd[2]; + + puts("testing EVFILT_WRITE.. "); + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) + abort(); + + EV_SET(&kev, sockfd[1], EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0, NULL); + kq_event(kq, &kev, 1, 0, 0, NULL); + puts("installed EVFILT_WRITE handler"); + + if (write(sockfd[0], "hi", 2) < 2) + abort(); + + /* wait for the event */ + puts("waiting for event"); + kq_event(kq, NULL, 0, &kev, 1, NULL); + puts ("got it"); + + close(sockfd[0]); + close(sockfd[1]); +} + void install_sighandler(kqueue_t kq) { struct kevent kev; signal(SIGUSR1, SIG_IGN); - EV_SET(&kev, SIGINT, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, NULL); + EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, NULL); kq_event(kq, &kev, 1, 0, 0, NULL); puts("installed SIGUSR1 handler"); @@ -27,7 +56,8 @@ int main() { kqueue_t kq; kq = kq_init(); - install_sighandler(kq); + //install_sighandler(kq); + test_evfilt_write(kq); kq_free(kq); puts("ok"); From a010d74dcbb1d7065ac90db9dfeb52a23e848d35 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 20 Nov 2013 02:07:58 +0000 Subject: [PATCH 0575/1120] Remove the dependency on pthreads, and move dispatching to a separate translation unit git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@663 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/kqlite/Makefile | 9 +++++- vendor/libkqueue/kqlite/dispatch.c | 47 +++++++++++++++++++++++++++ vendor/libkqueue/kqlite/kqlite.c | 52 ++++++++++++------------------ 3 files changed, 76 insertions(+), 32 deletions(-) create mode 100644 vendor/libkqueue/kqlite/dispatch.c diff --git a/vendor/libkqueue/kqlite/Makefile b/vendor/libkqueue/kqlite/Makefile index ca87913d0..dbdde88ee 100644 --- a/vendor/libkqueue/kqlite/Makefile +++ b/vendor/libkqueue/kqlite/Makefile @@ -1,5 +1,12 @@ test-lite: test-lite.c kqlite.c lite.h - gcc -D_GNU_SOURCE=1 -g -O0 -std=c99 -Wall -Werror -fopenmp -o test-lite test-lite.c kqlite.c + gcc -D_GNU_SOURCE=1 -g -O0 -std=c99 -Wall -Werror -o test-lite test-lite.c kqlite.c + +#TODO: +test-dispatch: test-dispatch.c lite.h + gcc -D_GNU_SOURCE=1 -g -O0 -std=c99 -Wall -Werror -fopenmp -o test-dispatch kqlite.c test-dispatch.c dispatch.c check: test-lite ./test-lite + +clean: + rm -f test-lite *.o diff --git a/vendor/libkqueue/kqlite/dispatch.c b/vendor/libkqueue/kqlite/dispatch.c new file mode 100644 index 000000000..0ccc8cee0 --- /dev/null +++ b/vendor/libkqueue/kqlite/dispatch.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#ifdef _OPENMP +#include +#endif /* _OPENMP */ + +/* + * EXPERIMENTAL dispatching API + */ +void +kq_dispatch(kqueue_t kq, void (*cb)(kqueue_t, struct kevent)) +{ + const int maxevents = 64; /* Should be more like 2xNCPU */ + struct kevent events[maxevents]; + ssize_t nevents; + int i; + + for (;;) { + nevents = kq_event(kq, NULL, 0, (struct kevent *) &events, maxevents, NULL); + if (nevents < 0) + abort(); + #pragma omp parallel + { + for (i = 0; i < nevents; i++) { + #pragma omp single nowait + (*cb)(kq, events[i]); + } + } + } +} + diff --git a/vendor/libkqueue/kqlite/kqlite.c b/vendor/libkqueue/kqlite/kqlite.c index 09a34abda..9121735b9 100644 --- a/vendor/libkqueue/kqlite/kqlite.c +++ b/vendor/libkqueue/kqlite/kqlite.c @@ -19,10 +19,6 @@ #include #include -#ifdef _OPENMP -#include -#endif /* _OPENMP */ - #include "./lite.h" #include "./utarray.h" @@ -44,7 +40,6 @@ #include #elif defined(__linux__) #define USE_EPOLL -#include #include #include #include @@ -52,6 +47,10 @@ #include #include +#ifdef KQ_THREADSAFE +#include +#endif + static char * epoll_event_to_str(struct epoll_event *); #else #error Unsupported operating system type @@ -70,7 +69,17 @@ struct kqueue { the 'ident' parameter of the 'struct kevent' in the knote. */ UT_array *knote[EVFILT_SYSCOUNT]; + + /* This allows all kevents to share a single inotify descriptor. + * Key: inotify watch descriptor returned by inotify_add_watch() + * Value: pointer to knote + */ + UT_array *ino_knote; + +#ifdef KQ_THREADSAFE pthread_mutex_t kq_mtx; +#endif + #else #error Undefined event system #endif @@ -84,7 +93,7 @@ struct knote { struct kevent kev; union { int timerfd; /* Each EVFILT_TIMER kevent has a timerfd */ - int inofd; /* Each EVFILT_VNODE kevent has an inotify fd */ + int ino_wd; /* EVFILT_VNODE: index within kq->ino_knote */ } aux; int deleted; /* When EV_DELETE is used, it marks the knote deleted instead of freeing the object. This helps with threadsafety by ensuring that threads don't try to access a freed object. It doesn't help with memory usage, as the memory is never reclaimed. */ }; @@ -92,15 +101,19 @@ struct knote { static inline void kq_lock(kqueue_t kq) { +#ifdef KQ_THREADSAFE if (pthread_mutex_lock(&kq->kq_mtx) != 0) abort(); +#endif } static inline void kq_unlock(kqueue_t kq) { +#ifdef KQ_THREADSAFE if (pthread_mutex_unlock(&kq->kq_mtx) != 0) abort(); +#endif } UT_icd knote_icd = { sizeof(struct knote), NULL, NULL, NULL }; @@ -127,8 +140,10 @@ kq_init(void) if ((kq = malloc(sizeof(*kq))) == NULL) return (NULL); +#ifdef KQ_THREADSAFE if (pthread_mutex_init(&kq->kq_mtx, NULL) != 0) goto errout; +#endif /* Create an index of kevents to allow lookups from epev.data.u32 */ @@ -457,31 +472,6 @@ int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, #endif } -/* - * EXPERIMENTAL dispatching API - */ -void -kq_dispatch(kqueue_t kq, void (*cb)(kqueue_t, struct kevent)) -{ - const int maxevents = 64; /* Should be more like 2xNCPU */ - struct kevent events[maxevents]; - ssize_t nevents; - int i; - - for (;;) { - nevents = kq_event(kq, NULL, 0, (struct kevent *) &events, maxevents, NULL); - if (nevents < 0) - abort(); - #pragma omp parallel - { - for (i = 0; i < nevents; i++) { - #pragma omp single nowait - (*cb)(kq, events[i]); - } - } - } -} - #if defined(USE_EPOLL) static char * epoll_event_to_str(struct epoll_event *evt) From b60866c51137e5dda28cdb7c43cf68cb2976919a Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 22 Jan 2014 04:02:58 +0000 Subject: [PATCH 0576/1120] kqlite: fix the signal handling test git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@664 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/kqlite/kqlite.c | 3 +++ vendor/libkqueue/kqlite/test-lite.c | 11 ++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/kqlite/kqlite.c b/vendor/libkqueue/kqlite/kqlite.c index 9121735b9..c3b1d3095 100644 --- a/vendor/libkqueue/kqlite/kqlite.c +++ b/vendor/libkqueue/kqlite/kqlite.c @@ -47,6 +47,9 @@ #include #include +//XXX - TEMPORARY DURING DEVELOPMENT +#define KQ_THREADSAFE 1 + #ifdef KQ_THREADSAFE #include #endif diff --git a/vendor/libkqueue/kqlite/test-lite.c b/vendor/libkqueue/kqlite/test-lite.c index 378bab854..8e705a202 100644 --- a/vendor/libkqueue/kqlite/test-lite.c +++ b/vendor/libkqueue/kqlite/test-lite.c @@ -34,10 +34,15 @@ void test_evfilt_write(kqueue_t kq) { close(sockfd[1]); } -void install_sighandler(kqueue_t kq) { +void test_evfilt_signal(kqueue_t kq) { struct kevent kev; + sigset_t mask; - signal(SIGUSR1, SIG_IGN); + /* Block the normal signal handler mechanism */ + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) + abort(); EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, NULL); kq_event(kq, &kev, 1, 0, 0, NULL); @@ -56,7 +61,7 @@ int main() { kqueue_t kq; kq = kq_init(); - //install_sighandler(kq); + test_evfilt_signal(kq); test_evfilt_write(kq); kq_free(kq); From cb24be2bfa08687165b53a620b6525b017340572 Mon Sep 17 00:00:00 2001 From: mheily Date: Wed, 22 Jan 2014 04:30:45 +0000 Subject: [PATCH 0577/1120] kqlite: add initial timerfd support git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@665 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/kqlite/kqlite.c | 27 +++++++++++++++++---------- vendor/libkqueue/kqlite/test-lite.c | 17 ++++++++++++++++- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/vendor/libkqueue/kqlite/kqlite.c b/vendor/libkqueue/kqlite/kqlite.c index c3b1d3095..f3f830647 100644 --- a/vendor/libkqueue/kqlite/kqlite.c +++ b/vendor/libkqueue/kqlite/kqlite.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -66,6 +67,7 @@ struct kqueue { int epfd; /* epoll */ int inofd; /* inotify */ int sigfd; /* signalfd */ + int timefd; /* timerfd */ int readfd, writefd; /* epoll descriptors for EVFILT_READ & EVFILT_WRITE */ sigset_t sigmask; /* All of the active knotes for each filter. The index in the array matches @@ -128,7 +130,7 @@ kq_init(void) struct kqueue *kq; #if defined(USE_KQUEUE) - if ((kq = malloc(sizeof(*kq))) == NULL) + if ((kq = calloc(1, sizeof(*kq))) == NULL) return (NULL); kq->kqfd = kqueue(); @@ -155,14 +157,14 @@ kq_init(void) /* Initialize all the event descriptors */ sigemptyset(&kq->sigmask); - kq->sigfd = kq->inofd = kq->epfd = kq->readfd = kq->writefd = -1; kq->sigfd = signalfd(-1, &kq->sigmask, 0); kq->inofd = inotify_init(); kq->epfd = epoll_create(10); kq->readfd = epoll_create(10); kq->writefd = epoll_create(10); + kq->timefd = timerfd_create(CLOCK_MONOTONIC, 0); if (kq->sigfd < 0 || kq->inofd < 0 || kq->epfd < 0 - || kq->readfd < 0 || kq->writefd < 0) + || kq->readfd < 0 || kq->writefd < 0 || kq->timefd < 0) goto errout; /* Add the signalfd descriptor to the epollset */ @@ -202,12 +204,7 @@ kq_init(void) return (kq); errout: - free(kq); - if (kq->epfd >= 0) close(kq->epfd); - if (kq->readfd >= 0) close(kq->readfd); - if (kq->writefd >= 0) close(kq->writefd); - if (kq->sigfd >= 0) close(kq->sigfd); - //FIXME: something like: if (kq->wfd[EVFILT_SIGNAL] >= 0) free(kq->epfd); + kq_free(kq); return (NULL); #endif } @@ -219,11 +216,21 @@ kq_free(kqueue_t kq) close(kq.kqfd); #elif defined(USE_EPOLL) + close(kq->sigfd); + close(kq->inofd); close(kq->epfd); + close(kq->readfd); + close(kq->writefd); + close(kq->timefd); + //FIXME: need to free each individual knote for (int i = 0; i < EVFILT_SYSCOUNT; i++) utarray_free(kq->knote[i]); - //FIXME: there are a more things to do + +# ifdef KQ_THREADSAFE + pthread_mutex_destroy(&kq->kq_mtx); +# endif + #endif free(kq); } diff --git a/vendor/libkqueue/kqlite/test-lite.c b/vendor/libkqueue/kqlite/test-lite.c index 8e705a202..d26119588 100644 --- a/vendor/libkqueue/kqlite/test-lite.c +++ b/vendor/libkqueue/kqlite/test-lite.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2013 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + #include "./lite.h" #include @@ -8,7 +24,6 @@ #include #include - void test_evfilt_write(kqueue_t kq) { struct kevent kev; int sockfd[2]; From 1ab2ff7a76eef9cefbbac3faf2857c2069000ed7 Mon Sep 17 00:00:00 2001 From: mheily Date: Sun, 26 Jan 2014 18:00:46 +0000 Subject: [PATCH 0578/1120] Switch to autoconf/automake git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@666 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- vendor/libkqueue/ChangeLog | 5 + vendor/libkqueue/Makefile.am | 47 ++++++++ vendor/libkqueue/configure | 198 ---------------------------------- vendor/libkqueue/configure.ac | 22 ++++ 4 files changed, 74 insertions(+), 198 deletions(-) create mode 100644 vendor/libkqueue/Makefile.am delete mode 100755 vendor/libkqueue/configure create mode 100644 vendor/libkqueue/configure.ac diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 70952be80..94defa233 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,3 +1,8 @@ +HEAD +------------------------------------------------------------------------ + + * Switch to autoconf/automake + 2013-05-08 v2.0.1 r646 ------------------------------------------------------------------------ diff --git a/vendor/libkqueue/Makefile.am b/vendor/libkqueue/Makefile.am new file mode 100644 index 000000000..49fe4b69f --- /dev/null +++ b/vendor/libkqueue/Makefile.am @@ -0,0 +1,47 @@ + +# FIXME - Only supports Linux for now + +lib_LTLIBRARIES = libkqueue.la +kqincludedir = $(includedir)/kqueue/sys +kqinclude_HEADERS = include/sys/event.h +dist_man_MANS = kqueue.2 + +libkqueue_la_CFLAGS = -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden + +libkqueue_la_SOURCES = \ + src/common/filter.c \ + src/common/knote.c \ + src/common/map.c \ + src/common/kevent.c \ + src/common/kqueue.c \ + src/posix/platform.c \ + src/linux/platform.c \ + src/linux/read.c \ + src/linux/write.c \ + src/linux/user.c \ + src/linux/vnode.c \ + src/linux/signal.c \ + src/linux/timer.c + +libkqueue_la_LIBADD = -lpthread -lrt + +check_PROGRAMS = kqtest + +TESTS = kqtest + +kqtest_SOURCES = \ + test/main.c \ + test/kevent.c \ + test/test.c \ + test/proc.c \ + test/read.c \ + test/signal.c \ + test/timer.c \ + test/vnode.c \ + test/user.c + +kqtest_CFLAGS = -g -O0 -Wall -Werror -I./include -I./test + +kqtest_LDADD = -lpthread -lrt libkqueue.la + + diff --git a/vendor/libkqueue/configure b/vendor/libkqueue/configure deleted file mode 100755 index 3de909985..000000000 --- a/vendor/libkqueue/configure +++ /dev/null @@ -1,198 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2013 Mark Heily -# -# Permission to use, copy, modify, and distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -usage() { -cat << "EOF" -Usage: configure [options] - -Installation options: - --bindir [DIRECTORY] TODO describe this [$(EPREFIX)/bin] - --datadir [DIRECTORY] TODO describe this [$(DATAROOTDIR)] - --datarootdir [DIRECTORY] TODO describe this [$(PREFIX)/share] - --docdir [DIRECTORY] TODO describe this [$(DATAROOTDIR)/doc/$(PACKAGE)] - --eprefix [DIRECTORY] TODO describe this [$(PREFIX)] - --includedir [DIRECTORY] TODO describe this [$(PREFIX)/include] - --infodir [DIRECTORY] TODO describe this [$(DATAROOTDIR)/info] - --libdir [DIRECTORY] TODO describe this [$(EPREFIX)/lib] - --libexecdir [DIRECTORY] TODO describe this [$(EPREFIX)/libexec] - --localedir [DIRECTORY] TODO describe this [$(DATAROOTDIR)/locale] - --localstatedir [DIRECTORY] TODO describe this [$(PREFIX)/var] - --mandir [DIRECTORY] TODO describe this [$(DATAROOTDIR)/man] - --oldincludedir [DIRECTORY] TODO describe this [/usr/include] - --pkgconfigdir [DIRECTORY] where to install pkg-config files [$(LIBDIR)/pkgconfig] - --pkgdatadir [DIRECTORY] TODO describe this [$(DATADIR)/$(PACKAGE)] - --pkgincludedir [DIRECTORY] TODO describe this [$(INCLUDEDIR)/$(PACKAGE)] - --pkglibdir [DIRECTORY] TODO describe this [$(LIBDIR)/$(PACKAGE)] - --prefix [DIRECTORY] TODO describe this [/usr/local] - --sbindir [DIRECTORY] TODO describe this [$(EPREFIX)/sbin] - --sharedstatedir [DIRECTORY] TODO describe this [$(PREFIX)/com] - --sysconfdir [DIRECTORY] TODO describe this [$(PREFIX)/etc] - -Project options: - -System types: - --build BUILD set the system type for building - --host HOST cross-compile programs to run on a different system type - --target TARGET build a compiler for cross-compiling - -Optional Features: - -Common options: - --disable-static Disable generation of static libraries - --disable-option-checking - -h, --help Show this message - -V, --version Display version information and exit -EOF -} - -err() { - echo "*** ERROR *** $*" - exit 1 -} - -require_var() { - key=$1 - eval "val=\$$key" - if [ "$val" = "" ] ; then - echo "ERROR: you must provide --$2 as a command line option" - exit 1 - fi -} - - -echo "# Automatically generated by ./configure -- do not edit" > config.mk -for arg in $* -do - if [ `echo "$arg" | grep "^--"` = "$arg" ] ; then - key=`echo $arg | sed "s/^--//; s/=.*//; s/^with-//;"` - val=`echo $arg | sed "s/.*=//"` - uc_key=`echo "$key" | tr "a-z" "A-Z" | tr "-" "_"` - case $key in - "help") - usage - exit 1 - ;; - bindir|datadir|datarootdir|docdir|includedir|infodir|libdir|libexecdir|localedir|localstatedir|mandir|pkgconfigdir|pkgdatadir|pkgincludedir|pkglibdir|prefix|sbindir|sharedstatedir|sysconfdir) - echo "$uc_key=$val" >> config.mk - ;; - exec-prefix) - echo "EPREFIX=$val" >> config.mk - ;; - program-prefix) - if [ "$val" != "" ] ; then err "FIXME - not implemented" ; fi - ;; - disable-static) - echo "$uc_key=1" >> config.mk - ;; - build|host) - # TODO: we should split this up, and override the other Makeconf - # variables like *_VENDOR, *_ARCH, *_CPU, *_KERNEL, *_SYSTEM - echo "$uc_key=$val" >> config.mk - eval "${key}_system_type=\"$val\"" - ;; - disable-option-checking) - # Not implemented, this behavior is the default (for now) - ;; - disable-dependency-tracking) - # Not implemented, dependency tracking is done in Ruby (for now) - ;; - # Android-specific variables - ndk|sdk) - echo "$uc_key=$val" >> config.mk - eval "$key=\"$val\"" - ;; - *) - echo "Warning: unrecognized option: $arg" - ;; - esac - fi -done - -# Android-specific options -if [ "`echo ${host_system_type} | grep androideabi`" != "" ] ; then - exec ./configure.rb $* -# require_var ndk with-ndk -# require_var sdk with-sdk -fi - -printf "checking for a C compiler... " -for cmd in ${host_system_type}-cc cc gcc gcc4 clang -do - $cmd --version >/dev/null 2>&1 - if [ $? -eq 0 ] ; then cc="$cmd" ; break ; fi -done -if [ -n "$CC" ] ; then cc="$CC" ; fi -if [ -n "$cc" ] ; then - echo "$cc" - echo "CC=$cc" >> config.mk - if [ "$cc" != "cc" ] ; then echo "LD=$cc" >> config.mk ; fi - if [ -n "$CFLAGS" ] ; then echo "CFLAGS=$CFLAGS" >> config.mk ; fi -else - echo "not found" - err "Please install a compiler and add it to your PATH" -fi - -printf "checking for ar.. " -for ar in ${host_system_type}-ar ar gar -do - $ar --version >/dev/null 2>&1 - if [ $? -eq 0 ] ; then ar="$ar" ; break ; fi -done -if [ -n "$ar" ] ; then - echo "$ar" - echo "AR=$ar" >> config.mk -else - echo "not found" - err "Please install an archiver and add it to your PATH" -fi - -printf "checking for ranlib.. " -for ranlib in ${host_system_type}-ranlib ranlib -do - $ar --version >/dev/null 2>&1 - if [ $? -eq 0 ] ; then ranlib="$ranlib" ; break ; fi -done -if [ -n "$ranlib" ] ; then - echo "$ranlib" - echo "RANLIB=$ranlib" >> config.mk -else - echo "not found" - err "Please install ranlib and add it to your PATH" -fi - -printf "checking for a usable make command... " -for cmd in make gmake -do - $cmd --version >/dev/null 2>&1 - if [ $? -eq 0 ] ; then make="$cmd" ; break ; fi -done -if [ -n "$make" ] ; then - echo "yes" - echo "MAKE=$make" >> config.mk -else - echo "not found" - err "Please install GNU Make and add it to your PATH as either make or gmake" -fi - -# Allow additional variables from the environment to override the defaults -# -test -n "$LD" && echo "LD=$LD" >> config.mk -test -n "$LDFLAGS" && echo "LDFLAGS=$LDFLAGS" >> config.mk -# TODO: need to add Makefile support for: LIBS, CPP, CPPFLAGS - -rm -f config.h -$make config.h diff --git a/vendor/libkqueue/configure.ac b/vendor/libkqueue/configure.ac new file mode 100644 index 000000000..6c2596fe4 --- /dev/null +++ b/vendor/libkqueue/configure.ac @@ -0,0 +1,22 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_INIT([libkqueue], [2.0.2]) +LT_INIT +AM_INIT_AUTOMAKE([foreign subdir-objects]) +AC_CONFIG_SRCDIR([configure.ac]) +AC_CONFIG_HEADERS([config.h]) +AC_PROG_CC + + +AC_CHECK_HEADER([sys/event.h]) +AC_CHECK_DECL([EPOLLRDHUP], [], [], [[#include ]]) +AC_CHECK_DECL([ppoll], [], [], [[ +#define _GNU_SOURCE +#include +]]) +AC_CHECK_HEADERS([[sys/epoll.h sys/inotify.h sys/signalfd.h sys/timerfd.h sys/eventfd.h]]) + + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT From 12c05c3efdf46aed1655e78ccbde6f5156d0d047 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sun, 23 Feb 2014 15:31:04 -0500 Subject: [PATCH 0579/1120] bump version to 2.0.2 --- vendor/libkqueue/ChangeLog | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 94defa233..00273f28f 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,6 +1,8 @@ -HEAD +2014-02-23 v2.0.2 ------------------------------------------------------------------------ + * Switch from SVN to Git + * Switch hosting providers to Github * Switch to autoconf/automake 2013-05-08 v2.0.1 r646 From 864985cf8a29235778d4d5cff70ee31a71e18bf6 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sun, 23 Feb 2014 15:31:57 -0500 Subject: [PATCH 0580/1120] remove GNUmakefile --- vendor/libkqueue/GNUmakefile | 279 ----------------------------------- 1 file changed, 279 deletions(-) delete mode 100644 vendor/libkqueue/GNUmakefile diff --git a/vendor/libkqueue/GNUmakefile b/vendor/libkqueue/GNUmakefile deleted file mode 100644 index e7b0d9cf2..000000000 --- a/vendor/libkqueue/GNUmakefile +++ /dev/null @@ -1,279 +0,0 @@ -# AUTOMATICALLY GENERATED -- DO NOT EDIT -AR = ar -BINDIR = $(EPREFIX)/bin -CC = cc -DATADIR = $(DATAROOTDIR) -DATAROOTDIR = $(PREFIX)/share -DOCDIR = $(DATAROOTDIR)/doc/$(PACKAGE) -EPREFIX = $(PREFIX) -INCLUDEDIR = $(PREFIX)/include -INFODIR = $(DATAROOTDIR)/info -INSTALL ?= /usr/bin/install -LD = cc -LIBDIR = $(EPREFIX)/lib -LIBEXECDIR = $(EPREFIX)/libexec -LOCALEDIR = $(DATAROOTDIR)/locale -LOCALSTATEDIR = $(PREFIX)/var -MANDIR = $(DATAROOTDIR)/man -OLDINCLUDEDIR = /usr/include -PKGCONFIGDIR = $(LIBDIR)/pkgconfig -PKGDATADIR = $(DATADIR)/$(PACKAGE) -PKGINCLUDEDIR = $(INCLUDEDIR)/$(PACKAGE) -PKGLIBDIR = $(LIBDIR)/$(PACKAGE) -PREFIX = /usr/local -RANLIB = ranlib -SBINDIR = $(EPREFIX)/sbin -SHAREDSTATEDIR = $(PREFIX)/com -SYSCONFDIR = $(PREFIX)/etc - - -# -# Detect the canonical system type of the system we are building on -# (build) and the system the package runs on (host) -# -BUILD_CPU=$(shell uname -m) -HOST_CPU=$(BUILD_CPU) -BUILD_VENDOR=unknown -HOST_VENDOR=$(BUILD_VENDOR) -BUILD_KERNEL=$(shell uname | tr '[A-Z]' '[a-z]') -HOST_KERNEL=$(BUILD_KERNEL) -BUILD_SYSTEM=gnu -HOST_SYSTEM=$(BUILD_SYSTEM) -BUILD_TYPE=$(BUILD_CPU)-$(BUILD_VENDOR)-$(BUILD_KERNEL)-$(BUILD_SYSTEM) -HOST_TYPE=$(HOST_CPU)-$(HOST_VENDOR)-$(HOST_KERNEL)-$(HOST_SYSTEM) - -# Allow variables to be overridden via a ./configure script that outputs config.mk -# FIXME -- requires GNU Make --include config.mk - -default: all - -all: libkqueue.so libkqueue.a kqtest libkqueue.pc - -check: kqtest - ./kqtest - -clean: - rm -f *.rpm - rm -f libkqueue-2.0.1.tar.gz - rm -f src/common/filter.o - rm -f src/common/knote.o - rm -f src/common/map.o - rm -f src/common/kevent.o - rm -f src/common/kqueue.o - rm -f src/posix/platform.o - rm -f src/linux/platform.o - rm -f src/linux/read.o - rm -f src/linux/write.o - rm -f src/linux/user.o - rm -f src/linux/vnode.o - rm -f src/linux/signal.o - rm -f src/linux/timer.o - rm -f libkqueue.so - rm -f libkqueue.a - rm -f test/main.o - rm -f test/kevent.o - rm -f test/test.o - rm -f test/proc.o - rm -f test/read.o - rm -f test/signal.o - rm -f test/timer.o - rm -f test/vnode.o - rm -f test/user.o - rm -f kqtest - -config.h: - @echo "checking build system type... $(BUILD_TYPE)" - @echo "checking host system type... $(HOST_TYPE)" - @echo "/* AUTOMATICALLY GENERATED -- DO NOT EDIT */" > config.h.tmp - @date > config.log - @printf "checking whether EPOLLRDHUP is declared in sys/epoll.h... " | tee -a config.log - @( printf '#define _GNU_SOURCE\n#include \nint main() { EPOLLRDHUP; }' | $(CC) $(CFLAGS) -E -x c - ) >/dev/null 2>>config.log && ( echo '#define HAVE_DECL_EPOLLRDHUP 1' >> config.h.tmp ; echo 'yes' ) || (echo '#define HAVE_DECL_EPOLLRDHUP 0' >> config.h.tmp ; echo 'no' ) - @printf "checking whether ppoll is declared in poll.h... " | tee -a config.log - @( printf '#define _GNU_SOURCE\n#include \nint main() { ppoll; }' | $(CC) $(CFLAGS) -E -x c - ) >/dev/null 2>>config.log && ( echo '#define HAVE_DECL_PPOLL 1' >> config.h.tmp ; echo 'yes' ) || (echo '#define HAVE_DECL_PPOLL 0' >> config.h.tmp ; echo 'no' ) - @printf "checking for sys/epoll.h... " - @( echo '#include ' | $(CC) $(CFLAGS) -E -x c - ) >/dev/null 2>&1 && ( echo '#define HAVE_SYS_EPOLL_H 1' >> config.h.tmp ; echo 'yes' ) || (echo '/* #undef HAVE_SYS_EPOLL_H */' >> config.h.tmp ; echo 'no' ) - @printf "checking for sys/event.h... " - @( echo '#include ' | $(CC) $(CFLAGS) -E -x c - ) >/dev/null 2>&1 && ( echo '#define HAVE_SYS_EVENT_H 1' >> config.h.tmp ; echo 'yes' ) || (echo '/* #undef HAVE_SYS_EVENT_H */' >> config.h.tmp ; echo 'no' ) - @printf "checking for sys/eventfd.h... " - @( echo '#include ' | $(CC) $(CFLAGS) -E -x c - ) >/dev/null 2>&1 && ( echo '#define HAVE_SYS_EVENTFD_H 1' >> config.h.tmp ; echo 'yes' ) || (echo '/* #undef HAVE_SYS_EVENTFD_H */' >> config.h.tmp ; echo 'no' ) - @printf "checking for sys/inotify.h... " - @( echo '#include ' | $(CC) $(CFLAGS) -E -x c - ) >/dev/null 2>&1 && ( echo '#define HAVE_SYS_INOTIFY_H 1' >> config.h.tmp ; echo 'yes' ) || (echo '/* #undef HAVE_SYS_INOTIFY_H */' >> config.h.tmp ; echo 'no' ) - @printf "checking for sys/signalfd.h... " - @( echo '#include ' | $(CC) $(CFLAGS) -E -x c - ) >/dev/null 2>&1 && ( echo '#define HAVE_SYS_SIGNALFD_H 1' >> config.h.tmp ; echo 'yes' ) || (echo '/* #undef HAVE_SYS_SIGNALFD_H */' >> config.h.tmp ; echo 'no' ) - @printf "checking for sys/timerfd.h... " - @( echo '#include ' | $(CC) $(CFLAGS) -E -x c - ) >/dev/null 2>&1 && ( echo '#define HAVE_SYS_TIMERFD_H 1' >> config.h.tmp ; echo 'yes' ) || (echo '/* #undef HAVE_SYS_TIMERFD_H */' >> config.h.tmp ; echo 'no' ) - @rm -f conftest.c conftest.o - @echo "creating config.h" - @mv config.h.tmp config.h - -dist: libkqueue-2.0.1.tar.gz - -distclean: clean - rm -f GNUmakefile - rm -f libkqueue-2.0.1.tar.gz - rm -f config.h - rm -f config.yaml - -distdir: config.h - umask 22 ; mkdir -p '$(distdir)/src/common' - umask 22 ; mkdir -p '$(distdir)/src/common/../posix' - umask 22 ; mkdir -p '$(distdir)/src/common/../posix/../../include/sys' - umask 22 ; mkdir -p '$(distdir)/src/common/../linux' - umask 22 ; mkdir -p '$(distdir)/src/posix' - umask 22 ; mkdir -p '$(distdir)/src/posix/../common' - umask 22 ; mkdir -p '$(distdir)/src/posix/../common/../posix' - umask 22 ; mkdir -p '$(distdir)/src/posix/../common/../posix/../../include/sys' - umask 22 ; mkdir -p '$(distdir)/src/posix/../common/../linux' - umask 22 ; mkdir -p '$(distdir)/src/linux' - umask 22 ; mkdir -p '$(distdir)/src/linux/../common' - umask 22 ; mkdir -p '$(distdir)/src/linux/../common/../posix' - umask 22 ; mkdir -p '$(distdir)/src/linux/../common/../posix/../../include/sys' - umask 22 ; mkdir -p '$(distdir)/src/linux/../common/../linux' - umask 22 ; mkdir -p '$(distdir)/include/sys' - umask 22 ; mkdir -p '$(distdir)/test' - umask 22 ; mkdir -p '$(distdir)/test/..' - cp -RL libkqueue.spec config.h GNUmakefile kqueue.2 libkqueue.pc.in configure configure.rb LICENSE $(distdir) - cp -RL src/common/filter.c src/common/private.h src/common/tree.h src/common/debug.h src/common/knote.c src/common/alloc.h src/common/map.c src/common/kevent.c src/common/kqueue.c $(distdir)/src/common - cp -RL src/common/../posix/platform.h $(distdir)/src/common/../posix - cp -RL src/common/../posix/../../include/sys/event.h $(distdir)/src/common/../posix/../../include/sys - cp -RL src/common/../linux/platform.h $(distdir)/src/common/../linux - cp -RL src/posix/platform.c $(distdir)/src/posix - cp -RL src/posix/../common/private.h src/posix/../common/tree.h src/posix/../common/debug.h $(distdir)/src/posix/../common - cp -RL src/posix/../common/../posix/platform.h $(distdir)/src/posix/../common/../posix - cp -RL src/posix/../common/../posix/../../include/sys/event.h $(distdir)/src/posix/../common/../posix/../../include/sys - cp -RL src/posix/../common/../linux/platform.h $(distdir)/src/posix/../common/../linux - cp -RL src/linux/platform.c src/linux/read.c src/linux/write.c src/linux/user.c src/linux/vnode.c src/linux/signal.c src/linux/timer.c $(distdir)/src/linux - cp -RL src/linux/../common/private.h src/linux/../common/tree.h src/linux/../common/debug.h $(distdir)/src/linux/../common - cp -RL src/linux/../common/../posix/platform.h $(distdir)/src/linux/../common/../posix - cp -RL src/linux/../common/../posix/../../include/sys/event.h $(distdir)/src/linux/../common/../posix/../../include/sys - cp -RL src/linux/../common/../linux/platform.h $(distdir)/src/linux/../common/../linux - cp -RL include/sys/event.h $(distdir)/include/sys - cp -RL test/main.c test/common.h test/kevent.c test/test.c test/proc.c test/read.c test/signal.c test/timer.c test/vnode.c test/user.c $(distdir)/test - cp -RL test/../config.h $(distdir)/test/.. - -install: - /usr/bin/test -e $(DESTDIR)$(LIBDIR) || $(INSTALL) -d -m 755 $(DESTDIR)$(LIBDIR) - $(INSTALL) -m 0644 libkqueue.so $(DESTDIR)$(LIBDIR)/libkqueue.so.0.0 - /usr/bin/test -e $(DESTDIR)$(INCLUDEDIR)/kqueue/sys || $(INSTALL) -d -m 755 $(DESTDIR)$(INCLUDEDIR)/kqueue/sys - $(INSTALL) -m 644 include/sys/event.h $(DESTDIR)$(INCLUDEDIR)/kqueue/sys - /usr/bin/test -e $(DESTDIR)$(MANDIR)/man2 || $(INSTALL) -d -m 755 $(DESTDIR)$(MANDIR)/man2 - $(INSTALL) -m 644 kqueue.2 $(DESTDIR)$(MANDIR)/man2 - /usr/bin/test -e $(DESTDIR)$(PKGCONFIGDIR) || $(INSTALL) -d -m 755 $(DESTDIR)$(PKGCONFIGDIR) - $(INSTALL) -m 644 libkqueue.pc $(DESTDIR)$(PKGCONFIGDIR) - rm -f $(DESTDIR)$(LIBDIR)/libkqueue.so - ln -s libkqueue.so.0.0 $(DESTDIR)$(LIBDIR)/libkqueue.so - rm -f $(DESTDIR)$(LIBDIR)/libkqueue.so.0 - ln -s libkqueue.so.0.0 $(DESTDIR)$(LIBDIR)/libkqueue.so.0 - rm -f $(DESTDIR)$(MANDIR)/man2/kevent.2 - ln -s kqueue.2 $(DESTDIR)$(MANDIR)/man2/kevent.2 - -kqtest: test/main.o test/kevent.o test/test.o test/proc.o test/read.o test/signal.o test/timer.o test/vnode.o test/user.o - $(LD) -o kqtest -L . -Wl,-rpath,. -L . $(LDFLAGS) test/main.o test/kevent.o test/test.o test/proc.o test/read.o test/signal.o test/timer.o test/vnode.o test/user.o libkqueue.a -lpthread -lrt $(LDADD) - -libkqueue-2.0.1.tar.gz: - rm -rf libkqueue-2.0.1 - mkdir libkqueue-2.0.1 - $(MAKE) distdir distdir=libkqueue-2.0.1 - rm -rf libkqueue-2.0.1.tar libkqueue-2.0.1.tar.gz - tar cf libkqueue-2.0.1.tar libkqueue-2.0.1 - gzip libkqueue-2.0.1.tar - rm -rf libkqueue-2.0.1 - -libkqueue.a: src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o -ifneq ($(DISABLE_STATIC),1) - $(AR) cru libkqueue.a src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o - $(RANLIB) libkqueue.a -endif - -libkqueue.pc: config.h - @echo 'creating libkqueue.pc' - @printf "prefix=$(PREFIX)\nexec_prefix=$(EPREFIX)\nlibdir=$(LIBDIR)\nincludedir=$(INCLUDEDIR)\n" > libkqueue.pc - @cat libkqueue.pc.in >> libkqueue.pc - -libkqueue.so: src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o - $(LD) -o libkqueue.so -shared -fPIC -L . -Wl,-soname,libkqueue.so.0 $(LDFLAGS) src/common/filter.o src/common/knote.o src/common/map.o src/common/kevent.o src/common/kqueue.o src/posix/platform.o src/linux/platform.o src/linux/read.o src/linux/write.o src/linux/user.o src/linux/vnode.o src/linux/signal.o src/linux/timer.o -lpthread -lrt $(LDADD) - -package: clean libkqueue-2.0.1.tar.gz - rm -rf rpm *.rpm - mkdir -p rpm/BUILD rpm/RPMS rpm/SOURCES rpm/SPECS rpm/SRPMS - mkdir -p rpm/RPMS/`uname -m` - cp libkqueue-2.0.1.tar.gz rpm/SOURCES - cp libkqueue.spec rpm/SPECS/libkqueue.spec - perl -pi -e 's/^Version:.*/Version: 2.0.1/' rpm/SPECS/libkqueue.spec - rpmbuild --define "_topdir `pwd`/rpm" -bs rpm/SPECS/libkqueue.spec - rpmbuild --define "_topdir `pwd`/rpm" -bb rpm/SPECS/libkqueue.spec - mv ./rpm/SRPMS/* ./rpm/RPMS/*/*.rpm . - rm -rf rpm - -src/common/filter.o: src/common/filter.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/filter.o -fPIC -DPIC $(CFLAGS) -c src/common/filter.c - -src/common/kevent.o: src/common/kevent.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/kevent.o -fPIC -DPIC $(CFLAGS) -c src/common/kevent.c - -src/common/knote.o: src/common/knote.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h src/common/alloc.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/knote.o -fPIC -DPIC $(CFLAGS) -c src/common/knote.c - -src/common/kqueue.o: src/common/kqueue.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/kqueue.o -fPIC -DPIC $(CFLAGS) -c src/common/kqueue.c - -src/common/map.o: src/common/map.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/common/map.o -fPIC -DPIC $(CFLAGS) -c src/common/map.c - -src/linux/platform.o: src/linux/platform.c src/linux/../common/private.h config.h src/linux/../common/tree.h src/linux/../common/../posix/platform.h src/linux/../common/../posix/../../include/sys/event.h src/linux/../common/../linux/platform.h src/linux/../common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/platform.o -fPIC -DPIC $(CFLAGS) -c src/linux/platform.c - -src/linux/read.o: src/linux/read.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/read.o -fPIC -DPIC $(CFLAGS) -c src/linux/read.c - -src/linux/signal.o: src/linux/signal.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/signal.o -fPIC -DPIC $(CFLAGS) -c src/linux/signal.c - -src/linux/timer.o: src/linux/timer.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/timer.o -fPIC -DPIC $(CFLAGS) -c src/linux/timer.c - -src/linux/user.o: src/linux/user.c include/sys/event.h src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/user.o -fPIC -DPIC $(CFLAGS) -c src/linux/user.c - -src/linux/vnode.o: src/linux/vnode.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/vnode.o -fPIC -DPIC $(CFLAGS) -c src/linux/vnode.c - -src/linux/write.o: src/linux/write.c src/common/private.h config.h src/common/tree.h src/common/../posix/platform.h src/common/../posix/../../include/sys/event.h src/common/../linux/platform.h src/common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/linux/write.o -fPIC -DPIC $(CFLAGS) -c src/linux/write.c - -src/posix/platform.o: src/posix/platform.c src/posix/../common/private.h config.h src/posix/../common/tree.h src/posix/../common/../posix/platform.h src/posix/../common/../posix/../../include/sys/event.h src/posix/../common/../linux/platform.h src/posix/../common/debug.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden -o src/posix/platform.o -fPIC -DPIC $(CFLAGS) -c src/posix/platform.c - -test/kevent.o: test/kevent.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/kevent.o $(CFLAGS) -c test/kevent.c - -test/main.o: test/main.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/main.o $(CFLAGS) -c test/main.c - -test/proc.o: test/proc.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/proc.o $(CFLAGS) -c test/proc.c - -test/read.o: test/read.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/read.o $(CFLAGS) -c test/read.c - -test/signal.o: test/signal.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/signal.o $(CFLAGS) -c test/signal.c - -test/test.o: test/test.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/test.o $(CFLAGS) -c test/test.c - -test/timer.o: test/timer.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/timer.o $(CFLAGS) -c test/timer.c - -test/user.o: test/user.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/user.o $(CFLAGS) -c test/user.c - -test/vnode.o: test/vnode.c test/common.h include/sys/event.h test/../config.h GNUmakefile - $(CC) -DHAVE_CONFIG_H -I. -g -O0 -Wall -Werror -I./include -I./test -g -O0 -o test/vnode.o $(CFLAGS) -c test/vnode.c - -uninstall: - rm -f $(DESTDIR)$(LIBDIR)/libkqueue.so - rm -f $(DESTDIR)$(INCLUDEDIR)/kqueue/sys/include/sys/event.h - rm -f $(DESTDIR)$(MANDIR)/man2/kqueue.2 - rm -f $(DESTDIR)$(PKGCONFIGDIR)/libkqueue.pc From a93587c6bda196ce092324cb1aaf5d58530fda35 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sun, 23 Feb 2014 16:31:45 -0500 Subject: [PATCH 0581/1120] fix the pkg-config generation --- vendor/libkqueue/configure.ac | 2 +- vendor/libkqueue/libkqueue.pc.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/configure.ac b/vendor/libkqueue/configure.ac index 6c2596fe4..25466b484 100644 --- a/vendor/libkqueue/configure.ac +++ b/vendor/libkqueue/configure.ac @@ -18,5 +18,5 @@ AC_CHECK_DECL([ppoll], [], [], [[ AC_CHECK_HEADERS([[sys/epoll.h sys/inotify.h sys/signalfd.h sys/timerfd.h sys/eventfd.h]]) -AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([Makefile libkqueue.pc]) AC_OUTPUT diff --git a/vendor/libkqueue/libkqueue.pc.in b/vendor/libkqueue/libkqueue.pc.in index 362f0493e..e02f947c7 100644 --- a/vendor/libkqueue/libkqueue.pc.in +++ b/vendor/libkqueue/libkqueue.pc.in @@ -1,7 +1,7 @@ Name: libkqueue Description: Emulates FreeBSD kqueue(2) on other platforms -Version: 0.1 +Version: @VERSION@ Requires: Libs: -lkqueue Libs.private: -lpthread From c7978f4ca550dbd88d789e6b105f1980028bd1af Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sun, 23 Feb 2014 16:52:38 -0500 Subject: [PATCH 0582/1120] update pkgconfig things --- vendor/libkqueue/Makefile.am | 3 +++ vendor/libkqueue/libkqueue.pc.in | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/Makefile.am b/vendor/libkqueue/Makefile.am index 49fe4b69f..3db76244b 100644 --- a/vendor/libkqueue/Makefile.am +++ b/vendor/libkqueue/Makefile.am @@ -25,6 +25,9 @@ libkqueue_la_SOURCES = \ libkqueue_la_LIBADD = -lpthread -lrt +pkgconfigdir=$(libdir)/pkgconfig +pkgconfig_DATA=libkqueue.pc + check_PROGRAMS = kqtest TESTS = kqtest diff --git a/vendor/libkqueue/libkqueue.pc.in b/vendor/libkqueue/libkqueue.pc.in index e02f947c7..5b3f68fe2 100644 --- a/vendor/libkqueue/libkqueue.pc.in +++ b/vendor/libkqueue/libkqueue.pc.in @@ -4,5 +4,5 @@ Description: Emulates FreeBSD kqueue(2) on other platforms Version: @VERSION@ Requires: Libs: -lkqueue -Libs.private: -lpthread +Libs.private: -lpthread -lrt Cflags: -I${includedir}/kqueue From 1b0f98f1330eaa0066f0de56b21f0edf4505738b Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sun, 23 Feb 2014 20:25:04 -0500 Subject: [PATCH 0583/1120] add missing headers --- vendor/libkqueue/Makefile.am | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/Makefile.am b/vendor/libkqueue/Makefile.am index 3db76244b..95f22092f 100644 --- a/vendor/libkqueue/Makefile.am +++ b/vendor/libkqueue/Makefile.am @@ -21,7 +21,13 @@ libkqueue_la_SOURCES = \ src/linux/user.c \ src/linux/vnode.c \ src/linux/signal.c \ - src/linux/timer.c + src/linux/timer.c \ + src/common/alloc.h \ + src/common/debug.h \ + src/common/private.h \ + src/common/queue.h \ + src/common/tree.h \ + src/linux/platform.h libkqueue_la_LIBADD = -lpthread -lrt From 618ff9ce498f6f241ffce53360eb4f444ae9968c Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sun, 23 Feb 2014 20:26:49 -0500 Subject: [PATCH 0584/1120] add missing header --- vendor/libkqueue/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/Makefile.am b/vendor/libkqueue/Makefile.am index 95f22092f..1350ad4dd 100644 --- a/vendor/libkqueue/Makefile.am +++ b/vendor/libkqueue/Makefile.am @@ -15,6 +15,7 @@ libkqueue_la_SOURCES = \ src/common/kevent.c \ src/common/kqueue.c \ src/posix/platform.c \ + src/posix/platform.h \ src/linux/platform.c \ src/linux/read.c \ src/linux/write.c \ From e0eec6135969a6a4910d5026f3cf6c29dd80c70e Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sun, 23 Feb 2014 20:34:25 -0500 Subject: [PATCH 0585/1120] add missing header --- vendor/libkqueue/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/Makefile.am b/vendor/libkqueue/Makefile.am index 1350ad4dd..e86e4fc39 100644 --- a/vendor/libkqueue/Makefile.am +++ b/vendor/libkqueue/Makefile.am @@ -48,7 +48,8 @@ kqtest_SOURCES = \ test/signal.c \ test/timer.c \ test/vnode.c \ - test/user.c + test/user.c \ + test/common.h kqtest_CFLAGS = -g -O0 -Wall -Werror -I./include -I./test From 64897741da438833b6f56dd0e58db9d2de94fc96 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sun, 9 Mar 2014 20:40:24 -0400 Subject: [PATCH 0586/1120] fix libkqueue.pc generation --- vendor/libkqueue/ChangeLog | 5 +++++ vendor/libkqueue/configure.ac | 2 +- vendor/libkqueue/libkqueue.pc.in | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 00273f28f..9595bcbed 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,3 +1,8 @@ +2014-03-09 v2.0.3 +------------------------------------------------------------------------ + + * Fix the generation of libkqueue.pc + 2014-02-23 v2.0.2 ------------------------------------------------------------------------ diff --git a/vendor/libkqueue/configure.ac b/vendor/libkqueue/configure.ac index 25466b484..4c1aa29f8 100644 --- a/vendor/libkqueue/configure.ac +++ b/vendor/libkqueue/configure.ac @@ -1,7 +1,7 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. -AC_INIT([libkqueue], [2.0.2]) +AC_INIT([libkqueue], [2.0.3]) LT_INIT AM_INIT_AUTOMAKE([foreign subdir-objects]) AC_CONFIG_SRCDIR([configure.ac]) diff --git a/vendor/libkqueue/libkqueue.pc.in b/vendor/libkqueue/libkqueue.pc.in index 5b3f68fe2..2c8ec1cc7 100644 --- a/vendor/libkqueue/libkqueue.pc.in +++ b/vendor/libkqueue/libkqueue.pc.in @@ -1,3 +1,7 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ Name: libkqueue Description: Emulates FreeBSD kqueue(2) on other platforms From 9e73d628e127d454a673b7bee2940a592ac8e705 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Thu, 24 Jul 2014 21:45:40 -0400 Subject: [PATCH 0587/1120] Fix a build failure on mips64el --- vendor/libkqueue/ChangeLog | 6 ++++++ vendor/libkqueue/src/common/knote.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 9595bcbed..b87771ef2 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,3 +1,9 @@ +UNRELEASED HEAD +------------------------------------------------------------------------ + + * Fix a build failure on mips64el. + (Credit: YunQiang Su, from Debian Bug #754376) + 2014-03-09 v2.0.3 ------------------------------------------------------------------------ diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 4dd255073..3142f95f4 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -120,7 +120,7 @@ knote_lookup(struct filter *filt, uintptr_t ident) ent = RB_FIND(knt, &filt->kf_knote, &query); pthread_rwlock_unlock(&filt->kf_knote_mtx); -#ifdef __x86_64__ +#if defined(__x86_64__) || defined(__mips64) dbg_printf("id=%lu ent=%p", ident, ent); #else dbg_printf("id=%u ent=%p", ident, ent); From db2c986354f0af1d117d3738cce1c7ad0fbbba80 Mon Sep 17 00:00:00 2001 From: Will Newton Date: Wed, 20 Aug 2014 15:06:01 +0100 Subject: [PATCH 0588/1120] configure.ac: Fix quoting on AC_CHECK_HEADERS Currently the output from autoheader contains the definition HAVE_SYS_EVENTFD_H_ (not the trailing underscore) so the sys/eventfd.h header is never used. Remove a layer of quoting which seems to fix the issue. --- vendor/libkqueue/configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/configure.ac b/vendor/libkqueue/configure.ac index 4c1aa29f8..f14ca1770 100644 --- a/vendor/libkqueue/configure.ac +++ b/vendor/libkqueue/configure.ac @@ -15,7 +15,7 @@ AC_CHECK_DECL([ppoll], [], [], [[ #define _GNU_SOURCE #include ]]) -AC_CHECK_HEADERS([[sys/epoll.h sys/inotify.h sys/signalfd.h sys/timerfd.h sys/eventfd.h]]) +AC_CHECK_HEADERS([sys/epoll.h sys/inotify.h sys/signalfd.h sys/timerfd.h sys/eventfd.h]) AC_CONFIG_FILES([Makefile libkqueue.pc]) From f6315c4bb1752d566b714ad318b98aea719885b1 Mon Sep 17 00:00:00 2001 From: Will Newton Date: Wed, 20 Aug 2014 15:07:34 +0100 Subject: [PATCH 0589/1120] src/common/knote.c: Portably print unitptr_t values The format string for uintptr_t values is defined in inttypes.h which is part of C99. Use that instead of having to special case every 64bit architecture. --- vendor/libkqueue/src/common/knote.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 3142f95f4..40d2232ce 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -14,6 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include #include @@ -120,11 +121,7 @@ knote_lookup(struct filter *filt, uintptr_t ident) ent = RB_FIND(knt, &filt->kf_knote, &query); pthread_rwlock_unlock(&filt->kf_knote_mtx); -#if defined(__x86_64__) || defined(__mips64) - dbg_printf("id=%lu ent=%p", ident, ent); -#else - dbg_printf("id=%u ent=%p", ident, ent); -#endif + dbg_printf("id=%" PRIuPTR " ent=%p", ident, ent); return (ent); } From f0367364aebc065ff22a2cd9c1ddc05b6e6706b7 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Mon, 26 Jan 2015 22:09:53 -0500 Subject: [PATCH 0590/1120] * Fix incorrect boolean logic in src/linux/read.c (Credit: marcos69, closes #5) --- vendor/libkqueue/ChangeLog | 3 +++ vendor/libkqueue/src/linux/read.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index b87771ef2..fb7baba1b 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,6 +1,9 @@ UNRELEASED HEAD ------------------------------------------------------------------------ + * Fix incorrect boolean logic in src/linux/read.c + (Credit: marcos69, closes #5) + * Fix a build failure on mips64el. (Credit: YunQiang Su, from Debian Bug #754376) diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index 21026313a..aa677ae26 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -204,7 +204,7 @@ evfilt_read_knote_delete(struct filter *filt, struct knote *kn) if (kn->kev.flags & EV_DISABLE) return (0); - if ((kn->kn_flags & KNFL_REGULAR_FILE && kn->kdata.kn_eventfd != -1) < 0) { + if ((kn->kn_flags & KNFL_REGULAR_FILE) && (kn->kdata.kn_eventfd != -1)) { if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kdata.kn_eventfd, NULL) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); From 0c0083c695b205abdb6e9cdee6d15f37db215c44 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sat, 6 Feb 2016 12:24:24 -0500 Subject: [PATCH 0591/1120] v2.0.4 --- vendor/libkqueue/ChangeLog | 2 +- vendor/libkqueue/configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index fb7baba1b..6793f0ac0 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,4 +1,4 @@ -UNRELEASED HEAD +2016-02-06 v2.0.4 ------------------------------------------------------------------------ * Fix incorrect boolean logic in src/linux/read.c diff --git a/vendor/libkqueue/configure.ac b/vendor/libkqueue/configure.ac index f14ca1770..266dcf6c3 100644 --- a/vendor/libkqueue/configure.ac +++ b/vendor/libkqueue/configure.ac @@ -1,7 +1,7 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. -AC_INIT([libkqueue], [2.0.3]) +AC_INIT([libkqueue], [2.0.4]) LT_INIT AM_INIT_AUTOMAKE([foreign subdir-objects]) AC_CONFIG_SRCDIR([configure.ac]) From c304899ec4d17afd1cc58db240547c1ccb852e48 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Wed, 16 Mar 2016 19:50:07 -0400 Subject: [PATCH 0592/1120] Linux: Use SYS_eventfd2 where available. Fixes build on AArch64 under Ubuntu 16.04. Credit: Galen Rhodes --- vendor/libkqueue/src/linux/platform.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index c6077fdcb..bcc0e5740 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -26,7 +26,11 @@ struct filter; #if HAVE_SYS_EVENTFD_H # include #else -# define eventfd(a,b) syscall(SYS_eventfd, (a), (b)) +# ifdef SYS_eventfd2 +# define eventfd(a,b) syscall(SYS_eventfd2, (a), (b)) +# else +# define eventfd(a,b) syscall(SYS_eventfd, (a), (b)) +# endif static inline int eventfd_write(int fd, uint64_t val) { if (write(fd, &val, sizeof(val)) < (ssize_t) sizeof(val)) From ac4255006d93144a470388a6f28be8ac1980c905 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Wed, 16 Mar 2016 19:52:03 -0400 Subject: [PATCH 0593/1120] Add log entry for previous commit --- vendor/libkqueue/ChangeLog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 6793f0ac0..cb8feed24 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,3 +1,10 @@ +Unreleased HEAD +------------------------------------------------------------------------ + + * Fix a build failure on Linux/AArch64 using Ubuntu 16.04. + (Credit: Galen Rhodes) + + 2016-02-06 v2.0.4 ------------------------------------------------------------------------ From 5f7c867fcd0cf695069788ebb158c411247d121e Mon Sep 17 00:00:00 2001 From: Vivian Kong Date: Tue, 19 Apr 2016 12:50:05 -0400 Subject: [PATCH 0594/1120] Fix endianness issue with ioctl - socket tests failed on big endian Linux --- vendor/libkqueue/src/linux/read.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index aa677ae26..18caeee91 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -124,11 +124,13 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) /* On return, data contains the number of bytes of protocol data available to read. */ - if (ioctl(dst->ident, SIOCINQ, &dst->data) < 0) { + int i; + if (ioctl(dst->ident, SIOCINQ, &i) < 0) { /* race condition with socket close, so ignore this error */ dbg_puts("ioctl(2) of socket failed"); dst->data = 0; } else { + dst->data = i; if (dst->data == 0) dst->flags |= EV_EOF; } From 33f17b4201e141d1926899277d85eeb768e5134c Mon Sep 17 00:00:00 2001 From: Ian Partridge Date: Thu, 26 May 2016 21:26:17 +0000 Subject: [PATCH 0595/1120] Add configure arg to disable install and build noinst ltlibrary --- vendor/libkqueue/Makefile.am | 11 ++++++++--- vendor/libkqueue/configure.ac | 7 +++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/Makefile.am b/vendor/libkqueue/Makefile.am index e86e4fc39..b32532c87 100644 --- a/vendor/libkqueue/Makefile.am +++ b/vendor/libkqueue/Makefile.am @@ -1,10 +1,15 @@ # FIXME - Only supports Linux for now -lib_LTLIBRARIES = libkqueue.la kqincludedir = $(includedir)/kqueue/sys -kqinclude_HEADERS = include/sys/event.h -dist_man_MANS = kqueue.2 + +if INSTALL + lib_LTLIBRARIES = libkqueue.la + kqinclude_HEADERS = include/sys/event.h + dist_man_MANS = kqueue.2 +else + noinst_LTLIBRARIES = libkqueue.la +endif libkqueue_la_CFLAGS = -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden diff --git a/vendor/libkqueue/configure.ac b/vendor/libkqueue/configure.ac index 266dcf6c3..a0f065584 100644 --- a/vendor/libkqueue/configure.ac +++ b/vendor/libkqueue/configure.ac @@ -8,6 +8,13 @@ AC_CONFIG_SRCDIR([configure.ac]) AC_CONFIG_HEADERS([config.h]) AC_PROG_CC +# When building as submodule allow selection of noinst targets +AC_ARG_ENABLE([libkqueue-install], + [AS_HELP_STRING([--disable-libkqueue-install], + [Disable install rules and build noinst libtool library])],, + [enable_libkqueue_install=yes] +) +AM_CONDITIONAL([INSTALL],[test "x$enable_libkqueue_install" != "xno"]) AC_CHECK_HEADER([sys/event.h]) AC_CHECK_DECL([EPOLLRDHUP], [], [], [[#include ]]) From 5d14f2d19f202b9f55db8b7032cd9fe821931397 Mon Sep 17 00:00:00 2001 From: Ian Partridge Date: Tue, 31 May 2016 15:41:58 +0100 Subject: [PATCH 0596/1120] Specify $top_srcdir for relative paths in CFLAGS --- vendor/libkqueue/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/Makefile.am b/vendor/libkqueue/Makefile.am index e86e4fc39..559224715 100644 --- a/vendor/libkqueue/Makefile.am +++ b/vendor/libkqueue/Makefile.am @@ -6,7 +6,7 @@ kqincludedir = $(includedir)/kqueue/sys kqinclude_HEADERS = include/sys/event.h dist_man_MANS = kqueue.2 -libkqueue_la_CFLAGS = -I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden +libkqueue_la_CFLAGS = -I$(top_srcdir)/src/common -I$(top_srcdir)/include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden libkqueue_la_SOURCES = \ src/common/filter.c \ @@ -51,7 +51,7 @@ kqtest_SOURCES = \ test/user.c \ test/common.h -kqtest_CFLAGS = -g -O0 -Wall -Werror -I./include -I./test +kqtest_CFLAGS = -g -O0 -Wall -Werror -I$(top_srcdir)/include -I$(top_srcdir)/test kqtest_LDADD = -lpthread -lrt libkqueue.la From 4f5ebb9624d3b65e948cecbe88d0a69db5e6ea81 Mon Sep 17 00:00:00 2001 From: Ian Partridge Date: Fri, 20 May 2016 19:43:54 +0000 Subject: [PATCH 0597/1120] Add EPOLLONESHOT if EV_ONESHOT or EV_DISPATCH --- vendor/libkqueue/src/linux/timer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 96e39171f..7cd48c5d6 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -151,7 +151,10 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) } memset(&ev, 0, sizeof(ev)); - ev.events = EPOLLIN; + ev.events = EPOLLIN | EPOLLET; + if (kn->kev.flags & (EV_ONESHOT | EV_DISPATCH)) + ev.events |= EPOLLONESHOT; + ev.data.ptr = kn; if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_ADD, tfd, &ev) < 0) { dbg_printf("epoll_ctl(2): %d", errno); From d8b09928cbdc96a93aef4cd7c994884cdc433c99 Mon Sep 17 00:00:00 2001 From: seabaylea Date: Tue, 21 Jun 2016 11:14:21 +0100 Subject: [PATCH 0598/1120] Allow tests to be built from separate build directory --- vendor/libkqueue/Makefile.am | 2 +- vendor/libkqueue/test/common.h | 6 +++--- vendor/libkqueue/test/lockstat.c | 2 +- vendor/libkqueue/test/stress/main.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/Makefile.am b/vendor/libkqueue/Makefile.am index 495f5bc37..5d1a8a787 100644 --- a/vendor/libkqueue/Makefile.am +++ b/vendor/libkqueue/Makefile.am @@ -56,7 +56,7 @@ kqtest_SOURCES = \ test/user.c \ test/common.h -kqtest_CFLAGS = -g -O0 -Wall -Werror -I$(top_srcdir)/include -I$(top_srcdir)/test +kqtest_CFLAGS = -g -O0 -Wall -Werror -I$(top_srcdir)/include -I$(top_srcdir)/test -I$(builddir) kqtest_LDADD = -lpthread -lrt libkqueue.la diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index a34b09e46..29fb5a0bb 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -48,11 +48,11 @@ #include #include #include -#include "../config.h" +#include "config.h" #include #else -# include "../include/sys/event.h" -# include "../src/windows/platform.h" +# include "include/sys/event.h" +# include "src/windows/platform.h" #endif struct test_context; diff --git a/vendor/libkqueue/test/lockstat.c b/vendor/libkqueue/test/lockstat.c index 6cd67ad39..e08e67a50 100644 --- a/vendor/libkqueue/test/lockstat.c +++ b/vendor/libkqueue/test/lockstat.c @@ -16,7 +16,7 @@ #include #include -#include "../src/common/private.h" +#include "src/common/private.h" int DEBUG_KQUEUE = 1; char * KQUEUE_DEBUG_IDENT = "lockstat"; diff --git a/vendor/libkqueue/test/stress/main.c b/vendor/libkqueue/test/stress/main.c index 6678089ea..e0baeccc9 100644 --- a/vendor/libkqueue/test/stress/main.c +++ b/vendor/libkqueue/test/stress/main.c @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "../config.h" +#include "config.h" #include #include From 47006096ea4f58518a6e4ee90d418a0526726317 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Thu, 23 Jun 2016 22:47:35 -0400 Subject: [PATCH 0599/1120] Add a Vagrantfile --- vendor/libkqueue/Vagrantfile | 71 ++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 vendor/libkqueue/Vagrantfile diff --git a/vendor/libkqueue/Vagrantfile b/vendor/libkqueue/Vagrantfile new file mode 100644 index 000000000..a280b7170 --- /dev/null +++ b/vendor/libkqueue/Vagrantfile @@ -0,0 +1,71 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# All Vagrant configuration is done below. The "2" in Vagrant.configure +# configures the configuration version (we support older styles for +# backwards compatibility). Please don't change it unless you know what +# you're doing. +Vagrant.configure("2") do |config| + # The most common configuration options are documented and commented below. + # For a complete reference, please see the online documentation at + # https://docs.vagrantup.com. + + # Every Vagrant development environment requires a box. You can search for + # boxes at https://atlas.hashicorp.com/search. + config.vm.box = "hashicorp/precise64" + + # Disable automatic box update checking. If you disable this, then + # boxes will only be checked for updates when the user runs + # `vagrant box outdated`. This is not recommended. + # config.vm.box_check_update = false + + # Create a forwarded port mapping which allows access to a specific port + # within the machine from a port on the host machine. In the example below, + # accessing "localhost:8080" will access port 80 on the guest machine. + # config.vm.network "forwarded_port", guest: 80, host: 8080 + + # Create a private network, which allows host-only access to the machine + # using a specific IP. + # config.vm.network "private_network", ip: "192.168.33.10" + + # Create a public network, which generally matched to bridged network. + # Bridged networks make the machine appear as another physical device on + # your network. + # config.vm.network "public_network" + + # Share an additional folder to the guest VM. The first argument is + # the path on the host to the actual folder. The second argument is + # the path on the guest to mount the folder. And the optional third + # argument is a set of non-required options. + # config.vm.synced_folder "../data", "/vagrant_data" + + # Provider-specific configuration so you can fine-tune various + # backing providers for Vagrant. These expose provider-specific options. + # Example for VirtualBox: + # + # config.vm.provider "virtualbox" do |vb| + # # Display the VirtualBox GUI when booting the machine + # vb.gui = true + # + # # Customize the amount of memory on the VM: + # vb.memory = "1024" + # end + # + # View the documentation for the provider you are using for more + # information on available options. + + # Define a Vagrant Push strategy for pushing to Atlas. Other push strategies + # such as FTP and Heroku are also available. See the documentation at + # https://docs.vagrantup.com/v2/push/atlas.html for more information. + # config.push.define "atlas" do |push| + # push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME" + # end + + # Enable provisioning with a shell script. Additional provisioners such as + # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the + # documentation for more information about their specific syntax and use. + config.vm.provision "shell", inline: <<-SHELL + apt-get update + apt-get install -y gcc make autoconf automake libtool + SHELL +end From e150f519f2eed5fc2f5e6e757703f072bfb8e832 Mon Sep 17 00:00:00 2001 From: Hubertus Franke Date: Wed, 29 Jun 2016 17:29:15 -0400 Subject: [PATCH 0600/1120] support for kevent type timer resolutions add documentation for timer resolution --- vendor/libkqueue/include/sys/event.h | 9 ++++++++ vendor/libkqueue/kqueue.2 | 16 ++++++++++++- vendor/libkqueue/src/linux/timer.c | 34 +++++++++++++++++++++++----- 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index 610ab4493..087917df1 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -168,6 +168,15 @@ struct kevent { program */ #define VQ_NOTRESPLOCK 0x0080 /* server lockd down */ +/* + * data/hint flags for EVFILT_TIMER as suported and defined in kevent64 + */ +#define NOTE_SECONDS 0x0001 /* time specified in seconds */ +#define NOTE_USECONDS 0x0002 /* time specified in micro seconds */ +#define NOTE_NSECONDS 0x0004 /* time specified in nano seconds */ +#define NOTE_ABSOLUTE 0x0008 /* data is an absolute timeout */ + + #ifndef __KERNEL__ #ifdef __cplusplus diff --git a/vendor/libkqueue/kqueue.2 b/vendor/libkqueue/kqueue.2 index 22cca6ccb..d8b5414f9 100644 --- a/vendor/libkqueue/kqueue.2 +++ b/vendor/libkqueue/kqueue.2 @@ -364,7 +364,21 @@ Establishes an arbitrary timer identified by .Va ident . When adding a timer, .Va data -specifies the timeout period in milliseconds. +specifies the timeout period and +.Va fflags +can be set to one of the following: +.Bl -tag -width XXNOTE_RENAME +.It NOTE_SECONDS +data is in seconds +.It NOTE_USECONDS +data is in microseconds +.It NOTE_NSECONDS +data is in nanoseconds +.It NOTE_ABSOLUTE +data is an absolute timeout +.El +.Pp +If fflags is not set, the default is milliseconds. The timer will be periodic unless EV_ONESHOT is specified. On return, .Va data diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 7cd48c5d6..06ddfc8bb 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -79,14 +79,33 @@ itimerspec_dump(struct itimerspec *ts) } #endif -/* Convert milliseconds into seconds+nanoseconds */ +/* Convert time data into seconds+nanoseconds */ + +#define NOTE_TIMER_MASK (NOTE_ABSOLUTE-1) + static void -convert_msec_to_itimerspec(struct itimerspec *dst, int src, int oneshot) +convert_timedata_to_itimerspec(struct itimerspec *dst, long src, + unsigned int flags, int oneshot) { time_t sec, nsec; - sec = src / 1000; - nsec = (src % 1000) * 1000000; + switch (flags & NOTE_TIMER_MASK) { + case NOTE_USECONDS: + sec = src / 1000000; + nsec = (src % 1000000); + break; + case NOTE_NSECONDS: + sec = src / 1000000000; + nsec = (src % 1000000000); + break; + case NOTE_SECONDS: + sec = src; + nsec = 0; + break; + default: /* milliseconds */ + sec = src / 1000; + nsec = (src % 1000) * 1000000; + } /* Set the interval */ if (oneshot) { @@ -133,6 +152,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) struct epoll_event ev; struct itimerspec ts; int tfd; + int flags; kn->kev.flags |= EV_CLEAR; @@ -143,8 +163,10 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) } dbg_printf("created timerfd %d", tfd); - convert_msec_to_itimerspec(&ts, kn->kev.data, kn->kev.flags & EV_ONESHOT); - if (timerfd_settime(tfd, 0, &ts, NULL) < 0) { + convert_timedata_to_itimerspec(&ts, kn->kev.data, kn->kev.fflags, + kn->kev.flags & EV_ONESHOT); + flags = (kn->kev.fflags & NOTE_ABSOLUTE) ? TFD_TIMER_ABSTIME : 0; + if (timerfd_settime(tfd, flags, &ts, NULL) < 0) { dbg_printf("timerfd_settime(2): %s", strerror(errno)); close(tfd); return (-1); From dcb4d202edf96f5a2f5d200497123ad9490a2c2a Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sun, 24 Jul 2016 21:23:24 -0400 Subject: [PATCH 0601/1120] Update changelog for v2.1.0 --- vendor/libkqueue/ChangeLog | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index cb8feed24..177db1009 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,10 +1,27 @@ -Unreleased HEAD +2016-07-24 v2.1.0 ------------------------------------------------------------------------ + * Fix an endianness issue when calling ioctl on Linux. + (Credit: Vivian Kong) + + * Allow tests to be built from separate build directory. + (Credit: Chris Bailey) + + * Add support for kevent64(2) timers from Darwin. + (Credit: Hubertus Franke) + + * Set EPOLLONESHOT for EPOLL_CTL_ADD after knote creation. + (Credit: Ian Partridge) + + * Add configure arg to disable install and build noinst ltlibrary. + (Credit: Ian Partridge) + + * Allow libkqueue to be used as a submodule within another build process. + (Credit: Ian Partridge) + * Fix a build failure on Linux/AArch64 using Ubuntu 16.04. (Credit: Galen Rhodes) - 2016-02-06 v2.0.4 ------------------------------------------------------------------------ From ce36ae0532361c26e0ee4d99b02e8cd9288e3198 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sun, 24 Jul 2016 21:25:09 -0400 Subject: [PATCH 0602/1120] Bump version in Autoconf --- vendor/libkqueue/configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/configure.ac b/vendor/libkqueue/configure.ac index a0f065584..6d9e47c88 100644 --- a/vendor/libkqueue/configure.ac +++ b/vendor/libkqueue/configure.ac @@ -1,7 +1,7 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. -AC_INIT([libkqueue], [2.0.4]) +AC_INIT([libkqueue], [2.1.0]) LT_INIT AM_INIT_AUTOMAKE([foreign subdir-objects]) AC_CONFIG_SRCDIR([configure.ac]) From ecfaff9ef082fbd0e73412f874f01d16318f642e Mon Sep 17 00:00:00 2001 From: Gonzalo Larralde Date: Wed, 31 Aug 2016 01:22:46 -0300 Subject: [PATCH 0603/1120] Add option to provide Bionic Libc (Android) support --- vendor/libkqueue/Makefile.am | 6 ++++++ vendor/libkqueue/configure.ac | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/vendor/libkqueue/Makefile.am b/vendor/libkqueue/Makefile.am index 5d1a8a787..5d2b5c620 100644 --- a/vendor/libkqueue/Makefile.am +++ b/vendor/libkqueue/Makefile.am @@ -35,7 +35,9 @@ libkqueue_la_SOURCES = \ src/common/tree.h \ src/linux/platform.h +if !BIONIC_LIBC libkqueue_la_LIBADD = -lpthread -lrt +endif pkgconfigdir=$(libdir)/pkgconfig pkgconfig_DATA=libkqueue.pc @@ -58,6 +60,10 @@ kqtest_SOURCES = \ kqtest_CFLAGS = -g -O0 -Wall -Werror -I$(top_srcdir)/include -I$(top_srcdir)/test -I$(builddir) +if BIONIC_LIBC +kqtest_LDADD = -lpthread +else kqtest_LDADD = -lpthread -lrt libkqueue.la +endif diff --git a/vendor/libkqueue/configure.ac b/vendor/libkqueue/configure.ac index 6d9e47c88..f74225078 100644 --- a/vendor/libkqueue/configure.ac +++ b/vendor/libkqueue/configure.ac @@ -16,6 +16,14 @@ AC_ARG_ENABLE([libkqueue-install], ) AM_CONDITIONAL([INSTALL],[test "x$enable_libkqueue_install" != "xno"]) +# Add option to provide Bionic Libc (Android) support +AC_ARG_ENABLE([bionic-libc], + [AS_HELP_STRING([--enable-bionic-libc], + [Build for Bionic Libc (Android)])],, + [enable_bionic_libc=yes] +) +AM_CONDITIONAL(BIONIC_LIBC, [test "x$enable_bionic_libc" == "xyes"]) + AC_CHECK_HEADER([sys/event.h]) AC_CHECK_DECL([EPOLLRDHUP], [], [], [[#include ]]) AC_CHECK_DECL([ppoll], [], [], [[ From 0133ed401617cea724ae9231779371ecfa8ed3f2 Mon Sep 17 00:00:00 2001 From: Gonzalo Larralde Date: Fri, 2 Sep 2016 20:25:47 -0300 Subject: [PATCH 0604/1120] Wrong library being referenced for kqtest. --- vendor/libkqueue/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/Makefile.am b/vendor/libkqueue/Makefile.am index 5d2b5c620..1dca508fc 100644 --- a/vendor/libkqueue/Makefile.am +++ b/vendor/libkqueue/Makefile.am @@ -61,7 +61,7 @@ kqtest_SOURCES = \ kqtest_CFLAGS = -g -O0 -Wall -Werror -I$(top_srcdir)/include -I$(top_srcdir)/test -I$(builddir) if BIONIC_LIBC -kqtest_LDADD = -lpthread +kqtest_LDADD = libkqueue.la else kqtest_LDADD = -lpthread -lrt libkqueue.la endif From 27d0ca430ab4838aa30d781d947375a1f5cd3786 Mon Sep 17 00:00:00 2001 From: David Grove Date: Tue, 20 Sep 2016 17:59:32 -0400 Subject: [PATCH 0605/1120] fix linux build break introduced by bionic-libc change Fixes build break on Linux introduced by d90d1ab. If no explicit command line argument is given, enable_bionic_libc should default to no. --- vendor/libkqueue/configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/configure.ac b/vendor/libkqueue/configure.ac index f74225078..a49f700ad 100644 --- a/vendor/libkqueue/configure.ac +++ b/vendor/libkqueue/configure.ac @@ -20,7 +20,7 @@ AM_CONDITIONAL([INSTALL],[test "x$enable_libkqueue_install" != "xno"]) AC_ARG_ENABLE([bionic-libc], [AS_HELP_STRING([--enable-bionic-libc], [Build for Bionic Libc (Android)])],, - [enable_bionic_libc=yes] + [enable_bionic_libc=no] ) AM_CONDITIONAL(BIONIC_LIBC, [test "x$enable_bionic_libc" == "xyes"]) From 3044ea9ae65455a5f4f44f88231928b64fe70d18 Mon Sep 17 00:00:00 2001 From: David Grove Date: Thu, 22 Sep 2016 10:26:20 -0400 Subject: [PATCH 0606/1120] Add .gitignore to ignore generated artifacts --- vendor/libkqueue/.gitignore | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 vendor/libkqueue/.gitignore diff --git a/vendor/libkqueue/.gitignore b/vendor/libkqueue/.gitignore new file mode 100644 index 000000000..beb9d5d93 --- /dev/null +++ b/vendor/libkqueue/.gitignore @@ -0,0 +1,37 @@ +# build files generated by autotools +Makefile +Makefile.in +aclocal.m4 +autom4te.cache +compile +configure +config.guess +config.h +config.h.in +config.h.in~ +config.log +config.status +config.sub +config +depcomp +install-sh +libkqueue.pc +libtool +ltmain.sh +m4 +missing +stamp-h1 + +# more generated files +.dirstamp +.deps +.libs +*.lo +*.la +*.o + +# generated test artifacts +*.log +*.trs +test-driver +kqtest \ No newline at end of file From a84254214aa6ebba9ae35d98182df2cb0bc27b70 Mon Sep 17 00:00:00 2001 From: lammertb Date: Mon, 17 Oct 2016 09:55:03 +0200 Subject: [PATCH 0607/1120] Fixed timespec redefinition in Visual Studio 2015 --- vendor/libkqueue/include/sys/event.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index 087917df1..053910495 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -185,10 +185,14 @@ extern "C" { #ifdef _WIN32 +#if (_MSC_VER < 1900) struct timespec { time_t tv_sec; long tv_nsec; }; +#else +#include +#endif __declspec(dllexport) int kqueue(void); From dab726868a055013439f7d7217d4dd28e6bfeb43 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 18 Oct 2016 17:41:32 -0400 Subject: [PATCH 0608/1120] Now on 2.1.0 (which will be 2.1.1 when this is released) --- vendor/libkqueue/libkqueue.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/libkqueue.spec b/vendor/libkqueue/libkqueue.spec index 36a581acc..2d25541aa 100644 --- a/vendor/libkqueue/libkqueue.spec +++ b/vendor/libkqueue/libkqueue.spec @@ -1,6 +1,6 @@ Name: libkqueue Summary: Userspace implementation of the kqueue event notification mechanism -Version: 2.0.1 +Version: 2.1.1 Release: 1 # The entire source code is MIT, event.h which is BSD (2-clause) License: MIT and BSD From f954ffcb8234c9e1081520a3679d514b1f1b50b9 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Mon, 5 Dec 2016 20:51:56 -0800 Subject: [PATCH 0609/1120] build: normalise whitespace The vast majority of the cmake rules were indented using hard tabs. Make everything uniform and clean up some bleeding whitespace. NFC. --- vendor/libkqueue/CMakeLists.txt | 36 ++++++++++++++++----------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index dfc32de10..ed8ef10fe 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -19,33 +19,33 @@ INCLUDE (CheckIncludeFiles) project(kqueue) -#files +# files file(GLOB_RECURSE INCL include/*.h) source_group(includes FILES ${INCL}) if(WIN32) - file(GLOB SRC + file(GLOB SRC src/windows/*.h src/windows/*.c - src/common/*.h + src/common/*.h src/*.c - src/common/map.c - src/common/filter.c - src/common/knote.c - src/common/kevent.c - src/common/kqueue.c + src/common/map.c + src/common/filter.c + src/common/knote.c + src/common/kevent.c + src/common/kqueue.c ) add_definitions( -DLIBKQUEUE_EXPORTS -D_USRDLL -D_WINDLL ) - if(MINGW) - SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -march=i486") - SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -march=i486") - endif() + if(MINGW) + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -march=i486") + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -march=i486") + endif() else() - file(GLOB SRC + file(GLOB SRC src/posix/*.h src/posix/platform.c src/linux/*.h @@ -62,7 +62,7 @@ else() src/common/knote.c src/common/map.c src/common/kevent.c - src/common/kqueue.c + src/common/kqueue.c ) include_directories( src/common @@ -86,9 +86,9 @@ include_directories( option(STATIC_KQUEUE "Enable to build libkqueue as static lib" OFF) if(STATIC_KQUEUE) message("-- building libkqueue as static lib") - add_library(kqueue STATIC ${SRC} ${INCL}) + add_library(kqueue STATIC ${SRC} ${INCL}) else() - add_library(kqueue SHARED ${SRC} ${INCL}) + add_library(kqueue SHARED ${SRC} ${INCL}) endif() if(WIN32) @@ -103,6 +103,6 @@ set_target_properties(kqueue PROPERTIES DEBUG_POSTFIX "D") #tests option(KQUEUE_TESTS "Enable to build tests for libkqueue" OFF) if(KQUEUE_TESTS) - message("-- Adding tests for libkqueue") - add_subdirectory(test) + message("-- Adding tests for libkqueue") + add_subdirectory(test) endif() From a179512197719e2dd7367d65f16ca077a4256e19 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Mon, 5 Dec 2016 22:56:48 -0800 Subject: [PATCH 0610/1120] rewrite the build system This rewrites the CMake to use more modern features and support Windows and Linux (and an untested Solaris target) via the CMake based build system. This eases cross-compilation as well. --- vendor/libkqueue/CMakeLists.txt | 190 +++++++++++++++++++------------- vendor/libkqueue/config.h.in | 11 ++ 2 files changed, 126 insertions(+), 75 deletions(-) create mode 100644 vendor/libkqueue/config.h.in diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index ed8ef10fe..ca53208ab 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -14,95 +14,135 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -cmake_minimum_required(VERSION 2.8) -INCLUDE (CheckIncludeFiles) +cmake_minimum_required(VERSION 2.8.4) +cmake_policy(SET CMP0063 OLD) -project(kqueue) +project(kqueue C) -# files -file(GLOB_RECURSE INCL include/*.h) -source_group(includes FILES ${INCL}) +set(CMAKE_C_VISIBILITY_PRESET hidden) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_STANDARD 99) -if(WIN32) - file(GLOB SRC - src/windows/*.h - src/windows/*.c - src/common/*.h - src/*.c - src/common/map.c - src/common/filter.c - src/common/knote.c - src/common/kevent.c - src/common/kqueue.c - ) - add_definitions( - -DLIBKQUEUE_EXPORTS - -D_USRDLL - -D_WINDLL - ) - if(MINGW) - SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -march=i486") - SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -march=i486") - endif() +option(STATIC_KQUEUE "build libkqueue as static library" OFF) +option(ENABLE_TESTS "build tests for libkqueue" OFF) + +set(CMAKE_THREAD_PREFER_PTHREAD TRUE) +set(THREADS_PREFER_PTHREADS_FLAG TRUE) +find_package(Threads REQUIRED) + +include(CheckIncludeFiles) +include(CheckSymbolExists) + +check_include_files(sys/signalfd.h HAVE_SYS_SIGNALFD_H) +check_include_files(sys/timerfd.h HAVE_SYS_TIMERFD_H) +check_include_files(sys/eventfd.h HAVE_SYS_EVENTFD_H) +if(ENABLE_TESTS) + check_include_files(err.h HAVE_ERR_H) +endif() + +check_symbol_exists(EPOLLRDHUP sys/epoll.h HAVE_EPOLLRDHUP) +check_symbol_exists(NOTE_TRUNCATE sys/event.h HAVE_NOTE_TRUNCATE) +if(ENABLE_TESTS) + check_symbol_exists(NOTE_REVOKE sys/event.h HAVE_NOTE_REVOKE) +endif() + +set(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE) +check_symbol_exists(ppoll poll.h HAVE_DECL_PPOLL) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/config.h) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +set(LIBKQUEUE_HEADERS + include/sys/event.h) + +set(LIBKQUEUE_SOURCES + src/common/alloc.h + src/common/debug.h + src/common/filter.c + src/common/kevent.c + src/common/knote.c + src/common/kqueue.c + src/common/map.c + src/common/private.h + src/common/queue.h + src/common/tree.h) + +if(CMAKE_SYSTEM_NAME MATCHES Windows) + list(APPEND LIBKQUEUE_SOURCES + src/windows/platform.c + src/windows/platform.h + src/windows/read.c + src/windows/stdint.h + src/windows/timer.c + src/windows/user.c) +elseif(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") + list(APPEND LIBKQUEUE_SOURCES + src/posix/platform.c + src/posix/platform.h + src/solaris/platform.c + src/solaris/platform.h + src/solaris/signal.c + src/solaris/socket.c + src/solaris/timer.c + src/solaris/user.c) +elseif(CMAKE_SYSTEM_NAME STREQUAL Linux) + list(APPEND LIBKQUEUE_SOURCES + src/posix/platform.c + src/posix/platform.h + src/linux/platform.c + src/linux/platform.h + src/linux/read.c + src/linux/signal.c + src/linux/timer.c + src/linux/user.c + src/linux/vnode.c + src/linux/write.c) else() - file(GLOB SRC - src/posix/*.h - src/posix/platform.c - src/linux/*.h - src/linux/platform.c - src/linux/signal.c - src/linux/socket.c - src/linux/timer.c - src/linux/user.c - src/linux/vnode.c - src/linux/write.c - src/linux/read.c - src/common/*.h - src/common/filter.c - src/common/knote.c - src/common/map.c - src/common/kevent.c - src/common/kqueue.c - ) - include_directories( - src/common - ) - add_definitions( - -Wall -Werror - -fpic - -D_XOPEN_SOURCE=600 - -std=c99 - -fvisibility=hidden - ) + message(FATAL_ERROR "unsupported host os") endif() -source_group(src FILES ${SRC}) -#includes -include_directories( - include -) +source_group(includes + FILES + ${LIBKQUEUE_HEADERS}) +source_group(src + FILES + ${LIBKQUEUE_SOURCES}) -#library (static or shared) -option(STATIC_KQUEUE "Enable to build libkqueue as static lib" OFF) if(STATIC_KQUEUE) - message("-- building libkqueue as static lib") - add_library(kqueue STATIC ${SRC} ${INCL}) + set(LIBRARY_TYPE STATIC) else() - add_library(kqueue SHARED ${SRC} ${INCL}) + set(LIBRARY_TYPE SHARED) endif() +add_library(kqueue ${LIBRARY_TYPE} ${LIBKQUEUE_SOURCES} ${LIBKQUEUE_HEADERS}) +set_target_properties(kqueue PROPERTIES DEBUG_POSTFIX "D") + if(WIN32) - set(LIB ${LIB} Ws2_32) + target_compile_definitions(kqueue PRIVATE LIBKQUEUE_EXPORTS;_USRDLL;_WINDLL) +else() + target_compile_definitions(kqueue PRIVATE _XOPEN_SOURCE=600) endif() + +target_include_directories(kqueue PRIVATE include) if(NOT WIN32) - set(LIB ${LIB} pthread) + target_include_directories(kqueue PRIVATE src/common) endif() -target_link_libraries(kqueue ${LIB}) -set_target_properties(kqueue PROPERTIES DEBUG_POSTFIX "D") -#tests -option(KQUEUE_TESTS "Enable to build tests for libkqueue" OFF) -if(KQUEUE_TESTS) - message("-- Adding tests for libkqueue") - add_subdirectory(test) +if(CMAKE_C_COMPILER_ID MATCHES GNU) + target_compile_options(kqueue PRIVATE -Wall -Werror) +endif() +if(MINGW AND CMAKE_C_COMPILER_ID MATCHES GNU) + target_compile_options(kqueue PRIVATE -march=i486) +endif() + +if(WIN32) + target_link_libraries(kqueue PRIVATE Ws2_32) +endif() +target_link_libraries(kqueue PRIVATE ${CMAKE_THREAD_LIBS_INIT}) + +if(ENABLE_TESTS) + add_subdirectory(test) endif() + diff --git a/vendor/libkqueue/config.h.in b/vendor/libkqueue/config.h.in new file mode 100644 index 000000000..cec3300ed --- /dev/null +++ b/vendor/libkqueue/config.h.in @@ -0,0 +1,11 @@ + +#cmakedefine01 HAVE_SYS_SIGNALFD_H +#cmakedefine01 HAVE_SYS_TIMERFD_H +#cmakedefine01 HAVE_SYS_EVENTFD_H +#cmakedefine01 HAVE_ERR_H + +#cmakedefine01 HAVE_EPOLLRDHUP +#cmakedefine01 HAVE_NOTE_TRUNCATE +#cmakedefine01 HAVE_DECL_PPOLL +#cmakedefine01 HAVE_NOTE_REVOKE + From bf5a0fca9b61135213edbeaf444e2307c524e72d Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 6 Dec 2016 20:42:55 -0800 Subject: [PATCH 0611/1120] windows: clear up some warnings from clang on Windows Address some -Wincompatible-pointer-types-discards-qualifier and -Wincompatible-pointer-types warnings from clang. Since the atomic operands are often int types and the _Interlocked{In,De}crement functions on Windows expect a `LONG volatile *`, clang emits a warning. Silence the warning with an explicit cast to the type. Identified by clang-cl 3.9.0 on Visual Studio 14. --- vendor/libkqueue/src/windows/platform.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index a9c98c19a..78dda4ba3 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -46,8 +46,8 @@ /* * Atomic integer operations */ -#define atomic_inc InterlockedIncrement -#define atomic_dec InterlockedDecrement +#define atomic_inc(value) InterlockedIncrement((LONG volatile *)value) +#define atomic_dec(value) InterlockedDecrement((LONG volatile *)value) #define atomic_cas(p, oval, nval) InterlockedCompareExchange(p, nval, oval) #define atomic_ptr_cas(p, oval, nval) InterlockedCompareExchangePointer(p, nval, oval) From fba7d36d336200dedd26ae2896bb1256efb52470 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 6 Dec 2016 20:49:51 -0800 Subject: [PATCH 0612/1120] build: tweak compile definitions for Windows Don't add LIBKQUEUE_EXPORTS. With CMake, we will have kqueue_EXPORTS available for that purpose. Furthermore, the macro definition is not currently used. Remove the unnecessary macro pollution. Clean up the compile warnings on "modern" Windows caused by the functions being marked with __declspec(deprecated(...)). When built with additional warnings, the deprecated warning spew is pretty high. Identified by clang-cl 3.9.0 on Visual Studio 14. This now builds clean. --- vendor/libkqueue/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index ca53208ab..4dcf1887a 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -120,7 +120,8 @@ add_library(kqueue ${LIBRARY_TYPE} ${LIBKQUEUE_SOURCES} ${LIBKQUEUE_HEADERS}) set_target_properties(kqueue PROPERTIES DEBUG_POSTFIX "D") if(WIN32) - target_compile_definitions(kqueue PRIVATE LIBKQUEUE_EXPORTS;_USRDLL;_WINDLL) + target_compile_definitions(kqueue PRIVATE _USRDLL;_WINDLL) + target_compile_definitions(kqueue PRIVATE _CRT_SECURE_NO_WARNINGS) else() target_compile_definitions(kqueue PRIVATE _XOPEN_SOURCE=600) endif() From 0b7ea14674198a1cf2993106fe520ba88469fe62 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 6 Dec 2016 20:57:22 -0800 Subject: [PATCH 0613/1120] build: remove the visual studio project The CMake based build is able to generate a visual studio project for both building and editing on Windows. Support CMake as the canonical build system on Windows as well as the source for the project. --- vendor/libkqueue/libkqueue.sln | 29 ------- vendor/libkqueue/libkqueue.vcxproj | 96 ---------------------- vendor/libkqueue/libkqueue.vcxproj.filters | 67 --------------- 3 files changed, 192 deletions(-) delete mode 100644 vendor/libkqueue/libkqueue.sln delete mode 100644 vendor/libkqueue/libkqueue.vcxproj delete mode 100644 vendor/libkqueue/libkqueue.vcxproj.filters diff --git a/vendor/libkqueue/libkqueue.sln b/vendor/libkqueue/libkqueue.sln deleted file mode 100644 index 57f8dd011..000000000 --- a/vendor/libkqueue/libkqueue.sln +++ /dev/null @@ -1,29 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual C++ Express 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libkqueue", "libkqueue.vcxproj", "{A29A2A03-DD72-6A48-80FB-43EE0B1A16E7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kqtest", "test\kqtest.vcxproj", "{7578F752-17DD-C6A5-C895-A00098131EEA}" - ProjectSection(ProjectDependencies) = postProject - {A29A2A03-DD72-6A48-80FB-43EE0B1A16E7} = {A29A2A03-DD72-6A48-80FB-43EE0B1A16E7} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A29A2A03-DD72-6A48-80FB-43EE0B1A16E7}.Debug|Win32.ActiveCfg = Debug|Win32 - {A29A2A03-DD72-6A48-80FB-43EE0B1A16E7}.Debug|Win32.Build.0 = Debug|Win32 - {A29A2A03-DD72-6A48-80FB-43EE0B1A16E7}.Release|Win32.ActiveCfg = Release|Win32 - {A29A2A03-DD72-6A48-80FB-43EE0B1A16E7}.Release|Win32.Build.0 = Release|Win32 - {7578F752-17DD-C6A5-C895-A00098131EEA}.Debug|Win32.ActiveCfg = Debug|Win32 - {7578F752-17DD-C6A5-C895-A00098131EEA}.Debug|Win32.Build.0 = Debug|Win32 - {7578F752-17DD-C6A5-C895-A00098131EEA}.Release|Win32.ActiveCfg = Release|Win32 - {7578F752-17DD-C6A5-C895-A00098131EEA}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/vendor/libkqueue/libkqueue.vcxproj b/vendor/libkqueue/libkqueue.vcxproj deleted file mode 100644 index 361b08368..000000000 --- a/vendor/libkqueue/libkqueue.vcxproj +++ /dev/null @@ -1,96 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - Win32Proj - - - - DynamicLibrary - true - - - DynamicLibrary - false - - - - - - - - - - - - - true - - - true - - - - WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBKQUEUE_EXPORTS;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level3 - ProgramDatabase - Disabled - - - MachineX86 - true - Windows - msvcrtd.lib;Libcmtd.lib;Ws2_32.lib;%(AdditionalDependencies) - - - - - WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBKQUEUE_EXPORTS;%(PreprocessorDefinitions) - MultiThreadedDLL - Level3 - ProgramDatabase - - - MachineX86 - true - Windows - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/libkqueue/libkqueue.vcxproj.filters b/vendor/libkqueue/libkqueue.vcxproj.filters deleted file mode 100644 index 986e4f4fe..000000000 --- a/vendor/libkqueue/libkqueue.vcxproj.filters +++ /dev/null @@ -1,67 +0,0 @@ - - - - - common - - - common - - - common - - - common - - - common - - - windows - - - windows - - - windows - - - windows - - - windows - - - - - common - - - common - - - common - - - common - - - windows - - - windows - - - windows - - - - - - {d00529d5-005e-4a55-950f-987dc27e5101} - - - {11f5eddb-b2fe-4fc5-9733-f52ee80e8a4c} - - - \ No newline at end of file From fc8587dc769a0035207ebcb7bc49c18db36acb73 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 6 Dec 2016 20:54:36 -0800 Subject: [PATCH 0614/1120] build: clean up warnings on test for Windows When building the tests for Windows with clang-cl 3.9 on Visual Studio 14, the output was completely cluttered with deprecation warnings for a number of APIs that the test uses. Furthermore, the tests have a number of unused variables. Silence the warnings. --- vendor/libkqueue/test/CMakeLists.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/vendor/libkqueue/test/CMakeLists.txt b/vendor/libkqueue/test/CMakeLists.txt index e09c4d754..5a27ef18d 100644 --- a/vendor/libkqueue/test/CMakeLists.txt +++ b/vendor/libkqueue/test/CMakeLists.txt @@ -56,5 +56,17 @@ else() endif() add_executable(libkqueue-test ${SRC}) +target_include_directories(libkqueue-test PRIVATE ${CMAKE_SOURCE_DIR}) +if(WIN32) + target_compile_definitions(libkqueue-test + PRIVATE + _CRT_SECURE_NO_WARNINGS + _CRT_NONSTDC_NO_WARNINGS + _WINSOCK_DEPRECATED_NO_WARNINGS) + if(CMAKE_C_COMPILER_ID MATCHES Clang) + target_compile_options(libkqueue-test PRIVATE -Wno-unused-variable) + endif() +endif() target_link_libraries(libkqueue-test kqueue ${LIBS}) set_target_properties(libkqueue-test PROPERTIES DEBUG_POSTFIX "D") + From f6e154c8d724db566ef40656eeb3701512b60714 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Sat, 17 Dec 2016 10:31:08 -0800 Subject: [PATCH 0615/1120] Windows: fix socket check `fstat` on a socket is poor way to test if a handle is a socket. Use `GetFileType` instead. On debug builds, especially on newer versions, we would trigger an assert. This addresses the TODO in the code path with an alternative and allows the previously failing test to pass as well. --- vendor/libkqueue/src/windows/platform.c | 38 +++++++++++-------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 1f8c04e6c..13f8fac72 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -188,29 +188,25 @@ windows_filter_free(struct kqueue *kq, struct filter *kf) int windows_get_descriptor_type(struct knote *kn) { + switch (GetFileType((HANDLE)kn->kev.ident)) { + case FILE_TYPE_PIPE: { socklen_t slen; + int lsock, i; + slen = sizeof(lsock); + lsock = 0; + i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_ACCEPTCONN, (char *)&lsock, &slen); + if (i == 0 && lsock) + kn->kn_flags |= KNFL_PASSIVE_SOCKET; + break; + } + default: { struct stat sb; - int i, lsock; - - /* - * Test if the descriptor is a socket. - */ - if (fstat( (int)kn->kev.ident, &sb) == 0) { - dbg_printf("HANDLE %d appears to a be regular file", kn->kev.ident); - kn->kn_flags |= KNFL_REGULAR_FILE; - } else { - /* Assume that the HANDLE is a socket. */ - /* TODO: we could do a WSAIoctl and check for WSAENOTSOCK */ - - /* - * Test if the socket is active or passive. - */ - slen = sizeof(lsock); - lsock = 0; - i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_ACCEPTCONN, (char *) &lsock, &slen); - if (i == 0 && lsock) - kn->kn_flags |= KNFL_PASSIVE_SOCKET; + if (fstat((int)kn->kev.ident, &sb) == 0) { + dbg_printf("HANDLE %d appears to be a regular file", kn->kev.ident); + kn->kn_flags |= KNFL_REGULAR_FILE; } + } + } - return (0); + return 0; } From 12130f0363b0a72919f4282af9efda0873782e1e Mon Sep 17 00:00:00 2001 From: David Grove Date: Wed, 21 Dec 2016 17:41:00 -0500 Subject: [PATCH 0616/1120] avoid hardwiring port number in test case Call bind with port 0 to request kernel to auto-assign a free port. Motivated by running kqueue tests in Swift CI environment where we see occasional failures due to the hardwired port already being in use (SR-2941). --- vendor/libkqueue/test/read.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 7d397dba1..cb93dbe35 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -22,26 +22,30 @@ * Create a connected TCP socket. */ static void -create_socket_connection(int *client, int *server, const short port) +create_socket_connection(int *client, int *server) { struct sockaddr_in sain; socklen_t sa_len = sizeof(sain); int one = 1; int clnt, srvr, accepted; + short port; /* Create a passive socket */ memset(&sain, 0, sizeof(sain)); sain.sin_family = AF_INET; - sain.sin_port = htons(port); + sain.sin_port = 0; if ((srvr = socket(PF_INET, SOCK_STREAM, 0)) < 0) err(1, "socket"); if (setsockopt(srvr, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one)) != 0) err(1, "setsockopt"); if (bind(srvr, (struct sockaddr *) &sain, sa_len) < 0) { - printf("unable to bind to port %d\n", port); + printf("unable to bind to auto-assigned port\n"); err(1, "bind-1"); } + if (getsockname(srvr, (struct sockaddr *) &sain, &sa_len) < 0) + err(1, "getsockname-1"); + port = ntohs(sain.sin_port); if (listen(srvr, 100) < 0) err(1, "listen"); @@ -252,19 +256,20 @@ test_kevent_socket_listen_backlog(struct test_context *ctx) short port; int clnt, srvr; - port = 14973 + ctx->iteration; - /* Create a passive socket */ memset(&sain, 0, sizeof(sain)); sain.sin_family = AF_INET; - sain.sin_port = htons(port); + sain.sin_port = 0; if ((srvr = socket(PF_INET, SOCK_STREAM, 0)) < 0) err(1, "socket()"); if (setsockopt(srvr, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one)) != 0) err(1, "setsockopt()"); if (bind(srvr, (struct sockaddr *) &sain, sa_len) < 0) - err(1, "bind-2", port); + err(1, "bind-2"); + if (getsockname(srvr, (struct sockaddr *) &sain, &sa_len) < 0) + err(1, "getsockname-2"); + port = ntohs(sain.sin_port); if (listen(srvr, 100) < 0) err(1, "listen()"); @@ -422,7 +427,7 @@ test_kevent_regular_file(struct test_context *ctx) void test_evfilt_read(struct test_context *ctx) { - create_socket_connection(&ctx->client_fd, &ctx->server_fd, ctx->iteration + 23456); + create_socket_connection(&ctx->client_fd, &ctx->server_fd); test(kevent_socket_add, ctx); test(kevent_socket_del, ctx); From ca22dab69224bc811aa35375c6afc446471c4ec9 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Mon, 26 Dec 2016 19:34:09 -0800 Subject: [PATCH 0617/1120] test: remove Visual Studio solution --- vendor/libkqueue/test/kqtest.sln | 20 ------ vendor/libkqueue/test/kqtest.vcxproj | 94 ---------------------------- 2 files changed, 114 deletions(-) delete mode 100644 vendor/libkqueue/test/kqtest.sln delete mode 100644 vendor/libkqueue/test/kqtest.vcxproj diff --git a/vendor/libkqueue/test/kqtest.sln b/vendor/libkqueue/test/kqtest.sln deleted file mode 100644 index ef1f1695d..000000000 --- a/vendor/libkqueue/test/kqtest.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual C++ Express 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kqtest", "kqtest.vcxproj", "{7578F752-17DD-C6A5-C895-A00098131EEA}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7578F752-17DD-C6A5-C895-A00098131EEA}.Debug|Win32.ActiveCfg = Debug|Win32 - {7578F752-17DD-C6A5-C895-A00098131EEA}.Debug|Win32.Build.0 = Debug|Win32 - {7578F752-17DD-C6A5-C895-A00098131EEA}.Release|Win32.ActiveCfg = Release|Win32 - {7578F752-17DD-C6A5-C895-A00098131EEA}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/vendor/libkqueue/test/kqtest.vcxproj b/vendor/libkqueue/test/kqtest.vcxproj deleted file mode 100644 index 30043fe6a..000000000 --- a/vendor/libkqueue/test/kqtest.vcxproj +++ /dev/null @@ -1,94 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - Win32Proj - - - - Application - true - - - Application - false - - - - - - - - - - - - - true - - - true - - - - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level3 - ProgramDatabase - Disabled - - - MachineX86 - true - Console - wsock32.lib;%(AdditionalDependencies) - - - - - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - Level3 - ProgramDatabase - - - MachineX86 - true - Console - true - true - - - - - - - - - - - - - - - - - - - - {74c1eceb-1d2b-2740-8a0b-9ec65aa06eab} - - - - - - \ No newline at end of file From af0bbcf5cbaf2f82608039d04dc269057911ff2a Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 27 Dec 2016 18:06:07 -0800 Subject: [PATCH 0618/1120] build: remove autotools build Remove the autotools build in favour for the CMake build. Subsequent updates will update the CMake build system to support installation (and packaging!) for Unixish targets. --- vendor/libkqueue/Makefile.am | 69 ------- vendor/libkqueue/config.inc | 117 ----------- vendor/libkqueue/configure.ac | 37 ---- vendor/libkqueue/configure.rb | 320 ------------------------------- vendor/libkqueue/libkqueue.la.in | 35 ---- vendor/libkqueue/test/Makefile | 78 -------- vendor/libkqueue/test/config.inc | 52 ----- vendor/libkqueue/test/configure | 1 - 8 files changed, 709 deletions(-) delete mode 100644 vendor/libkqueue/Makefile.am delete mode 100644 vendor/libkqueue/config.inc delete mode 100644 vendor/libkqueue/configure.ac delete mode 100755 vendor/libkqueue/configure.rb delete mode 100644 vendor/libkqueue/libkqueue.la.in delete mode 100644 vendor/libkqueue/test/Makefile delete mode 100755 vendor/libkqueue/test/config.inc delete mode 120000 vendor/libkqueue/test/configure diff --git a/vendor/libkqueue/Makefile.am b/vendor/libkqueue/Makefile.am deleted file mode 100644 index 1dca508fc..000000000 --- a/vendor/libkqueue/Makefile.am +++ /dev/null @@ -1,69 +0,0 @@ - -# FIXME - Only supports Linux for now - -kqincludedir = $(includedir)/kqueue/sys - -if INSTALL - lib_LTLIBRARIES = libkqueue.la - kqinclude_HEADERS = include/sys/event.h - dist_man_MANS = kqueue.2 -else - noinst_LTLIBRARIES = libkqueue.la -endif - -libkqueue_la_CFLAGS = -I$(top_srcdir)/src/common -I$(top_srcdir)/include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600 -fvisibility=hidden - -libkqueue_la_SOURCES = \ - src/common/filter.c \ - src/common/knote.c \ - src/common/map.c \ - src/common/kevent.c \ - src/common/kqueue.c \ - src/posix/platform.c \ - src/posix/platform.h \ - src/linux/platform.c \ - src/linux/read.c \ - src/linux/write.c \ - src/linux/user.c \ - src/linux/vnode.c \ - src/linux/signal.c \ - src/linux/timer.c \ - src/common/alloc.h \ - src/common/debug.h \ - src/common/private.h \ - src/common/queue.h \ - src/common/tree.h \ - src/linux/platform.h - -if !BIONIC_LIBC -libkqueue_la_LIBADD = -lpthread -lrt -endif - -pkgconfigdir=$(libdir)/pkgconfig -pkgconfig_DATA=libkqueue.pc - -check_PROGRAMS = kqtest - -TESTS = kqtest - -kqtest_SOURCES = \ - test/main.c \ - test/kevent.c \ - test/test.c \ - test/proc.c \ - test/read.c \ - test/signal.c \ - test/timer.c \ - test/vnode.c \ - test/user.c \ - test/common.h - -kqtest_CFLAGS = -g -O0 -Wall -Werror -I$(top_srcdir)/include -I$(top_srcdir)/test -I$(builddir) - -if BIONIC_LIBC -kqtest_LDADD = libkqueue.la -else -kqtest_LDADD = -lpthread -lrt libkqueue.la -endif - - diff --git a/vendor/libkqueue/config.inc b/vendor/libkqueue/config.inc deleted file mode 100644 index 1a0c2095c..000000000 --- a/vendor/libkqueue/config.inc +++ /dev/null @@ -1,117 +0,0 @@ -program="libkqueue" -version="2.0a" -abi_major="0" -abi_minor="0" -abi_version="$abi_major.$abi_minor" -cflags="-Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600" -ldflags="" -sources="src/common/filter.c src/common/knote.c src/common/map.c - src/common/kevent.c src/common/kqueue.c" -libdepends="" -deps="src/common/private.h src/common/debug.h" -mans="kqueue.2" -headers="src/common/private.h" -extra_dist="*.in" -subdirs="src include test" - -# Package metadata -pkg_summary="Emulates the kqueue and kevent system calls" -pkg_description="Emulates the kqueue and kevent system calls" -license="BSD" -author="Mark Heily" - -pre_configure_hook() { - if [ "$debug" = "yes" ] ; then - cflags="$cflags -g3 -O0 -rdynamic" - fi - - if [ "$target" != "windows" ] ; then - cflags="$cflags -fpic" - fi - - optional_headers="err.h" - - libdepends=" -L$libdir" - if [ $target = "linux" ] ; then - - check_symbol sys/epoll.h EPOLLRDHUP - - # TODO - note this as a GCC 4.X dependency - cflags="$cflags -fvisibility=hidden" - - libdepends="$libdepends -lpthread -lrt" - required_headers="sys/epoll.h sys/inotify.h" - optional_headers="sys/signalfd.h sys/timerfd.h sys/eventfd.h" - fi - - if [ $target = "solaris" ] ; then - cflags="$cflags -m64" - ldflags="$ldflags -m64" - libdepends="$libdepends -lsocket -lnsl" - fi -} - -post_configure_hook() { - finalize target "$target" - - platform="src/posix/platform.c" - evfilt_signal="src/posix/signal.c" - evfilt_proc="src/$target/proc.c" - evfilt_socket="src/$target/socket.c" - evfilt_timer="src/posix/timer.c" - evfilt_user="src/posix/user.c" - evfilt_vnode="src/$target/vnode.c" - - if [ $target = "linux" ] ; then - evfilt_user="src/linux/user.c" - evfilt_socket="src/linux/read.c src/linux/write.c" - - #XXX-FIXME disabled - evfilt_proc="" - - if [ "$have_sys_signalfd_h" = "yes" ] ; then - evfilt_signal="src/linux/signal.c" - fi - if [ "$have_sys_timerfd_h" = "yes" ] ; then - evfilt_timer="src/linux/timer.c" - fi - platform="$platform src/linux/platform.c" - fi - - if [ $target = "solaris" ] ; then - cflags="$cflags -D__EXTENSIONS__" - platform="$platform src/solaris/platform.c" - evfilt_timer="src/solaris/timer.c" - evfilt_user="src/solaris/user.c" - evfilt_signal="src/solaris/signal.c" - evfilt_proc="" - evfilt_vnode="" - fi - - # FIXME: This will compile but not actually work - if [ $target = "freebsd" ] ; then - evfilt_signal="src/posix/signal.c" - evfilt_proc="" - evfilt_socket="" - evfilt_timer="" - evfilt_vnode="" - fi - - if [ $target = "windows" ] ; then - platform="src/windows/platform.c" - cflags="$cflags -march=i686 -lws2_32" - ldflags="$ldflags -march=i686" - ldadd="-lws2_32" - evfilt_proc="" - evfilt_signal="" - #evfilt_socket="src/windows/read.c src/linux/write.c" - evfilt_socket="src/windows/read.c" - evfilt_timer="src/windows/timer.c" - evfilt_user="src/windows/user.c" - evfilt_vnode="" - fi - - sources="$sources $platform - $evfilt_signal $evfilt_proc - $evfilt_socket $evfilt_timer $evfilt_user $evfilt_vnode" -} diff --git a/vendor/libkqueue/configure.ac b/vendor/libkqueue/configure.ac deleted file mode 100644 index a49f700ad..000000000 --- a/vendor/libkqueue/configure.ac +++ /dev/null @@ -1,37 +0,0 @@ -# -*- Autoconf -*- -# Process this file with autoconf to produce a configure script. - -AC_INIT([libkqueue], [2.1.0]) -LT_INIT -AM_INIT_AUTOMAKE([foreign subdir-objects]) -AC_CONFIG_SRCDIR([configure.ac]) -AC_CONFIG_HEADERS([config.h]) -AC_PROG_CC - -# When building as submodule allow selection of noinst targets -AC_ARG_ENABLE([libkqueue-install], - [AS_HELP_STRING([--disable-libkqueue-install], - [Disable install rules and build noinst libtool library])],, - [enable_libkqueue_install=yes] -) -AM_CONDITIONAL([INSTALL],[test "x$enable_libkqueue_install" != "xno"]) - -# Add option to provide Bionic Libc (Android) support -AC_ARG_ENABLE([bionic-libc], - [AS_HELP_STRING([--enable-bionic-libc], - [Build for Bionic Libc (Android)])],, - [enable_bionic_libc=no] -) -AM_CONDITIONAL(BIONIC_LIBC, [test "x$enable_bionic_libc" == "xyes"]) - -AC_CHECK_HEADER([sys/event.h]) -AC_CHECK_DECL([EPOLLRDHUP], [], [], [[#include ]]) -AC_CHECK_DECL([ppoll], [], [], [[ -#define _GNU_SOURCE -#include -]]) -AC_CHECK_HEADERS([sys/epoll.h sys/inotify.h sys/signalfd.h sys/timerfd.h sys/eventfd.h]) - - -AC_CONFIG_FILES([Makefile libkqueue.pc]) -AC_OUTPUT diff --git a/vendor/libkqueue/configure.rb b/vendor/libkqueue/configure.rb deleted file mode 100755 index 2fc7e9b0e..000000000 --- a/vendor/libkqueue/configure.rb +++ /dev/null @@ -1,320 +0,0 @@ -#!/usr/bin/env ruby -# -# Copyright (c) 2012 Mark Heily -# -# Permission to use, copy, modify, and distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -begin -require 'makeconf' -rescue LoadError - $LOAD_PATH << "makeconf" - require 'makeconf' -end - -# Determine the list of compiler flags -def get_cflags - cflags='-I./src/common -I./include -Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600'.split(/ /) - - if Platform.is_linux? - # TODO - note this as a GCC 4.X dependency - cflags.push ' -fvisibility=hidden' - end - if Platform.is_solaris? - cflags.push "-D__EXTENSIONS__" - end - cflags -end - -# Determine the list of source code files for libkqueue -def get_source_list(project) - src = %w{ - src/common/filter.c - src/common/knote.c - src/common/map.c - src/common/kevent.c - src/common/kqueue.c - } - - if Platform.is_solaris? - src.push 'src/solaris/signal.c', - 'src/solaris/timer.c', - 'src/solaris/platform.c', - 'src/solaris/user.c' - end - - if Platform.is_linux? or Platform.is_solaris? - src.push 'src/posix/platform.c' - end - - if Platform.is_linux? - src.push 'src/linux/platform.c', - 'src/linux/read.c', - 'src/linux/write.c', - 'src/linux/user.c', - 'src/linux/vnode.c' - - # FIXME: needed for RHEL5 - #src.push 'src/posix/user.c' - - if project.check_header('sys/signalfd.h') - src.push 'src/linux/signal.c' - else - src.push 'src/posix/signal.c' - end - - src.push 'src/linux/timer.c' - end - - if Platform.is_windows? - src.push 'src/windows/timer.c', - 'src/windows/platform.c', - 'src/windows/read.c', - 'src/windows/user.c' - end - - src -end - -# Generate the linker flags -def get_ldadd - ldadd = '' - - if Platform.is_linux? or Platform.is_solaris? - ldadd += ' -lpthread' - end - - if Platform.is_linux? - ldadd += ' -lrt' - end - - if Platform.is_windows? - ldadd += ' ws2_32.lib' - end - - ldadd -end - -# -# MAIN() -# - -project = Project.new \ - :id => 'libkqueue', - :version => '2.0.1' - -kq = Library.new( - :id => 'libkqueue', - :cflags => get_cflags(), - :ldadd => get_ldadd(), - :sources => get_source_list(project) - ) - - -project.check_header 'sys/event.h' -if Platform.is_linux? - project.check_decl 'EPOLLRDHUP', :include => 'sys/epoll.h' - project.check_decl 'ppoll', :cflags => '#define _GNU_SOURCE', :include => 'poll.h' - - - project.check_header('sys/epoll.h') or throw 'epoll is required' - project.check_header('sys/inotify.h') or throw 'inotify is required' - project.check_header %w{ sys/signalfd.h sys/timerfd.h sys/eventfd.h } -end - -project.add(kq) - -project.add(Header.new( - :id => 'event.h', - :sources => 'include/sys/event.h', - :namespace => 'kqueue/sys' - )) - -project.add(Manual.new('kqueue.2', :alias => 'kevent.2')) - -test_ldadd = get_ldadd() -test_ldadd += ' libkqueue.a' -if Platform.is_windows? - project.add( - Test.new( - :id => 'kqtest', - :cflags => '-g -O0 -Wall -Werror -Iinclude -Itest', - :sources => %w{ - test/main.c - test/kevent.c - test/test.c - test/read.c - test/timer.c - test/vnode.c - test/user.c - }, # NOTE: signal.c and proc.c are removed - :ldadd => test_ldadd.split(' ') - ) - ) -else - project.add( - Test.new( - :id => 'kqtest', - :cflags => '-g -O0 -Wall -Werror -I./include -I./test', - :sources => %w{ - test/main.c - test/kevent.c - test/test.c - test/proc.c - test/read.c - test/signal.c - test/timer.c - test/vnode.c - test/user.c - }, - :ldadd => test_ldadd.split(' ') - ) - ) -end - - -project.add(PkgConfig.new( - :name => 'libkqueue', - :description => 'Emulates FreeBSD kqueue(2) on other platforms', - :requires => '', - :libs => '-lkqueue', - :libs_private => '-lpthread', - :export_cflags => '-I${includedir}/kqueue' - )) - -project.packager.add 'libkqueue.spec' - -mc = Makeconf.new() -mc.configure(project) - -__END__ -# -# BEGIN: old config.inc contents -# -program="libkqueue" -version="2.0a" -abi_major="0" -abi_minor="0" -abi_version="$abi_major.$abi_minor" -cflags="-Wall -Wextra -Wno-missing-field-initializers -Werror -g -O2 -std=c99 -D_XOPEN_SOURCE=600" -ldflags="" -sources="src/common/filter.c src/common/knote.c src/common/map.c - src/common/kevent.c src/common/kqueue.c" -libdepends="" -deps="src/common/private.h src/common/debug.h" -mans="kqueue.2" -headers="src/common/private.h" -extra_dist="*.in" -subdirs="src include test" - -# Package metadata -pkg_summary="Emulates the kqueue and kevent system calls" -pkg_description="Emulates the kqueue and kevent system calls" -license="BSD" -author="Mark Heily" - -pre_configure_hook() { - if [ "$debug" = "yes" ] ; then - cflags="$cflags -g3 -O0 -rdynamic" - fi - - if [ "$target" != "windows" ] ; then - cflags="$cflags -fpic" - fi - - optional_headers="err.h" - - libdepends=" -L$libdir" - if [ $target = "linux" ] ; then - - check_symbol sys/epoll.h EPOLLRDHUP - - # TODO - note this as a GCC 4.X dependency - cflags="$cflags -fvisibility=hidden" - - libdepends="$libdepends -lpthread -lrt" - required_headers="sys/epoll.h sys/inotify.h" - optional_headers="sys/signalfd.h sys/timerfd.h sys/eventfd.h" - fi - - if [ $target = "solaris" ] ; then - cflags="$cflags -m64" - ldflags="$ldflags -m64" - libdepends="$libdepends -lsocket -lnsl" - fi -} - -post_configure_hook() { - finalize target "$target" - - platform="src/posix/platform.c" - evfilt_signal="src/posix/signal.c" - evfilt_proc="src/$target/proc.c" - evfilt_socket="src/$target/socket.c" - evfilt_timer="src/posix/timer.c" - evfilt_user="src/posix/user.c" - evfilt_vnode="src/$target/vnode.c" - - if [ $target = "linux" ] ; then - evfilt_user="src/linux/user.c" - evfilt_socket="src/linux/read.c src/linux/write.c" - - #XXX-FIXME disabled - evfilt_proc="" - - if [ "$have_sys_signalfd_h" = "yes" ] ; then - evfilt_signal="src/linux/signal.c" - fi - if [ "$have_sys_timerfd_h" = "yes" ] ; then - evfilt_timer="src/linux/timer.c" - fi - platform="$platform src/linux/platform.c" - fi - - if [ $target = "solaris" ] ; then - cflags="$cflags -D__EXTENSIONS__" - platform="$platform src/solaris/platform.c" - evfilt_timer="src/solaris/timer.c" - evfilt_user="src/solaris/user.c" - evfilt_signal="src/solaris/signal.c" - evfilt_proc="" - evfilt_vnode="" - fi - - # FIXME: This will compile but not actually work - if [ $target = "freebsd" ] ; then - evfilt_signal="src/posix/signal.c" - evfilt_proc="" - evfilt_socket="" - evfilt_timer="" - evfilt_vnode="" - fi - - if [ $target = "windows" ] ; then - platform="src/windows/platform.c" - cflags="$cflags -march=i686 -lws2_32" - ldflags="$ldflags -march=i686" - ldadd="-lws2_32" - evfilt_proc="" - evfilt_signal="" - #evfilt_socket="src/windows/read.c src/linux/write.c" - evfilt_socket="src/windows/read.c" - evfilt_timer="src/windows/timer.c" - evfilt_user="src/windows/user.c" - evfilt_vnode="" - fi - - sources="$sources $platform - $evfilt_signal $evfilt_proc - $evfilt_socket $evfilt_timer $evfilt_user $evfilt_vnode" -} diff --git a/vendor/libkqueue/libkqueue.la.in b/vendor/libkqueue/libkqueue.la.in deleted file mode 100644 index 4e863c595..000000000 --- a/vendor/libkqueue/libkqueue.la.in +++ /dev/null @@ -1,35 +0,0 @@ -# @@PROGRAM@@.la - a libtool library file -# Generated by ltmain.sh - GNU libtool 1.5.20 (1.1220.2.287 2005/08/31 18:54:15) -# -# Please DO NOT delete this file! -# It is necessary for linking the library. - -# The name that we can dlopen(3). -dlname='@@PROGRAM@@.so.0' - -# Names of this library. -library_names='@@PROGRAM@@.so' - -# The name of the static archive. -old_library='@@PROGRAM@@.a' - -# Libraries that this one depends upon. -dependency_libs=' @@LIBDEPENDS@@' - -# Version information for @@PROGRAM@@. -current=0 -age=0 -revision=0 - -# Is this an already installed library? -installed=yes - -# Should we warn about portability when linking against -modules? -shouldnotlink=no - -# Files to dlopen/dlpreopen -dlopen='' -dlpreopen='' - -# Directory that this library needs to be installed in: -libdir='@@LIBDIR@@' diff --git a/vendor/libkqueue/test/Makefile b/vendor/libkqueue/test/Makefile deleted file mode 100644 index 975a71f50..000000000 --- a/vendor/libkqueue/test/Makefile +++ /dev/null @@ -1,78 +0,0 @@ -# -# Copyright (c) 2009 Mark Heily -# -# Permission to use, copy, modify, and distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -tests=kqtest kqtest_debug lockstat static-lib-test - -include config.mk - -all: $(tests) - -lockstat: lockstat.c - $(CC) -o lockstat $(CFLAGS) lockstat.c $(LDADD) - -kqtest: $(SOURCES) - $(CC) -pg -o kqtest -DMAKE_STATIC=1 $(CFLAGS) $(SOURCES) ../libkqueue.a -lpthread - -kqtest_debug: $(SOURCES) - $(CC) -pg -o kqtest_debug -DMAKE_STATIC=1 $(CFLAGS) $(SOURCES) ../libkqueue_debug.a -lpthread - -static-lib-test: $(SOURCES) - $(CC) -o static-lib-test -DMAKE_STATIC=1 $(CFLAGS) $(SOURCES) ../libkqueue.a -lpthread - -check: kqtest - ./kqtest $(KQTEST_OPTS) - -debug: kqtest - gdb ./kqtest $(KQTEST_OPTS) - -valgrind: kqtest - valgrind --tool=memcheck --leak-check=full --show-reachable=yes --num-callers=20 --track-fds=yes ./kqtest - -helgrind: kqtest - valgrind --tool=helgrind ./kqtest -c 25 -n 1 - -callgrind: kqtest - rm -f callgrind.* - valgrind --tool=callgrind --branch-sim=yes ./kqtest || true - kcachegrind callgrind.* - -cachegrind: kqtest - rm -f cachegrind.* - valgrind --tool=cachegrind --branch-sim=yes ./kqtest || true - #CLI: - #cg_annotate cachegrind.* - #GUI: - kcachegrind - -check-installed: - $(CC) -o kqtest $(CFLAGS) $(SOURCES) $(LDADD) -lkqueue - ./kqtest - -check-libtool: - gcc $(CFLAGS) -c *.c - libtool --mode=link gcc -g -O0 -o kqtest *.o $(LIBDIR)/libkqueue.la - ./kqtest - -distclean: clean - rm -f config.mk config.h - for x in libdispatch stress; do cd $$x && make distclean && cd .. ; done - -edit: - $(EDITOR) *.[ch] - -clean: - rm -f *.o *.a $(tests) - for x in libdispatch stress; do cd $$x && make clean && cd ..; done diff --git a/vendor/libkqueue/test/config.inc b/vendor/libkqueue/test/config.inc deleted file mode 100755 index cbaa960c0..000000000 --- a/vendor/libkqueue/test/config.inc +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/sh - -program=libkqueue-test -version=0.1 -cflags="-g -O0 -Wall -Werror -Wl,-rpath,.." -sources="main.c kevent.c test.c proc.c read.c signal.c timer.c vnode.c" - -pre_configure_hook() { - - check_header "err.h" - check_header "sys/event.h" \ - && sys_event_h="sys/event.h" \ - || { - sys_event_h="../include/sys/event.h" - cflags="$cflags -I../include -L.." - if [ "$target" = "windows" ] - then - ldadd="$ldadd ../libkqueue.so" - else - ldadd="$ldadd ../libkqueue_debug.a -lpthread -lrt" - fi - } - - check_symbol $sys_event_h EV_DISPATCH - check_symbol $sys_event_h EV_RECEIPT - check_symbol $sys_event_h NOTE_TRUNCATE - check_symbol $sys_event_h EVFILT_TIMER - check_symbol $sys_event_h EVFILT_USER && \ - sources="$sources user.c" - - if [ "$target" = "solaris" ] - then - ldadd="$ldadd -lsocket -lnsl -m64" - - check_symbol port.h PORT_SOURCE_FILE - fi - - if [ "$target" = "linux" ] - then - cflags="$cflags -rdynamic" - fi - - if [ "$target" = "windows" ] - then - cflags="$cflags -march=i686" - ldflags="$ldflags -march=i686" - ldadd="$ldadd -lws2_32" - # KLUDGE: to remove signal.c, proc.c - sources="main.c kevent.c test.c read.c timer.c user.c vnode.c" - fi - -} diff --git a/vendor/libkqueue/test/configure b/vendor/libkqueue/test/configure deleted file mode 120000 index c9d4efb4f..000000000 --- a/vendor/libkqueue/test/configure +++ /dev/null @@ -1 +0,0 @@ -../configure \ No newline at end of file From 20a681c540a137cc9815de8b9a37ef90240aba3d Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 27 Dec 2016 18:00:43 -0800 Subject: [PATCH 0619/1120] build: add support for installing from CMake We can now install the library, manpage, and pkg-config data from CMake. At this point, for Linux, FreeBSD, Windows, and android, cmake is sufficient and should be treated as the canonical build system. Bump CMake requirement to 3.4.3. This should be old enough to be generally available and matches what LLVM, clang, and swift support as a minimum requirement. --- vendor/libkqueue/CMakeLists.txt | 26 ++++++++++++++++++++++++-- vendor/libkqueue/libkqueue.pc.in | 10 +++++----- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 4dcf1887a..ac6e73325 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -14,10 +14,10 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -cmake_minimum_required(VERSION 2.8.4) +cmake_minimum_required(VERSION 3.4.3) cmake_policy(SET CMP0063 OLD) -project(kqueue C) +project(kqueue VERSION 2.1.1 LANGUAGES C) set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_POSITION_INDEPENDENT_CODE ON) @@ -33,6 +33,7 @@ find_package(Threads REQUIRED) include(CheckIncludeFiles) include(CheckSymbolExists) +include(GNUInstallDirs) check_include_files(sys/signalfd.h HAVE_SYS_SIGNALFD_H) check_include_files(sys/timerfd.h HAVE_SYS_TIMERFD_H) @@ -147,3 +148,24 @@ if(ENABLE_TESTS) add_subdirectory(test) endif() +configure_file("${CMAKE_SOURCE_DIR}/libkqueue.pc.in" + "${CMAKE_BINARY_DIR}/libkqueue.pc" + @ONLY) + +install(FILES + "include/sys/event.h" + DESTINATION + "${CMAKE_INSTALL_FULL_INCLUDEDIR}/sys") +install(TARGETS + kqueue + DESTINATION + "${CMAKE_INSTALL_FULL_LIBDIR}") +install(FILES + kqueue.2 + DESTINATION + "${CMAKE_INSTALL_FULL_MANDIR}") +install(FILES + "${CMAKE_BINARY_DIR}/libkqueue.pc" + DESTINATION + "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig") + diff --git a/vendor/libkqueue/libkqueue.pc.in b/vendor/libkqueue/libkqueue.pc.in index 2c8ec1cc7..ee9939a54 100644 --- a/vendor/libkqueue/libkqueue.pc.in +++ b/vendor/libkqueue/libkqueue.pc.in @@ -1,11 +1,11 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ +includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ Name: libkqueue Description: Emulates FreeBSD kqueue(2) on other platforms -Version: @VERSION@ +Version: @PROJECT_VERSION@ Requires: Libs: -lkqueue Libs.private: -lpthread -lrt From fd6843cfafde50d460ffd504396d6acebe454e97 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 27 Dec 2016 18:51:35 -0800 Subject: [PATCH 0620/1120] build: clean up the test handling for CMake This integrates better into ctest and provides a helpful `make test` target for running the tests. This will help provide a unified packaging infrastructure. --- vendor/libkqueue/CMakeLists.txt | 8 +-- vendor/libkqueue/test/CMakeLists.txt | 73 ++++++++++++---------------- 2 files changed, 36 insertions(+), 45 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index ac6e73325..7407cf393 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -18,6 +18,7 @@ cmake_minimum_required(VERSION 3.4.3) cmake_policy(SET CMP0063 OLD) project(kqueue VERSION 2.1.1 LANGUAGES C) +enable_testing() set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_POSITION_INDEPENDENT_CODE ON) @@ -25,7 +26,6 @@ set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD 99) option(STATIC_KQUEUE "build libkqueue as static library" OFF) -option(ENABLE_TESTS "build tests for libkqueue" OFF) set(CMAKE_THREAD_PREFER_PTHREAD TRUE) set(THREADS_PREFER_PTHREADS_FLAG TRUE) @@ -38,13 +38,13 @@ include(GNUInstallDirs) check_include_files(sys/signalfd.h HAVE_SYS_SIGNALFD_H) check_include_files(sys/timerfd.h HAVE_SYS_TIMERFD_H) check_include_files(sys/eventfd.h HAVE_SYS_EVENTFD_H) -if(ENABLE_TESTS) +if(ENABLE_TESTING) check_include_files(err.h HAVE_ERR_H) endif() check_symbol_exists(EPOLLRDHUP sys/epoll.h HAVE_EPOLLRDHUP) check_symbol_exists(NOTE_TRUNCATE sys/event.h HAVE_NOTE_TRUNCATE) -if(ENABLE_TESTS) +if(ENABLE_TESTING) check_symbol_exists(NOTE_REVOKE sys/event.h HAVE_NOTE_REVOKE) endif() @@ -144,7 +144,7 @@ if(WIN32) endif() target_link_libraries(kqueue PRIVATE ${CMAKE_THREAD_LIBS_INIT}) -if(ENABLE_TESTS) +if(ENABLE_TESTING) add_subdirectory(test) endif() diff --git a/vendor/libkqueue/test/CMakeLists.txt b/vendor/libkqueue/test/CMakeLists.txt index 5a27ef18d..051a1acb3 100644 --- a/vendor/libkqueue/test/CMakeLists.txt +++ b/vendor/libkqueue/test/CMakeLists.txt @@ -14,49 +14,25 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -#files +set(LIBKQUEUE_TEST_SOURCES + kevent.c + main.c + read.c + test.c + timer.c + user.c + vnode.c) if(UNIX) - set(SRC - main.c - kevent.c - test.c - proc.c - read.c - signal.c - timer.c - vnode.c - user.c - ) -else() - set(SRC - common.h - kevent.c - main.c - read.c - test.c - timer.c - user.c - vnode.c - ) + list(APPEND LIBKQUEUE_TEST_SOURCES + proc.c + signal.c) endif() - -#includes -include_directories( - ../include -) - -if(UNIX) - add_definitions( - -rdynamic - ) - set(LIBS pthread rt) -else() - set(LIBS wsock32) -endif() - -add_executable(libkqueue-test ${SRC}) -target_include_directories(libkqueue-test PRIVATE ${CMAKE_SOURCE_DIR}) +add_executable(libkqueue-test ${LIBKQUEUE_TEST_SOURCES}) +target_include_directories(libkqueue-test + PRIVATE + "${CMAKE_SOURCE_DIR}" + "${CMAKE_SOURCE_DIR}/include") if(WIN32) target_compile_definitions(libkqueue-test PRIVATE @@ -66,7 +42,22 @@ if(WIN32) if(CMAKE_C_COMPILER_ID MATCHES Clang) target_compile_options(libkqueue-test PRIVATE -Wno-unused-variable) endif() +elseif(UNIX) + target_compile_options(libkqueue-test + PRIVATE + -rdynamic) +endif() +target_link_libraries(libkqueue-test + PRIVATE + kqueue + ${CMAKE_THREAD_LIBS_INIT}) +if(WIN32) + target_link_libraries(libkqueue-test + PRIVATE + Ws2_32) endif() -target_link_libraries(libkqueue-test kqueue ${LIBS}) set_target_properties(libkqueue-test PROPERTIES DEBUG_POSTFIX "D") +add_test(NAME libkqueue-test + COMMAND libkqueue-test) + From dc1e2d63db943d73de8ed3919ad8642273f25095 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 27 Dec 2016 18:52:49 -0800 Subject: [PATCH 0621/1120] build: modernise/correct threads package detection Use the modern imported library as suggested by CMake's upstream. --- vendor/libkqueue/CMakeLists.txt | 4 ++-- vendor/libkqueue/test/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 7407cf393..64ee2a46a 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -28,7 +28,7 @@ set(CMAKE_C_STANDARD 99) option(STATIC_KQUEUE "build libkqueue as static library" OFF) set(CMAKE_THREAD_PREFER_PTHREAD TRUE) -set(THREADS_PREFER_PTHREADS_FLAG TRUE) +set(THREADS_PREFER_PTHREAD_FLAG TRUE) find_package(Threads REQUIRED) include(CheckIncludeFiles) @@ -142,7 +142,7 @@ endif() if(WIN32) target_link_libraries(kqueue PRIVATE Ws2_32) endif() -target_link_libraries(kqueue PRIVATE ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries(kqueue PRIVATE Threads::Threads) if(ENABLE_TESTING) add_subdirectory(test) diff --git a/vendor/libkqueue/test/CMakeLists.txt b/vendor/libkqueue/test/CMakeLists.txt index 051a1acb3..d51b3dbb1 100644 --- a/vendor/libkqueue/test/CMakeLists.txt +++ b/vendor/libkqueue/test/CMakeLists.txt @@ -50,7 +50,7 @@ endif() target_link_libraries(libkqueue-test PRIVATE kqueue - ${CMAKE_THREAD_LIBS_INIT}) + Threads::Threads) if(WIN32) target_link_libraries(libkqueue-test PRIVATE From 4a96f40c242cd66ebbefdecaaebd537553e7fe93 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 27 Dec 2016 18:53:51 -0800 Subject: [PATCH 0622/1120] build: use Windows naming conventions on Windows Use the lowercase "d" to indicate debug builds as per modern Windows naming conventions rather than an uppercase "D". NFC. --- vendor/libkqueue/CMakeLists.txt | 2 +- vendor/libkqueue/test/CMakeLists.txt | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 64ee2a46a..ad574cd12 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -118,7 +118,7 @@ else() endif() add_library(kqueue ${LIBRARY_TYPE} ${LIBKQUEUE_SOURCES} ${LIBKQUEUE_HEADERS}) -set_target_properties(kqueue PROPERTIES DEBUG_POSTFIX "D") +set_target_properties(kqueue PROPERTIES DEBUG_POSTFIX "d") if(WIN32) target_compile_definitions(kqueue PRIVATE _USRDLL;_WINDLL) diff --git a/vendor/libkqueue/test/CMakeLists.txt b/vendor/libkqueue/test/CMakeLists.txt index d51b3dbb1..01339fcc4 100644 --- a/vendor/libkqueue/test/CMakeLists.txt +++ b/vendor/libkqueue/test/CMakeLists.txt @@ -56,7 +56,9 @@ if(WIN32) PRIVATE Ws2_32) endif() -set_target_properties(libkqueue-test PROPERTIES DEBUG_POSTFIX "D") +set_target_properties(libkqueue-test + PROPERTIES + DEBUG_POSTFIX "d") add_test(NAME libkqueue-test COMMAND libkqueue-test) From 048ccf238beaee923516fddd62f74778e047f405 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 27 Dec 2016 18:54:22 -0800 Subject: [PATCH 0623/1120] build: integrate CPack into the build infrastructure This integrates the basic packaging tools into the build allowing for a unified build system to both build for all the targets as well as package for the various Linux distributions (RPM or DEB). --- vendor/libkqueue/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index ad574cd12..aa8ee8650 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -169,3 +169,8 @@ install(FILES DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig") +set(CPACK_PACKAGE_NAME ${PACKAGE_NAME}) +set(CPACK_PACKAGE_VERSION ${PACKAGE_VERSION}) +set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Mark Heily ") +include(CPack) + From 6dce584afd93fad104a001eab1935c26c934b523 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 27 Dec 2016 19:06:22 -0800 Subject: [PATCH 0624/1120] README: update rules Update the documentation to use CMake for building for all the targets. Add documentation for using CTest for running the tests and CPack for generating the RPM and DEB. Add documentation for building for Windows using Visual Studio and/or clang. --- vendor/libkqueue/README.md | 40 +++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index 2d2f5acaf..935072a09 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -17,31 +17,53 @@ Supported Event Types Installation - Linux, Solaris ----------------------------- - ./configure + cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib make make install Installation - Red Hat ---------------------- - ./configure - make package - rpm -i *.rpm + cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib + make + cpack -G RPM + +Installation - Debian +--------------------- + + cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib + make + cpack -G DEB Installation - Android ---------------------- - ruby ./configure.rb --host=arm-linux-androideabi \ - --with-ndk=/opt/android-ndk-r8c \ - --with-sdk=/opt/android-sdks + cmake -G "Unix Makefiles" -DCMAKE_C_COMPILER= -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib make +Windows (Visual Studio Project) +------------------------------- + + cmake -G "Visual Studio 14 2015" + cmake --build . + +Windows (clang/C2) (Visual Studio Project) +------------------------------------------ + + cmake -G "Visual Studio 14 2015" -T "LLVM-vs2014" + cmake --build . + +Xcode (project) +--------------- + + cmake -G "Xcode" + Running Unit Tests ------------------ - ./configure + cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib -DENABLE_TESTING=YES make - make check + make test Building Applications --------------------- From eddcf03033a7527942d07bc71c47fae18a24e42e Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 27 Dec 2016 19:08:40 -0800 Subject: [PATCH 0625/1120] ports: remove in favour of CMake Now that we have a CMake based system, rely on that to generate the deb package. --- vendor/libkqueue/ports/debian/changelog | 5 -- vendor/libkqueue/ports/debian/compat | 1 - vendor/libkqueue/ports/debian/control | 30 --------- vendor/libkqueue/ports/debian/copyright | 66 ------------------- .../ports/debian/libkqueue-dev.files | 5 -- .../libkqueue/ports/debian/libkqueue0.files | 2 - vendor/libkqueue/ports/debian/rules | 58 ---------------- vendor/libkqueue/ports/debian/source/format | 1 - vendor/libkqueue/ports/debian/watch | 2 - 9 files changed, 170 deletions(-) delete mode 100644 vendor/libkqueue/ports/debian/changelog delete mode 100644 vendor/libkqueue/ports/debian/compat delete mode 100644 vendor/libkqueue/ports/debian/control delete mode 100644 vendor/libkqueue/ports/debian/copyright delete mode 100644 vendor/libkqueue/ports/debian/libkqueue-dev.files delete mode 100644 vendor/libkqueue/ports/debian/libkqueue0.files delete mode 100755 vendor/libkqueue/ports/debian/rules delete mode 100644 vendor/libkqueue/ports/debian/source/format delete mode 100644 vendor/libkqueue/ports/debian/watch diff --git a/vendor/libkqueue/ports/debian/changelog b/vendor/libkqueue/ports/debian/changelog deleted file mode 100644 index 6ab770680..000000000 --- a/vendor/libkqueue/ports/debian/changelog +++ /dev/null @@ -1,5 +0,0 @@ -libkqueue (@@VERSION@@-1) unstable; urgency=low - - * Initial release (Closes: #576317) - - -- Mark Heily Sun, 28 Mar 2010 18:58:58 -0400 diff --git a/vendor/libkqueue/ports/debian/compat b/vendor/libkqueue/ports/debian/compat deleted file mode 100644 index 7f8f011eb..000000000 --- a/vendor/libkqueue/ports/debian/compat +++ /dev/null @@ -1 +0,0 @@ -7 diff --git a/vendor/libkqueue/ports/debian/control b/vendor/libkqueue/ports/debian/control deleted file mode 100644 index 19bf6e984..000000000 --- a/vendor/libkqueue/ports/debian/control +++ /dev/null @@ -1,30 +0,0 @@ -Source: libkqueue -Section: libs -Priority: extra -Maintainer: Mark Heily -Build-Depends: debhelper (>= 7) -Standards-Version: 3.8.4 -Vcs-Svn: svn://mark.heily.com/libkqueue -Homepage: http://mark.heily.com/libkqueue - -Package: libkqueue0 -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} -Description: cross-platform library for kernel event notification - libkqueue is a portable userspace implementation of the kqueue(2) - kernel event notification mechanism found in FreeBSD and other BSD-based - operating systems. The library translates between the kevent structure - and the native kernel facilities of the host machine. - -Package: libkqueue-dev -Section: libdevel -Architecture: any -Depends: libkqueue0 (= ${binary:Version}), ${misc:Depends} -Description: Development files for libkqueue - Contains the header files, manpages, and static libraries for use in - developing applications that use the libkqueue library. - . - libkqueue is a portable userspace implementation of the kqueue(2) - kernel event notification mechanism found in FreeBSD and other BSD-based - operating systems. The library translates between the kevent structure - and the native kernel facilities of the host machine. diff --git a/vendor/libkqueue/ports/debian/copyright b/vendor/libkqueue/ports/debian/copyright deleted file mode 100644 index 78a80afda..000000000 --- a/vendor/libkqueue/ports/debian/copyright +++ /dev/null @@ -1,66 +0,0 @@ -This package was debianized by Mark Heily on -Sun, 28 Mar 2010 18:58:58 -0400 - -It was downloaded from http://mark.heily.com/libkqueue/trunk/ - -Upstream Author(s): - - Mark Heily - -Copyright: - - Copyright (C) 2009 Mark Heily - Copyright (c) 2000 Jonathan Lemon - Copyright 2002 Niels Provos - -License: - - Copyright (c) 2009 Mark Heily - - Permission to use, copy, modify, and distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -Portions of the code taken from FreeBSD are licensed: - - Copyright 2002 Niels Provos - Copyright (c) 1999,2000,2001 Jonathan Lemon - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - -The Debian packaging is: - - Copyright (C) 2010 Mark Heily - -and is licensed under the BSD license, -see `/usr/share/common-licenses/BSD'. - diff --git a/vendor/libkqueue/ports/debian/libkqueue-dev.files b/vendor/libkqueue/ports/debian/libkqueue-dev.files deleted file mode 100644 index bf3eb7035..000000000 --- a/vendor/libkqueue/ports/debian/libkqueue-dev.files +++ /dev/null @@ -1,5 +0,0 @@ -usr/lib/libkqueue.so -usr/lib/pkgconfig/libkqueue.pc -usr/lib/libkqueue.a -usr/include/kqueue/sys/event.h -usr/share/man/man2/* diff --git a/vendor/libkqueue/ports/debian/libkqueue0.files b/vendor/libkqueue/ports/debian/libkqueue0.files deleted file mode 100644 index f026d3297..000000000 --- a/vendor/libkqueue/ports/debian/libkqueue0.files +++ /dev/null @@ -1,2 +0,0 @@ -usr/lib/libkqueue.so.* -usr/lib/libkqueue.so.*.* diff --git a/vendor/libkqueue/ports/debian/rules b/vendor/libkqueue/ports/debian/rules deleted file mode 100755 index ca2dd6aa7..000000000 --- a/vendor/libkqueue/ports/debian/rules +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/make -f - -# Uncomment this to turn on verbose mode. -export DH_VERBOSE=1 - -build: build-stamp -build-stamp: - dh_testdir - CFLAGS="" LDFLAGS="" ./configure --prefix=/usr --mandir=\$${prefix}/share/man - $(MAKE) - touch $@ - -clean: - dh_testdir - dh_testroot - rm -f build-stamp - - # Add here commands to clean up after the build process. - [ ! -f config.mk ] || $(MAKE) distclean - - dh_clean - -install: build - dh_testdir - dh_testroot - dh_prep - dh_installdirs - - # Add here commands to install the package into debian/tmp - $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install - -# Build architecture-independent files here. -binary-indep: install -# We have nothing to do by default. - -# Build architecture-dependent files here. -binary-arch: install - dh_testdir - dh_testroot - dh_movefiles - dh_installchangelogs ChangeLog - dh_installdocs - dh_installexamples - dh_install - dh_installman - dh_link - dh_strip - dh_compress - dh_fixperms - dh_makeshlibs -V - dh_installdeb - dh_shlibdeps - dh_gencontrol - dh_md5sums - dh_builddeb - -binary: binary-indep binary-arch -.PHONY: build clean binary-indep binary-arch binary install diff --git a/vendor/libkqueue/ports/debian/source/format b/vendor/libkqueue/ports/debian/source/format deleted file mode 100644 index d3827e75a..000000000 --- a/vendor/libkqueue/ports/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -1.0 diff --git a/vendor/libkqueue/ports/debian/watch b/vendor/libkqueue/ports/debian/watch deleted file mode 100644 index 507b67d8c..000000000 --- a/vendor/libkqueue/ports/debian/watch +++ /dev/null @@ -1,2 +0,0 @@ -version=3 -http://mark.heily.com/libkqueue/dist/libkqueue-(.*)\.tar\.gz From c4befda3a8dae297f80fb424881c730b39c4c4ef Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 27 Dec 2016 19:09:09 -0800 Subject: [PATCH 0626/1120] ports: use CPack for the RPM Now that we have a cmake based build system, rely on that to build the RPM rather than a hand crafted spec file. --- vendor/libkqueue/libkqueue.spec | 89 --------------------------------- 1 file changed, 89 deletions(-) delete mode 100644 vendor/libkqueue/libkqueue.spec diff --git a/vendor/libkqueue/libkqueue.spec b/vendor/libkqueue/libkqueue.spec deleted file mode 100644 index 2d25541aa..000000000 --- a/vendor/libkqueue/libkqueue.spec +++ /dev/null @@ -1,89 +0,0 @@ -Name: libkqueue -Summary: Userspace implementation of the kqueue event notification mechanism -Version: 2.1.1 -Release: 1 -# The entire source code is MIT, event.h which is BSD (2-clause) -License: MIT and BSD -Group: System Environment/Libraries -URL: http://sourceforge.net/p/libkqueue/wiki/Home/ -Source0: http://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.gz -Provides: libkqueue.so.0 - -%description -A user space implementation of the kqueue(2) kernel event notification -mechanism. libkqueue acts as a translator between the kevent structure and the -native kernel facilities. - -%package devel -Group: Development/Libraries -Summary: Development files for %{name}-%{version} -Requires: %{name}%{?_isa} = %{version}-%{release} - -%description devel -%{summary} - -%prep -%setup -q - -# %%{configure} sets --target 'x86_64-redhat-linux-gnu' instead of 'linux' -%build -CFLAGS="%{optflags} -fpic" %{_configure} --prefix=%{_prefix} --libdir=%{_libdir} -make - -%install -%{make_install} - -%check -make check - -%post -p /sbin/ldconfig - -%postun -p /sbin/ldconfig - -%files -%doc LICENSE -%{_libdir}/libkqueue.so.* - -%files devel -%dir %{_includedir}/kqueue -%dir %{_includedir}/kqueue/sys -%{_libdir}/libkqueue.so -%{_includedir}/kqueue/sys/event.h -%{_libdir}/pkgconfig/libkqueue.pc -%{_mandir}/man2/kqueue.2.* -%{_mandir}/man2/kevent.2.* - -%changelog -* Wed May 08 2013 Mark Heily - 2.0.1-1 -- New upstream release - -* Wed May 01 2013 Eric Radman - 2.0-1 -- Adapt to libkqueue 2.0 - -* Thu Apr 04 2013 Eric Radman - 1.0.1-6 -- Set CFLAGS using optflags since we're using a custom configure -- Shorten summary - -* Wed Apr 03 2013 Eric Radman - 1.0.1-5 -- Use %% to avoid warning about special character in comment -- Remove defattr - -* Fri Jan 18 2013 Eric Radman - 1.0.1-4 -- Configure respects CFLAGS and LDFLAGS. Also pass --libdir to the configure script - -* Sat Jan 12 2013 Eric Radman - 1.0.1-3 -- Add license text for event.h -- Use the dir macro for the include directories -- Remove static package, exclude .a file, and make sure new directories are owned by the RPM - -* Thu Jan 03 2013 Eric Radman - 1.0.1-3 -- Configure respects CFLAGS and LDFLAGS. Also pass --libdir= to the configure script instead of setting LIB - -* Mon Dec 31 2012 Eric Radman - 1.0.1-2 -- Do not set the buildroot (F-10 does not require it) -- Do not manually clean (F-13) - -* Thu Dec 27 2012 Eric Radman - 1.0.1-1 -- Initial build with separate -devel package. Based on work done by Mark Heily, - Aditya Patawari and John Haxby - From 1a45cc367cfbe07b61981833b2d1f2028e0ac6d5 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 27 Dec 2016 19:10:18 -0800 Subject: [PATCH 0627/1120] xcode: remove the xcode project in favour of CMake CMake can generate a Xcode project if desired. Remove the workspace, letting the user generate the project if they desire. --- .../libkqueue.xcodeproj/project.pbxproj | 315 - .../contents.xcworkspacedata | 7 - .../UserInterfaceState.xcuserstate | 6467 ----------------- .../xcschemes/libkqueue.xcscheme | 58 - .../xcschemes/xcschememanagement.plist | 22 - 5 files changed, 6869 deletions(-) delete mode 100644 vendor/libkqueue/libkqueue.xcodeproj/project.pbxproj delete mode 100644 vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/xcuserdata/jocke.xcuserdatad/UserInterfaceState.xcuserstate delete mode 100644 vendor/libkqueue/libkqueue.xcodeproj/xcuserdata/jocke.xcuserdatad/xcschemes/libkqueue.xcscheme delete mode 100644 vendor/libkqueue/libkqueue.xcodeproj/xcuserdata/jocke.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/vendor/libkqueue/libkqueue.xcodeproj/project.pbxproj b/vendor/libkqueue/libkqueue.xcodeproj/project.pbxproj deleted file mode 100644 index d97bc2963..000000000 --- a/vendor/libkqueue/libkqueue.xcodeproj/project.pbxproj +++ /dev/null @@ -1,315 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXFileReference section */ - 8547D6CE1384F4FA00830A5D /* read.c */ = {isa = PBXFileReference; fileEncoding = 4; path = read.c; sourceTree = ""; }; - 8547D6CF1384F4FA00830A5D /* write.c */ = {isa = PBXFileReference; fileEncoding = 4; path = write.c; sourceTree = ""; }; - 8547D6D01384F50F00830A5D /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; path = debug.h; sourceTree = ""; }; - 8547D6D11384F52100830A5D /* read.c */ = {isa = PBXFileReference; fileEncoding = 4; path = read.c; sourceTree = ""; }; - 8547D6D21384F52100830A5D /* user.c */ = {isa = PBXFileReference; fileEncoding = 4; path = user.c; sourceTree = ""; }; - 8547D6D61385034E00830A5D /* read.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = read.c; sourceTree = ""; }; - 8547D6D81385034E00830A5D /* signal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = signal.c; sourceTree = ""; }; - 8547D6D91385034E00830A5D /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; }; - 8547D6DC1385034E00830A5D /* vnode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vnode.c; sourceTree = ""; }; - 8547D6E21385034E00830A5D /* test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = test.c; sourceTree = ""; }; - 8547D6E41385034E00830A5D /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; - 8547D6E61385034E00830A5D /* proc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = proc.c; sourceTree = ""; }; - 8547D6E71385034E00830A5D /* timer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = timer.c; sourceTree = ""; }; - 8547D6E81385034E00830A5D /* user.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = user.c; sourceTree = ""; }; - 8547D6EA1385034E00830A5D /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; - 8547D6EC1385034E00830A5D /* kevent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kevent.c; sourceTree = ""; }; - 8547D6F01385034E00830A5D /* lockstat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lockstat.c; sourceTree = ""; }; - 8547D6F11385034E00830A5D /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; - 85F0626E131E3AB10013C05E /* event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = event.h; path = include/sys/event.h; sourceTree = ""; }; - 85F062A1131E3AE90013C05E /* filter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = filter.c; sourceTree = ""; }; - 85F062A2131E3AE90013C05E /* kevent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kevent.c; sourceTree = ""; }; - 85F062A3131E3AE90013C05E /* queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = queue.h; sourceTree = ""; }; - 85F062A4131E3AE90013C05E /* map.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = map.c; sourceTree = ""; }; - 85F062A5131E3AE90013C05E /* kqueue.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kqueue.c; sourceTree = ""; }; - 85F062A6131E3AE90013C05E /* knote.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = knote.c; sourceTree = ""; }; - 85F062A7131E3AE90013C05E /* private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = private.h; sourceTree = ""; }; - 85F062A8131E3AE90013C05E /* alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = alloc.h; sourceTree = ""; }; - 85F062A9131E3AE90013C05E /* tree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tree.h; sourceTree = ""; }; - 85F062AC131E3AE90013C05E /* platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform.h; sourceTree = ""; }; - 85F062AD131E3AE90013C05E /* signal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = signal.c; sourceTree = ""; }; - 85F062AE131E3AE90013C05E /* vnode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vnode.c; sourceTree = ""; }; - 85F062AF131E3AE90013C05E /* timer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = timer.c; sourceTree = ""; }; - 85F062B0131E3AE90013C05E /* proc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = proc.c; sourceTree = ""; }; - 85F062B1131E3AE90013C05E /* user.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = user.c; sourceTree = ""; }; - 85F062B2131E3AE90013C05E /* platform.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = platform.c; sourceTree = ""; }; - 85F062B4131E3AE90013C05E /* platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform.h; sourceTree = ""; }; - 85F062B5131E3AE90013C05E /* user.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = user.c; sourceTree = ""; }; - 85F062B6131E3AE90013C05E /* signal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = signal.c; sourceTree = ""; }; - 85F062B7131E3AE90013C05E /* proc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = proc.c; sourceTree = ""; }; - 85F062B8131E3AE90013C05E /* kevent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kevent.c; sourceTree = ""; }; - 85F062B9131E3AE90013C05E /* platform.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = platform.c; sourceTree = ""; }; - 85F062BA131E3AE90013C05E /* timer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = timer.c; sourceTree = ""; }; - 85F062BC131E3AE90013C05E /* timer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = timer.c; sourceTree = ""; }; - 85F062BD131E3AE90013C05E /* platform.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = platform.c; sourceTree = ""; }; - 85F062BE131E3AE90013C05E /* socket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = socket.c; sourceTree = ""; }; - 85F062BF131E3AE90013C05E /* user.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = user.c; sourceTree = ""; }; - 85F062C0131E3AE90013C05E /* platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform.h; sourceTree = ""; }; - 85F062C1131E3AE90013C05E /* signal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = signal.c; sourceTree = ""; }; - 85F062C3131E3AE90013C05E /* platform.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = platform.c; sourceTree = ""; }; - 85F062C4131E3AE90013C05E /* timer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = timer.c; sourceTree = ""; }; - 85F062C5131E3AE90013C05E /* platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform.h; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXGroup section */ - 8547D6D31385034E00830A5D /* test */ = { - isa = PBXGroup; - children = ( - 8547D6D61385034E00830A5D /* read.c */, - 8547D6D81385034E00830A5D /* signal.c */, - 8547D6D91385034E00830A5D /* common.h */, - 8547D6DC1385034E00830A5D /* vnode.c */, - 8547D6E21385034E00830A5D /* test.c */, - 8547D6E61385034E00830A5D /* proc.c */, - 8547D6E71385034E00830A5D /* timer.c */, - 8547D6E81385034E00830A5D /* user.c */, - 8547D6EC1385034E00830A5D /* kevent.c */, - 8547D6F01385034E00830A5D /* lockstat.c */, - 8547D6F11385034E00830A5D /* main.c */, - 8547D6E31385034E00830A5D /* libdispatch */, - 8547D6E91385034E00830A5D /* stress */, - ); - path = test; - sourceTree = ""; - }; - 8547D6E31385034E00830A5D /* libdispatch */ = { - isa = PBXGroup; - children = ( - 8547D6E41385034E00830A5D /* main.c */, - ); - path = libdispatch; - sourceTree = ""; - }; - 8547D6E91385034E00830A5D /* stress */ = { - isa = PBXGroup; - children = ( - 8547D6EA1385034E00830A5D /* main.c */, - ); - path = stress; - sourceTree = ""; - }; - 85F06227131E3A3D0013C05E = { - isa = PBXGroup; - children = ( - 85F0626E131E3AB10013C05E /* event.h */, - 85F062A0131E3AE90013C05E /* common */, - 85F062AA131E3AE90013C05E /* linux */, - 85F062B3131E3AE90013C05E /* posix */, - 85F062BB131E3AE90013C05E /* solaris */, - 85F062C2131E3AE90013C05E /* windows */, - 8547D6D31385034E00830A5D /* test */, - ); - sourceTree = ""; - }; - 85F062A0131E3AE90013C05E /* common */ = { - isa = PBXGroup; - children = ( - 8547D6D01384F50F00830A5D /* debug.h */, - 85F062A1131E3AE90013C05E /* filter.c */, - 85F062A2131E3AE90013C05E /* kevent.c */, - 85F062A3131E3AE90013C05E /* queue.h */, - 85F062A4131E3AE90013C05E /* map.c */, - 85F062A5131E3AE90013C05E /* kqueue.c */, - 85F062A6131E3AE90013C05E /* knote.c */, - 85F062A7131E3AE90013C05E /* private.h */, - 85F062A8131E3AE90013C05E /* alloc.h */, - 85F062A9131E3AE90013C05E /* tree.h */, - ); - name = common; - path = src/common; - sourceTree = ""; - }; - 85F062AA131E3AE90013C05E /* linux */ = { - isa = PBXGroup; - children = ( - 8547D6CE1384F4FA00830A5D /* read.c */, - 8547D6CF1384F4FA00830A5D /* write.c */, - 85F062AC131E3AE90013C05E /* platform.h */, - 85F062AD131E3AE90013C05E /* signal.c */, - 85F062AE131E3AE90013C05E /* vnode.c */, - 85F062AF131E3AE90013C05E /* timer.c */, - 85F062B0131E3AE90013C05E /* proc.c */, - 85F062B1131E3AE90013C05E /* user.c */, - 85F062B2131E3AE90013C05E /* platform.c */, - ); - name = linux; - path = src/linux; - sourceTree = ""; - }; - 85F062B3131E3AE90013C05E /* posix */ = { - isa = PBXGroup; - children = ( - 85F062B4131E3AE90013C05E /* platform.h */, - 85F062B5131E3AE90013C05E /* user.c */, - 85F062B6131E3AE90013C05E /* signal.c */, - 85F062B7131E3AE90013C05E /* proc.c */, - 85F062B8131E3AE90013C05E /* kevent.c */, - 85F062B9131E3AE90013C05E /* platform.c */, - 85F062BA131E3AE90013C05E /* timer.c */, - ); - name = posix; - path = src/posix; - sourceTree = ""; - }; - 85F062BB131E3AE90013C05E /* solaris */ = { - isa = PBXGroup; - children = ( - 85F062BC131E3AE90013C05E /* timer.c */, - 85F062BD131E3AE90013C05E /* platform.c */, - 85F062BE131E3AE90013C05E /* socket.c */, - 85F062BF131E3AE90013C05E /* user.c */, - 85F062C0131E3AE90013C05E /* platform.h */, - 85F062C1131E3AE90013C05E /* signal.c */, - ); - name = solaris; - path = src/solaris; - sourceTree = ""; - }; - 85F062C2131E3AE90013C05E /* windows */ = { - isa = PBXGroup; - children = ( - 8547D6D11384F52100830A5D /* read.c */, - 8547D6D21384F52100830A5D /* user.c */, - 85F062C3131E3AE90013C05E /* platform.c */, - 85F062C4131E3AE90013C05E /* timer.c */, - 85F062C5131E3AE90013C05E /* platform.h */, - ); - name = windows; - path = src/windows; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXLegacyTarget section */ - 85F0622E131E3A3D0013C05E /* libkqueue */ = { - isa = PBXLegacyTarget; - buildArgumentsString = "$(ACTION)"; - buildConfigurationList = 85F06231131E3A3D0013C05E /* Build configuration list for PBXLegacyTarget "libkqueue" */; - buildPhases = ( - ); - buildToolPath = /usr/bin/make; - dependencies = ( - ); - name = libkqueue; - passBuildSettingsInEnvironment = 1; - productName = libkqueue; - }; -/* End PBXLegacyTarget section */ - -/* Begin PBXProject section */ - 85F06229131E3A3D0013C05E /* Project object */ = { - isa = PBXProject; - attributes = { - ORGANIZATIONNAME = Tbricks; - }; - buildConfigurationList = 85F0622C131E3A3D0013C05E /* Build configuration list for PBXProject "libkqueue" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 85F06227131E3A3D0013C05E; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 85F0622E131E3A3D0013C05E /* libkqueue */, - ); - }; -/* End PBXProject section */ - -/* Begin XCBuildConfiguration section */ - 85F0622F131E3A3D0013C05E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = DEBUG; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - }; - name = Debug; - }; - 85F06230131E3A3D0013C05E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; - SDKROOT = macosx; - }; - name = Release; - }; - 85F06232131E3A3D0013C05E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = NO; - DEBUGGING_SYMBOLS = YES; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_GENERATE_DEBUGGING_SYMBOLS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 85F06233131E3A3D0013C05E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 85F0622C131E3A3D0013C05E /* Build configuration list for PBXProject "libkqueue" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 85F0622F131E3A3D0013C05E /* Debug */, - 85F06230131E3A3D0013C05E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 85F06231131E3A3D0013C05E /* Build configuration list for PBXLegacyTarget "libkqueue" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 85F06232131E3A3D0013C05E /* Debug */, - 85F06233131E3A3D0013C05E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 85F06229131E3A3D0013C05E /* Project object */; -} diff --git a/vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index ecdfdff53..000000000 --- a/vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/xcuserdata/jocke.xcuserdatad/UserInterfaceState.xcuserstate b/vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/xcuserdata/jocke.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index ee4ba9047..000000000 --- a/vendor/libkqueue/libkqueue.xcodeproj/project.xcworkspace/xcuserdata/jocke.xcuserdatad/UserInterfaceState.xcuserstate +++ /dev/null @@ -1,6467 +0,0 @@ - - - - - $archiver - NSKeyedArchiver - $objects - - $null - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 2 - - - CF$UID - 3 - - - NS.objects - - - CF$UID - 4 - - - CF$UID - 220 - - - - B8DD28BF-0B77-4F6B-BE84-8CFDEBA37869 - IDEWorkspaceDocument - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 5 - - - CF$UID - 6 - - - CF$UID - 7 - - - CF$UID - 8 - - - CF$UID - 9 - - - CF$UID - 10 - - - NS.objects - - - CF$UID - 11 - - - CF$UID - 12 - - - CF$UID - 14 - - - CF$UID - 10 - - - CF$UID - 2 - - - CF$UID - 15 - - - - IDEWindowFrame - IDEOrderedWorkspaceTabControllers - IDEWindowToolbarIsVisible - IDEActiveWorkspaceTabController - IDEWorkspaceWindowControllerUniqueIdentifier - IDEWorkspaceTabController_EC0EC534-0E04-4AE1-A499-3DB51327C249 - {{225, 30}, {1453, 1036}} - - $class - - CF$UID - 13 - - NS.objects - - - CF$UID - 10 - - - - - $classes - - NSArray - NSObject - - $classname - NSArray - - - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 16 - - - CF$UID - 17 - - - CF$UID - 18 - - - CF$UID - 19 - - - CF$UID - 20 - - - CF$UID - 21 - - - CF$UID - 22 - - - CF$UID - 23 - - - NS.objects - - - CF$UID - 24 - - - CF$UID - 14 - - - CF$UID - 46 - - - CF$UID - 164 - - - CF$UID - 171 - - - CF$UID - 210 - - - CF$UID - 120 - - - CF$UID - 219 - - - - IDEEditorArea - IDEShowNavigator - AssistantEditorsLayout - IDEWorkspaceTabControllerUtilityAreaSplitView - IDENavigatorArea - IDEWorkspaceTabControllerDesignAreaSplitView - IDEShowUtilities - IDETabLabel - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 25 - - - CF$UID - 26 - - - CF$UID - 27 - - - CF$UID - 28 - - - CF$UID - 29 - - - CF$UID - 30 - - - CF$UID - 31 - - - CF$UID - 32 - - - CF$UID - 33 - - - NS.objects - - - CF$UID - 34 - - - CF$UID - 56 - - - CF$UID - 89 - - - CF$UID - 14 - - - CF$UID - 46 - - - CF$UID - 129 - - - CF$UID - 155 - - - CF$UID - 163 - - - CF$UID - 120 - - - - layoutTree - IDEEDitorArea_DebugArea - IDEEditorMode_Standard - IDEShowEditor - EditorMode - IDEEditorMode_Version - DebuggerSplitView - DefaultPersistentRepresentations - ShowDebuggerArea - - $class - - CF$UID - 55 - - geniusEditorContextNode - - CF$UID - 0 - - primaryEditorContextNode - - CF$UID - 35 - - rootLayoutTreeNode - - CF$UID - 52 - - - - $class - - CF$UID - 54 - - children - - CF$UID - 0 - - contentType - 1 - documentArchivableRepresentation - - CF$UID - 36 - - orientation - 0 - parent - - CF$UID - 52 - - - - $class - - CF$UID - 51 - - DocumentLocation - - CF$UID - 47 - - DomainIdentifier - - CF$UID - 37 - - IdentifierPath - - CF$UID - 38 - - IndexOfDocumentIdentifier - - CF$UID - 46 - - - Xcode.IDENavigableItemDomain.WorkspaceStructure - - $class - - CF$UID - 13 - - NS.objects - - - CF$UID - 39 - - - CF$UID - 42 - - - CF$UID - 44 - - - - - $class - - CF$UID - 41 - - Identifier - - CF$UID - 40 - - - kevent.c - - $classes - - IDEArchivableStringIndexPair - NSObject - - $classname - IDEArchivableStringIndexPair - - - $class - - CF$UID - 41 - - Identifier - - CF$UID - 43 - - - common - - $class - - CF$UID - 41 - - Identifier - - CF$UID - 45 - - - libkqueue - 0 - - $class - - CF$UID - 50 - - documentURL - - CF$UID - 48 - - timestamp - - CF$UID - 0 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/kevent.c - - - $classes - - NSMutableString - NSString - NSObject - - $classname - NSMutableString - - - $classes - - DVTDocumentLocation - NSObject - - $classname - DVTDocumentLocation - - - $classes - - IDENavigableItemArchivableRepresentation - NSObject - - $classname - IDENavigableItemArchivableRepresentation - - - $class - - CF$UID - 54 - - children - - CF$UID - 53 - - contentType - 0 - documentArchivableRepresentation - - CF$UID - 0 - - orientation - 0 - parent - - CF$UID - 0 - - - - $class - - CF$UID - 13 - - NS.objects - - - CF$UID - 35 - - - - - $classes - - IDEWorkspaceTabControllerLayoutTreeNode - NSObject - - $classname - IDEWorkspaceTabControllerLayoutTreeNode - - - $classes - - IDEWorkspaceTabControllerLayoutTree - NSObject - - $classname - IDEWorkspaceTabControllerLayoutTree - - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 57 - - - CF$UID - 58 - - - CF$UID - 59 - - - CF$UID - 60 - - - CF$UID - 61 - - - CF$UID - 62 - - - NS.objects - - - CF$UID - 63 - - - CF$UID - 64 - - - CF$UID - 67 - - - CF$UID - 63 - - - CF$UID - 70 - - - CF$UID - 83 - - - - LayoutFocusMode - console - variables - LayoutMode - IDEDebuggerAreaSplitView - IDEDebugArea_SplitView - 1 - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 65 - - - NS.objects - - - CF$UID - 46 - - - - ConsoleFilterMode - - $classes - - NSMutableDictionary - NSDictionary - NSObject - - $classname - NSMutableDictionary - - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 68 - - - NS.objects - - - CF$UID - 69 - - - - DBGVariablesViewFilterMode - 2 - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 71 - - - NS.objects - - - CF$UID - 72 - - - - DVTSplitViewItems - - $class - - CF$UID - 82 - - NS.objects - - - CF$UID - 73 - - - CF$UID - 79 - - - - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 74 - - - CF$UID - 75 - - - NS.objects - - - CF$UID - 76 - - - CF$UID - 77 - - - - DVTIdentifier - DVTViewMagnitude - VariablesView - 555 - - $classes - - NSDictionary - NSObject - - $classname - NSDictionary - - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 74 - - - CF$UID - 75 - - - NS.objects - - - CF$UID - 80 - - - CF$UID - 81 - - - - ConsoleArea - 554 - - $classes - - NSMutableArray - NSArray - NSObject - - $classname - NSMutableArray - - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 71 - - - NS.objects - - - CF$UID - 84 - - - - - $class - - CF$UID - 82 - - NS.objects - - - CF$UID - 85 - - - CF$UID - 87 - - - - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 74 - - - CF$UID - 75 - - - NS.objects - - - CF$UID - 76 - - - CF$UID - 86 - - - - 555 - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 74 - - - CF$UID - 75 - - - NS.objects - - - CF$UID - 80 - - - CF$UID - 88 - - - - 554 - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 90 - - - NS.objects - - - CF$UID - 91 - - - - EditorLayout_PersistentRepresentation - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 92 - - - NS.objects - - - CF$UID - 93 - - - - Main - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 94 - - - CF$UID - 95 - - - CF$UID - 96 - - - NS.objects - - - CF$UID - 97 - - - CF$UID - 46 - - - CF$UID - 127 - - - - EditorLayout_StateSavingStateDictionaries - EditorLayout_Selected - EditorLayout_Geometry - - $class - - CF$UID - 13 - - NS.objects - - - CF$UID - 98 - - - - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 99 - - - CF$UID - 100 - - - CF$UID - 101 - - - CF$UID - 102 - - - CF$UID - 103 - - - CF$UID - 104 - - - CF$UID - 105 - - - NS.objects - - - CF$UID - 106 - - - CF$UID - 107 - - - CF$UID - 113 - - - CF$UID - 122 - - - CF$UID - 40 - - - CF$UID - 123 - - - CF$UID - 124 - - - - FileDataType - ArchivableRepresentation - EditorState - NavigableItemName - DocumentNavigableItemName - DocumentExtensionIdentifier - DocumentURL - public.c-source - - $class - - CF$UID - 51 - - DocumentLocation - - CF$UID - 47 - - DomainIdentifier - - CF$UID - 37 - - IdentifierPath - - CF$UID - 108 - - IndexOfDocumentIdentifier - - CF$UID - 46 - - - - $class - - CF$UID - 13 - - NS.objects - - - CF$UID - 109 - - - CF$UID - 110 - - - CF$UID - 111 - - - - - $class - - CF$UID - 41 - - Identifier - - CF$UID - 40 - - - - $class - - CF$UID - 41 - - Identifier - - CF$UID - 43 - - - - $class - - CF$UID - 41 - - Identifier - - CF$UID - 112 - - - libkqueue - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 118 - - - CF$UID - 119 - - - CF$UID - 120 - - - CF$UID - 121 - - - - PrimaryDocumentTimestamp - PrimaryDocumentVisibleCharacterRange - HideAllIssues - PrimaryDocumentSelectedCharacterRange - 327515822.77097303 - {6982, 1750} - - {8174, 11} - kevent() - Xcode.IDEKit.EditorDocument.SourceCode - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 125 - - - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/kevent.c - - $classes - - NSURL - NSObject - - $classname - NSURL - - - $class - - CF$UID - 13 - - NS.objects - - - CF$UID - 128 - - - - {{0, 0}, {1110, 938}} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 130 - - - CF$UID - 90 - - - NS.objects - - - CF$UID - 46 - - - CF$UID - 131 - - - - VersionsEditorSubmode - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 92 - - - NS.objects - - - CF$UID - 132 - - - - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 94 - - - CF$UID - 95 - - - CF$UID - 96 - - - NS.objects - - - CF$UID - 133 - - - CF$UID - 46 - - - CF$UID - 153 - - - - - $class - - CF$UID - 13 - - NS.objects - - - CF$UID - 134 - - - - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 99 - - - CF$UID - 100 - - - CF$UID - 101 - - - CF$UID - 102 - - - CF$UID - 103 - - - CF$UID - 104 - - - CF$UID - 105 - - - NS.objects - - - CF$UID - 106 - - - CF$UID - 135 - - - CF$UID - 145 - - - CF$UID - 149 - - - CF$UID - 138 - - - CF$UID - 150 - - - CF$UID - 151 - - - - - $class - - CF$UID - 51 - - DocumentLocation - - CF$UID - 143 - - DomainIdentifier - - CF$UID - 37 - - IdentifierPath - - CF$UID - 136 - - IndexOfDocumentIdentifier - - CF$UID - 46 - - - - $class - - CF$UID - 13 - - NS.objects - - - CF$UID - 137 - - - CF$UID - 139 - - - CF$UID - 141 - - - - - $class - - CF$UID - 41 - - Identifier - - CF$UID - 138 - - - read.c - - $class - - CF$UID - 41 - - Identifier - - CF$UID - 140 - - - test - - $class - - CF$UID - 41 - - Identifier - - CF$UID - 142 - - - libkqueue - - $class - - CF$UID - 50 - - documentURL - - CF$UID - 144 - - timestamp - - CF$UID - 0 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/read.c - - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 146 - - - CF$UID - 147 - - - CF$UID - 120 - - - CF$UID - 148 - - - - 327507826.66487598 - {6959, 1898} - {7915, 8} - test_kevent_socket_dispatch() - Xcode.IDEKit.EditorDocument.SourceCodeComparisonEditor - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 152 - - - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/read.c - - $class - - CF$UID - 13 - - NS.objects - - - CF$UID - 154 - - - - {{0, 0}, {1193, 938}} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 71 - - - NS.objects - - - CF$UID - 156 - - - - - $class - - CF$UID - 82 - - NS.objects - - - CF$UID - 157 - - - CF$UID - 160 - - - - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 74 - - - CF$UID - 75 - - - NS.objects - - - CF$UID - 158 - - - CF$UID - 159 - - - - IDEEditor - 203 - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 74 - - - CF$UID - 75 - - - NS.objects - - - CF$UID - 161 - - - CF$UID - 162 - - - - IDEDebuggerArea - 115 - - $class - - CF$UID - 66 - - NS.keys - - NS.objects - - - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 71 - - - NS.objects - - - CF$UID - 165 - - - - - $class - - CF$UID - 82 - - NS.objects - - - CF$UID - 166 - - - CF$UID - 169 - - - - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 74 - - - CF$UID - 75 - - - NS.objects - - - CF$UID - 167 - - - CF$UID - 168 - - - - - 727 - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 74 - - - CF$UID - 75 - - - NS.objects - - - CF$UID - 167 - - - CF$UID - 170 - - - - 211 - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 172 - - - CF$UID - 173 - - - CF$UID - 174 - - - NS.objects - - - CF$UID - 175 - - - CF$UID - 172 - - - CF$UID - 188 - - - - Xcode.IDEKit.Navigator.BatchFind - SelectedNavigator - Xcode.IDEKit.Navigator.Structure - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 176 - - - CF$UID - 177 - - - CF$UID - 178 - - - CF$UID - 179 - - - CF$UID - 180 - - - CF$UID - 181 - - - CF$UID - 182 - - - NS.objects - - - CF$UID - 46 - - - CF$UID - 120 - - - CF$UID - 167 - - - CF$UID - 183 - - - CF$UID - 184 - - - CF$UID - 46 - - - CF$UID - 186 - - - - IDEBatchFindNavigatorScrollPosition - IDEBatchFindNavigatorShowsOptions - IDEBatchFindNavigatorReplaceString - IDEBatchFindNavigatorFindString - IDEBatchFindNavigatorSelectedRowIndexes - IDEBatchFindNavigatorFindMode - IDEBatchFindNavigatorCollapsedGroups - WITEM_CACHE - - $class - - CF$UID - 185 - - NSLength - 1 - NSLocation - 2 - NSRangeCount - 1 - - - $classes - - NSIndexSet - NSObject - - $classname - NSIndexSet - - - $class - - CF$UID - 187 - - NSRangeCount - 0 - - - $classes - - NSMutableIndexSet - NSIndexSet - NSObject - - $classname - NSMutableIndexSet - - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 189 - - - CF$UID - 190 - - - CF$UID - 191 - - - CF$UID - 192 - - - CF$UID - 193 - - - CF$UID - 194 - - - CF$UID - 195 - - - NS.objects - - - CF$UID - 196 - - - CF$UID - 120 - - - CF$UID - 197 - - - CF$UID - 120 - - - CF$UID - 120 - - - CF$UID - 199 - - - CF$UID - 202 - - - - IDEVisibleRect - IDEUnsavedDocumentFilteringEnabled - IDENavigatorExpandedItemsBeforeFilteringSet - IDERecentDocumentFilteringEnabled - IDESCMStatusFilteringEnabled - IDESelectedObjects - IDEExpandedItemsSet - {{0, 0}, {342, 894}} - - $class - - CF$UID - 198 - - NS.objects - - - - $classes - - NSSet - NSObject - - $classname - NSSet - - - $class - - CF$UID - 13 - - NS.objects - - - CF$UID - 200 - - - - - $class - - CF$UID - 82 - - NS.objects - - - CF$UID - 201 - - - CF$UID - 43 - - - CF$UID - 40 - - - - libkqueue - - $class - - CF$UID - 198 - - NS.objects - - - CF$UID - 203 - - - CF$UID - 204 - - - CF$UID - 205 - - - CF$UID - 207 - - - CF$UID - 209 - - - - - $class - - CF$UID - 82 - - NS.objects - - - CF$UID - 201 - - - - - $class - - CF$UID - 82 - - NS.objects - - - CF$UID - 201 - - - CF$UID - 43 - - - - - $class - - CF$UID - 82 - - NS.objects - - - CF$UID - 201 - - - CF$UID - 206 - - - - linux - - $class - - CF$UID - 82 - - NS.objects - - - CF$UID - 201 - - - CF$UID - 208 - - - - solaris - - $class - - CF$UID - 82 - - NS.objects - - - CF$UID - 201 - - - CF$UID - 140 - - - - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 71 - - - NS.objects - - - CF$UID - 211 - - - - - $class - - CF$UID - 82 - - NS.objects - - - CF$UID - 212 - - - CF$UID - 214 - - - CF$UID - 216 - - - - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 74 - - - CF$UID - 75 - - - NS.objects - - - CF$UID - 20 - - - CF$UID - 213 - - - - 343 - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 74 - - - CF$UID - 75 - - - NS.objects - - - CF$UID - 16 - - - CF$UID - 215 - - - - 1110 - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 74 - - - CF$UID - 75 - - - NS.objects - - - CF$UID - 217 - - - CF$UID - 218 - - - - IDEUtilitiesArea - 260 - kevent.c - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 221 - - - CF$UID - 222 - - - CF$UID - 223 - - - CF$UID - 224 - - - CF$UID - 225 - - - CF$UID - 226 - - - CF$UID - 227 - - - CF$UID - 228 - - - CF$UID - 229 - - - NS.objects - - - CF$UID - 120 - - - CF$UID - 230 - - - CF$UID - 46 - - - CF$UID - 502 - - - CF$UID - 505 - - - CF$UID - 510 - - - CF$UID - 511 - - - CF$UID - 120 - - - CF$UID - 120 - - - - BreakpointsActivated - DefaultEditorStatesForURLs - DebuggingWindowBehavior - ActiveScheme - ActiveRunDestination - DocumentWindows - RecentEditorDocumentURLs - AppFocusInMiniDebugging - MiniDebuggingConsole - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 150 - - - CF$UID - 231 - - - CF$UID - 123 - - - NS.objects - - - CF$UID - 232 - - - CF$UID - 288 - - - CF$UID - 360 - - - - Xcode.Xcode3ProjectSupport.EditorDocument.Xcode3Project - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 233 - - - CF$UID - 234 - - - CF$UID - 236 - - - CF$UID - 238 - - - CF$UID - 239 - - - CF$UID - 241 - - - CF$UID - 243 - - - CF$UID - 245 - - - CF$UID - 247 - - - CF$UID - 249 - - - NS.objects - - - CF$UID - 251 - - - CF$UID - 254 - - - CF$UID - 257 - - - CF$UID - 260 - - - CF$UID - 264 - - - CF$UID - 268 - - - CF$UID - 272 - - - CF$UID - 276 - - - CF$UID - 280 - - - CF$UID - 284 - - - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 48 - - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 235 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/solaris/signal.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 237 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/filter.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 144 - - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 240 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/windows/read.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 242 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/proc.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 244 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/solaris/platform.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 246 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/linux/read.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 248 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/solaris/socket.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 250 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/knote.c - - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 117 - - - CF$UID - 114 - - - CF$UID - 115 - - - NS.objects - - - CF$UID - 252 - - - CF$UID - 253 - - - CF$UID - 252 - - - - {0, 0} - 327502698.73993701 - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 117 - - - CF$UID - 115 - - - CF$UID - 114 - - - NS.objects - - - CF$UID - 252 - - - CF$UID - 255 - - - CF$UID - 256 - - - - {641, 1780} - 327483300.588404 - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 117 - - - CF$UID - 115 - - - CF$UID - 114 - - - NS.objects - - - CF$UID - 252 - - - CF$UID - 258 - - - CF$UID - 259 - - - - {3292, 1552} - 327483354.533373 - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 261 - - - CF$UID - 262 - - - CF$UID - 120 - - - CF$UID - 263 - - - - 327507825.58967799 - {6959, 1898} - {7915, 8} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 117 - - - CF$UID - 115 - - - CF$UID - 114 - - - NS.objects - - - CF$UID - 265 - - - CF$UID - 266 - - - CF$UID - 267 - - - - {4061, 8} - {1239, 1734} - 327507729.79866397 - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 117 - - - CF$UID - 115 - - - CF$UID - 114 - - - NS.objects - - - CF$UID - 269 - - - CF$UID - 270 - - - CF$UID - 271 - - - - {4776, 8} - {981, 1624} - 327507731.96671999 - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 273 - - - CF$UID - 274 - - - CF$UID - 120 - - - CF$UID - 275 - - - - 327507815.27077597 - {3447, 2155} - {2760, 0} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 117 - - - CF$UID - 115 - - - CF$UID - 114 - - - NS.objects - - - CF$UID - 277 - - - CF$UID - 278 - - - CF$UID - 279 - - - - {4874, 8} - {3953, 1837} - 327507753.85920501 - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 117 - - - CF$UID - 115 - - - CF$UID - 114 - - - NS.objects - - - CF$UID - 281 - - - CF$UID - 282 - - - CF$UID - 283 - - - - {1080, 0} - {1932, 1806} - 327507765.95997798 - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 117 - - - CF$UID - 115 - - - CF$UID - 114 - - - NS.objects - - - CF$UID - 285 - - - CF$UID - 286 - - - CF$UID - 287 - - - - {896, 0} - {0, 1554} - 327507820.57061797 - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 289 - - - CF$UID - 291 - - - CF$UID - 293 - - - NS.objects - - - CF$UID - 295 - - - CF$UID - 320 - - - CF$UID - 347 - - - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 290 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/libkqueue.xcodeproj/ - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 292 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue.xcodeproj/ - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 294 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue/libkqueue.xcodeproj - - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 296 - - - CF$UID - 297 - - - CF$UID - 298 - - - CF$UID - 299 - - - CF$UID - 300 - - - NS.objects - - - CF$UID - 301 - - - CF$UID - 302 - - - CF$UID - 308 - - - CF$UID - 309 - - - CF$UID - 319 - - - - Xcode3ProjectEditorPreviousProjectEditorClass - Xcode3ProjectEditor.sourceList.splitview - Xcode3ProjectEditorPreviousTargetEditorClass - Xcode3ProjectEditorSelectedDocumentLocations - Xcode3ProjectEditor_Xcode3InfoEditor - Xcode3ProjectInfoEditor - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 71 - - - NS.objects - - - CF$UID - 303 - - - - - $class - - CF$UID - 82 - - NS.objects - - - CF$UID - 304 - - - CF$UID - 306 - - - - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 74 - - - CF$UID - 75 - - - NS.objects - - - CF$UID - 167 - - - CF$UID - 305 - - - - 170 - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 74 - - - CF$UID - 75 - - - NS.objects - - - CF$UID - 167 - - - CF$UID - 307 - - - - 1023 - Xcode3InfoEditor - - $class - - CF$UID - 13 - - NS.objects - - - CF$UID - 310 - - - - - $class - - CF$UID - 318 - - documentURL - - CF$UID - 311 - - selection - - CF$UID - 313 - - timestamp - - CF$UID - 312 - - - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/libkqueue.xcodeproj/ - 327480573.75054502 - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 314 - - - CF$UID - 315 - - - NS.objects - - - CF$UID - 316 - - - CF$UID - 317 - - - - Editor - Target - Xcode3InfoEditor - libkqueue - - $classes - - Xcode3ProjectDocumentLocation - DVTDocumentLocation - NSObject - - $classname - Xcode3ProjectDocumentLocation - - - $class - - CF$UID - 66 - - NS.keys - - NS.objects - - - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 321 - - - CF$UID - 322 - - - CF$UID - 323 - - - CF$UID - 324 - - - CF$UID - 325 - - - NS.objects - - - CF$UID - 326 - - - CF$UID - 327 - - - CF$UID - 337 - - - CF$UID - 338 - - - CF$UID - 346 - - - - Xcode3ProjectEditorPreviousProjectEditorClass - Xcode3ProjectEditor.sourceList.splitview - Xcode3ProjectEditorPreviousTargetEditorClass - Xcode3ProjectEditorSelectedDocumentLocations - Xcode3ProjectEditor_Xcode3InfoEditor - Xcode3ProjectInfoEditor - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 328 - - - NS.objects - - - CF$UID - 329 - - - - DVTSplitViewItems - - $class - - CF$UID - 82 - - NS.objects - - - CF$UID - 330 - - - CF$UID - 335 - - - - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 331 - - - CF$UID - 332 - - - NS.objects - - - CF$UID - 333 - - - CF$UID - 334 - - - - DVTIdentifier - DVTViewMagnitude - - 170 - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 331 - - - CF$UID - 332 - - - NS.objects - - - CF$UID - 333 - - - CF$UID - 336 - - - - 970 - Xcode3InfoEditor - - $class - - CF$UID - 13 - - NS.objects - - - CF$UID - 339 - - - - - $class - - CF$UID - 318 - - documentURL - - CF$UID - 340 - - selection - - CF$UID - 342 - - timestamp - - CF$UID - 341 - - - file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue.xcodeproj/ - 320748289.81788599 - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 343 - - - CF$UID - 344 - - - NS.objects - - - CF$UID - 337 - - - CF$UID - 345 - - - - Editor - Target - libkqueue - - $class - - CF$UID - 66 - - NS.keys - - NS.objects - - - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 321 - - - CF$UID - 322 - - - CF$UID - 323 - - - CF$UID - 324 - - - CF$UID - 325 - - - NS.objects - - - CF$UID - 326 - - - CF$UID - 348 - - - CF$UID - 337 - - - CF$UID - 354 - - - CF$UID - 359 - - - - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 328 - - - NS.objects - - - CF$UID - 349 - - - - - $class - - CF$UID - 82 - - NS.objects - - - CF$UID - 350 - - - CF$UID - 352 - - - - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 331 - - - CF$UID - 332 - - - NS.objects - - - CF$UID - 333 - - - CF$UID - 351 - - - - 162 - - $class - - CF$UID - 78 - - NS.keys - - - CF$UID - 331 - - - CF$UID - 332 - - - NS.objects - - - CF$UID - 333 - - - CF$UID - 353 - - - - 978 - - $class - - CF$UID - 13 - - NS.objects - - - CF$UID - 355 - - - - - $class - - CF$UID - 318 - - documentURL - - CF$UID - 356 - - selection - - CF$UID - 358 - - timestamp - - CF$UID - 357 - - - file://localhost/home/jocke/gcd/cb/2011-03-02_09-14-21/libkqueue/trunk/libkqueue/libkqueue.xcodeproj/ - 320748102.08692503 - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 343 - - - CF$UID - 344 - - - NS.objects - - - CF$UID - 337 - - - CF$UID - 345 - - - - - $class - - CF$UID - 66 - - NS.keys - - NS.objects - - - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 361 - - - CF$UID - 363 - - - CF$UID - 365 - - - CF$UID - 247 - - - CF$UID - 367 - - - CF$UID - 369 - - - CF$UID - 371 - - - CF$UID - 373 - - - CF$UID - 245 - - - CF$UID - 239 - - - CF$UID - 241 - - - CF$UID - 375 - - - CF$UID - 377 - - - CF$UID - 233 - - - CF$UID - 379 - - - CF$UID - 234 - - - CF$UID - 381 - - - CF$UID - 383 - - - CF$UID - 385 - - - CF$UID - 387 - - - CF$UID - 389 - - - CF$UID - 236 - - - CF$UID - 391 - - - CF$UID - 393 - - - CF$UID - 395 - - - CF$UID - 397 - - - CF$UID - 399 - - - NS.objects - - - CF$UID - 401 - - - CF$UID - 405 - - - CF$UID - 408 - - - CF$UID - 411 - - - CF$UID - 415 - - - CF$UID - 418 - - - CF$UID - 421 - - - CF$UID - 425 - - - CF$UID - 428 - - - CF$UID - 432 - - - CF$UID - 436 - - - CF$UID - 440 - - - CF$UID - 444 - - - CF$UID - 448 - - - CF$UID - 452 - - - CF$UID - 456 - - - CF$UID - 460 - - - CF$UID - 464 - - - CF$UID - 468 - - - CF$UID - 472 - - - CF$UID - 476 - - - CF$UID - 480 - - - CF$UID - 484 - - - CF$UID - 487 - - - CF$UID - 491 - - - CF$UID - 495 - - - CF$UID - 498 - - - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 362 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/knote.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 364 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/kqueue.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 366 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/CMakeLists.txt - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 368 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/kqtest.sln - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 370 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/solaris/timer.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 372 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/windows/timer.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 374 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/include/sys/event.h - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 376 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/debug.h - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 378 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/read.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 380 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/kevent.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 382 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/signal.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 384 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/linux/platform.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 386 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/solaris/platform.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 388 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/posix/signal.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 390 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/linux/write.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 392 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/config.mk - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 394 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/linux/signal.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 396 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/windows/platform.c - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 398 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/config.h - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 400 - - - - $class - - CF$UID - 49 - - NS.string - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/private.h - - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 402 - - - CF$UID - 403 - - - CF$UID - 120 - - - CF$UID - 404 - - - - 327515288.24181002 - {2380, 1756} - {3481, 46} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 406 - - - CF$UID - 407 - - - CF$UID - 120 - - - CF$UID - 252 - - - - 327501746.70619398 - {1942, 1354} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 409 - - - CF$UID - 410 - - - CF$UID - 120 - - - CF$UID - 252 - - - - 327484326.94135398 - {0, 1437} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 412 - - - CF$UID - 413 - - - CF$UID - 120 - - - CF$UID - 414 - - - - 327510440.30511099 - {806, 1549} - {1554, 14} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 416 - - - CF$UID - 417 - - - CF$UID - 120 - - - CF$UID - 252 - - - - 327484267.83185202 - {0, 880} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 419 - - - CF$UID - 420 - - - CF$UID - 120 - - - CF$UID - 252 - - - - 327502220.41982299 - {0, 2018} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 422 - - - CF$UID - 423 - - - CF$UID - 120 - - - CF$UID - 424 - - - - 327510899.55966902 - {2630, 1684} - {3654, 12} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 426 - - - CF$UID - 427 - - - CF$UID - 120 - - - CF$UID - 252 - - - - 327501403.16790402 - {0, 2611} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 429 - - - CF$UID - 430 - - - CF$UID - 120 - - - CF$UID - 431 - - - - 327508285.43267101 - {3358, 2094} - {4911, 7} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 433 - - - CF$UID - 434 - - - CF$UID - 120 - - - CF$UID - 435 - - - - 327508343.95512998 - {3020, 1730} - {4061, 8} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 437 - - - CF$UID - 438 - - - CF$UID - 120 - - - CF$UID - 439 - - - - 327508336.51981598 - {3119, 1726} - {4776, 8} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 441 - - - CF$UID - 442 - - - CF$UID - 120 - - - CF$UID - 443 - - - - 327511143.49480402 - {2256, 2475} - {3507, 18} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 445 - - - CF$UID - 446 - - - CF$UID - 120 - - - CF$UID - 447 - - - - 327510568.35661697 - {9888, 1763} - {11545, 0} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 449 - - - CF$UID - 450 - - - CF$UID - 120 - - - CF$UID - 451 - - - - 327515822.76584601 - {6982, 1750} - {8174, 11} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 453 - - - CF$UID - 454 - - - CF$UID - 120 - - - CF$UID - 455 - - - - 327484401.83084399 - {0, 1977} - {892, 15} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 457 - - - CF$UID - 458 - - - CF$UID - 120 - - - CF$UID - 459 - - - - 327514969.09328401 - {2608, 1740} - {3613, 11} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 461 - - - CF$UID - 462 - - - CF$UID - 120 - - - CF$UID - 463 - - - - 327510759.63499302 - {1547, 1617} - {2310, 26} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 465 - - - CF$UID - 466 - - - CF$UID - 120 - - - CF$UID - 467 - - - - 327510518.82097101 - {3548, 1751} - {4489, 10} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 469 - - - CF$UID - 470 - - - CF$UID - 120 - - - CF$UID - 471 - - - - 327511788.54017502 - {3042, 2286} - {3942, 11} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 473 - - - CF$UID - 474 - - - CF$UID - 120 - - - CF$UID - 475 - - - - 327511824.70484197 - {3125, 1625} - {4189, 11} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 477 - - - CF$UID - 478 - - - CF$UID - 120 - - - CF$UID - 479 - - - - 327508472.07515299 - {1328, 1840} - {2431, 7} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 481 - - - CF$UID - 482 - - - CF$UID - 120 - - - CF$UID - 483 - - - - 327501730.97626501 - {2013, 1857} - {954, 11} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 485 - - - CF$UID - 486 - - - CF$UID - 120 - - - CF$UID - 252 - - - - 327484259.86375898 - {0, 798} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 488 - - - CF$UID - 489 - - - CF$UID - 120 - - - CF$UID - 490 - - - - 327510511.21733099 - {2366, 1519} - {2964, 0} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 492 - - - CF$UID - 493 - - - CF$UID - 120 - - - CF$UID - 494 - - - - 327511609.71706301 - {3199, 1940} - {4798, 12} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 496 - - - CF$UID - 497 - - - CF$UID - 120 - - - CF$UID - 252 - - - - 327484310.625539 - {0, 406} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 114 - - - CF$UID - 115 - - - CF$UID - 116 - - - CF$UID - 117 - - - NS.objects - - - CF$UID - 499 - - - CF$UID - 500 - - - CF$UID - 120 - - - CF$UID - 501 - - - - 327510895.31517202 - {3808, 2573} - {6073, 12} - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 503 - - - NS.objects - - - CF$UID - 504 - - - - IDENameString - libkqueue - - $class - - CF$UID - 66 - - NS.keys - - - CF$UID - 506 - - - CF$UID - 507 - - - NS.objects - - - CF$UID - 508 - - - CF$UID - 509 - - - - IDEDeviceLocation - IDEDeviceArchitecture - dvtdevice-local-computer:localhost - x86_64 - - $class - - CF$UID - 82 - - NS.objects - - - CF$UID - 2 - - - - - $class - - CF$UID - 82 - - NS.objects - - - CF$UID - 512 - - - CF$UID - 514 - - - CF$UID - 516 - - - CF$UID - 518 - - - CF$UID - 520 - - - CF$UID - 522 - - - CF$UID - 524 - - - CF$UID - 526 - - - CF$UID - 528 - - - CF$UID - 530 - - - - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 513 - - - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/kevent.c - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 515 - - - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/knote.c - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 517 - - - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/solaris/signal.c - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 519 - - - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/posix/signal.c - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 521 - - - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/solaris/platform.c - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 523 - - - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/windows/platform.c - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 525 - - - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/debug.h - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 527 - - - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/windows/timer.c - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 529 - - - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/src/common/private.h - - $class - - CF$UID - 126 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 531 - - - file://localhost/home/jocke/gcd/cb/2011-05-19_08-47-35/libkqueue/trunk/test/signal.c - - $top - - State - - CF$UID - 1 - - - $version - 100000 - - diff --git a/vendor/libkqueue/libkqueue.xcodeproj/xcuserdata/jocke.xcuserdatad/xcschemes/libkqueue.xcscheme b/vendor/libkqueue/libkqueue.xcodeproj/xcuserdata/jocke.xcuserdatad/xcschemes/libkqueue.xcscheme deleted file mode 100644 index 36d8fdcff..000000000 --- a/vendor/libkqueue/libkqueue.xcodeproj/xcuserdata/jocke.xcuserdatad/xcschemes/libkqueue.xcscheme +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/libkqueue/libkqueue.xcodeproj/xcuserdata/jocke.xcuserdatad/xcschemes/xcschememanagement.plist b/vendor/libkqueue/libkqueue.xcodeproj/xcuserdata/jocke.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 573d47860..000000000 --- a/vendor/libkqueue/libkqueue.xcodeproj/xcuserdata/jocke.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - SchemeUserState - - libkqueue.xcscheme - - orderHint - 0 - - - SuppressBuildableAutocreation - - 85F0622E131E3A3D0013C05E - - primary - - - - - From b90377a77bcdb5c1a2742e615a8f2752329889a1 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 30 Dec 2016 12:18:52 -0800 Subject: [PATCH 0628/1120] gitignore: update for new build system Remove the autotools ignore list, update for the cmake output. --- vendor/libkqueue/.gitignore | 50 ++++++++++++------------------------- 1 file changed, 16 insertions(+), 34 deletions(-) diff --git a/vendor/libkqueue/.gitignore b/vendor/libkqueue/.gitignore index beb9d5d93..11b6a3aa4 100644 --- a/vendor/libkqueue/.gitignore +++ b/vendor/libkqueue/.gitignore @@ -1,37 +1,19 @@ -# build files generated by autotools -Makefile -Makefile.in -aclocal.m4 -autom4te.cache -compile -configure -config.guess -config.h -config.h.in -config.h.in~ -config.log -config.status -config.sub -config -depcomp -install-sh -libkqueue.pc -libtool -ltmain.sh -m4 -missing -stamp-h1 -# more generated files -.dirstamp -.deps -.libs -*.lo -*.la +# cmake output +CMakeCache.txt +CMakeFiles/ +CPackConfig.cmake +CPackSourcenfig.cmake +CTestTestfile.cmake +Testing/ +_CPack_Packages/ +cmake_install.cmake +install_manifest.txt +kqueue-*.deb +libkqueue.so +test/CMakeCache.txt +test/CMakeFiles/ +test/cmake_install.cmake + *.o -# generated test artifacts -*.log -*.trs -test-driver -kqtest \ No newline at end of file From 513382fa4981032b735bfcc5e9e93e9947784ac7 Mon Sep 17 00:00:00 2001 From: Philippe Wooding Date: Mon, 12 Jun 2017 23:23:05 +0200 Subject: [PATCH 0629/1120] Fix to allow pcap FDs to be used correctly with libkqueue. Currently, the EV_EOF flag is set when packets are available from a pcap FD because SIOCINQ always returns 0. --- vendor/libkqueue/src/linux/platform.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index e97eacc51..3b0f4830f 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -301,6 +301,7 @@ linux_get_descriptor_type(struct knote *kn) socklen_t slen; struct stat sb; int i, lsock; + socklen_t out_len; /* * Test if the descriptor is a socket. @@ -327,7 +328,6 @@ linux_get_descriptor_type(struct knote *kn) if (i < 0) { switch (errno) { case ENOTSOCK: /* same as lsock = 0 */ - return (0); break; default: dbg_perror("getsockopt(3)"); @@ -336,8 +336,30 @@ linux_get_descriptor_type(struct knote *kn) } else { if (lsock) kn->kn_flags |= KNFL_PASSIVE_SOCKET; - return (0); } + + /* + * Test if socket has a filter + * pcap file descriptors need to be considered as passive sockets as + * SIOCINQ always returns 0 even if data is available. + * Looking at SO_GET_FILTER is a good way of doing this. + */ + out_len = 0; + i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_GET_FILTER, NULL, &out_len); + if (i < 0) { + switch (errno) { + case ENOTSOCK: /* same as lsock = 0 */ + break; + default: + dbg_perror("getsockopt(3)"); + return (-1); + } + } else { + if (out_len) + kn->kn_flags |= KNFL_PASSIVE_SOCKET; + } + + return (0); } char * From abd6407e779463906d7aa04973fe075d65db06c7 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 16 Jun 2017 19:43:59 -0400 Subject: [PATCH 0630/1120] Fix CPACK_PACKAGE_VERSION* variables - ``set(CPACK_PACKAGE_NAME ${PACKAGE_NAME})`` is incorrect. Should be ``${PROJECT_NAME}`` as per https://cmake.org/cmake/help/v3.0/command/project.html - ``set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})`` is incorrect. Should be ``${PROJECT_VERSION}`` as per https://cmake.org/cmake/help/v3.0/command/project.html ``CPACK_PACKAGE_VERSION_MAJOR`` must also be set, else ``CPACK_PACKAGE_VERSION_MAJOR`` is set to 0 in the generated ``CPackConfig.cmake`` file. The others are set for completeness. This was observed with ``cpack3 version 3.6.3`` --- vendor/libkqueue/CMakeLists.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index aa8ee8650..f69c6ca42 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -169,8 +169,11 @@ install(FILES DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig") -set(CPACK_PACKAGE_NAME ${PACKAGE_NAME}) -set(CPACK_PACKAGE_VERSION ${PACKAGE_VERSION}) +set(CPACK_PACKAGE_NAME ${PROJECT_NAME}) +set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) +set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) +set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) +set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Mark Heily ") include(CPack) From 939e3af6cc3349fda1c0107559b6812920d0774b Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 17 Jun 2017 00:15:58 -0400 Subject: [PATCH 0631/1120] Prefix the project name with lib - So that packages are named correctly --- vendor/libkqueue/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index f69c6ca42..ad9ba15f1 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -17,7 +17,7 @@ cmake_minimum_required(VERSION 3.4.3) cmake_policy(SET CMP0063 OLD) -project(kqueue VERSION 2.1.1 LANGUAGES C) +project(libkqueue VERSION 2.1.1 LANGUAGES C) enable_testing() set(CMAKE_C_VISIBILITY_PRESET hidden) From e25b31e0fd9133932bed4d966481d13b687361ac Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 17 Jun 2017 00:20:05 -0400 Subject: [PATCH 0632/1120] Split files into components and add RPM packaging meta-data --- vendor/libkqueue/CMakeLists.txt | 59 ++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index ad9ba15f1..e3a7e78a1 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -14,6 +14,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # +# Note: In order for RPM packaging to work correctly version >= 3.8 is required cmake_minimum_required(VERSION 3.4.3) cmake_policy(SET CMP0063 OLD) @@ -155,19 +156,23 @@ configure_file("${CMAKE_SOURCE_DIR}/libkqueue.pc.in" install(FILES "include/sys/event.h" DESTINATION - "${CMAKE_INSTALL_FULL_INCLUDEDIR}/sys") + "${CMAKE_INSTALL_FULL_INCLUDEDIR}/sys" + COMPONENT headers) install(TARGETS kqueue DESTINATION - "${CMAKE_INSTALL_FULL_LIBDIR}") + "${CMAKE_INSTALL_FULL_LIBDIR}" + COMPONENT libraries) install(FILES kqueue.2 DESTINATION - "${CMAKE_INSTALL_FULL_MANDIR}") + "${CMAKE_INSTALL_FULL_MANDIR}" + COMPONENT man) install(FILES "${CMAKE_BINARY_DIR}/libkqueue.pc" DESTINATION - "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig") + "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig" + COMPONENT pkgconfig) set(CPACK_PACKAGE_NAME ${PROJECT_NAME}) set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) @@ -175,5 +180,51 @@ set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Mark Heily ") + +# Specify the location of source files to be installed by the debuginfo package +set(CPACK_BUILD_SOURCE_DIRS ${CMAKE_SOURCE_DIR}/src) + +# Group the components into packages +# - devel contains header files and becomes libkqueue-devel +# - main contains everything else and becomes libkqueue +set(CPACK_COMPONENT_HEADERS_GROUP "devel") +set(CPACK_COMPONENT_LIBRARIES_GROUP "main") +set(CPACK_COMPONENT_MAN_GROUP "main") +set(CPACK_COMPONENT_PKGCONFIG_GROUP "main") +set(CPACK_COMPONENT_HEADERS_DEPENDS "main") + +# +# Metadata common to all packaging systems +# +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Userspace implementation of the kqueue event notification mechanism") + +set(CPACK_COMPONENT_MAIN_DESCRIPTION "A user space implementation of the kqueue(2) kernel event notification +mechanism. libkqueue acts as a translator between the kevent structure and the +native kernel facilities.") +set(CPACK_COMPONENT_DEVEL_DESCRIPTION "Development files for ${PROJECT_NAME}-${PROJECT_VERSION}") + +# +# RPM Specific configuration +# +set(CPACK_RPM_PACKAGE_LICENSE "MIT and BSD") +set(CPACK_RPM_PACKAGE_URL "http://sourceforge.net/p/libkqueue/wiki/Home/") + +set(CPACK_RPM_MAIN_PACKAGE_GROUP "System Environment/Libraries") +set(CPACK_RPM_MAIN_PACKAGE_DESCRIPTION ${CPACK_COMPONENT_MAIN_DESCRIPTION}) + +set(CPACK_RPM_DEVEL_PACKAGE_GROUP "Development/Libraries") +set(CPACK_RPM_DEVEL_PACKAGE_SUMMARY ${CPACK_COMPONENT_DEVEL_DESCRIPTION}) +set(CPACK_RPM_DEVEL_PACKAGE_REQUIRES "${CPACK_PACKAGE_NAME} = %{version}-%{release}") + +set(CPACK_RPM_MAIN_COMPONENT "main") # Nominate the component to be packed into libkqueue +set(CPACK_RPM_COMPONENT_INSTALL ON) # Enable component based packaging (generate multiple packages) +set(CPACK_RPM_FILE_NAME RPM-DEFAULT) # Use rpmbuild's package naming scheme + +# +# Build a debuginfo package containing the source an debugging symbols +# +set(CPACK_RPM_MAIN_DEBUGINFO_PACKAGE ON) +set(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE ON) +set(CPACK_RPM_MAIN_BUILD_SOURCE_DIRS_PREFIX /usr/src/debug/${PROJECT_NAME}-${PROJECT_VERSION}) include(CPack) From 26e5667610e5c4a17143baf771293020bb187248 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 17 Jun 2017 00:25:26 -0400 Subject: [PATCH 0633/1120] Keep debug symbols --- vendor/libkqueue/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index e3a7e78a1..83d09c235 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -25,6 +25,7 @@ set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD 99) +set(CMAKE_BUILD_TYPE RelWithDebInfo) option(STATIC_KQUEUE "build libkqueue as static library" OFF) From 0319f8f5c60a3711a3aa938f45b63b59fade5e6d Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 20 Nov 2017 22:37:29 +0000 Subject: [PATCH 0634/1120] Trim trailing whitespace --- vendor/libkqueue/src/linux/vnode.c | 44 +++++++++++++++--------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 4d5533859..a02c505c5 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -49,7 +49,7 @@ inotify_event_dump(struct inotify_event *evt) { static __thread char buf[1024]; - snprintf(buf, sizeof(buf), "wd=%d mask=%s", + snprintf(buf, sizeof(buf), "wd=%d mask=%s", evt->wd, inotify_mask_dump(evt->mask)); @@ -80,7 +80,7 @@ get_one_event(struct inotify_event *dst, int inofd) dbg_printf("read(2) from inotify wd: %ld bytes", (long) n); /* FIXME-TODO: if len > 0, read(len) */ - if (dst->len != 0) + if (dst->len != 0) abort(); @@ -103,11 +103,11 @@ add_watch(struct filter *filt, struct knote *kn) mask = IN_CLOSE; if (kn->kev.fflags & NOTE_DELETE) mask |= IN_ATTRIB | IN_DELETE_SELF; - if (kn->kev.fflags & NOTE_WRITE) + if (kn->kev.fflags & NOTE_WRITE) mask |= IN_MODIFY | IN_ATTRIB; if (kn->kev.fflags & NOTE_EXTEND) mask |= IN_MODIFY | IN_ATTRIB; - if ((kn->kev.fflags & NOTE_ATTRIB) || + if ((kn->kev.fflags & NOTE_ATTRIB) || (kn->kev.fflags & NOTE_LINK)) mask |= IN_ATTRIB; if (kn->kev.fflags & NOTE_RENAME) @@ -123,7 +123,7 @@ add_watch(struct filter *filt, struct knote *kn) } /* Add the watch */ - dbg_printf("inotify_add_watch(2); inofd=%d, %s, path=%s", + dbg_printf("inotify_add_watch(2); inofd=%d, %s, path=%s", ifd, inotify_mask_dump(mask), path); kn->kev.data = inotify_add_watch(ifd, path, mask); if (kn->kev.data < 0) { @@ -183,7 +183,7 @@ evfilt_vnode_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) return (0); } - /* Check if the watched file has been closed, and + /* Check if the watched file has been closed, and XXX-this may not exactly match the kevent() behavior if multiple file de scriptors reference the same file. */ @@ -198,38 +198,38 @@ scriptors reference the same file. /* No error checking because fstat(2) should rarely fail */ //FIXME: EINTR - if ((evt.mask & IN_ATTRIB || evt.mask & IN_MODIFY) + if ((evt.mask & IN_ATTRIB || evt.mask & IN_MODIFY) && fstat(src->kev.ident, &sb) == 0) { - if (sb.st_nlink == 0 && src->kev.fflags & NOTE_DELETE) + if (sb.st_nlink == 0 && src->kev.fflags & NOTE_DELETE) dst->fflags |= NOTE_DELETE; - if (sb.st_nlink != src->data.vnode.nlink && src->kev.fflags & NOTE_LINK) + if (sb.st_nlink != src->data.vnode.nlink && src->kev.fflags & NOTE_LINK) dst->fflags |= NOTE_LINK; #if HAVE_NOTE_TRUNCATE - if (sb.st_nsize == 0 && src->kev.fflags & NOTE_TRUNCATE) + if (sb.st_nsize == 0 && src->kev.fflags & NOTE_TRUNCATE) dst->fflags |= NOTE_TRUNCATE; #endif - if (sb.st_size > src->data.vnode.size && src->kev.fflags & NOTE_WRITE) + if (sb.st_size > src->data.vnode.size && src->kev.fflags & NOTE_WRITE) dst->fflags |= NOTE_EXTEND; src->data.vnode.nlink = sb.st_nlink; src->data.vnode.size = sb.st_size; } - if (evt.mask & IN_MODIFY && src->kev.fflags & NOTE_WRITE) + if (evt.mask & IN_MODIFY && src->kev.fflags & NOTE_WRITE) dst->fflags |= NOTE_WRITE; - if (evt.mask & IN_ATTRIB && src->kev.fflags & NOTE_ATTRIB) + if (evt.mask & IN_ATTRIB && src->kev.fflags & NOTE_ATTRIB) dst->fflags |= NOTE_ATTRIB; - if (evt.mask & IN_MOVE_SELF && src->kev.fflags & NOTE_RENAME) + if (evt.mask & IN_MOVE_SELF && src->kev.fflags & NOTE_RENAME) dst->fflags |= NOTE_RENAME; - if (evt.mask & IN_DELETE_SELF && src->kev.fflags & NOTE_DELETE) + if (evt.mask & IN_DELETE_SELF && src->kev.fflags & NOTE_DELETE) dst->fflags |= NOTE_DELETE; - if (evt.mask & IN_MODIFY && src->kev.fflags & NOTE_WRITE) + if (evt.mask & IN_MODIFY && src->kev.fflags & NOTE_WRITE) dst->fflags |= NOTE_WRITE; - if (evt.mask & IN_ATTRIB && src->kev.fflags & NOTE_ATTRIB) + if (evt.mask & IN_ATTRIB && src->kev.fflags & NOTE_ATTRIB) dst->fflags |= NOTE_ATTRIB; - if (evt.mask & IN_MOVE_SELF && src->kev.fflags & NOTE_RENAME) + if (evt.mask & IN_MOVE_SELF && src->kev.fflags & NOTE_RENAME) dst->fflags |= NOTE_RENAME; - if (evt.mask & IN_DELETE_SELF && src->kev.fflags & NOTE_DELETE) + if (evt.mask & IN_DELETE_SELF && src->kev.fflags & NOTE_DELETE) dst->fflags |= NOTE_DELETE; return (0); @@ -252,7 +252,7 @@ evfilt_vnode_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_vnode_knote_modify(struct filter *filt, struct knote *kn, +evfilt_vnode_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { (void)filt; @@ -263,7 +263,7 @@ evfilt_vnode_knote_modify(struct filter *filt, struct knote *kn, int evfilt_vnode_knote_delete(struct filter *filt, struct knote *kn) -{ +{ return delete_watch(filt, kn); } @@ -288,5 +288,5 @@ const struct filter evfilt_vnode = { evfilt_vnode_knote_modify, evfilt_vnode_knote_delete, evfilt_vnode_knote_enable, - evfilt_vnode_knote_disable, + evfilt_vnode_knote_disable, }; From 2a87c7dea691c653d0ca450122efe9bbe21c3515 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 20 Nov 2017 18:58:17 +0000 Subject: [PATCH 0635/1120] Deal with inotify events containing filenames correctly From inotify(7) The name field is present only when an event is returned for a file inside a watched directory; it identifies the file pathname relative to the watched directory. This pathname is null-terminated, and may include further null bytes ('\0') to align subsequent reads to a suitable address boundary. Without this patch, the abort is triggered after the loop exits. Removing the abort would cause misaligned reads, where the next time get_one_event was called, the structure would be populate with the name of the file from the previous event. --- vendor/libkqueue/src/linux/vnode.c | 71 ++++++++++++++++++------------ 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index a02c505c5..e8a5d0eed 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -49,9 +49,15 @@ inotify_event_dump(struct inotify_event *evt) { static __thread char buf[1024]; - snprintf(buf, sizeof(buf), "wd=%d mask=%s", - evt->wd, - inotify_mask_dump(evt->mask)); + if (evt->len > 0) + snprintf(buf, sizeof(buf), "wd=%d mask=%s name=%s", + evt->wd, + inotify_mask_dump(evt->mask), + evt->name); + else + snprintf(buf, sizeof(buf), "wd=%d mask=%s", + evt->wd, + inotify_mask_dump(evt->mask)); return (buf); } @@ -59,30 +65,37 @@ inotify_event_dump(struct inotify_event *evt) #endif /* !NDEBUG */ -/* TODO: USE this to get events with name field */ int -get_one_event(struct inotify_event *dst, int inofd) +get_one_event(struct inotify_event *dst, size_t len, int inofd) { ssize_t n; + size_t want = sizeof(struct inotify_event); dbg_puts("reading one inotify event"); for (;;) { - n = read(inofd, dst, sizeof(*dst)); + if (len < want) { + dbg_printf("Needed %zu bytes have %zu bytes", want, len); + return (-1); + } + + n = read(inofd, dst, want); if (n < 0) { - if (errno == EINTR) + switch (errno) { + case EINVAL: + want += sizeof(struct inotify_event); + /* FALL-THROUGH */ + + case EINTR: continue; + } + dbg_perror("read"); return (-1); - } else { - break; } + break; } - dbg_printf("read(2) from inotify wd: %ld bytes", (long) n); - - /* FIXME-TODO: if len > 0, read(len) */ - if (dst->len != 0) - abort(); + dbg_printf("read(2) from inotify wd: %ld bytes", (long)n); return (0); } @@ -170,14 +183,16 @@ delete_watch(struct filter *filt, struct knote *kn) int evfilt_vnode_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) { - struct inotify_event evt; + uint8_t buf[sizeof(struct inotify_event) + NAME_MAX + 1] __attribute__ ((aligned(__alignof__(struct inotify_event)))); + struct inotify_event *evt; struct stat sb; - if (get_one_event(&evt, src->kdata.kn_inotifyfd) < 0) + evt = (struct inotify_event *)buf; + if (get_one_event(evt, sizeof(buf), src->kdata.kn_inotifyfd) < 0) return (-1); - dbg_printf("inotify event: %s", inotify_event_dump(&evt)); - if (evt.mask & IN_IGNORED) { + dbg_printf("inotify event: %s", inotify_event_dump(evt)); + if (evt->mask & IN_IGNORED) { /* TODO: possibly return error when fs is unmounted */ dst->filter = 0; return (0); @@ -187,7 +202,7 @@ evfilt_vnode_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) XXX-this may not exactly match the kevent() behavior if multiple file de scriptors reference the same file. */ - if (evt.mask & IN_CLOSE_WRITE || evt.mask & IN_CLOSE_NOWRITE) { + if (evt->mask & IN_CLOSE_WRITE || evt->mask & IN_CLOSE_NOWRITE) { src->kn_flags |= EV_ONESHOT; /* KLUDGE: causes the knote to be deleted */ dst->filter = 0; /* KLUDGE: causes the event to be discarded */ return (0); @@ -198,7 +213,7 @@ scriptors reference the same file. /* No error checking because fstat(2) should rarely fail */ //FIXME: EINTR - if ((evt.mask & IN_ATTRIB || evt.mask & IN_MODIFY) + if ((evt->mask & IN_ATTRIB || evt->mask & IN_MODIFY) && fstat(src->kev.ident, &sb) == 0) { if (sb.st_nlink == 0 && src->kev.fflags & NOTE_DELETE) dst->fflags |= NOTE_DELETE; @@ -214,22 +229,22 @@ scriptors reference the same file. src->data.vnode.size = sb.st_size; } - if (evt.mask & IN_MODIFY && src->kev.fflags & NOTE_WRITE) + if (evt->mask & IN_MODIFY && src->kev.fflags & NOTE_WRITE) dst->fflags |= NOTE_WRITE; - if (evt.mask & IN_ATTRIB && src->kev.fflags & NOTE_ATTRIB) + if (evt->mask & IN_ATTRIB && src->kev.fflags & NOTE_ATTRIB) dst->fflags |= NOTE_ATTRIB; - if (evt.mask & IN_MOVE_SELF && src->kev.fflags & NOTE_RENAME) + if (evt->mask & IN_MOVE_SELF && src->kev.fflags & NOTE_RENAME) dst->fflags |= NOTE_RENAME; - if (evt.mask & IN_DELETE_SELF && src->kev.fflags & NOTE_DELETE) + if (evt->mask & IN_DELETE_SELF && src->kev.fflags & NOTE_DELETE) dst->fflags |= NOTE_DELETE; - if (evt.mask & IN_MODIFY && src->kev.fflags & NOTE_WRITE) + if (evt->mask & IN_MODIFY && src->kev.fflags & NOTE_WRITE) dst->fflags |= NOTE_WRITE; - if (evt.mask & IN_ATTRIB && src->kev.fflags & NOTE_ATTRIB) + if (evt->mask & IN_ATTRIB && src->kev.fflags & NOTE_ATTRIB) dst->fflags |= NOTE_ATTRIB; - if (evt.mask & IN_MOVE_SELF && src->kev.fflags & NOTE_RENAME) + if (evt->mask & IN_MOVE_SELF && src->kev.fflags & NOTE_RENAME) dst->fflags |= NOTE_RENAME; - if (evt.mask & IN_DELETE_SELF && src->kev.fflags & NOTE_DELETE) + if (evt->mask & IN_DELETE_SELF && src->kev.fflags & NOTE_DELETE) dst->fflags |= NOTE_DELETE; return (0); From 55301857050f27f03e68f05bc83387ad591e4705 Mon Sep 17 00:00:00 2001 From: Philippe Wooding Date: Wed, 22 Nov 2017 06:00:58 -0500 Subject: [PATCH 0636/1120] Avoid RPM install conflict by not handling /usr/share/man/ --- vendor/libkqueue/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 83d09c235..e21dd320f 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -154,6 +154,11 @@ configure_file("${CMAKE_SOURCE_DIR}/libkqueue.pc.in" "${CMAKE_BINARY_DIR}/libkqueue.pc" @ONLY) +# +# Avoid conflicts by not trying to create /usr/share/man directory +# +set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION ${CMAKE_INSTALL_FULL_MANDIR}) + install(FILES "include/sys/event.h" DESTINATION From 1c82d631b3b8e8fdae21f9092d2882fc6f3cb85b Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 23 Nov 2017 16:21:16 +0000 Subject: [PATCH 0637/1120] Trim trailing whitespace --- vendor/libkqueue/src/common/private.h | 12 ++++++------ vendor/libkqueue/src/linux/platform.c | 24 ++++++++++++------------ vendor/libkqueue/src/linux/read.c | 10 +++++----- vendor/libkqueue/src/windows/platform.c | 12 ++++++------ 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index d56adf4da..68ce70bfa 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -63,16 +63,16 @@ struct eventfd { #endif }; -/* +/* * Flags used by knote->kn_flags */ #define KNFL_PASSIVE_SOCKET (0x01) /* Socket is in listen(2) mode */ #define KNFL_REGULAR_FILE (0x02) /* File descriptor is a regular file */ #define KNFL_KNOTE_DELETED (0x10) /* The knote object is no longer valid */ - + struct knote { struct kevent kev; - int kn_flags; + int kn_flags; union { /* OLD */ int pfd; /* Used by timerfd */ @@ -81,7 +81,7 @@ struct knote { nlink_t nlink; /* Used by vnode */ off_t size; /* Used by vnode */ } vnode; - timer_t timerid; + timer_t timerid; struct sleepreq *sleepreq; /* Used by posix/timer.c */ void *handle; /* Used by win32 filters */ } data; @@ -113,7 +113,7 @@ struct filter { /* knote operations */ int (*kn_create)(struct filter *, struct knote *); - int (*kn_modify)(struct filter *, struct knote *, + int (*kn_modify)(struct filter *, struct knote *, const struct kevent *); int (*kn_delete)(struct filter *, struct knote *); int (*kn_enable)(struct filter *, struct knote *); @@ -141,7 +141,7 @@ struct filter { struct kqueue { int kq_id; struct filter kq_filt[EVFILT_SYSCOUNT]; - fd_set kq_fds, kq_rfds; + fd_set kq_fds, kq_rfds; int kq_nfds; tracing_mutex_t kq_mtx; volatile uint32_t kq_ref; diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index e97eacc51..2391d93ca 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -30,10 +30,10 @@ static __thread struct epoll_event epevt[MAX_KEVENT]; const struct kqueue_vtable kqops = { linux_kqueue_init, linux_kqueue_free, - linux_kevent_wait, - linux_kevent_copyout, - NULL, - NULL, + linux_kevent_wait, + linux_kevent_copyout, + NULL, + NULL, linux_eventfd_init, linux_eventfd_close, linux_eventfd_raise, @@ -89,7 +89,7 @@ linux_kqueue_free(struct kqueue *kq UNUSED) static int linux_kevent_wait_hires( - struct kqueue *kq, + struct kqueue *kq, const struct timespec *timeout) { int n; @@ -128,7 +128,7 @@ linux_kevent_wait_hires( int linux_kevent_wait( - struct kqueue *kq, + struct kqueue *kq, int nevents, const struct timespec *ts) { @@ -144,7 +144,7 @@ linux_kevent_wait( timeout = 0; } else { /* Convert timeout to the format used by epoll_wait() */ - if (ts == NULL) + if (ts == NULL) timeout = -1; else timeout = (1000 * ts->tv_sec) + (ts->tv_nsec / 1000000); @@ -185,7 +185,7 @@ linux_kevent_copyout(struct kqueue *kq, int nready, * Certain flags cause the associated knote to be deleted * or disabled. */ - if (eventlist->flags & EV_DISPATCH) + if (eventlist->flags & EV_DISPATCH) knote_disable(filt, kn); //FIXME: Error checking if (eventlist->flags & EV_ONESHOT) { knote_delete(filt, kn); //FIXME: Error checking @@ -241,7 +241,7 @@ linux_eventfd_raise(struct eventfd *e) counter = 1; if (write(e->ef_id, &counter, sizeof(counter)) < 0) { switch (errno) { - case EAGAIN: + case EAGAIN: /* Not considered an error */ break; @@ -269,7 +269,7 @@ linux_eventfd_lower(struct eventfd *e) n = read(e->ef_id, &cur, sizeof(cur)); if (n < 0) { switch (errno) { - case EAGAIN: + case EAGAIN: /* Not considered an error */ break; @@ -334,7 +334,7 @@ linux_get_descriptor_type(struct knote *kn) return (-1); } } else { - if (lsock) + if (lsock) kn->kn_flags |= KNFL_PASSIVE_SOCKET; return (0); } @@ -369,7 +369,7 @@ epoll_event_dump(struct epoll_event *evt) int epoll_update(int op, struct filter *filt, struct knote *kn, struct epoll_event *ev) { - dbg_printf("op=%d fd=%d events=%s", op, (int)kn->kev.ident, + dbg_printf("op=%d fd=%d events=%s", op, (int)kn->kev.ident, epoll_event_dump(ev)); if (epoll_ctl(filter_epfd(filt), op, kn->kev.ident, ev) < 0) { dbg_printf("epoll_ctl(2): %s", strerror(errno)); diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index 18caeee91..b1add6861 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -84,7 +84,7 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) dbg_perror("inotify_init(2)"); (void) close(inofd); return (-1); - } + } src->kdata.kn_inotifyfd = inofd; if (linux_fd_to_path(&path[0], sizeof(path), src->kev.ident) < 0) return (-1); @@ -114,9 +114,9 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) #endif if (ev->events & EPOLLERR) dst->fflags = 1; /* FIXME: Return the actual socket error */ - + if (src->kn_flags & KNFL_PASSIVE_SOCKET) { - /* On return, data contains the length of the + /* On return, data contains the length of the socket backlog. This is not available under Linux. */ dst->data = 1; @@ -191,7 +191,7 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_read_knote_modify(struct filter *filt, struct knote *kn, +evfilt_read_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { (void) filt; @@ -267,5 +267,5 @@ const struct filter evfilt_read = { evfilt_read_knote_modify, evfilt_read_knote_delete, evfilt_read_knote_enable, - evfilt_read_knote_disable, + evfilt_read_knote_disable, }; diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 13f8fac72..d0b630e19 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -46,7 +46,7 @@ const struct kqueue_vtable kqops = { int windows_kqueue_init(struct kqueue *kq) { - kq->kq_iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, + kq->kq_iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR) 0, 0); if (kq->kq_iocp == NULL) { dbg_lasterror("CreateIoCompletionPort"); @@ -91,7 +91,7 @@ windows_kevent_wait(struct kqueue *kq, int no, const struct timespec *timeout) int retval; DWORD timeout_ms; BOOL success; - + if (timeout == NULL) { timeout_ms = INFINITE; } else if ( timeout->tv_sec == 0 && timeout->tv_nsec < 1000000 ) { @@ -110,10 +110,10 @@ windows_kevent_wait(struct kqueue *kq, int no, const struct timespec *timeout) #if 0 if(timeout_ms <= 0) dbg_printf("Woop, not waiting !?"); -#endif +#endif memset(&iocp_buf, 0, sizeof(iocp_buf)); - success = GetQueuedCompletionStatus(kq->kq_iocp, - &iocp_buf.bytes, &iocp_buf.key, &iocp_buf.overlap, + success = GetQueuedCompletionStatus(kq->kq_iocp, + &iocp_buf.bytes, &iocp_buf.key, &iocp_buf.overlap, timeout_ms); if (success) { return (1); @@ -153,7 +153,7 @@ windows_kevent_copyout(struct kqueue *kq, int nready, * Certain flags cause the associated knote to be deleted * or disabled. */ - if (eventlist->flags & EV_DISPATCH) + if (eventlist->flags & EV_DISPATCH) knote_disable(filt, kn); //TODO: Error checking if (eventlist->flags & EV_ONESHOT) knote_delete(filt, kn); //TODO: Error checking From cc2fdd8ae790fa3be103c5f5ea81a3c99e373fd6 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 23 Nov 2017 16:27:57 +0000 Subject: [PATCH 0638/1120] The EOF flag should only be set on stream sockets with a zero length read Datagrams can legitimately be zero length --- vendor/libkqueue/src/common/private.h | 1 + vendor/libkqueue/src/linux/platform.c | 15 +++++++++++++-- vendor/libkqueue/src/linux/read.c | 2 +- vendor/libkqueue/src/windows/platform.c | 13 ++++++++++++- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 68ce70bfa..bda929c2a 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -68,6 +68,7 @@ struct eventfd { */ #define KNFL_PASSIVE_SOCKET (0x01) /* Socket is in listen(2) mode */ #define KNFL_REGULAR_FILE (0x02) /* File descriptor is a regular file */ +#define KNFL_STREAM_SOCKET (0x03) /* File descriptor is a stream socket */ #define KNFL_KNOTE_DELETED (0x10) /* The knote object is no longer valid */ struct knote { diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 2391d93ca..fb84e99f6 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -300,7 +300,7 @@ linux_get_descriptor_type(struct knote *kn) { socklen_t slen; struct stat sb; - int i, lsock; + int i, lsock, stype; /* * Test if the descriptor is a socket. @@ -336,8 +336,19 @@ linux_get_descriptor_type(struct knote *kn) } else { if (lsock) kn->kn_flags |= KNFL_PASSIVE_SOCKET; - return (0); } + + slen = sizeof(stype); + stype = 0; + i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_TYPE, (char *) &lsock, &slen); + if (i < 0) { + dbg_perror("getsockopt(3)"); + return (-1); + } + if (stype == SOCK_STREAM) + kn->kn_flags |= KNFL_STREAM_SOCKET; + + return (0); } char * diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index b1add6861..c0e4b7dcc 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -131,7 +131,7 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) dst->data = 0; } else { dst->data = i; - if (dst->data == 0) + if (dst->data == 0 && src->kn_flags & KNFL_STREAM_SOCKET) dst->flags |= EV_EOF; } } diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index d0b630e19..849b3c361 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -191,12 +191,23 @@ windows_get_descriptor_type(struct knote *kn) switch (GetFileType((HANDLE)kn->kev.ident)) { case FILE_TYPE_PIPE: { socklen_t slen; - int lsock, i; + int lsock, stype, i; + slen = sizeof(lsock); lsock = 0; i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_ACCEPTCONN, (char *)&lsock, &slen); if (i == 0 && lsock) kn->kn_flags |= KNFL_PASSIVE_SOCKET; + + slen = sizeof(stype); + stype = 0; + i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_TYPE, (char *) &lsock, &slen); + if (i < 0) { + dbg_perror("getsockopt(3)"); + return (-1); + } + if (stype == SOCK_STREAM) + kn->kn_flags |= KNFL_STREAM_SOCKET; break; } default: { From b7968ce9deaed46d5460f4bdab0652a680283b4b Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Fri, 24 Nov 2017 20:12:01 +0000 Subject: [PATCH 0639/1120] Fix build problems in Vagrant --- vendor/libkqueue/Vagrantfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/Vagrantfile b/vendor/libkqueue/Vagrantfile index a280b7170..33cbbdd71 100644 --- a/vendor/libkqueue/Vagrantfile +++ b/vendor/libkqueue/Vagrantfile @@ -12,7 +12,7 @@ Vagrant.configure("2") do |config| # Every Vagrant development environment requires a box. You can search for # boxes at https://atlas.hashicorp.com/search. - config.vm.box = "hashicorp/precise64" + config.vm.box = "ubuntu/xenial64" # Disable automatic box update checking. If you disable this, then # boxes will only be checked for updates when the user runs @@ -66,6 +66,6 @@ Vagrant.configure("2") do |config| # documentation for more information about their specific syntax and use. config.vm.provision "shell", inline: <<-SHELL apt-get update - apt-get install -y gcc make autoconf automake libtool + apt-get install -y gcc make cmake SHELL end From a8f9cf3862e315a5246c3922ed1240b1c5eaf564 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Fri, 24 Nov 2017 20:29:23 +0000 Subject: [PATCH 0640/1120] Add missing items to .gitignore --- vendor/libkqueue/.gitignore | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/.gitignore b/vendor/libkqueue/.gitignore index 11b6a3aa4..1ec367d25 100644 --- a/vendor/libkqueue/.gitignore +++ b/vendor/libkqueue/.gitignore @@ -1,10 +1,13 @@ - -# cmake output +.vagrant/ +config.h +*.pc +*.log CMakeCache.txt CMakeFiles/ CPackConfig.cmake -CPackSourcenfig.cmake +CPackSourceConfig.cmake CTestTestfile.cmake +Makefile Testing/ _CPack_Packages/ cmake_install.cmake @@ -14,6 +17,4 @@ libkqueue.so test/CMakeCache.txt test/CMakeFiles/ test/cmake_install.cmake - -*.o - +test/libkqueue-test From 85ca406dc1cabcda166bb86125ba9cd29218bc7d Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sun, 26 Nov 2017 20:42:30 +0000 Subject: [PATCH 0641/1120] Merge patch from https://github.com/mheily/libkqueue/pull/36 --- vendor/libkqueue/src/linux/vnode.c | 37 +++++++++++++++--------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index e8a5d0eed..418572ade 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -210,33 +210,32 @@ scriptors reference the same file. memcpy(dst, &src->kev, sizeof(*dst)); dst->data = 0; + dst->fflags = 0; /* No error checking because fstat(2) should rarely fail */ //FIXME: EINTR - if ((evt->mask & IN_ATTRIB || evt->mask & IN_MODIFY) - && fstat(src->kev.ident, &sb) == 0) { - if (sb.st_nlink == 0 && src->kev.fflags & NOTE_DELETE) + if (fstat(src->kev.ident, &sb) < 0 && errno == ENOENT) { + if (src->kev.fflags & NOTE_DELETE) dst->fflags |= NOTE_DELETE; - if (sb.st_nlink != src->data.vnode.nlink && src->kev.fflags & NOTE_LINK) - dst->fflags |= NOTE_LINK; + } else { + if ((evt->mask & IN_ATTRIB || evt->mask & IN_MODIFY)) { + if (sb.st_nlink == 0 && src->kev.fflags & NOTE_DELETE) + dst->fflags |= NOTE_DELETE; + if (sb.st_nlink != src->data.vnode.nlink && + src->kev.fflags & NOTE_LINK) + dst->fflags |= NOTE_LINK; #if HAVE_NOTE_TRUNCATE - if (sb.st_nsize == 0 && src->kev.fflags & NOTE_TRUNCATE) - dst->fflags |= NOTE_TRUNCATE; + if (sb.st_nsize == 0 && src->kev.fflags & NOTE_TRUNCATE) + dst->fflags |= NOTE_TRUNCATE; #endif - if (sb.st_size > src->data.vnode.size && src->kev.fflags & NOTE_WRITE) - dst->fflags |= NOTE_EXTEND; - src->data.vnode.nlink = sb.st_nlink; - src->data.vnode.size = sb.st_size; + if (sb.st_size > src->data.vnode.size && + src->kev.fflags & NOTE_WRITE) + dst->fflags |= NOTE_EXTEND; + src->data.vnode.nlink = sb.st_nlink; + src->data.vnode.size = sb.st_size; + } } - if (evt->mask & IN_MODIFY && src->kev.fflags & NOTE_WRITE) - dst->fflags |= NOTE_WRITE; - if (evt->mask & IN_ATTRIB && src->kev.fflags & NOTE_ATTRIB) - dst->fflags |= NOTE_ATTRIB; - if (evt->mask & IN_MOVE_SELF && src->kev.fflags & NOTE_RENAME) - dst->fflags |= NOTE_RENAME; - if (evt->mask & IN_DELETE_SELF && src->kev.fflags & NOTE_DELETE) - dst->fflags |= NOTE_DELETE; if (evt->mask & IN_MODIFY && src->kev.fflags & NOTE_WRITE) dst->fflags |= NOTE_WRITE; From 76e808656d11dfa835b6614199ccbde4facb4004 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sun, 26 Nov 2017 20:51:32 +0000 Subject: [PATCH 0642/1120] Version 2.2.0 --- vendor/libkqueue/ChangeLog | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 177db1009..f2a75fa32 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,3 +1,18 @@ +2017-11-26 v2.2.0 +------------------------------------------------------------------------ + + * Fixed: the EOF flag should only be set on stream sockets with a zero length r +ead + Author: Arran Cudbard-Bell + + * Fix to deal with inotify events containing filenames correctly. + Author: Arran Cudbard-Bell + + * Fix to allow libpcap FDs to be used. + Author: Philippe Wooding + + * Switch to CMake as the build and packaging system. + 2016-07-24 v2.1.0 ------------------------------------------------------------------------ From 708c3dd296b5b3d3f2f2199b826132bf536984fc Mon Sep 17 00:00:00 2001 From: maxice8 Date: Mon, 27 Nov 2017 00:42:41 -0200 Subject: [PATCH 0643/1120] test/test.c: check if linux is using glibc This will fix building tests on system like Alpine and Void Linux musl doesn't provide execinfo.h and also doesn't provide a __MUSL__ macro, so we work around it by checking if the system is running __GLIBC__, we also check if it's not running __UCLIBC__ since uclibc claims to be __GLIBC__ for compatibility purposes but doesn't actually provide a working execinfo.h implementation. --- vendor/libkqueue/test/test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/test/test.c b/vendor/libkqueue/test/test.c index 97017f392..c49a1840d 100644 --- a/vendor/libkqueue/test/test.c +++ b/vendor/libkqueue/test/test.c @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#if defined(__linux__) && !defined(__ANDROID__) +#if defined(__linux__) && (defined(__GLIBC__) && !defined(__UCLIBC__)) #include #endif #include @@ -30,7 +30,7 @@ static int error_flag = 1; static void error_handler(int signum) { -#if defined(__linux__) && !defined(__ANDROID__) +#if defined(__linux__) && (defined(__GLIBC__) && !defined(__UCLIBC__)) void *buf[32]; /* FIXME: the symbols aren't printing */ From dd1c0c00ab67665a3be57103a6fa55ed12ff07e3 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 28 Nov 2017 11:03:18 +0000 Subject: [PATCH 0644/1120] Add Travis CIT --- vendor/libkqueue/.travis.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 vendor/libkqueue/.travis.yml diff --git a/vendor/libkqueue/.travis.yml b/vendor/libkqueue/.travis.yml new file mode 100644 index 000000000..e31ada2a6 --- /dev/null +++ b/vendor/libkqueue/.travis.yml @@ -0,0 +1,22 @@ +language: c +compiler: +- clang +- gcc +dist: trusty +env: + global: + - M_PERTURB=0x42 +addons: + apt: + packages: + - doxygen +before_install: +- $CC --version +before_script: +# Cmake that ships with Trusty (v3.2.2) is too old, we need at least v3.4.3 +- mkdir /tmp/cmake && wget -O cmake.sh https://cmake.org/files/v3.10/cmake-3.10.0-Linux-x86_64.sh && chmod +x cmake.sh && ./cmake.sh --prefix=/tmp/cmake --skip-license +- /tmp/cmake/bin/cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib -DENABLE_TESTING=YES ./ +- make -j2 +- /tmp/cmake/bin/cpack -G DEB +script: +- make test From 3738e5419b17695dc4b8de49cf6218f967942f61 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Wed, 29 Nov 2017 01:11:47 +0000 Subject: [PATCH 0645/1120] Update the Changelog --- vendor/libkqueue/ChangeLog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index f2a75fa32..3362b24f8 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,3 +1,8 @@ +Unreleased +------------------------------------------------------------------------ + + * Enable continuous integration testing via travis-ci.org + 2017-11-26 v2.2.0 ------------------------------------------------------------------------ From 55c0837f75c659648e05a9fdeb230c4b23494736 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 29 Nov 2017 11:06:14 +0000 Subject: [PATCH 0646/1120] Add Travis CI status button --- vendor/libkqueue/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index 935072a09..4e26dd570 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -1,6 +1,8 @@ libkqueue ========= +[![Travis CI build status][BuildStatus]][BuildStatusLink] + A user space implementation of the kqueue(2) kernel event notification mechanism libkqueue acts as a translator between the kevent structure and the native kernel facilities on Linux, Android, Solaris, and Windows. @@ -84,3 +86,6 @@ Releases History 2.0 add support for Android _2013-04-29_ 1.0 stable relesae for Linux, Solaris, and Windows _2010-09-18_ + +[BuildStatus]: https://travis-ci.org/mheily/libkqueue.svg?branch=master "Travis CI status" +[BuildStatusLink]: https://travis-ci.org/mheily/libkqueue From c0e9feb70d6881b1729fd8c42e9d566d729df3b9 Mon Sep 17 00:00:00 2001 From: Philippe Wooding Date: Fri, 8 Dec 2017 10:32:42 +0100 Subject: [PATCH 0647/1120] Fix typo --- vendor/libkqueue/src/linux/vnode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 418572ade..c275e4a6c 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -203,7 +203,7 @@ evfilt_vnode_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) scriptors reference the same file. */ if (evt->mask & IN_CLOSE_WRITE || evt->mask & IN_CLOSE_NOWRITE) { - src->kn_flags |= EV_ONESHOT; /* KLUDGE: causes the knote to be deleted */ + src->kev.flags |= EV_ONESHOT; /* KLUDGE: causes the knote to be deleted */ dst->filter = 0; /* KLUDGE: causes the event to be discarded */ return (0); } From 51174fdba07b53d6c91114c4fbc48845f007d193 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 14 Dec 2017 19:49:24 +0000 Subject: [PATCH 0648/1120] Use SO_ATTACH_FILTER for older kernels (Centos 6) Closes #43 --- vendor/libkqueue/src/linux/platform.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 4a1606cef..f3b8985be 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -18,6 +18,10 @@ # include #include "../common/private.h" +#ifndef SO_GET_FILTER +#define SO_GET_FILTER SO_ATTACH_FILTER +#endif + //XXX-FIXME TEMP const struct filter evfilt_proc = EVFILT_NOTIMPL; From da3827e8dfd9367ede27e92be761d7d81ded007a Mon Sep 17 00:00:00 2001 From: Philippe Wooding Date: Thu, 8 Feb 2018 09:16:47 -0500 Subject: [PATCH 0649/1120] Check return value of kn_delete --- vendor/libkqueue/src/common/knote.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 40d2232ce..c669b8c10 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -100,7 +100,8 @@ knote_delete(struct filter *filt, struct knote *kn) } pthread_rwlock_unlock(&filt->kf_knote_mtx); - filt->kn_delete(filt, kn); //XXX-FIXME check return value + if (filt->kn_delete(filt, kn) < 0) + return (-1); kn->kn_flags |= KNFL_KNOTE_DELETED; From 4f7d5aa1aa73e17b9a19ddeac64fff23b91f0bd9 Mon Sep 17 00:00:00 2001 From: Philippe Wooding Date: Thu, 8 Feb 2018 09:22:21 -0500 Subject: [PATCH 0650/1120] Missing return statement in evfilt_read_knote_delete --- vendor/libkqueue/src/linux/read.c | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index c0e4b7dcc..c06db3115 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -213,6 +213,7 @@ evfilt_read_knote_delete(struct filter *filt, struct knote *kn) } (void) close(kn->kdata.kn_eventfd); kn->kdata.kn_eventfd = -1; + return (0); } else { return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); } From 191583fee045554f6e2a0e9d24b8f72b629c3712 Mon Sep 17 00:00:00 2001 From: Philippe Wooding Date: Tue, 20 Feb 2018 17:22:59 +0100 Subject: [PATCH 0651/1120] Only degister fd from epoll if it is registered --- vendor/libkqueue/src/linux/platform.h | 1 + vendor/libkqueue/src/linux/read.c | 9 ++++++++- vendor/libkqueue/src/linux/user.c | 7 +++++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index bcc0e5740..8960cd11c 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -67,6 +67,7 @@ extern long int syscall (long int __sysno, ...); */ #define KNOTE_PLATFORM_SPECIFIC \ int kn_epollfd; /* A copy of filter->epfd */ \ + int kn_registered; /* Is FD registered with epoll */ \ union { \ int kn_timerfd; \ int kn_signalfd; \ diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index c06db3115..125aaa8a6 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -69,6 +69,7 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) dbg_perror("epoll_ctl(2)"); return (-1); } + src->kn_registered = 0; #if FIXME /* XXX-FIXME Switch to using kn_inotifyfd to monitor for IN_ATTRIB events @@ -184,6 +185,9 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) dbg_printf("epoll_ctl(2): %s", strerror(errno)); return (-1); } + + kn->kn_registered = 1; + return (0); } @@ -207,10 +211,11 @@ evfilt_read_knote_delete(struct filter *filt, struct knote *kn) return (0); if ((kn->kn_flags & KNFL_REGULAR_FILE) && (kn->kdata.kn_eventfd != -1)) { - if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kdata.kn_eventfd, NULL) < 0) { + if (kn->kn_registered && epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kdata.kn_eventfd, NULL) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); } + kn->kn_registered = 0; (void) close(kn->kdata.kn_eventfd); kn->kdata.kn_eventfd = -1; return (0); @@ -236,6 +241,7 @@ evfilt_read_knote_enable(struct filter *filt, struct knote *kn) dbg_perror("epoll_ctl(2)"); return (-1); } + kn->kn_registered = 1; return (0); } else { return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); @@ -253,6 +259,7 @@ evfilt_read_knote_disable(struct filter *filt, struct knote *kn) dbg_perror("epoll_ctl(2)"); return (-1); } + kn->kn_registered = 1; return (0); } else { return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index e3bc28a74..aa1b93b18 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -136,12 +136,14 @@ linux_evfilt_user_knote_create(struct filter *filt, struct knote *kn) } kn->kdata.kn_eventfd = evfd; + kn->kn_registered = 1; return (0); errout: (void) close(evfd); kn->kdata.kn_eventfd = -1; + kn->kn_registered = 0; return (-1); } @@ -188,11 +190,12 @@ linux_evfilt_user_knote_modify(struct filter *filt UNUSED, struct knote *kn, int linux_evfilt_user_knote_delete(struct filter *filt, struct knote *kn) { - if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_DEL, - kn->kdata.kn_eventfd, NULL) < 0) { + if (kn->kn_registered && epoll_ctl(filter_epfd(filt), EPOLL_CTL_DEL, + kn->kdata.kn_eventfd, NULL) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); } + kn->kn_registered = 0; if (close(kn->kdata.kn_eventfd) < 0) { dbg_perror("close(2)"); return (-1); From d8f6f5dfb0fb270a7aa5e43fa48586af8787ded5 Mon Sep 17 00:00:00 2001 From: Philippe Wooding Date: Thu, 22 Mar 2018 08:30:12 +0100 Subject: [PATCH 0652/1120] Remove extra spaces --- vendor/libkqueue/src/common/filter.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index 678fa785b..75fe9e6db 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -39,7 +39,7 @@ filter_register(struct kqueue *kq, short filter, const struct filter *src) int rv = 0; filt = (-1 * filter) - 1; - if (filt >= EVFILT_SYSCOUNT) + if (filt >= EVFILT_SYSCOUNT) return (-1); dst = &kq->kq_filt[filt]; @@ -73,7 +73,7 @@ filter_register(struct kqueue *kq, short filter, const struct filter *src) /* Add the filter's event descriptor to the main fdset */ if (dst->kf_pfd > 0) { FD_SET(dst->kf_pfd, &kq->kq_fds); - if (dst->kf_pfd > kq->kq_nfds) + if (dst->kf_pfd > kq->kq_nfds) kq->kq_nfds = dst->kf_pfd; dbg_printf("fds: added %d (nfds=%d)", dst->kf_pfd, kq->kq_nfds); } @@ -121,7 +121,7 @@ filter_unregister_all(struct kqueue *kq) if (kq->kq_filt[i].kf_id == 0) continue; - if (kq->kq_filt[i].kf_destroy != NULL) + if (kq->kq_filt[i].kf_destroy != NULL) kq->kq_filt[i].kf_destroy(&kq->kq_filt[i]); //XXX-FIXME @@ -160,14 +160,14 @@ filter_name(short filt) const char *fname[EVFILT_SYSCOUNT] = { "EVFILT_READ", "EVFILT_WRITE", - "EVFILT_AIO", + "EVFILT_AIO", "EVFILT_VNODE", "EVFILT_PROC", - "EVFILT_SIGNAL", - "EVFILT_TIMER", - "EVFILT_NETDEV", - "EVFILT_FS", - "EVFILT_LIO", + "EVFILT_SIGNAL", + "EVFILT_TIMER", + "EVFILT_NETDEV", + "EVFILT_FS", + "EVFILT_LIO", "EVFILT_USER" }; From f55d256ebc1f0f5203a5dc514aea5992058e4129 Mon Sep 17 00:00:00 2001 From: Philippe Wooding Date: Thu, 22 Mar 2018 08:31:23 +0100 Subject: [PATCH 0653/1120] Add knote_free_all function --- vendor/libkqueue/src/common/filter.c | 3 +-- vendor/libkqueue/src/common/knote.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index 75fe9e6db..ae97f8a27 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -124,8 +124,7 @@ filter_unregister_all(struct kqueue *kq) if (kq->kq_filt[i].kf_destroy != NULL) kq->kq_filt[i].kf_destroy(&kq->kq_filt[i]); - //XXX-FIXME - //knote_free_all(&kq->kq_filt[i]); + knote_free_all(&kq->kq_filt[i]); if (kqops.filter_free != NULL) kqops.filter_free(kq, &kq->kq_filt[i]); diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index c669b8c10..f6bf93108 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -147,6 +147,23 @@ knote_get_by_data(struct filter *filt, intptr_t data) } #endif +int knote_free_all(struct filter *filt) +{ + struct knote *kn; + + pthread_rwlock_rdlock(&filt->kf_knote_mtx); + RB_FOREACH(kn, knt, &filt->kf_knote) { + /* Check return code */ + filt->kn_delete(filt, kn); + + kn->kn_flags |= KNFL_KNOTE_DELETED; + + knote_release(kn); + } + pthread_rwlock_unlock(&filt->kf_knote_mtx); + return (0); +} + int knote_disable(struct filter *filt, struct knote *kn) { From 080272fc424628e089437be50ecd104c04e5eb25 Mon Sep 17 00:00:00 2001 From: Philippe Wooding Date: Tue, 20 Mar 2018 22:22:23 +0100 Subject: [PATCH 0654/1120] =?UTF-8?q?Don=E2=80=99t=20make=20get=5Ffd=5Flim?= =?UTF-8?q?it=20static?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vendor/libkqueue/src/common/kqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index c05f4e12b..c015700f2 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -35,7 +35,7 @@ pthread_mutex_t kq_mtx = PTHREAD_MUTEX_INITIALIZER; pthread_once_t kq_is_initialized = PTHREAD_ONCE_INIT; #endif -static unsigned int +unsigned int get_fd_limit(void) { #ifdef _WIN32 From 48ba223f5df3b861d3872b6434fad8827ec94589 Mon Sep 17 00:00:00 2001 From: Philippe Wooding Date: Thu, 22 Mar 2018 08:40:34 +0100 Subject: [PATCH 0655/1120] Fix format --- vendor/libkqueue/src/common/kqueue.c | 4 ++-- vendor/libkqueue/src/linux/platform.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index c015700f2..457837635 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -126,7 +126,7 @@ kqueue_lookup(int kq) int VISIBLE kqueue(void) { - struct kqueue *kq; + struct kqueue *kq; struct kqueue *tmp; #ifdef _WIN32 @@ -147,7 +147,7 @@ kqueue(void) if (kq == NULL) return (-1); - tracing_mutex_init(&kq->kq_mtx, NULL); + tracing_mutex_init(&kq->kq_mtx, NULL); if (kqops.kqueue_init(kq) < 0) { free(kq); diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 8960cd11c..fc5e36ba3 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -66,7 +66,7 @@ extern long int syscall (long int __sysno, ...); * Additional members of struct knote */ #define KNOTE_PLATFORM_SPECIFIC \ - int kn_epollfd; /* A copy of filter->epfd */ \ + int kn_epollfd; /* A copy of filter->epfd */ \ int kn_registered; /* Is FD registered with epoll */ \ union { \ int kn_timerfd; \ From 5b05f199e1639448c0fb544dd7c3e00aaf574c5b Mon Sep 17 00:00:00 2001 From: Philippe Wooding Date: Thu, 22 Mar 2018 08:41:31 +0100 Subject: [PATCH 0656/1120] Add monitoring thread that takes care of cleaning up closed kqueues (on linux only) --- vendor/libkqueue/src/common/kqueue.c | 8 +- vendor/libkqueue/src/common/private.h | 1 + vendor/libkqueue/src/linux/platform.c | 247 +++++++++++++++++++++++++- vendor/libkqueue/src/linux/platform.h | 6 +- 4 files changed, 253 insertions(+), 9 deletions(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 457837635..2f18094f9 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -156,16 +156,22 @@ kqueue(void) dbg_printf("created kqueue, fd=%d", kq->kq_id); + /* Delete and insert should be atomic */ + (void) pthread_mutex_lock(&kq_mtx); + tmp = map_delete(kqmap, kq->kq_id); if (tmp != NULL) { - dbg_puts("FIXME -- memory leak here"); // TODO: kqops.kqueue_free(tmp), or (better yet) decrease it's refcount + kqops.kqueue_free(tmp); } + if (map_insert(kqmap, kq->kq_id, kq) < 0) { dbg_puts("map insertion failed"); kqops.kqueue_free(kq); return (-1); } + pthread_mutex_unlock(&kq_mtx); + return (kq->kq_id); } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index bda929c2a..39ffe6749 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -184,6 +184,7 @@ extern const struct kqueue_vtable kqops; /* * knote internal API */ +int knote_free_all(struct filter *filt); struct knote * knote_lookup(struct filter *, uintptr_t); //DEADWOOD: struct knote * knote_get_by_data(struct filter *filt, intptr_t); struct knote * knote_new(void); diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index f3b8985be..8eadf3611 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -16,6 +16,8 @@ # define _GNU_SOURCE # include +#include +#include #include "../common/private.h" #ifndef SO_GET_FILTER @@ -31,6 +33,34 @@ const struct filter evfilt_proc = EVFILT_NOTIMPL; */ static __thread struct epoll_event epevt[MAX_KEVENT]; +extern pthread_mutex_t kq_mtx; +/* + * Monitoring thread that takes care of cleaning up kqueues (on linux only) + */ +static pthread_t monitoring_thread; +static pid_t monitoring_tid; /* Monitoring thread */ +pthread_once_t monitoring_thread_initialized = PTHREAD_ONCE_INIT; +pthread_cond_t monitoring_thread_cond = PTHREAD_COND_INITIALIZER; + +/* + * Number of active kqueues. + * When the last kqueue is closed, the monitoring thread can be stopped. + */ +static unsigned int kqueue_cnt = 0; + +/* + * Map for kqueue pipes where index is the read side (for which signals are received) + * and value is the write side that gets closed and corresponds to the kqueue id. + */ +static unsigned int *fd_map; + +/* + * Map kqueue id to counter for kq cleanups. + * When cleanup counter is at 0, cleanup can be performed by signal handler. + * Otherwise, it means cleanup was already performed for this FD in linux_kqueue_free. + */ +static unsigned int *fd_cleanup_cnt; + const struct kqueue_vtable kqops = { linux_kqueue_init, linux_kqueue_free, @@ -45,20 +75,180 @@ const struct kqueue_vtable kqops = { linux_eventfd_descriptor }; +static void +linux_kqueue_cleanup(struct kqueue *kq); + +unsigned int get_fd_limit(void); +/* + * Monitoring thread that loops on waiting for signals to be received + */ +static void * +monitoring_thread_start(void *arg) +{ + short end_thread = 0; + int res = 0; + siginfo_t info; + int fd; + int nb_max_fd; + struct kqueue *kq; + sigset_t monitoring_sig_set; + + nb_max_fd = get_fd_limit(); + + sigemptyset(&monitoring_sig_set); + sigaddset(&monitoring_sig_set, SIGRTMIN + 1); + + pthread_sigmask(SIG_BLOCK, &monitoring_sig_set, NULL); + + (void) pthread_mutex_lock(&kq_mtx); + + monitoring_tid = syscall(SYS_gettid); + + fd_map = calloc(nb_max_fd, sizeof(unsigned int)); + + if (fd_map == NULL) + return NULL; + + fd_cleanup_cnt = calloc(nb_max_fd, sizeof(unsigned int)); + + if (fd_cleanup_cnt == NULL) + return NULL; + + /* + * Now that thread is initialized, let kqueue init resume + */ + pthread_cond_broadcast(&monitoring_thread_cond); + (void) pthread_mutex_unlock(&kq_mtx); + + pthread_detach(pthread_self()); + + while (!end_thread) { + /* + * Wait for signal notifying us that a change has occured on the pipe + * It's not possible to only listen on FD close but no other operation + * should be performed on the kqueue. + */ + res = sigwaitinfo(&monitoring_sig_set, &info); + if( res != -1 ) { + (void) pthread_mutex_lock(&kq_mtx); + /* + * Signal is received for read side of pipe + * Get FD for write side as it's the kqueue identifier + */ + fd = fd_map[info.si_fd]; + if (fd) { + kq = kqueue_lookup(fd); + if (kq) { + /* If kqueue instance for this FD hasn't been cleaned yet */ + if (fd_cleanup_cnt[kq->kq_id] == 0) { + linux_kqueue_cleanup(kq); + } + + /* Decrement cleanup counter as signal handler has been run for this FD */ + fd_cleanup_cnt[kq->kq_id]--; + } else { + /* Should not happen */ + dbg_puts("Failed to lookup FD"); + } + } else { + /* Should not happen */ + dbg_puts("Got signal from unknown FD"); + } + + /* + * Stop thread if all kqueues have been closed + */ + if (kqueue_cnt == 0) { + end_thread = 1; + + /* Reset so that thread can be restarted */ + monitoring_thread_initialized = PTHREAD_ONCE_INIT; + + /* Free thread resources */ + free(fd_map); + free(fd_cleanup_cnt); + } + + (void) pthread_mutex_unlock(&kq_mtx); + } else { + dbg_perror("sigwait()"); + } + } + + return NULL; +} + +static void +linux_kqueue_start_thread() +{ + if (pthread_create(&monitoring_thread, NULL, &monitoring_thread_start, NULL)) { + dbg_perror("linux_kqueue_start_thread failure"); + } + + /* Wait for thread creating to be done as we need monitoring_tid to be available */ + pthread_cond_wait(&monitoring_thread_cond, &kq_mtx); +} + int linux_kqueue_init(struct kqueue *kq) { - kq->kq_id = epoll_create(1); - if (kq->kq_id < 0) { + struct f_owner_ex sig_owner; + + kq->epollfd = epoll_create(1); + if (kq->epollfd < 0) { dbg_perror("epoll_create(2)"); return (-1); } + /* + * The standard behaviour when closing a kqueue fd is for the underlying resources to be freed. + * In order to catch the close on the libkqueue fd, we use a pipe and return the write end as kq_id. + * Closing the end will cause the pipe to be close which will be caught by the monitoring thread. + */ + if (pipe(kq->pipefd)) { + close(kq->epollfd); + return (-1); + } + if (filter_register_all(kq) < 0) { - close(kq->kq_id); + error: + close(kq->epollfd); + close(kq->pipefd[0]); + close(kq->pipefd[1]); return (-1); } + kq->kq_id = kq->pipefd[1]; + + if (fcntl(kq->pipefd[0], F_SETFL, fcntl(kq->pipefd[0], F_GETFL, 0) | O_ASYNC) < 0) { + dbg_perror("failed setting O_ASYNC"); + goto error; + } + + if (fcntl(kq->pipefd[0], F_SETSIG, SIGRTMIN + 1) < 0) { + dbg_perror("failed settting F_SETSIG"); + goto error; + } + + (void) pthread_mutex_lock(&kq_mtx); + + /* Start monitoring thread during first initialization */ + (void) pthread_once(&monitoring_thread_initialized, linux_kqueue_start_thread); + + /* Update pipe FD map */ + fd_map[kq->pipefd[0]] = kq->pipefd[1]; + + /* Increment kqueue counter */ + kqueue_cnt++; + + sig_owner.type = F_OWNER_TID; + sig_owner.pid = monitoring_tid; + if (fcntl(kq->pipefd[0], F_SETOWN_EX, &sig_owner) < 0) { + dbg_perror("failed settting F_SETOWN"); + goto error; + } + + (void) pthread_mutex_unlock(&kq_mtx); #if DEADWOOD //might be useful in posix @@ -85,10 +275,56 @@ linux_kqueue_init(struct kqueue *kq) return (0); } +/* + * Cleanup kqueue resources + * Should be done while holding kq_mtx + */ +static void +linux_kqueue_cleanup(struct kqueue *kq) +{ + char buffer; + ssize_t ret; + filter_unregister_all(kq); + if (kq->epollfd > 0) { + close(kq->epollfd); + kq->epollfd = -1; + } + + /* + * read will return 0 on pipe EOF (i.e. if the write end of the pipe has been closed) + */ + ret = read(kq->pipefd[0], &buffer, 1); + if (ret == -1 && errno == EWOULDBLOCK) { + // Shoudn't happen unless kqops.kqueue_free is called on an open FD + dbg_puts("kqueue wasn't closed"); + close(kq->pipefd[1]); + kq->pipefd[1] = -1; + } else if (ret > 0) { + // Shouldn't happen unless data is written to kqueue FD + // Ignore write and continue with close + dbg_puts("Unexpected data available on kqueue FD"); + } + + if (kq->pipefd[0] > 0) { + close(kq->pipefd[0]); + kq->pipefd[0] = -1; + } + + fd_map[kq->pipefd[0]] = 0; + + /* Decrement kqueue counter */ + kqueue_cnt--; +} + void -linux_kqueue_free(struct kqueue *kq UNUSED) +linux_kqueue_free(struct kqueue *kq) { - abort();//FIXME + linux_kqueue_cleanup(kq); + + /* Increment cleanup counter as cleanup is being performed outside signal handler */ + fd_cleanup_cnt[kq->kq_id]++; + + free(kq); } static int @@ -429,4 +665,3 @@ linux_fd_to_path(char *buf, size_t bufsz, int fd) memset(buf, 0, bufsz); return (readlink(path, buf, bufsz)); } - diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index fc5e36ba3..73239f57b 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -54,8 +54,8 @@ extern long int syscall (long int __sysno, ...); #endif /* Convenience macros to access the epoll descriptor for the kqueue */ -#define kqueue_epfd(kq) ((kq)->kq_id) -#define filter_epfd(filt) ((filt)->kf_kqueue->kq_id) +#define kqueue_epfd(kq) ((kq)->epollfd) +#define filter_epfd(filt) ((filt)->kf_kqueue->epollfd) /* * Additional members of struct filter @@ -79,6 +79,8 @@ extern long int syscall (long int __sysno, ...); * Additional members of struct kqueue */ #define KQUEUE_PLATFORM_SPECIFIC \ + int epollfd; /* Main epoll FD */ \ + int pipefd[2]; /* FD for pipe that catches close */ \ struct epoll_event kq_plist[MAX_KEVENT]; \ size_t kq_nplist From db9ad9077b8862a3b96497b67fc215d6b7589e4e Mon Sep 17 00:00:00 2001 From: Philippe Wooding Date: Mon, 16 Apr 2018 22:17:07 +0200 Subject: [PATCH 0657/1120] Fix signal conflict --- vendor/libkqueue/src/linux/platform.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 8eadf3611..b2bec410c 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -96,10 +96,13 @@ monitoring_thread_start(void *arg) nb_max_fd = get_fd_limit(); sigemptyset(&monitoring_sig_set); - sigaddset(&monitoring_sig_set, SIGRTMIN + 1); + sigfillset(&monitoring_sig_set); pthread_sigmask(SIG_BLOCK, &monitoring_sig_set, NULL); + sigemptyset(&monitoring_sig_set); + sigaddset(&monitoring_sig_set, SIGRTMIN + 1); + (void) pthread_mutex_lock(&kq_mtx); monitoring_tid = syscall(SYS_gettid); From 07afbf7c4170ee1ce09708894aab092e892c5360 Mon Sep 17 00:00:00 2001 From: Philippe Wooding Date: Mon, 16 Apr 2018 22:18:53 +0200 Subject: [PATCH 0658/1120] Only increment cleanup counter is cleanup was done --- vendor/libkqueue/src/linux/platform.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index b2bec410c..fec7655b0 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -75,7 +75,7 @@ const struct kqueue_vtable kqops = { linux_eventfd_descriptor }; -static void +static bool linux_kqueue_cleanup(struct kqueue *kq); unsigned int get_fd_limit(void); @@ -210,7 +210,7 @@ linux_kqueue_init(struct kqueue *kq) */ if (pipe(kq->pipefd)) { close(kq->epollfd); - return (-1); + return (-1); } if (filter_register_all(kq) < 0) { @@ -281,8 +281,11 @@ linux_kqueue_init(struct kqueue *kq) /* * Cleanup kqueue resources * Should be done while holding kq_mtx + * return + * - true if epoll fd and pipes were closed + * - false if epoll fd was already closed */ -static void +static bool linux_kqueue_cleanup(struct kqueue *kq) { char buffer; @@ -291,6 +294,9 @@ linux_kqueue_cleanup(struct kqueue *kq) if (kq->epollfd > 0) { close(kq->epollfd); kq->epollfd = -1; + } else { + // Don't do cleanup if epollfd has already been closed + return false; } /* @@ -317,15 +323,18 @@ linux_kqueue_cleanup(struct kqueue *kq) /* Decrement kqueue counter */ kqueue_cnt--; + + return true; } void linux_kqueue_free(struct kqueue *kq) { - linux_kqueue_cleanup(kq); - /* Increment cleanup counter as cleanup is being performed outside signal handler */ - fd_cleanup_cnt[kq->kq_id]++; + if (linux_kqueue_cleanup(kq)) + fd_cleanup_cnt[kq->kq_id]++; + else /* Reset counter as FD had already been cleaned */ + fd_cleanup_cnt[kq->kq_id] = 0; free(kq); } From 6abd72e1e2e9e238c9ac297f141c47061e9ff198 Mon Sep 17 00:00:00 2001 From: Philippe Wooding Date: Mon, 16 Apr 2018 22:21:46 +0200 Subject: [PATCH 0659/1120] Add test for Linux FD cleanup --- vendor/libkqueue/test/main.c | 92 +++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 3161bef93..12e444f8f 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -14,6 +14,10 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#if defined(__linux__) +#include +#include +#endif #include "common.h" /* Maximum number of threads that can be created */ @@ -51,7 +55,7 @@ test_kqueue_descriptor_is_pollable(void) } /* - * Test the method for detecting when one end of a socketpair + * Test the method for detecting when one end of a socketpair * has been closed. This technique is used in kqueue_validate() */ static void @@ -72,14 +76,14 @@ test_peer_close_detection(void *unused) pfd.events = POLLIN | POLLHUP; pfd.revents = 0; - if (poll(&pfd, 1, 0) > 0) + if (poll(&pfd, 1, 0) > 0) die("unexpected data"); if (close(sockfd[1]) < 0) die("close"); if (poll(&pfd, 1, 0) > 0) { - if (recv(sockfd[0], buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT) != 0) + if (recv(sockfd[0], buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT) != 0) die("failed to detect peer shutdown"); } #endif @@ -109,6 +113,78 @@ test_kevent(void *unused) die("invalid kq parameter"); } +#if defined(__linux__) +/* Maximum number of FD for current process */ +#define MAX_FDS 32 +/* + * Test the cleanup process for Linux + */ +void +test_cleanup(void *unused) +{ + int i; + int max_fds = MAX_FDS; + struct rlimit curr_rlim, rlim; + int kqfd1, kqfd2; + struct kevent kev; + + /* Remeber current FD limit */ + if (getrlimit(RLIMIT_NOFILE, &curr_rlim) < 0) { + die("getrlimit failed"); + } + + /* lower FD limit to 32 */ + if (max_fds < rlim.rlim_cur) { + /* Set FD limit to MAX_FDS */ + rlim = curr_rlim; + rlim.rlim_cur = 32; + if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) { + die("setrlimit failed"); + } + } else { + max_fds = rlim.rlim_cur; + } + + /* Create initial kqueue to avoid cleanup thread being destroyed on each close */ + if ((kqfd1 = kqueue()) < 0) + die("kqueue()"); + + /* Create and close 2 * max fd number of kqueues */ + for (i=0; i < 2 * max_fds + 1; i++) { + if ((kqfd2 = kqueue()) < 0) + die("kqueue()"); + + kevent_add(kqfd2, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000,NULL); + + if (close(kqfd2) < 0) + die("close()"); + } + + if (close(kqfd1) < 0) + die("close()"); + + /* + * Run same test again but without extra kqueue + * Cleanup thread will be destroyed + * Create and close 2 * max fd number of kqueues + */ + for (i=0; i < 2 * max_fds + 1; i++) { + if ((kqfd2 = kqueue()) < 0) + die("kqueue()"); + + kevent_add(kqfd2, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000,NULL); + + if (close(kqfd2) < 0) + die("close()"); + } + + /* Restore FD limit */ + if (setrlimit(RLIMIT_NOFILE, &curr_rlim) < 0) { + die("setrlimit failed"); + } +} +#endif + void test_ev_receipt(void *unused) { @@ -160,11 +236,15 @@ test_harness(struct unit_test tests[MAX_TESTS], int iterations) test(kqueue, ctx); test(kevent, ctx); +#if defined(__linux__) + test(cleanup, ctx); +#endif + if ((kqfd = kqueue()) < 0) die("kqueue()"); test(ev_receipt, ctx); - /* TODO: this fails now, but would be good later + /* TODO: this fails now, but would be good later test(kqueue_descriptor_is_pollable); */ @@ -200,7 +280,7 @@ usage(void) exit(1); } -int +int main(int argc, char **argv) { struct unit_test tests[MAX_TESTS] = { @@ -229,7 +309,7 @@ main(int argc, char **argv) #ifdef _WIN32 /* Initialize the Winsock library */ WSADATA wsaData; - if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) + if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) err(1, "WSAStartup failed"); #endif From bbf755dadf62f589052aa320b4c66f8f656132ff Mon Sep 17 00:00:00 2001 From: Philippe Wooding Date: Fri, 4 May 2018 12:10:11 +0200 Subject: [PATCH 0660/1120] Remove comment --- vendor/libkqueue/src/common/kqueue.c | 1 - 1 file changed, 1 deletion(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 2f18094f9..0c3c15eaf 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -161,7 +161,6 @@ kqueue(void) tmp = map_delete(kqmap, kq->kq_id); if (tmp != NULL) { - // TODO: kqops.kqueue_free(tmp), or (better yet) decrease it's refcount kqops.kqueue_free(tmp); } From fd67e0ca15d3af2ce56856b381036e77d0f201f3 Mon Sep 17 00:00:00 2001 From: Mister X <3520734+Mister-X-@users.noreply.github.com> Date: Fri, 10 Aug 2018 02:17:20 +0000 Subject: [PATCH 0661/1120] Fixed compilation with GCC 8.1 --- vendor/libkqueue/src/common/kevent.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index f2903447e..aa2c5f579 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -62,7 +62,7 @@ kevent_fflags_dump(const struct kevent *kev) KEVFFL_DUMP(NOTE_FFCOPY); KEVFFL_DUMP(NOTE_TRIGGER); } else { - strncat((char *) &buf[0], " ", 1); + buf[0] = ' '; } buf[strlen(buf) - 1] = ')'; @@ -101,7 +101,7 @@ kevent_flags_dump(const struct kevent *kev) const char * kevent_dump(const struct kevent *kev) { - static __thread char buf[1024]; + static __thread char buf[4096]; snprintf((char *) &buf[0], sizeof(buf), "{ ident=%d, filter=%s, %s, %s, data=%d, udata=%p }", From 097b066e0db33f495dd4d51db7e4643977759037 Mon Sep 17 00:00:00 2001 From: Mister X <3520734+Mister-X-@users.noreply.github.com> Date: Fri, 10 Aug 2018 02:18:38 +0000 Subject: [PATCH 0662/1120] Fix warning in test reported by GCC 8.1 --- vendor/libkqueue/test/test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/test/test.c b/vendor/libkqueue/test/test.c index c49a1840d..7882ee29c 100644 --- a/vendor/libkqueue/test/test.c +++ b/vendor/libkqueue/test/test.c @@ -19,6 +19,7 @@ #endif #include #include +#include #include "common.h" From 9ade1232f0e3aa1f090ee81ea5120775cb13a641 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 9 Aug 2018 22:37:48 -0400 Subject: [PATCH 0663/1120] Trim buffer --- vendor/libkqueue/src/common/kevent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index aa2c5f579..49c64d2c6 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -101,7 +101,7 @@ kevent_flags_dump(const struct kevent *kev) const char * kevent_dump(const struct kevent *kev) { - static __thread char buf[4096]; + static __thread char buf[2049]; snprintf((char *) &buf[0], sizeof(buf), "{ ident=%d, filter=%s, %s, %s, data=%d, udata=%p }", From d47fb5fb7341c679a4686c73163165baccdb5f84 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 9 Aug 2018 22:53:09 -0400 Subject: [PATCH 0664/1120] Appease GCC 8.1 --- vendor/libkqueue/src/common/kevent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 49c64d2c6..fe808f188 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -101,7 +101,7 @@ kevent_flags_dump(const struct kevent *kev) const char * kevent_dump(const struct kevent *kev) { - static __thread char buf[2049]; + static __thread char buf[2147]; snprintf((char *) &buf[0], sizeof(buf), "{ ident=%d, filter=%s, %s, %s, data=%d, udata=%p }", From ec0cef0788a0dbadd74de6ea531cb61e225f619b Mon Sep 17 00:00:00 2001 From: Dmitry Selyutin Date: Tue, 28 Aug 2018 23:45:29 +0300 Subject: [PATCH 0665/1120] fix naming for write evfilt callbacks --- vendor/libkqueue/src/linux/write.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/vendor/libkqueue/src/linux/write.c b/vendor/libkqueue/src/linux/write.c index 4c95a678b..ae4395e57 100644 --- a/vendor/libkqueue/src/linux/write.c +++ b/vendor/libkqueue/src/linux/write.c @@ -31,7 +31,7 @@ #include "private.h" int -evfilt_socket_copyout(struct kevent *dst, struct knote *src, void *ptr) +evfilt_write_copyout(struct kevent *dst, struct knote *src, void *ptr) { struct epoll_event * const ev = (struct epoll_event *) ptr; @@ -58,7 +58,7 @@ evfilt_socket_copyout(struct kevent *dst, struct knote *src, void *ptr) } int -evfilt_socket_knote_create(struct filter *filt, struct knote *kn) +evfilt_write_knote_create(struct filter *filt, struct knote *kn) { struct epoll_event ev; @@ -84,7 +84,7 @@ evfilt_socket_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_socket_knote_modify(struct filter *filt, struct knote *kn, +evfilt_write_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { (void) filt; @@ -94,7 +94,7 @@ evfilt_socket_knote_modify(struct filter *filt, struct knote *kn, } int -evfilt_socket_knote_delete(struct filter *filt, struct knote *kn) +evfilt_write_knote_delete(struct filter *filt, struct knote *kn) { if (kn->kev.flags & EV_DISABLE) return (0); @@ -103,7 +103,7 @@ evfilt_socket_knote_delete(struct filter *filt, struct knote *kn) } int -evfilt_socket_knote_enable(struct filter *filt, struct knote *kn) +evfilt_write_knote_enable(struct filter *filt, struct knote *kn) { struct epoll_event ev; @@ -115,7 +115,7 @@ evfilt_socket_knote_enable(struct filter *filt, struct knote *kn) } int -evfilt_socket_knote_disable(struct filter *filt, struct knote *kn) +evfilt_write_knote_disable(struct filter *filt, struct knote *kn) { return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); } @@ -124,10 +124,10 @@ const struct filter evfilt_write = { EVFILT_WRITE, NULL, NULL, - evfilt_socket_copyout, - evfilt_socket_knote_create, - evfilt_socket_knote_modify, - evfilt_socket_knote_delete, - evfilt_socket_knote_enable, - evfilt_socket_knote_disable, + evfilt_write_copyout, + evfilt_write_knote_create, + evfilt_write_knote_modify, + evfilt_write_knote_delete, + evfilt_write_knote_enable, + evfilt_write_knote_disable, }; From 9e09917a7e8625f536a811db2b986efa7fdc03f9 Mon Sep 17 00:00:00 2001 From: Dmitry Selyutin Date: Wed, 29 Aug 2018 21:45:30 +0300 Subject: [PATCH 0666/1120] knote: support more kn_flags and socket errors It is possible to determine the actual socket error via SO_ERROR socket option. However, this system call does not work for descriptors other than sockets, and it'd be a total waste of time to call it just to get ENOTSOCK. In order to avoid the cost of the context switch, let's store some additional information from the times the knote was created. This change mostly deals with the Linux code only; likely the same changes can be applied to Windows as well. However, this issue is to be addressed by a separate commit. --- vendor/libkqueue/src/common/kevent.c | 2 +- vendor/libkqueue/src/common/private.h | 17 ++-- vendor/libkqueue/src/linux/platform.c | 101 ++++++++++++++++++------ vendor/libkqueue/src/linux/read.c | 25 +++--- vendor/libkqueue/src/linux/write.c | 16 +++- vendor/libkqueue/src/windows/platform.c | 8 +- vendor/libkqueue/src/windows/read.c | 2 +- 7 files changed, 123 insertions(+), 48 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index fe808f188..21bf23417 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -144,7 +144,7 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) memcpy(&kn->kev, src, sizeof(kn->kev)); kn->kev.flags &= ~EV_ENABLE; kn->kev.flags |= EV_ADD;//FIXME why? - kn->kn_kq = kq; + kn->kn_kq = kq; assert(filt->kn_create); if (filt->kn_create(filt, kn) < 0) { knote_release(kn); diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 39ffe6749..89e2281c6 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -66,14 +66,21 @@ struct eventfd { /* * Flags used by knote->kn_flags */ -#define KNFL_PASSIVE_SOCKET (0x01) /* Socket is in listen(2) mode */ -#define KNFL_REGULAR_FILE (0x02) /* File descriptor is a regular file */ -#define KNFL_STREAM_SOCKET (0x03) /* File descriptor is a stream socket */ -#define KNFL_KNOTE_DELETED (0x10) /* The knote object is no longer valid */ +#define KNFL_FILE (1U << 0U) +#define KNFL_PIPE (1U << 1U) +#define KNFL_SOCKET (1U << 2U) +#define KNFL_BLOCKDEV (1U << 3U) +#define KNFL_CHARDEV (1U << 4U) +#define KNFL_SOCKET_PASSIVE (KNFL_SOCKET | (1U << 5U)) +#define KNFL_SOCKET_STREAM (KNFL_SOCKET | (1U << 6U)) +#define KNFL_SOCKET_DGRAM (KNFL_SOCKET | (1U << 7U)) +#define KNFL_SOCKET_RDM (KNFL_SOCKET | (1U << 8U)) +#define KNFL_SOCKET_SEQPACKET (KNFL_SOCKET | (1U << 9U)) +#define KNFL_KNOTE_DELETED (1U << 31U) struct knote { struct kevent kev; - int kn_flags; + unsigned int kn_flags; union { /* OLD */ int pfd; /* Used by timerfd */ diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index fec7655b0..7067933bd 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -552,32 +552,95 @@ linux_get_descriptor_type(struct knote *kn) { socklen_t slen; struct stat sb; - int i, lsock, stype; + int ret, lsock, stype; socklen_t out_len; + const int fd = (int)kn->kev.ident; /* - * Test if the descriptor is a socket. + * Determine the actual descriptor type. */ - if (fstat(kn->kev.ident, &sb) < 0) { + if (fstat(fd, &sb) < 0) { dbg_perror("fstat(2)"); return (-1); } - if (S_ISREG(sb.st_mode)) { - kn->kn_flags |= KNFL_REGULAR_FILE; - dbg_printf("fd %d is a regular file\n", (int)kn->kev.ident); - return (0); + switch (sb.st_mode & S_IFMT) { + case S_IFREG: + dbg_printf("fd %d is a regular file\n", fd); + kn->kn_flags |= KNFL_FILE; + break; + + case S_IFIFO: + dbg_printf("fd %d is a pipe\n", fd); + kn->kn_flags |= KNFL_PIPE; + break; + + case S_IFBLK: + dbg_printf("fd %d is a block device\n", fd); + kn->kn_flags |= KNFL_BLOCKDEV; + break; + + case S_IFCHR: + dbg_printf("fd %d is a character device\n", fd); + kn->kn_flags |= KNFL_CHARDEV; + break; + + case S_IFSOCK: + dbg_printf("fd %d is a socket\n", fd); + kn->kn_flags |= KNFL_SOCKET; + break; + + default: + errno = EBADF; + dbg_perror("unknown fd type"); + return -1; } /* * Test if the socket is active or passive. */ - if (! S_ISSOCK(sb.st_mode)) + if (!S_ISSOCK(sb.st_mode)) return (0); + /* + * Determine socket type. + */ + slen = sizeof(stype); + stype = 0; + ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, &stype, &slen); + if (ret < 0) { + dbg_perror("getsockopt(3)"); + return (-1); + } + switch (stype) { + case SOCK_STREAM: + dbg_printf("fd %d is a stream socket\n", fd); + kn->kn_flags |= KNFL_SOCKET_STREAM; + break; + + case SOCK_DGRAM: + dbg_printf("fd %d is a datagram socket\n", fd); + kn->kn_flags |= KNFL_SOCKET_DGRAM; + break; + + case SOCK_RDM: + dbg_printf("fd %d is a reliable datagram socket\n", fd); + kn->kn_flags |= KNFL_SOCKET_RDM; + break; + + case SOCK_SEQPACKET: + dbg_printf("fd %d is a sequenced and reliable datagram socket\n", fd); + kn->kn_flags |= KNFL_SOCKET_SEQPACKET; + break; + + default: + errno = EBADF; + dbg_perror("unknown socket type"); + return (-1); + } slen = sizeof(lsock); lsock = 0; - i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_ACCEPTCONN, (char *) &lsock, &slen); - if (i < 0) { + ret = getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &lsock, &slen); + if (ret < 0) { switch (errno) { case ENOTSOCK: /* same as lsock = 0 */ break; @@ -587,7 +650,7 @@ linux_get_descriptor_type(struct knote *kn) } } else { if (lsock) - kn->kn_flags |= KNFL_PASSIVE_SOCKET; + kn->kn_flags |= KNFL_SOCKET_PASSIVE; } /* @@ -597,8 +660,8 @@ linux_get_descriptor_type(struct knote *kn) * Looking at SO_GET_FILTER is a good way of doing this. */ out_len = 0; - i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_GET_FILTER, NULL, &out_len); - if (i < 0) { + ret = getsockopt(fd, SOL_SOCKET, SO_GET_FILTER, NULL, &out_len); + if (ret < 0) { switch (errno) { case ENOTSOCK: /* same as lsock = 0 */ break; @@ -608,18 +671,8 @@ linux_get_descriptor_type(struct knote *kn) } } else { if (out_len) - kn->kn_flags |= KNFL_PASSIVE_SOCKET; - } - - slen = sizeof(stype); - stype = 0; - i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_TYPE, (char *) &lsock, &slen); - if (i < 0) { - dbg_perror("getsockopt(3)"); - return (-1); + kn->kn_flags |= KNFL_SOCKET_PASSIVE; } - if (stype == SOCK_STREAM) - kn->kn_flags |= KNFL_STREAM_SOCKET; return (0); } diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index 125aaa8a6..efb712245 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -56,10 +56,13 @@ get_eof_offset(int fd) int evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) { + int ret; + int serr; + socklen_t slen = sizeof(serr); struct epoll_event * const ev = (struct epoll_event *) ptr; /* Special case: for regular files, return the offset from current position to end of file */ - if (src->kn_flags & KNFL_REGULAR_FILE) { + if (src->kn_flags & KNFL_FILE) { memcpy(dst, &src->kev, sizeof(*dst)); dst->data = get_eof_offset(src->kev.ident); @@ -113,10 +116,14 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) if (ev->events & EPOLLHUP) dst->flags |= EV_EOF; #endif - if (ev->events & EPOLLERR) - dst->fflags = 1; /* FIXME: Return the actual socket error */ + if (ev->events & EPOLLERR) { + if (src->kn_flags & KNFL_SOCKET) { + ret = getsockopt(src->kev.ident, SOL_SOCKET, SO_ERROR, &serr, &slen); + dst->fflags = ((ret < 0) ? errno : serr); + } else { dst->fflags = EIO; } + } - if (src->kn_flags & KNFL_PASSIVE_SOCKET) { + if (src->kn_flags & KNFL_SOCKET_PASSIVE) { /* On return, data contains the length of the socket backlog. This is not available under Linux. */ @@ -132,7 +139,7 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) dst->data = 0; } else { dst->data = i; - if (dst->data == 0 && src->kn_flags & KNFL_STREAM_SOCKET) + if (dst->data == 0 && src->kn_flags & KNFL_SOCKET_STREAM) dst->flags |= EV_EOF; } } @@ -164,7 +171,7 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) ev.data.ptr = kn; /* Special case: for regular files, add a surrogate eventfd that is always readable */ - if (kn->kn_flags & KNFL_REGULAR_FILE) { + if (kn->kn_flags & KNFL_FILE) { int evfd; kn->kn_epollfd = filter_epfd(filt); @@ -210,7 +217,7 @@ evfilt_read_knote_delete(struct filter *filt, struct knote *kn) if (kn->kev.flags & EV_DISABLE) return (0); - if ((kn->kn_flags & KNFL_REGULAR_FILE) && (kn->kdata.kn_eventfd != -1)) { + if ((kn->kn_flags & KNFL_FILE) && (kn->kdata.kn_eventfd != -1)) { if (kn->kn_registered && epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kdata.kn_eventfd, NULL) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); @@ -236,7 +243,7 @@ evfilt_read_knote_enable(struct filter *filt, struct knote *kn) ev.events = kn->data.events; ev.data.ptr = kn; - if (kn->kn_flags & KNFL_REGULAR_FILE) { + if (kn->kn_flags & KNFL_FILE) { if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_eventfd, &ev) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); @@ -254,7 +261,7 @@ evfilt_read_knote_enable(struct filter *filt, struct knote *kn) int evfilt_read_knote_disable(struct filter *filt, struct knote *kn) { - if (kn->kn_flags & KNFL_REGULAR_FILE) { + if (kn->kn_flags & KNFL_FILE) { if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kdata.kn_eventfd, NULL) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); diff --git a/vendor/libkqueue/src/linux/write.c b/vendor/libkqueue/src/linux/write.c index ae4395e57..3305ee015 100644 --- a/vendor/libkqueue/src/linux/write.c +++ b/vendor/libkqueue/src/linux/write.c @@ -33,6 +33,9 @@ int evfilt_write_copyout(struct kevent *dst, struct knote *src, void *ptr) { + int ret; + int serr; + socklen_t slen = sizeof(serr); struct epoll_event * const ev = (struct epoll_event *) ptr; epoll_event_dump(ev); @@ -44,8 +47,12 @@ evfilt_write_copyout(struct kevent *dst, struct knote *src, void *ptr) if (ev->events & EPOLLHUP) dst->flags |= EV_EOF; #endif - if (ev->events & EPOLLERR) - dst->fflags = 1; /* FIXME: Return the actual socket error */ + if (ev->events & EPOLLERR) { + if (src->kn_flags & KNFL_SOCKET) { + ret = getsockopt(src->kev.ident, SOL_SOCKET, SO_ERROR, &serr, &slen); + dst->fflags = ((ret < 0) ? errno : serr); + } else { dst->fflags = EIO; } + } /* On return, data contains the the amount of space remaining in the write buffer */ if (ioctl(dst->ident, SIOCOUTQ, &dst->data) < 0) { @@ -65,9 +72,10 @@ evfilt_write_knote_create(struct filter *filt, struct knote *kn) if (linux_get_descriptor_type(kn) < 0) return (-1); - /* TODO: return EBADF? */ - if (kn->kn_flags & KNFL_REGULAR_FILE) + if (kn->kn_flags & KNFL_FILE) { + errno = EBADF; return (-1); + } /* Convert the kevent into an epoll_event */ kn->data.events = EPOLLOUT; diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 849b3c361..b09e108b1 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -197,24 +197,24 @@ windows_get_descriptor_type(struct knote *kn) lsock = 0; i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_ACCEPTCONN, (char *)&lsock, &slen); if (i == 0 && lsock) - kn->kn_flags |= KNFL_PASSIVE_SOCKET; + kn->kn_flags |= KNFL_SOCKET_PASSIVE; slen = sizeof(stype); stype = 0; - i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_TYPE, (char *) &lsock, &slen); + i = getsockopt(kn->kev.ident, SOL_SOCKET, SO_TYPE, (char *)&stype, &slen); if (i < 0) { dbg_perror("getsockopt(3)"); return (-1); } if (stype == SOCK_STREAM) - kn->kn_flags |= KNFL_STREAM_SOCKET; + kn->kn_flags |= KNFL_SOCKET_STREAM; break; } default: { struct stat sb; if (fstat((int)kn->kev.ident, &sb) == 0) { dbg_printf("HANDLE %d appears to be a regular file", kn->kev.ident); - kn->kn_flags |= KNFL_REGULAR_FILE; + kn->kn_flags |= KNFL_FILE; } } } diff --git a/vendor/libkqueue/src/windows/read.c b/vendor/libkqueue/src/windows/read.c index 2b32e5978..07b19c12f 100644 --- a/vendor/libkqueue/src/windows/read.c +++ b/vendor/libkqueue/src/windows/read.c @@ -94,7 +94,7 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) //struct event_buf * const ev = (struct event_buf *) ptr; /* TODO: handle regular files - if (src->flags & KNFL_REGULAR_FILE) { ... } */ + if (src->flags & KNFL_FILE) { ... } */ memcpy(dst, &src->kev, sizeof(*dst)); if (src->kn_flags & KNFL_PASSIVE_SOCKET) { From 99a9571a4f07ad98aaf8c834af0f9da82d5acaa7 Mon Sep 17 00:00:00 2001 From: Dmitry Selyutin Date: Thu, 30 Aug 2018 00:52:21 +0300 Subject: [PATCH 0667/1120] knote: rethink KNFL_SOCKET flag --- vendor/libkqueue/src/common/private.h | 19 +++++++++++-------- vendor/libkqueue/src/linux/platform.c | 3 +-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 89e2281c6..6939097b9 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -68,15 +68,18 @@ struct eventfd { */ #define KNFL_FILE (1U << 0U) #define KNFL_PIPE (1U << 1U) -#define KNFL_SOCKET (1U << 2U) -#define KNFL_BLOCKDEV (1U << 3U) -#define KNFL_CHARDEV (1U << 4U) -#define KNFL_SOCKET_PASSIVE (KNFL_SOCKET | (1U << 5U)) -#define KNFL_SOCKET_STREAM (KNFL_SOCKET | (1U << 6U)) -#define KNFL_SOCKET_DGRAM (KNFL_SOCKET | (1U << 7U)) -#define KNFL_SOCKET_RDM (KNFL_SOCKET | (1U << 8U)) -#define KNFL_SOCKET_SEQPACKET (KNFL_SOCKET | (1U << 9U)) +#define KNFL_BLOCKDEV (1U << 2U) +#define KNFL_CHARDEV (1U << 3U) +#define KNFL_SOCKET_PASSIVE (1U << 4U) +#define KNFL_SOCKET_STREAM (1U << 5U) +#define KNFL_SOCKET_DGRAM (1U << 6U) +#define KNFL_SOCKET_RDM (1U << 7U) +#define KNFL_SOCKET_SEQPACKET (1U << 8U) #define KNFL_KNOTE_DELETED (1U << 31U) +#define KNFL_SOCKET (KNFL_SOCKET_STREAM |\ + KNFL_SOCKET_DGRAM |\ + KNFL_SOCKET_RDM |\ + KNFL_SOCKET_SEQPACKET) struct knote { struct kevent kev; diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 7067933bd..dd335b035 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -586,8 +586,7 @@ linux_get_descriptor_type(struct knote *kn) case S_IFSOCK: dbg_printf("fd %d is a socket\n", fd); - kn->kn_flags |= KNFL_SOCKET; - break; + break; /* deferred type determination */ default: errno = EBADF; From 4dc81b33ee3184f66705bfe25b87d1b2244b3646 Mon Sep 17 00:00:00 2001 From: Cameron Nemo Date: Tue, 18 Sep 2018 10:52:15 -0700 Subject: [PATCH 0668/1120] kevent: refactor to remove goto statement Signed-off-by: Cameron Nemo --- vendor/libkqueue/TODO | 2 -- vendor/libkqueue/src/common/kevent.c | 12 +++--------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/vendor/libkqueue/TODO b/vendor/libkqueue/TODO index 6ebb725fd..967684a1b 100644 --- a/vendor/libkqueue/TODO +++ b/vendor/libkqueue/TODO @@ -8,8 +8,6 @@ * Add a dbg_printf() statement within kevent_wait() to report the value of the timeout. - * Refactor kevent_copyin() to remove the goto statements. - * Fix the crasher w/ corruption in test/vnode.c * Add the kevent64() syscall as implemented on MacOS X. This guarantees diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index fe808f188..248715542 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -198,23 +198,17 @@ kevent_copyin(struct kqueue *kq, const struct kevent *src, int nchanges, dbg_printf("nchanges=%d nevents=%d", nchanges, nevents); - /* TODO: refactor, this has become convoluted to support EV_RECEIPT */ for (nret = 0; nchanges > 0; src++, nchanges--) { if (kevent_copyin_one(kq, src) < 0) { dbg_printf("errno=%s",strerror(errno)); status = errno; - goto err_path; + } else if (src->flags & EV_RECEIPT) { + status = 0; } else { - if (src->flags & EV_RECEIPT) { - status = 0; - goto err_path; - } + continue; } - continue; - -err_path: if (nevents > 0) { memcpy(eventlist, src, sizeof(*src)); eventlist->data = status; From 54e95bfb1ef5967822e9e85300df23038af357d3 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sun, 25 Nov 2018 16:05:39 -0500 Subject: [PATCH 0669/1120] Update the ChangeLog to reflect v2.3.0 --- vendor/libkqueue/ChangeLog | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 3362b24f8..274b659ff 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,7 +1,20 @@ -Unreleased +2018-11-25 v2.3.0 ------------------------------------------------------------------------ - * Enable continuous integration testing via travis-ci.org + * kevent: refactor to remove goto statement + (Credit: Cameron Nemo) + + * Multiple fixes for compilation issues with GCC 8.1 + (Credit: Arran Cudbard-Bell) + + * Add a monitoring thread that takes care of cleaning up closed kqueues + (Credit: Philippe Wooding) + + * Multiple bug fixes for leaking descriptors in kn_delete() + (Credit: Philippe Wooding) + + * Fix build errors on Linux systems that do not use glibc + (Credit: maxice8) 2017-11-26 v2.2.0 ------------------------------------------------------------------------ From 59468bb2493ca2e278836a999caa2cdee0c109bb Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 10 Jan 2019 09:17:17 +0800 Subject: [PATCH 0670/1120] Bump minimum cmake version --- vendor/libkqueue/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index e21dd320f..12ecbfa97 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -15,7 +15,7 @@ # # Note: In order for RPM packaging to work correctly version >= 3.8 is required -cmake_minimum_required(VERSION 3.4.3) +cmake_minimum_required(VERSION 3.8.0) cmake_policy(SET CMP0063 OLD) project(libkqueue VERSION 2.1.1 LANGUAGES C) From c52c1629bc013d58eeb06937648aac1093c47c2e Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 10 Jan 2019 09:17:35 +0800 Subject: [PATCH 0671/1120] Bump package version --- vendor/libkqueue/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 12ecbfa97..056267cde 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -18,7 +18,7 @@ cmake_minimum_required(VERSION 3.8.0) cmake_policy(SET CMP0063 OLD) -project(libkqueue VERSION 2.1.1 LANGUAGES C) +project(libkqueue VERSION 2.3.0 LANGUAGES C) enable_testing() set(CMAKE_C_VISIBILITY_PRESET hidden) From f630ec8ffe7e7525d05f2b25709b4a37404d17cc Mon Sep 17 00:00:00 2001 From: Matthew Newton Date: Thu, 10 Jan 2019 13:02:04 +0000 Subject: [PATCH 0672/1120] CPACK_COMPONENT_HEADERS_DEPENDS should list components, not groups With a group here, CPack thinks there's a component called "main", as well as a group called "main". It then builds packages for the "missing" component because it isn't included in any groups. This "component" package is both broken, and built after the main package. It has the same name as the proper package, so overwrites it. --- vendor/libkqueue/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 056267cde..6aaef0b88 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -197,7 +197,7 @@ set(CPACK_COMPONENT_HEADERS_GROUP "devel") set(CPACK_COMPONENT_LIBRARIES_GROUP "main") set(CPACK_COMPONENT_MAN_GROUP "main") set(CPACK_COMPONENT_PKGCONFIG_GROUP "main") -set(CPACK_COMPONENT_HEADERS_DEPENDS "main") +set(CPACK_COMPONENT_HEADERS_DEPENDS "libraries") # # Metadata common to all packaging systems From 37430f667c2b3604a3065f96146b276185d0cb51 Mon Sep 17 00:00:00 2001 From: Matthew Newton Date: Thu, 10 Jan 2019 13:07:16 +0000 Subject: [PATCH 0673/1120] Fix package description for Debian packaging Debian packages have two descriptions - a summary and a full description. CPack seems to have no concept of this, so puts the whole description, as-is, in the Description: field. This means that lines following a line-break don't start with a space. This spectacularly breaks component packages. Essentially a CPack bug, which should have a package Summary and a package Description and handle them correctly, but messing around with the format here will also affect the RPM packages because the debian-specific settings don't override the generic one. So simplest to put the whole thing on one line. --- vendor/libkqueue/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 6aaef0b88..c3c01afd9 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -204,9 +204,7 @@ set(CPACK_COMPONENT_HEADERS_DEPENDS "libraries") # set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Userspace implementation of the kqueue event notification mechanism") -set(CPACK_COMPONENT_MAIN_DESCRIPTION "A user space implementation of the kqueue(2) kernel event notification -mechanism. libkqueue acts as a translator between the kevent structure and the -native kernel facilities.") +set(CPACK_COMPONENT_MAIN_DESCRIPTION "A user space implementation of the kqueue(2) kernel event notification mechanism. libkqueue acts as a translator between the kevent structure and the native kernel facilities.") set(CPACK_COMPONENT_DEVEL_DESCRIPTION "Development files for ${PROJECT_NAME}-${PROJECT_VERSION}") # From 5846ad670195b2811d5ceed9c920e5452b3378b7 Mon Sep 17 00:00:00 2001 From: Matthew Newton Date: Thu, 10 Jan 2019 13:34:35 +0000 Subject: [PATCH 0674/1120] For Debian put headers in a separate dev package --- vendor/libkqueue/CMakeLists.txt | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index c3c01afd9..301c8f0cb 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -230,5 +230,18 @@ set(CPACK_RPM_FILE_NAME RPM-DEFAULT) # Use rpmbuild's package naming set(CPACK_RPM_MAIN_DEBUGINFO_PACKAGE ON) set(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE ON) set(CPACK_RPM_MAIN_BUILD_SOURCE_DIRS_PREFIX /usr/src/debug/${PROJECT_NAME}-${PROJECT_VERSION}) -include(CPack) +# +# DEB Specific configuration +# +set(CPACK_DEBIAN_MAIN_PACKAGE_NAME "${CPACK_PACKAGE_NAME}") +set(CPACK_DEBIAN_MAIN_PACKAGE_SECTION "libs") + +set(CPACK_DEBIAN_DEVEL_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-dev") +set(CPACK_DEBIAN_DEVEL_PACKAGE_SECTION "libdevel") +set(CPACK_DEBIAN_DEVEL_PACKAGE_DEPENDS "${CPACK_PACKAGE_NAME} (= ${PROJECT_VERSION})") + +set(CPACK_DEB_COMPONENT_INSTALL ON) # Enable component based packaging (generate multiple packages) +set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) # Use default Debian package naming scheme + +include(CPack) From 6c9af9faf34f4c31e93ae974d299b013f2bf0b5d Mon Sep 17 00:00:00 2001 From: Matthew Newton Date: Thu, 10 Jan 2019 14:15:08 +0000 Subject: [PATCH 0675/1120] update .gitignore --- vendor/libkqueue/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/.gitignore b/vendor/libkqueue/.gitignore index 1ec367d25..d0b4a3281 100644 --- a/vendor/libkqueue/.gitignore +++ b/vendor/libkqueue/.gitignore @@ -11,7 +11,7 @@ Makefile Testing/ _CPack_Packages/ cmake_install.cmake -install_manifest.txt +install_manifest*.txt kqueue-*.deb libkqueue.so test/CMakeCache.txt From 36e534d953a2ee86c5b0188b7daad68790b1564c Mon Sep 17 00:00:00 2001 From: Matthew Newton Date: Thu, 10 Jan 2019 14:51:38 +0000 Subject: [PATCH 0676/1120] Move man page to development package This is correct, according to both Debian and Fedora packaging policy, as it's not useful to normal users. --- vendor/libkqueue/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 301c8f0cb..cffafbb19 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -191,11 +191,11 @@ set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Mark Heily ") set(CPACK_BUILD_SOURCE_DIRS ${CMAKE_SOURCE_DIR}/src) # Group the components into packages -# - devel contains header files and becomes libkqueue-devel +# - devel contains header files and man pages and becomes libkqueue-devel # - main contains everything else and becomes libkqueue set(CPACK_COMPONENT_HEADERS_GROUP "devel") set(CPACK_COMPONENT_LIBRARIES_GROUP "main") -set(CPACK_COMPONENT_MAN_GROUP "main") +set(CPACK_COMPONENT_MAN_GROUP "devel") set(CPACK_COMPONENT_PKGCONFIG_GROUP "main") set(CPACK_COMPONENT_HEADERS_DEPENDS "libraries") From 649e2c9943035329e3e6dd4c3825c581a2e63d30 Mon Sep 17 00:00:00 2001 From: Matthew Newton Date: Thu, 10 Jan 2019 15:00:24 +0000 Subject: [PATCH 0677/1120] Put the man page somewhere it can be found --- vendor/libkqueue/CMakeLists.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index cffafbb19..55803372c 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -155,9 +155,11 @@ configure_file("${CMAKE_SOURCE_DIR}/libkqueue.pc.in" @ONLY) # -# Avoid conflicts by not trying to create /usr/share/man directory +# Avoid conflicts by not trying to create existing directories # -set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION ${CMAKE_INSTALL_FULL_MANDIR}) +set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION ${CMAKE_INSTALL_FULL_MANDIR} + ${CMAKE_INSTALL_FULL_MANDIR}/man2 + ${CMAKE_INSTALL_FULL_INCLUDEDIR}/sys) install(FILES "include/sys/event.h" @@ -172,7 +174,7 @@ install(TARGETS install(FILES kqueue.2 DESTINATION - "${CMAKE_INSTALL_FULL_MANDIR}" + "${CMAKE_INSTALL_FULL_MANDIR}/man2" COMPONENT man) install(FILES "${CMAKE_BINARY_DIR}/libkqueue.pc" From afe00477b31280f1a618034c1a1ee639268e12e1 Mon Sep 17 00:00:00 2001 From: Matthew Newton Date: Wed, 6 Feb 2019 17:37:18 +0000 Subject: [PATCH 0678/1120] Bump version to 2.3.1, note recent changes --- vendor/libkqueue/CMakeLists.txt | 2 +- vendor/libkqueue/ChangeLog | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 55803372c..992c8a37f 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -18,7 +18,7 @@ cmake_minimum_required(VERSION 3.8.0) cmake_policy(SET CMP0063 OLD) -project(libkqueue VERSION 2.3.0 LANGUAGES C) +project(libkqueue VERSION 2.3.1 LANGUAGES C) enable_testing() set(CMAKE_C_VISIBILITY_PRESET hidden) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 274b659ff..daabe61d2 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,3 +1,12 @@ +2019-02-06 v2.3.1 +------------------------------------------------------------------------ + + * Support more knote flags + (Credit: Dmitry Selyutin, PR #49) + + * Debian packaging updates + (Credit: Matthew Newton) + 2018-11-25 v2.3.0 ------------------------------------------------------------------------ From dada61f1cf1006f3566ceda8aebe604bca519ee2 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 22 Feb 2019 12:03:38 +0800 Subject: [PATCH 0679/1120] It's cmake3 on centos 7 Same with cpack... --- vendor/libkqueue/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index 4e26dd570..3d6d18cb5 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -26,9 +26,9 @@ Installation - Linux, Solaris Installation - Red Hat ---------------------- - cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib + cmake3 -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib make - cpack -G RPM + cpack3 -G RPM Installation - Debian --------------------- From 589db77e903d1f020657e9abde1a7651bcb2f3fb Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 22 Feb 2019 15:50:28 +0800 Subject: [PATCH 0680/1120] Strip whitespace from line endings ...so those who of us are using editors which do this automatically don't generate noise in diffs. --- vendor/libkqueue/.travis.yml | 4 +-- vendor/libkqueue/BUGS | 22 +++++++------- vendor/libkqueue/ChangeLog | 34 +++++++++++----------- vendor/libkqueue/include/sys/event.h | 4 +-- vendor/libkqueue/kern/Makefile | 2 +- vendor/libkqueue/kern/kqueue.c | 20 ++++++------- vendor/libkqueue/kern/test.c | 2 +- vendor/libkqueue/kqlite/README | 2 +- vendor/libkqueue/kqlite/dispatch.c | 2 +- vendor/libkqueue/kqlite/kqlite.c | 22 +++++++------- vendor/libkqueue/kqlite/utarray.h | 8 ++--- vendor/libkqueue/kqueue.2 | 8 ++--- vendor/libkqueue/libkqueue.pc.in | 2 +- vendor/libkqueue/src/common/alloc.h | 8 ++--- vendor/libkqueue/src/common/debug.h | 16 +++++----- vendor/libkqueue/src/common/kevent.c | 12 ++++---- vendor/libkqueue/src/common/knote.c | 6 ++-- vendor/libkqueue/src/common/kqueue.c | 8 ++--- vendor/libkqueue/src/common/map.c | 2 +- vendor/libkqueue/src/common/tree.h | 2 +- vendor/libkqueue/src/linux/platform.h | 4 +-- vendor/libkqueue/src/linux/proc.c | 26 ++++++++--------- vendor/libkqueue/src/linux/signal.c | 8 ++--- vendor/libkqueue/src/linux/timer.c | 12 ++++---- vendor/libkqueue/src/linux/user.c | 10 +++---- vendor/libkqueue/src/linux/write.c | 2 +- vendor/libkqueue/src/posix/kevent.c | 4 +-- vendor/libkqueue/src/posix/platform.h | 2 +- vendor/libkqueue/src/posix/proc.c | 18 ++++++------ vendor/libkqueue/src/posix/signal.c | 18 ++++++------ vendor/libkqueue/src/posix/timer.c | 10 +++---- vendor/libkqueue/src/posix/user.c | 8 ++--- vendor/libkqueue/src/solaris/platform.c | 12 ++++---- vendor/libkqueue/src/solaris/signal.c | 22 +++++++------- vendor/libkqueue/src/solaris/socket.c | 18 ++++++------ vendor/libkqueue/src/solaris/timer.c | 12 ++++---- vendor/libkqueue/src/solaris/user.c | 8 ++--- vendor/libkqueue/src/windows/platform.h | 6 ++-- vendor/libkqueue/src/windows/read.c | 24 +++++++-------- vendor/libkqueue/src/windows/stdint.h | 18 ++++++------ vendor/libkqueue/src/windows/timer.c | 8 ++--- vendor/libkqueue/src/windows/user.c | 8 ++--- vendor/libkqueue/test/benchmark/abtest | 4 +-- vendor/libkqueue/test/common.h | 2 +- vendor/libkqueue/test/kevent.c | 14 ++++----- vendor/libkqueue/test/libdispatch/Makefile | 2 +- vendor/libkqueue/test/libdispatch/main.c | 10 +++---- vendor/libkqueue/test/lockstat.c | 2 +- vendor/libkqueue/test/read.c | 34 +++++++++++----------- vendor/libkqueue/test/signal.c | 4 +-- vendor/libkqueue/test/stress/Makefile | 2 +- vendor/libkqueue/test/stress/main.c | 6 ++-- vendor/libkqueue/test/test.c | 2 +- vendor/libkqueue/test/timer.c | 12 ++++---- vendor/libkqueue/test/user.c | 20 ++++++------- vendor/libkqueue/test/vnode.c | 26 ++++++++--------- 56 files changed, 292 insertions(+), 292 deletions(-) diff --git a/vendor/libkqueue/.travis.yml b/vendor/libkqueue/.travis.yml index e31ada2a6..4c65e7d8f 100644 --- a/vendor/libkqueue/.travis.yml +++ b/vendor/libkqueue/.travis.yml @@ -14,9 +14,9 @@ before_install: - $CC --version before_script: # Cmake that ships with Trusty (v3.2.2) is too old, we need at least v3.4.3 -- mkdir /tmp/cmake && wget -O cmake.sh https://cmake.org/files/v3.10/cmake-3.10.0-Linux-x86_64.sh && chmod +x cmake.sh && ./cmake.sh --prefix=/tmp/cmake --skip-license +- mkdir /tmp/cmake && wget -O cmake.sh https://cmake.org/files/v3.10/cmake-3.10.0-Linux-x86_64.sh && chmod +x cmake.sh && ./cmake.sh --prefix=/tmp/cmake --skip-license - /tmp/cmake/bin/cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib -DENABLE_TESTING=YES ./ - make -j2 -- /tmp/cmake/bin/cpack -G DEB +- /tmp/cmake/bin/cpack -G DEB script: - make test diff --git a/vendor/libkqueue/BUGS b/vendor/libkqueue/BUGS index 344267209..8ce69d193 100644 --- a/vendor/libkqueue/BUGS +++ b/vendor/libkqueue/BUGS @@ -15,14 +15,14 @@ * need to uninitialize library after fork() using pthread_atfork() * Solaris unit test failure. - + LD_LIBRARY_PATH="..:/usr/sfw/lib/64" ./kqtest - 1: test_peer_close_detection() - 2: test_kqueue() - 3: test_kevent_socket_add() - 4: test_kevent_socket_del() - 5: test_kevent_socket_add_without_ev_add() - 6: test_kevent_socket_get() + 1: test_peer_close_detection() + 2: test_kqueue() + 3: test_kevent_socket_add() + 4: test_kevent_socket_del() + 5: test_kevent_socket_add_without_ev_add() + 6: test_kevent_socket_get() [read.c:84]: Unexpected event:_test_no_kevents(): [ident=7, filter=-1, flags = 1 (EV_ADD), fflags = 0, data=0, udata=fffffd7fff08c6b4]: Error 0 @@ -31,7 +31,7 @@ These need to be cleaned up; at a minimum, they should emit very loud debugging output saying "FIXME -- UNIMPLEMENTED". - $ grep STUB src/*/*.c + $ grep STUB src/*/*.c src/linux/proc.c: return (-1); /*STUB*/ src/linux/proc.c: return (0); /* STUB */ src/linux/proc.c: return (0); /* STUB */ @@ -50,7 +50,7 @@ * kqueue() should defer thread cancellation until the end. - * kevent() should defer thread cancellation and call pthread_testcancel() - before and after the call to kevent_wait(). This may require changing the - way that EINTR is handled, to make sure that the EINTR is propagated up + * kevent() should defer thread cancellation and call pthread_testcancel() + before and after the call to kevent_wait(). This may require changing the + way that EINTR is handled, to make sure that the EINTR is propagated up the call stack to kevent(). diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index daabe61d2..d9165ac2f 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -7,7 +7,7 @@ * Debian packaging updates (Credit: Matthew Newton) -2018-11-25 v2.3.0 +2018-11-25 v2.3.0 ------------------------------------------------------------------------ * kevent: refactor to remove goto statement @@ -19,7 +19,7 @@ * Add a monitoring thread that takes care of cleaning up closed kqueues (Credit: Philippe Wooding) - * Multiple bug fixes for leaking descriptors in kn_delete() + * Multiple bug fixes for leaking descriptors in kn_delete() (Credit: Philippe Wooding) * Fix build errors on Linux systems that do not use glibc @@ -37,7 +37,7 @@ ead * Fix to allow libpcap FDs to be used. Author: Philippe Wooding - + * Switch to CMake as the build and packaging system. 2016-07-24 v2.1.0 @@ -46,8 +46,8 @@ ead * Fix an endianness issue when calling ioctl on Linux. (Credit: Vivian Kong) - * Allow tests to be built from separate build directory. - (Credit: Chris Bailey) + * Allow tests to be built from separate build directory. + (Credit: Chris Bailey) * Add support for kevent64(2) timers from Darwin. (Credit: Hubertus Franke) @@ -73,12 +73,12 @@ ead * Fix a build failure on mips64el. (Credit: YunQiang Su, from Debian Bug #754376) -2014-03-09 v2.0.3 +2014-03-09 v2.0.3 ------------------------------------------------------------------------ * Fix the generation of libkqueue.pc -2014-02-23 v2.0.2 +2014-02-23 v2.0.2 ------------------------------------------------------------------------ * Switch from SVN to Git @@ -106,13 +106,13 @@ ead * Call epoll_wait after linux_kevent_wait_hires() (Credit: Eric Wong) - * Detect regular files correctly + * Detect regular files correctly (Credit: Eric Wong) - * Ensure that calling close() on a file descriptor will remove any + * Ensure that calling close() on a file descriptor will remove any kevents that reference the descriptor. [merged from ^/branches/stable@551] - * Remove the SERIALIZE_KEVENT macro, and always protect kevent_copyin() + * Remove the SERIALIZE_KEVENT macro, and always protect kevent_copyin() and kevent_copyout() with a mutex. * Remove fine-grained locking at the knote level. @@ -139,7 +139,7 @@ ead ------------------------------------------------------------------------ * Fix a typo in kevent_copyin() that caused EV_RECEIPT to set the - data field incorrectly in some cases. + data field incorrectly in some cases. (Credit to Julien Blache for discovering and fixing this bug) 2010-08-05 v0.9.2 r289 @@ -159,7 +159,7 @@ ead ------------------------------------------------------------------------ * Set kevent.data = 1 for passive sockets that have at least one pending - connection. + connection. (Credit to Julien Blache for finding and researching this bug) * Fix various compilation errors under Solaris. @@ -171,7 +171,7 @@ ead ------------------------------------------------------------------------ * Fix a bug that prevented a knote with the EV_DISPATCH flag from - being re-enabled after an event had been triggered. + being re-enabled after an event had been triggered. (Credit to Julien Blache for finding and researching this bug) 2010-06-08 v0.7 r248 @@ -191,12 +191,12 @@ ead * Implement knote modification for signals. - * Implement POSIX signal.c + * Implement POSIX signal.c 2010-02-09 v0.5 r200 ------------------------------------------------------------------------ - * Prevent namespace pollution by hiding all ELF symbols except for + * Prevent namespace pollution by hiding all ELF symbols except for kqueue() and kevent(). * Add reference counting to the garbage collection mechanism so that @@ -205,7 +205,7 @@ ead * Improve scalability by using red-black trees instead of linked lists. - * Refactor the internal API to promote modularity and code reuse. + * Refactor the internal API to promote modularity and code reuse. Five methods are added to each filter: create, modify, delete, enable, disable. These replace the copyin() method, which was overly complicated. @@ -250,7 +250,7 @@ ead function under OpenBSD 4.4 using the native kqueue(2) and kevent(2) system calls. - * The kqueue_free() function has been removed. + * The kqueue_free() function has been removed. * A helper thread performs garbage collection when close(2) is called on the file descriptor returned by kqueue(). diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index 053910495..ccd1007dc 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -35,7 +35,7 @@ #ifdef __KERNEL__ #define intptr_t long #else -#include +#include #if defined(_WIN32) && _MSC_VER < 1600 && !defined(__MINGW32__) # include "../../src/windows/stdint.h" #else @@ -155,7 +155,7 @@ struct kevent { #define NOTE_LINKDOWN 0x0002 /* link is down */ #define NOTE_LINKINV 0x0004 /* link state is invalid */ -/* KLUDGE: This is from on FreeBSD and is used by +/* KLUDGE: This is from on FreeBSD and is used by the EVFILT_FS filter. */ /* vfsquery flags */ #define VQ_NOTRESP 0x0001 /* server down */ diff --git a/vendor/libkqueue/kern/Makefile b/vendor/libkqueue/kern/Makefile index 39b9769e4..d5a38a926 100644 --- a/vendor/libkqueue/kern/Makefile +++ b/vendor/libkqueue/kern/Makefile @@ -4,7 +4,7 @@ # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. -# +# # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR diff --git a/vendor/libkqueue/kern/kqueue.c b/vendor/libkqueue/kern/kqueue.c index b5ddfd653..4c2bc383d 100644 --- a/vendor/libkqueue/kern/kqueue.c +++ b/vendor/libkqueue/kern/kqueue.c @@ -56,11 +56,11 @@ static int kqueue_open (struct inode *inode, struct file *file); static int kqueue_release (struct inode *inode, struct file *file); static int kqueue_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -static ssize_t kqueue_read(struct file *file, char __user *buf, +static ssize_t kqueue_read(struct file *file, char __user *buf, size_t lbuf, loff_t *ppos); -static ssize_t kqueue_write(struct file *file, const char __user *buf, +static ssize_t kqueue_write(struct file *file, const char __user *buf, size_t lbuf, loff_t *ppos); - + struct file_operations fops = { .owner = THIS_MODULE, .ioctl = kqueue_ioctl, @@ -113,7 +113,7 @@ static struct task_struct *kq_thread; static struct kfilter * kfilter_lookup(struct kqueue *kq, int filt) { - if (filt > 0 || filt + EVFILT_SYSCOUNT < 0) + if (filt > 0 || filt + EVFILT_SYSCOUNT < 0) return NULL; return &kq->kq_filt[~filt]; } @@ -132,7 +132,7 @@ static int kqueue_main(void *arg) return 0; } -static int kqueue_open (struct inode *inode, struct file *file) +static int kqueue_open (struct inode *inode, struct file *file) { struct kqueue *kq; int i; @@ -145,14 +145,14 @@ static int kqueue_open (struct inode *inode, struct file *file) return -1; } spin_lock_init(&kq->kq_lock); - for (i = 0; i < EVFILT_SYSCOUNT; i++) + for (i = 0; i < EVFILT_SYSCOUNT; i++) kq->kq_filt[i].kf_note = RB_ROOT; file->private_data = kq; return 0; } -static int kqueue_release (struct inode *inode, struct file *file) +static int kqueue_release (struct inode *inode, struct file *file) { printk("kqueue_release\n"); kfree(file->private_data); @@ -161,7 +161,7 @@ static int kqueue_release (struct inode *inode, struct file *file) } static int kqueue_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { int fd; @@ -173,7 +173,7 @@ static int kqueue_ioctl(struct inode *inode, struct file *file, return 0; } -static ssize_t kqueue_read(struct file *file, char __user *buf, +static ssize_t kqueue_read(struct file *file, char __user *buf, size_t lbuf, loff_t *ppos) { struct kqueue *kq = file->private_data; @@ -185,7 +185,7 @@ static ssize_t kqueue_read(struct file *file, char __user *buf, return sizeof(struct kevent); } -static ssize_t kqueue_write(struct file *file, const char __user *buf, +static ssize_t kqueue_write(struct file *file, const char __user *buf, size_t lbuf, loff_t *ppos) { struct kqueue *kq = file->private_data; diff --git a/vendor/libkqueue/kern/test.c b/vendor/libkqueue/kern/test.c index 0750ff5d0..89e51f7ae 100644 --- a/vendor/libkqueue/kern/test.c +++ b/vendor/libkqueue/kern/test.c @@ -24,7 +24,7 @@ #include "../include/sys/event.h" -int +int main(int argc, char **argv) { struct kevent kev; diff --git a/vendor/libkqueue/kqlite/README b/vendor/libkqueue/kqlite/README index 6611597b9..ad698ea98 100644 --- a/vendor/libkqueue/kqlite/README +++ b/vendor/libkqueue/kqlite/README @@ -3,7 +3,7 @@ kqlite has the following goals: * be lightweight and efficient * provide a strict subset of the functionality of kqueue(2) and kevent(2) * closely resemble the kqueue API, but not guarantee 100% compatibility - * support modern POSIX operating systems + * support modern POSIX operating systems It should be possible to switch between kqlite and the full libkqueue using a few preprocessor macros: diff --git a/vendor/libkqueue/kqlite/dispatch.c b/vendor/libkqueue/kqlite/dispatch.c index 0ccc8cee0..73008a9f8 100644 --- a/vendor/libkqueue/kqlite/dispatch.c +++ b/vendor/libkqueue/kqlite/dispatch.c @@ -24,7 +24,7 @@ * EXPERIMENTAL dispatching API */ void -kq_dispatch(kqueue_t kq, void (*cb)(kqueue_t, struct kevent)) +kq_dispatch(kqueue_t kq, void (*cb)(kqueue_t, struct kevent)) { const int maxevents = 64; /* Should be more like 2xNCPU */ struct kevent events[maxevents]; diff --git a/vendor/libkqueue/kqlite/kqlite.c b/vendor/libkqueue/kqlite/kqlite.c index f3f830647..0a665c555 100644 --- a/vendor/libkqueue/kqlite/kqlite.c +++ b/vendor/libkqueue/kqlite/kqlite.c @@ -13,7 +13,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - + #include #include #include @@ -22,8 +22,8 @@ #include "./lite.h" #include "./utarray.h" -/* The maximum number of events that can be returned in - a single kq_event() call +/* The maximum number of events that can be returned in + a single kq_event() call */ #define EPEV_BUF_MAX 512 @@ -77,7 +77,7 @@ struct kqueue { /* This allows all kevents to share a single inotify descriptor. * Key: inotify watch descriptor returned by inotify_add_watch() - * Value: pointer to knote + * Value: pointer to knote */ UT_array *ino_knote; @@ -107,7 +107,7 @@ static inline void kq_lock(kqueue_t kq) { #ifdef KQ_THREADSAFE - if (pthread_mutex_lock(&kq->kq_mtx) != 0) + if (pthread_mutex_lock(&kq->kq_mtx) != 0) abort(); #endif } @@ -116,7 +116,7 @@ static inline void kq_unlock(kqueue_t kq) { #ifdef KQ_THREADSAFE - if (pthread_mutex_unlock(&kq->kq_mtx) != 0) + if (pthread_mutex_unlock(&kq->kq_mtx) != 0) abort(); #endif } @@ -138,7 +138,7 @@ kq_init(void) free(kq); return (NULL); } - + #elif defined(USE_EPOLL) struct epoll_event epev; @@ -163,7 +163,7 @@ kq_init(void) kq->readfd = epoll_create(10); kq->writefd = epoll_create(10); kq->timefd = timerfd_create(CLOCK_MONOTONIC, 0); - if (kq->sigfd < 0 || kq->inofd < 0 || kq->epfd < 0 + if (kq->sigfd < 0 || kq->inofd < 0 || kq->epfd < 0 || kq->readfd < 0 || kq->writefd < 0 || kq->timefd < 0) goto errout; @@ -214,7 +214,7 @@ kq_free(kqueue_t kq) { #if defined(USE_KQUEUE) close(kq.kqfd); - + #elif defined(USE_EPOLL) close(kq->sigfd); close(kq->inofd); @@ -391,7 +391,7 @@ _get_signal(struct kevent *dst, kqueue_t kq) kn = knote_lookup(kq, EVFILT_SIGNAL, sig.ssi_signo); memcpy(dst, &kn->kev, sizeof(*dst)); - + return (0); } @@ -427,7 +427,7 @@ int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, } /* Convert timeout to the format used by epoll_wait() */ - if (timeout == NULL) + if (timeout == NULL) eptimeout = -1; else eptimeout = (1000 * timeout->tv_sec) + (timeout->tv_nsec / 1000000); diff --git a/vendor/libkqueue/kqlite/utarray.h b/vendor/libkqueue/kqlite/utarray.h index 3bb87f097..e1232a479 100644 --- a/vendor/libkqueue/kqlite/utarray.h +++ b/vendor/libkqueue/kqlite/utarray.h @@ -21,7 +21,7 @@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* a dynamic array implementation using macros +/* a dynamic array implementation using macros */ #ifndef UTARRAY_H #define UTARRAY_H @@ -29,9 +29,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define UTARRAY_VERSION 1.9.8 #ifdef __GNUC__ -#define _UNUSED_ __attribute__ ((__unused__)) +#define _UNUSED_ __attribute__ ((__unused__)) #else -#define _UNUSED_ +#define _UNUSED_ #endif #include /* size_t */ @@ -189,7 +189,7 @@ typedef struct { #define utarray_renew(a,u) do { \ if (a) utarray_clear(a); \ else utarray_new((a),(u)); \ -} while(0) +} while(0) #define utarray_clear(a) do { \ if ((a)->i > 0) { \ diff --git a/vendor/libkqueue/kqueue.2 b/vendor/libkqueue/kqueue.2 index d8b5414f9..7be32b792 100644 --- a/vendor/libkqueue/kqueue.2 +++ b/vendor/libkqueue/kqueue.2 @@ -203,7 +203,7 @@ will not return it. The filter itself is not disabled. .It EV_DISPATCH Disable the event source immediately after delivery of an event. -See +See .Dv EV_DISABLE above. .It EV_DELETE @@ -217,7 +217,7 @@ any pending events. When passed as input, it forces .Dv EV_ERROR to always be returned. -When a filter is successfully added the +When a filter is successfully added the .Va data field will be zero. .It EV_ONESHOT @@ -394,10 +394,10 @@ Establishes a user event identified by .Va ident which is not assosicated with any kernel mechanism but is triggered by user level code. -The lower 24 bits of the +The lower 24 bits of the .Va fflags may be used for user defined flags and manipulated using the following: -.Bl -tag -width XXNOTE_FFLAGSMASK +.Bl -tag -width XXNOTE_FFLAGSMASK .It Dv NOTE_FFNOP Ignore the input .Va fflags . diff --git a/vendor/libkqueue/libkqueue.pc.in b/vendor/libkqueue/libkqueue.pc.in index ee9939a54..f633f1fcc 100644 --- a/vendor/libkqueue/libkqueue.pc.in +++ b/vendor/libkqueue/libkqueue.pc.in @@ -6,7 +6,7 @@ includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ Name: libkqueue Description: Emulates FreeBSD kqueue(2) on other platforms Version: @PROJECT_VERSION@ -Requires: +Requires: Libs: -lkqueue Libs.private: -lpthread -lrt Cflags: -I${includedir}/kqueue diff --git a/vendor/libkqueue/src/common/alloc.h b/vendor/libkqueue/src/common/alloc.h index f82628c93..65b341661 100644 --- a/vendor/libkqueue/src/common/alloc.h +++ b/vendor/libkqueue/src/common/alloc.h @@ -20,7 +20,7 @@ * * Each translation unit in a program can include this header and * have access to it's own private memory allocator. This can be useful - * for improving the performance of programs which frequently allocate + * for improving the performance of programs which frequently allocate * and deallocate objects with a fixed size. * * The allocator must be initialized by calling mem_init(). This @@ -57,9 +57,9 @@ mem_init(size_t objsize, size_t cachesize) static inline void * mem_alloc(void) { - if (_ma.ac_count > 0) + if (_ma.ac_count > 0) return (_ma.ac_cache[_ma.ac_count--]); - else + else return (malloc(_ma.ac_size)); } @@ -79,6 +79,6 @@ mem_free(void *ptr) { if (_ma.ac_count < _ma.ac_max) _ma.ac_cache[_ma.ac_count++] = ptr; - else + else free(ptr); } diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index fa5e8815e..c5530a957 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -35,7 +35,7 @@ extern char *KQUEUE_DEBUG_IDENT; # define THREAD_ID ((int) pthread_self()) #elif defined(_WIN32) # define THREAD_ID (int)(GetCurrentThreadId()) -#else +#else # error Unsupported platform #endif @@ -80,7 +80,7 @@ extern char *KQUEUE_DEBUG_IDENT; # endif /* - * Tracing mutexes are a thin wrapper around the pthread_mutex_t + * Tracing mutexes are a thin wrapper around the pthread_mutex_t * datatype that tracks and reports when a mutex is locked or unlocked. * It also allows you to assert that a mutex has (or has not) been locked * by calling tracing_mutex_assert(). @@ -90,10 +90,10 @@ extern char *KQUEUE_DEBUG_IDENT; # define MTX_LOCKED 1 typedef struct { - pthread_mutex_t mtx_lock; - int mtx_status; + pthread_mutex_t mtx_lock; + int mtx_status; int mtx_owner; -} tracing_mutex_t; +} tracing_mutex_t; # define tracing_mutex_init(mtx, attr) do { \ pthread_mutex_init(&(mtx)->mtx_lock, (attr)); \ @@ -134,14 +134,14 @@ typedef struct { # define dbg_lasterror(str) do {} while (0) # define dbg_wsalasterror(str) do {} while (0) # define reset_errno() do {} while (0) -# define MTX_UNLOCKED -# define MTX_LOCKED +# define MTX_UNLOCKED +# define MTX_LOCKED # define tracing_mutex_t pthread_mutex_t # define tracing_mutex_init pthread_mutex_init # define tracing_mutex_destroy pthread_mutex_destroy # define tracing_mutex_assert(x,y) do {} while (0) # define tracing_mutex_lock pthread_mutex_lock # define tracing_mutex_unlock pthread_mutex_unlock -#endif +#endif #endif /* ! _DEBUG_H */ diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 245c4ed1b..768b93a35 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -33,7 +33,7 @@ kevent_filter_dump(const struct kevent *kev) { static __thread char buf[64]; - snprintf(&buf[0], sizeof(buf), "%d (%s)", + snprintf(&buf[0], sizeof(buf), "%d (%s)", kev->filter, filter_name(kev->filter)); return ((const char *) &buf[0]); } @@ -103,7 +103,7 @@ kevent_dump(const struct kevent *kev) { static __thread char buf[2147]; - snprintf((char *) &buf[0], sizeof(buf), + snprintf((char *) &buf[0], sizeof(buf), "{ ident=%d, filter=%s, %s, %s, data=%d, udata=%p }", (u_int) kev->ident, kevent_filter_dump(kev), @@ -128,7 +128,7 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) return (-1); } - if (filter_lookup(&filt, kq, src->filter) < 0) + if (filter_lookup(&filt, kq, src->filter) < 0) return (-1); dbg_printf("src=%s", kevent_dump(src)); @@ -150,7 +150,7 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) knote_release(kn); errno = EFAULT; return (-1); - } + } knote_insert(filt, kn); dbg_printf("created kevent %s", kevent_dump(src)); @@ -163,7 +163,7 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) return (0); } else { - dbg_printf("no entry found for ident=%u", (unsigned int)src->ident); + dbg_printf("no entry found for ident=%u", (unsigned int)src->ident); errno = ENOENT; return (-1); } @@ -268,7 +268,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, } rv = 0; - + /* * Wait for events and copy them to the eventlist */ diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index f6bf93108..0fbfb6408 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -33,7 +33,7 @@ knote_init(void) static int knote_cmp(struct knote *a, struct knote *b) { - return memcmp(&a->kev.ident, &b->kev.ident, sizeof(a->kev.ident)); + return memcmp(&a->kev.ident, &b->kev.ident, sizeof(a->kev.ident)); } RB_GENERATE(knt, knote, kn_entries, knote_cmp) @@ -126,7 +126,7 @@ knote_lookup(struct filter *filt, uintptr_t ident) return (ent); } - + #if DEADWOOD struct knote * knote_get_by_data(struct filter *filt, intptr_t data) @@ -135,7 +135,7 @@ knote_get_by_data(struct filter *filt, intptr_t data) pthread_rwlock_rdlock(&filt->kf_knote_mtx); RB_FOREACH(kn, knt, &filt->kf_knote) { - if (data == kn->kev.data) + if (data == kn->kev.data) break; } if (kn != NULL) { diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 0c3c15eaf..29f1c0716 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -47,7 +47,7 @@ get_fd_limit(void) return 65536; #else struct rlimit rlim; - + if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { dbg_perror("getrlimit(2)"); return (65536); @@ -72,7 +72,7 @@ libkqueue_init(void) #ifdef _WIN32 /* Initialize the Winsock library */ WSADATA wsaData; - if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) + if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) abort(); #endif @@ -89,7 +89,7 @@ libkqueue_init(void) kqmap = map_new(get_fd_limit()); // INT_MAX if (kqmap == NULL) - abort(); + abort(); if (knote_init() < 0) abort(); dbg_puts("library initialization complete"); @@ -102,7 +102,7 @@ libkqueue_init(void) static int kqueue_cmp(struct kqueue *a, struct kqueue *b) { - return memcmp(&a->kq_id, &b->kq_id, sizeof(int)); + return memcmp(&a->kq_id, &b->kq_id, sizeof(int)); } /* Must hold the kqtree_mtx when calling this */ diff --git a/vendor/libkqueue/src/common/map.c b/vendor/libkqueue/src/common/map.c index 50ba0cfc7..d3f2153c7 100644 --- a/vendor/libkqueue/src/common/map.c +++ b/vendor/libkqueue/src/common/map.c @@ -38,7 +38,7 @@ map_new(size_t len) } dst->len = len; #else - dst->data = mmap(NULL, len * sizeof(void *), PROT_READ | PROT_WRITE, + dst->data = mmap(NULL, len * sizeof(void *), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_NORESERVE | MAP_ANON, -1, 0); if (dst->data == MAP_FAILED) { dbg_perror("mmap(2)"); diff --git a/vendor/libkqueue/src/common/tree.h b/vendor/libkqueue/src/common/tree.h index 8df581357..54b9ba034 100644 --- a/vendor/libkqueue/src/common/tree.h +++ b/vendor/libkqueue/src/common/tree.h @@ -86,7 +86,7 @@ struct { \ SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ (head)->sph_root = tmp; \ } while (/*CONSTCOND*/ 0) - + #define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ SPLAY_LEFT(tmp, field) = (head)->sph_root; \ diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 73239f57b..ec037df3a 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -52,7 +52,7 @@ struct filter; #ifndef __ANDROID__ extern long int syscall (long int __sysno, ...); #endif - + /* Convenience macros to access the epoll descriptor for the kqueue */ #define kqueue_epfd(kq) ((kq)->epollfd) #define filter_epfd(filt) ((filt)->kf_kqueue->epollfd) @@ -60,7 +60,7 @@ extern long int syscall (long int __sysno, ...); /* * Additional members of struct filter */ -#undef FILTER_PLATFORM_SPECIFIC +#undef FILTER_PLATFORM_SPECIFIC /* * Additional members of struct knote diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index 9716aa293..4c9cba657 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -50,7 +50,7 @@ wait_thread(void *arg) { struct filter *filt = (struct filter *) arg; uint64_t counter = 1; - const int options = WEXITED | WNOWAIT; + const int options = WEXITED | WNOWAIT; struct knote *kn; siginfo_t si; sigset_t sigmask; @@ -76,12 +76,12 @@ wait_thread(void *arg) if (errno == EINTR) continue; dbg_perror("waitid(2)"); - break; + break; } /* Scan the wait queue to see if anyone is interested */ kn = knote_lookup(filt, si.si_pid); - if (kn == NULL) + if (kn == NULL) continue; /* Create a proc_event */ @@ -90,11 +90,11 @@ wait_thread(void *arg) } else if (si.si_code == CLD_KILLED) { /* FIXME: probably not true on BSD */ /* FIXME: arbitrary non-zero number */ - kn->kev.data = 254; + kn->kev.data = 254; } else { /* Should never happen. */ /* FIXME: arbitrary non-zero number */ - kn->kev.data = 1; + kn->kev.data = 1; } knote_enqueue(filt, kn); @@ -127,12 +127,12 @@ evfilt_proc_init(struct filter *filt) pthread_mutex_init(&ed->wait_mtx, NULL); pthread_cond_init(&ed->wait_cond, NULL); - if ((efd = eventfd(0, 0)) < 0) + if ((efd = eventfd(0, 0)) < 0) goto errout; - if (fcntl(filt->kf_pfd, F_SETFL, O_NONBLOCK) < 0) + if (fcntl(filt->kf_pfd, F_SETFL, O_NONBLOCK) < 0) goto errout; filt->kf_pfd = efd; - if (pthread_create(&ed->wthr_id, NULL, wait_thread, filt) != 0) + if (pthread_create(&ed->wthr_id, NULL, wait_thread, filt) != 0) goto errout; @@ -156,8 +156,8 @@ evfilt_proc_destroy(struct filter *filt) } int -evfilt_proc_copyout(struct filter *filt, - struct kevent *dst, +evfilt_proc_copyout(struct filter *filt, + struct kevent *dst, int maxevents) { struct knote *kn; @@ -191,14 +191,14 @@ evfilt_proc_copyout(struct filter *filt, } if (knote_events_pending(filt)) { - /* XXX-FIXME: If there are leftover events on the waitq, + /* XXX-FIXME: If there are leftover events on the waitq, re-arm the eventfd. list */ abort(); } return (nevents); } - + int evfilt_proc_knote_create(struct filter *filt, struct knote *kn) { @@ -206,7 +206,7 @@ evfilt_proc_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_proc_knote_modify(struct filter *filt, struct knote *kn, +evfilt_proc_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { return (0); /* STUB */ diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index 6177271ad..4766b524d 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -134,7 +134,7 @@ evfilt_signal_copyout(struct kevent *dst, struct knote *src, void *x UNUSED) /* NOTE: dst->data should be the number of times the signal occurred, but that information is not available. */ - dst->data = 1; + dst->data = 1; return (0); } @@ -156,8 +156,8 @@ evfilt_signal_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_signal_knote_modify(struct filter *filt UNUSED, - struct knote *kn UNUSED, +evfilt_signal_knote_modify(struct filter *filt UNUSED, + struct knote *kn UNUSED, const struct kevent *kev UNUSED) { /* Nothing to do since the signal number does not change. */ @@ -214,5 +214,5 @@ const struct filter evfilt_signal = { evfilt_signal_knote_modify, evfilt_signal_knote_delete, evfilt_signal_knote_enable, - evfilt_signal_knote_disable, + evfilt_signal_knote_disable, }; diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 06ddfc8bb..b1a3bf175 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -33,12 +33,12 @@ #define SYS_timerfd_gettime __NR_timerfd_gettime #endif /* ! SYS_timerfd_create */ -/* XXX-FIXME +/* XXX-FIXME These are horrible hacks that are only known to be true on RHEL 5 x86. */ #ifndef SYS_timerfd_settime #define SYS_timerfd_settime (SYS_timerfd_create + 1) -#endif +#endif #ifndef SYS_timerfd_gettime #define SYS_timerfd_gettime (SYS_timerfd_create + 2) #endif @@ -132,7 +132,7 @@ evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr) memcpy(dst, &src->kev, sizeof(*dst)); if (ev->events & EPOLLERR) dst->fflags = 1; /* FIXME: Return the actual timer error */ - + /* On return, data contains the number of times the timer has been trigered. */ @@ -140,7 +140,7 @@ evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr) if (n != sizeof(expired)) { dbg_puts("invalid read from timerfd"); expired = 1; /* Fail gracefully */ - } + } dst->data = expired; return (0); @@ -189,7 +189,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_timer_knote_modify(struct filter *filt, struct knote *kn, +evfilt_timer_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { (void)filt; @@ -240,5 +240,5 @@ const struct filter evfilt_timer = { evfilt_timer_knote_modify, evfilt_timer_knote_delete, evfilt_timer_knote_enable, - evfilt_timer_knote_disable, + evfilt_timer_knote_disable, }; diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index aa1b93b18..cb7cb1b88 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -40,7 +40,7 @@ eventfd_raise(int evfd) counter = 1; if (write(evfd, &counter, sizeof(counter)) < 0) { switch (errno) { - case EAGAIN: + case EAGAIN: /* Not considered an error */ break; @@ -69,7 +69,7 @@ eventfd_lower(int evfd) n = read(evfd, &cur, sizeof(cur)); if (n < 0) { switch (errno) { - case EAGAIN: + case EAGAIN: /* Not considered an error */ break; @@ -148,7 +148,7 @@ linux_evfilt_user_knote_create(struct filter *filt, struct knote *kn) } int -linux_evfilt_user_knote_modify(struct filter *filt UNUSED, struct knote *kn, +linux_evfilt_user_knote_modify(struct filter *filt UNUSED, struct knote *kn, const struct kevent *kev) { unsigned int ffctrl; @@ -200,7 +200,7 @@ linux_evfilt_user_knote_delete(struct filter *filt, struct knote *kn) dbg_perror("close(2)"); return (-1); } - dbg_printf("removed eventfd %d from the epollfd", kn->kdata.kn_eventfd); + dbg_printf("removed eventfd %d from the epollfd", kn->kdata.kn_eventfd); kn->kdata.kn_eventfd = -1; return (0); @@ -229,5 +229,5 @@ const struct filter evfilt_user = { linux_evfilt_user_knote_modify, linux_evfilt_user_knote_delete, linux_evfilt_user_knote_enable, - linux_evfilt_user_knote_disable, + linux_evfilt_user_knote_disable, }; diff --git a/vendor/libkqueue/src/linux/write.c b/vendor/libkqueue/src/linux/write.c index 3305ee015..e31b93f6d 100644 --- a/vendor/libkqueue/src/linux/write.c +++ b/vendor/libkqueue/src/linux/write.c @@ -53,7 +53,7 @@ evfilt_write_copyout(struct kevent *dst, struct knote *src, void *ptr) dst->fflags = ((ret < 0) ? errno : serr); } else { dst->fflags = EIO; } } - + /* On return, data contains the the amount of space remaining in the write buffer */ if (ioctl(dst->ident, SIOCOUTQ, &dst->data) < 0) { /* race condition with socket close, so ignore this error */ diff --git a/vendor/libkqueue/src/posix/kevent.c b/vendor/libkqueue/src/posix/kevent.c index 722ec0ca3..96be0b8aa 100644 --- a/vendor/libkqueue/src/posix/kevent.c +++ b/vendor/libkqueue/src/posix/kevent.c @@ -23,7 +23,7 @@ const struct filter evfilt_proc = EVFILT_NOTIMPL; int posix_kevent_wait( - struct kqueue *kq, + struct kqueue *kq, const struct timespec *timeout) { int n, nfds; @@ -58,7 +58,7 @@ posix_kevent_copyout(struct kqueue *kq, int nready, nret = 0; for (i = 0; (i < EVFILT_SYSCOUNT && nready > 0 && nevents > 0); i++) { // dbg_printf("eventlist: n = %d nevents = %d", nready, nevents); - filt = &kq->kq_filt[i]; + filt = &kq->kq_filt[i]; // dbg_printf("pfd[%d] = %d", i, filt->kf_pfd); if (FD_ISSET(filt->kf_pfd, &kq->kq_rfds)) { dbg_printf("pending events for filter %d (%s)", filt->kf_id, filter_name(filt->kf_id)); diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index ef14e32d0..cc800b4a6 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -23,7 +23,7 @@ #include "../../include/sys/event.h" /* - * GCC-compatible atomic operations + * GCC-compatible atomic operations */ #define atomic_inc(p) __sync_add_and_fetch((p), 1) #define atomic_dec(p) __sync_sub_and_fetch((p), 1) diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 605c44c8f..64e53e068 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -69,7 +69,7 @@ wait_thread(void *arg) continue; dbg_printf("wait(2): %s", strerror(errno)); break; - } + } /* Create a proc_event */ if (WIFEXITED(status)) { @@ -87,7 +87,7 @@ wait_thread(void *arg) kn = knote_lookup(filt, pid); if (kn != NULL) { kn->kev.data = result; - kn->kev.fflags = NOTE_EXIT; + kn->kev.fflags = NOTE_EXIT; LIST_REMOVE(kn, entries); LIST_INSERT_HEAD(&filt->kf_eventlist, kn, entries); /* Indicate read(2) readiness */ @@ -110,9 +110,9 @@ evfilt_proc_init(struct filter *filt) if ((ed = calloc(1, sizeof(*ed))) == NULL) return (-1); - if (filter_socketpair(filt) < 0) + if (filter_socketpair(filt) < 0) goto errout; - if (pthread_create(&ed->wthr_id, NULL, wait_thread, filt) != 0) + if (pthread_create(&ed->wthr_id, NULL, wait_thread, filt) != 0) goto errout; return (0); @@ -130,7 +130,7 @@ evfilt_proc_destroy(struct filter *filt) } int -evfilt_proc_copyin(struct filter *filt, +evfilt_proc_copyin(struct filter *filt, struct knote *dst, const struct kevent *src) { if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) { @@ -147,8 +147,8 @@ evfilt_proc_copyin(struct filter *filt, } int -evfilt_proc_copyout(struct filter *filt, - struct kevent *dst, +evfilt_proc_copyout(struct filter *filt, + struct kevent *dst, int maxevents) { struct knote *kn; @@ -166,7 +166,7 @@ evfilt_proc_copyout(struct filter *filt, } #if FIXME /* XXX - NEED TO use safe foreach instead */ - if (kn->kev.flags & EV_ONESHOT) + if (kn->kev.flags & EV_ONESHOT) knote_free(kn); #endif @@ -175,7 +175,7 @@ evfilt_proc_copyout(struct filter *filt, dst++; } - if (!LIST_EMPTY(&filt->kf_eventlist)) + if (!LIST_EMPTY(&filt->kf_eventlist)) filter_raise(filt); return (nevents); diff --git a/vendor/libkqueue/src/posix/signal.c b/vendor/libkqueue/src/posix/signal.c index babbc8974..e7a453db2 100644 --- a/vendor/libkqueue/src/posix/signal.c +++ b/vendor/libkqueue/src/posix/signal.c @@ -54,7 +54,7 @@ signal_handler(int sig) dbg_printf("caught sig=%d", sig); atomic_inc(&s->s_cnt); #if defined(__sun__) - if (port_send(s->s_filt->kf_kqueue->kq_port, + if (port_send(s->s_filt->kf_kqueue->kq_port, X_PORT_SOURCE_SIGNAL, &sigtbl[sig]) < 0) { return; //FIXME: errorhandling } @@ -68,7 +68,7 @@ catch_signal(struct filter *filt, struct knote *kn) { int sig; struct sigaction sa; - + sig = kn->kev.ident; memset(&sa, 0, sizeof(sa)); sa.sa_handler = signal_handler; @@ -93,7 +93,7 @@ static int ignore_signal(int sig) { struct sigaction sa; - + memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_IGN; sigemptyset(&sa.sa_mask); @@ -130,7 +130,7 @@ int evfilt_signal_knote_create(struct filter *filt, struct knote *kn) { if (kn->kev.ident >= SIGNAL_MAX) { - dbg_printf("unsupported signal number %u", + dbg_printf("unsupported signal number %u", (unsigned int) kn->kev.ident); return (-1); } @@ -141,7 +141,7 @@ evfilt_signal_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_signal_knote_modify(struct filter *filt, struct knote *kn, +evfilt_signal_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { (void) filt; @@ -151,7 +151,7 @@ evfilt_signal_knote_modify(struct filter *filt, struct knote *kn, int evfilt_signal_knote_delete(struct filter *filt, struct knote *kn) -{ +{ (void) filt; return ignore_signal(kn->kev.ident); } @@ -196,9 +196,9 @@ evfilt_signal_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) dst->ident = sig; dst->filter = EVFILT_SIGNAL; dst->udata = kn->kev.udata; - dst->flags = kn->kev.flags; + dst->flags = kn->kev.flags; dst->fflags = 0; - dst->data = 1; + dst->data = 1; #if DEADWOOD if (kn->kev.flags & EV_DISPATCH) { @@ -222,5 +222,5 @@ const struct filter evfilt_signal = { evfilt_signal_knote_modify, evfilt_signal_knote_delete, evfilt_signal_knote_enable, - evfilt_signal_knote_disable, + evfilt_signal_knote_disable, }; diff --git a/vendor/libkqueue/src/posix/timer.c b/vendor/libkqueue/src/posix/timer.c index a7e383d18..01c1fe904 100644 --- a/vendor/libkqueue/src/posix/timer.c +++ b/vendor/libkqueue/src/posix/timer.c @@ -126,8 +126,8 @@ sleeper_thread(void *arg) /* FIXME: handle EAGAIN */ dbg_perror("write(2)"); } else if ((size_t)cnt < sizeof(si)) { - dbg_puts("FIXME: handle short write"); - } + dbg_puts("FIXME: handle short write"); + } cts = false; si.counter = 0; } @@ -269,7 +269,7 @@ evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) } else if (kn->kev.flags & EV_ONESHOT) { _timer_delete(kn); knote_free(filt, kn); - } + } #endif return (1); @@ -282,7 +282,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_timer_knote_modify(struct filter *filt, struct knote *kn, +evfilt_timer_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { (void) filt; @@ -323,5 +323,5 @@ const struct filter evfilt_timer = { evfilt_timer_knote_modify, evfilt_timer_knote_delete, evfilt_timer_knote_enable, - evfilt_timer_knote_disable, + evfilt_timer_knote_disable, }; diff --git a/vendor/libkqueue/src/posix/user.c b/vendor/libkqueue/src/posix/user.c index fe29bb84e..497254b6c 100644 --- a/vendor/libkqueue/src/posix/user.c +++ b/vendor/libkqueue/src/posix/user.c @@ -53,7 +53,7 @@ posix_evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSE memcpy(dst, &src->kev, sizeof(*dst)); struct knote *kn; int nevents = 0; - + dst->fflags &= ~NOTE_FFCTRLMASK; //FIXME: Not sure if needed dst->fflags &= ~NOTE_TRIGGER; if (src->kev.flags & EV_ADD) { @@ -67,7 +67,7 @@ posix_evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSE kqops.eventfd_raise(&src->kdata.kn_eventfd); } - if (src->kev.flags & EV_DISPATCH) + if (src->kev.flags & EV_DISPATCH) src->kev.fflags &= ~NOTE_TRIGGER; return (0); @@ -90,7 +90,7 @@ posix_evfilt_user_knote_create(struct filter *filt, struct knote *kn) } int -posix_evfilt_user_knote_modify(struct filter *filt, struct knote *kn, +posix_evfilt_user_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { unsigned int ffctrl; @@ -160,7 +160,7 @@ const struct filter evfilt_user = { evfilt_user_knote_modify, evfilt_user_knote_delete, evfilt_user_knote_enable, - evfilt_user_knote_disable, + evfilt_user_knote_disable, }; */ diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index e94562a99..6f2864ac3 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -114,7 +114,7 @@ solaris_kqueue_free(struct kqueue *kq) int solaris_kevent_wait( - struct kqueue *kq, + struct kqueue *kq, int nevents UNUSED, const struct timespec *ts) @@ -166,14 +166,14 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, /* For sockets, the event port object must be reassociated after each event is retrieved. */ - if (rv == 0 && !(kn->kev.flags & EV_DISPATCH + if (rv == 0 && !(kn->kev.flags & EV_DISPATCH || kn->kev.flags & EV_ONESHOT)) { rv = filt->kn_create(filt, kn); } - + if (eventlist->data == 0) // if zero data is returned, we raced with a read of data from the socket, skip event to have proper semantics skip_event = 1; - + break; case PORT_SOURCE_TIMER: @@ -211,9 +211,9 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, * Certain flags cause the associated knote to be deleted * or disabled. */ - if (eventlist->flags & EV_DISPATCH) + if (eventlist->flags & EV_DISPATCH) knote_disable(filt, kn); //TODO: Error checking - if (eventlist->flags & EV_ONESHOT) + if (eventlist->flags & EV_ONESHOT) { knote_delete(filt, kn); //TODO: Error checking } diff --git a/vendor/libkqueue/src/solaris/signal.c b/vendor/libkqueue/src/solaris/signal.c index e973e842f..cd52e44a0 100644 --- a/vendor/libkqueue/src/solaris/signal.c +++ b/vendor/libkqueue/src/solaris/signal.c @@ -32,13 +32,13 @@ static void signal_handler(int sig) { struct sentry *s; - + if (sig < 0 || sig >= SIGNAL_MAX) // 0..31 are valid - { + { dbg_printf("Received unexpected signal %d", sig); return; } - + s = &sigtbl[sig]; dbg_printf("sig=%d %d", sig, s->st_signum); atomic_inc((volatile uint32_t *) &s->st_count); @@ -51,7 +51,7 @@ catch_signal(struct filter *filt, struct knote *kn) { int sig; struct sigaction sa; - + sig = kn->kev.ident; memset(&sa, 0, sizeof(sa)); sa.sa_handler = signal_handler; @@ -79,7 +79,7 @@ static int ignore_signal(int sig) { struct sigaction sa; - + memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_IGN; sigemptyset(&sa.sa_mask); @@ -97,7 +97,7 @@ int evfilt_signal_knote_create(struct filter *filt, struct knote *kn) { if (kn->kev.ident >= SIGNAL_MAX) { - dbg_printf("unsupported signal number %u", + dbg_printf("unsupported signal number %u", (unsigned int) kn->kev.ident); return (-1); } @@ -108,7 +108,7 @@ evfilt_signal_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_signal_knote_modify(struct filter *filt UNUSED, struct knote *kn, +evfilt_signal_knote_modify(struct filter *filt UNUSED, struct knote *kn, const struct kevent *kev) { kn->kev.flags = kev->flags | EV_CLEAR; @@ -117,7 +117,7 @@ evfilt_signal_knote_modify(struct filter *filt UNUSED, struct knote *kn, int evfilt_signal_knote_delete(struct filter *filt UNUSED, struct knote *kn) -{ +{ return ignore_signal(kn->kev.ident); } @@ -144,12 +144,12 @@ evfilt_signal_copyout(struct kevent *dst, struct knote *src, void *ptr) dst->ident = ent->st_kev.ident; dst->filter = EVFILT_SIGNAL; dst->udata = ent->st_kev.udata; - dst->flags = ent->st_kev.flags; + dst->flags = ent->st_kev.flags; dst->fflags = 0; dst->data = 1; pthread_mutex_unlock(&sigtbl_mtx); - if (src->kev.flags & EV_DISPATCH || src->kev.flags & EV_ONESHOT) + if (src->kev.flags & EV_DISPATCH || src->kev.flags & EV_ONESHOT) ignore_signal(src->kev.ident); return (1); @@ -164,5 +164,5 @@ const struct filter evfilt_signal = { evfilt_signal_knote_modify, evfilt_signal_knote_delete, evfilt_signal_knote_enable, - evfilt_signal_knote_disable, + evfilt_signal_knote_disable, }; diff --git a/vendor/libkqueue/src/solaris/socket.c b/vendor/libkqueue/src/solaris/socket.c index 83f8f4b40..e04a707c0 100644 --- a/vendor/libkqueue/src/solaris/socket.c +++ b/vendor/libkqueue/src/solaris/socket.c @@ -47,10 +47,10 @@ evfilt_socket_knote_create(struct filter *filt, struct knote *kn) dbg_puts("invalid filter"); return (-1); } - + dbg_printf("port_associate kq fd %d with actual fd %ld", filter_epfd(filt), kn->kev.ident); - rv = port_associate(filter_epfd(filt), PORT_SOURCE_FD, kn->kev.ident, + rv = port_associate(filter_epfd(filt), PORT_SOURCE_FD, kn->kev.ident, events, kn); if (rv < 0) { dbg_perror("port_associate(2)"); @@ -61,7 +61,7 @@ evfilt_socket_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_socket_knote_modify(struct filter *filt, struct knote *kn, +evfilt_socket_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { dbg_puts("XXX-FIXME"); @@ -106,7 +106,7 @@ evfilt_socket_copyout(struct kevent *dst, struct knote *src, void *ptr) { port_event_t *pe = (port_event_t *) ptr; unsigned int pending_data = 0; - + memcpy(dst, &src->kev, sizeof(*dst)); if (pe->portev_events == 8) //XXX-FIXME Should be POLLHUP) dst->flags |= EV_EOF; @@ -123,12 +123,12 @@ evfilt_socket_copyout(struct kevent *dst, struct knote *src, void *ptr) /* race condition with socket close, so ignore this error */ dbg_puts("ioctl(2) of socket failed"); dst->data = 0; - } + } else dst->data = pending_data; } - - /* FIXME: make sure this is in kqops.copyout() + + /* FIXME: make sure this is in kqops.copyout() if (src->kev.flags & EV_DISPATCH || src->kev.flags & EV_ONESHOT) { socket_knote_delete(filt->kf_kqueue->kq_port, kn->kev.ident); } @@ -146,7 +146,7 @@ const struct filter evfilt_read = { evfilt_socket_knote_modify, evfilt_socket_knote_delete, evfilt_socket_knote_enable, - evfilt_socket_knote_disable, + evfilt_socket_knote_disable, }; const struct filter evfilt_write = { @@ -158,5 +158,5 @@ const struct filter evfilt_write = { evfilt_socket_knote_modify, evfilt_socket_knote_delete, evfilt_socket_knote_enable, - evfilt_socket_knote_disable, + evfilt_socket_knote_disable, }; diff --git a/vendor/libkqueue/src/solaris/timer.c b/vendor/libkqueue/src/solaris/timer.c index e0895bfe3..9d0b5acfc 100644 --- a/vendor/libkqueue/src/solaris/timer.c +++ b/vendor/libkqueue/src/solaris/timer.c @@ -94,11 +94,11 @@ evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) //if (ev->events & EPOLLERR) // dst->fflags = 1; /* FIXME: Return the actual timer error */ - dst->data = timer_getoverrun(src->data.timerid) + 1; + dst->data = timer_getoverrun(src->data.timerid) + 1; #if FIXME timerid = src->data.timerid; - //should be done in kqops.copyout() + //should be done in kqops.copyout() if (src->kev.flags & EV_DISPATCH) { timer_delete(src->data.timerid); } else if (src->kev.flags & EV_ONESHOT) { @@ -126,10 +126,10 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) se.sigev_value.sival_ptr = &pn; if (timer_create (CLOCK_MONOTONIC, &se, &timerid) < 0) { - dbg_perror("timer_create(2)"); + dbg_perror("timer_create(2)"); return (-1); } - + convert_msec_to_itimerspec(&ts, kn->kev.data, kn->kev.flags & EV_ONESHOT); if (timer_settime(timerid, 0, &ts, NULL) < 0) { dbg_perror("timer_settime(2)"); @@ -144,7 +144,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_timer_knote_modify(struct filter *filt, struct knote *kn, +evfilt_timer_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { (void)filt; @@ -184,5 +184,5 @@ const struct filter evfilt_timer = { evfilt_timer_knote_modify, evfilt_timer_knote_delete, evfilt_timer_knote_enable, - evfilt_timer_knote_disable, + evfilt_timer_knote_disable, }; diff --git a/vendor/libkqueue/src/solaris/user.c b/vendor/libkqueue/src/solaris/user.c index c3ee163dd..03dac44c4 100644 --- a/vendor/libkqueue/src/solaris/user.c +++ b/vendor/libkqueue/src/solaris/user.c @@ -20,7 +20,7 @@ int evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) { //port_event_t *pe = (port_event_t *) ptr; - + memcpy(dst, &src->kev, sizeof(*dst)); dst->fflags &= ~NOTE_FFCTRLMASK; //FIXME: Not sure if needed dst->fflags &= ~NOTE_TRIGGER; @@ -65,7 +65,7 @@ evfilt_user_knote_create(struct filter *filt UNUSED, struct knote *kn UNUSED) } int -evfilt_user_knote_modify(struct filter *filt, struct knote *kn, +evfilt_user_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { unsigned int ffctrl; @@ -97,7 +97,7 @@ evfilt_user_knote_modify(struct filter *filt, struct knote *kn, if ((!(kn->kev.flags & EV_DISABLE)) && kev->fflags & NOTE_TRIGGER) { kn->kev.fflags |= NOTE_TRIGGER; - return (port_send(filter_epfd(filt), X_PORT_SOURCE_USER, kn)); + return (port_send(filter_epfd(filt), X_PORT_SOURCE_USER, kn)); } return (0); @@ -132,5 +132,5 @@ const struct filter evfilt_user = { evfilt_user_knote_modify, evfilt_user_knote_delete, evfilt_user_knote_enable, - evfilt_user_knote_disable, + evfilt_user_knote_disable, }; diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 78dda4ba3..caeba114f 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -33,7 +33,7 @@ #include #include #include - + #define _CRT_SECURE_NO_WARNINGS 1 /* The #define doesn't seem to work, but the #pragma does.. */ #ifdef _MSC_VER @@ -44,7 +44,7 @@ /* - * Atomic integer operations + * Atomic integer operations */ #define atomic_inc(value) InterlockedIncrement((LONG volatile *)value) #define atomic_dec(value) InterlockedDecrement((LONG volatile *)value) @@ -105,7 +105,7 @@ int windows_get_descriptor_type(struct knote *); /* Function visibility macros */ #define VISIBLE __declspec(dllexport) -#define HIDDEN +#define HIDDEN #if !defined(__func__) && !defined(__GNUC__) #define __func__ __FUNCDNAME__ diff --git a/vendor/libkqueue/src/windows/read.c b/vendor/libkqueue/src/windows/read.c index 07b19c12f..95a0c27fc 100644 --- a/vendor/libkqueue/src/windows/read.c +++ b/vendor/libkqueue/src/windows/read.c @@ -30,7 +30,7 @@ evfilt_read_callback(void *param, BOOLEAN fired) dbg_puts("called, but event was not triggered(?)"); return; } - + assert(param); kn = (struct knote*)param; // FIXME: check if knote is pending destroyed @@ -39,7 +39,7 @@ evfilt_read_callback(void *param, BOOLEAN fired) /* Retrieve the socket events and update the knote */ rv = WSAEnumNetworkEvents( - (SOCKET) kn->kev.ident, + (SOCKET) kn->kev.ident, kn->data.handle, &events); if (rv != 0) { @@ -47,7 +47,7 @@ evfilt_read_callback(void *param, BOOLEAN fired) return; //fIXME: should crash or invalidate the knote } /* FIXME: check for errors somehow.. - if (events.lNetworkEvents & FD_ACCEPT) + if (events.lNetworkEvents & FD_ACCEPT) kn->kev.flags |= EV */ @@ -58,7 +58,7 @@ evfilt_read_callback(void *param, BOOLEAN fired) /* FIXME: need more extreme action */ } - /* DEADWOOD + /* DEADWOOD kn = (struct knote *) param; evt_signal(kn->kn_kq->kq_loop, EVT_WAKEUP, kn); */ @@ -93,10 +93,10 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) //struct event_buf * const ev = (struct event_buf *) ptr; - /* TODO: handle regular files + /* TODO: handle regular files if (src->flags & KNFL_FILE) { ... } */ - memcpy(dst, &src->kev, sizeof(*dst)); + memcpy(dst, &src->kev, sizeof(*dst)); if (src->kn_flags & KNFL_PASSIVE_SOCKET) { /* TODO: should contains the length of the socket backlog */ dst->data = 1; @@ -131,15 +131,15 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) } rv = WSAEventSelect( - (SOCKET) kn->kev.ident, - evt, + (SOCKET) kn->kev.ident, + evt, FD_READ | FD_ACCEPT | FD_CLOSE); if (rv != 0) { dbg_wsalasterror("WSAEventSelect()"); CloseHandle(evt); return (-1); } - + /* TODO: handle regular files in addition to sockets */ /* TODO: handle in copyout @@ -151,7 +151,7 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) kn->data.handle = evt; - if (RegisterWaitForSingleObject(&kn->kn_event_whandle, evt, + if (RegisterWaitForSingleObject(&kn->kn_event_whandle, evt, evfilt_read_callback, kn, INFINITE, 0) == 0) { dbg_puts("RegisterWaitForSingleObject failed"); CloseHandle(evt); @@ -162,7 +162,7 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_read_knote_modify(struct filter *filt, struct knote *kn, +evfilt_read_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { return (-1); /* STUB */ @@ -208,5 +208,5 @@ const struct filter evfilt_read = { evfilt_read_knote_modify, evfilt_read_knote_delete, evfilt_read_knote_enable, - evfilt_read_knote_disable, + evfilt_read_knote_disable, }; diff --git a/vendor/libkqueue/src/windows/stdint.h b/vendor/libkqueue/src/windows/stdint.h index d02608a59..c66fbb817 100644 --- a/vendor/libkqueue/src/windows/stdint.h +++ b/vendor/libkqueue/src/windows/stdint.h @@ -1,32 +1,32 @@ // ISO C9x compliant stdint.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// // Copyright (c) 2006-2008 Alexander Chemeris -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: -// +// // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. -// +// // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. -// +// // 3. The name of the author may be used to endorse or promote products // derived from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +// /////////////////////////////////////////////////////////////////////////////// #ifndef _MSC_VER // [ diff --git a/vendor/libkqueue/src/windows/timer.c b/vendor/libkqueue/src/windows/timer.c index e0abfcb21..5d84a1d73 100644 --- a/vendor/libkqueue/src/windows/timer.c +++ b/vendor/libkqueue/src/windows/timer.c @@ -103,7 +103,7 @@ evfilt_timer_copyout(struct kevent* dst, struct knote* src, void* ptr) { memcpy(dst, &src->kev, sizeof(struct kevent)); // TODO: Timer error handling - + /* We have no way to determine the number of times the timer triggered, thus we assume it was only once */ @@ -128,7 +128,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) dbg_printf("created timer handle %p", th); convert_msec_to_filetime(&liDueTime, kn->kev.data); - + // XXX-FIXME add completion routine to this call if (!SetWaitableTimer(th, &liDueTime, (LONG)( (kn->kev.flags & EV_ONESHOT) ? 0 : kn->kev.data ), NULL, NULL, FALSE)) { dbg_lasterror("SetWaitableTimer()"); @@ -144,7 +144,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_timer_knote_modify(struct filter *filt, struct knote *kn, +evfilt_timer_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { return (0); /* STUB */ @@ -177,5 +177,5 @@ const struct filter evfilt_timer = { evfilt_timer_knote_modify, evfilt_timer_knote_delete, evfilt_timer_knote_enable, - evfilt_timer_knote_disable, + evfilt_timer_knote_disable, }; diff --git a/vendor/libkqueue/src/windows/user.c b/vendor/libkqueue/src/windows/user.c index bdbc1bf34..fa0b3d481 100644 --- a/vendor/libkqueue/src/windows/user.c +++ b/vendor/libkqueue/src/windows/user.c @@ -31,7 +31,7 @@ int evfilt_user_copyout(struct kevent* dst, struct knote* src, void* ptr) { memcpy(dst, &src->kev, sizeof(struct kevent)); - + dst->fflags &= ~NOTE_FFCTRLMASK; //FIXME: Not sure if needed dst->fflags &= ~NOTE_TRIGGER; if (src->kev.flags & EV_ADD) { @@ -55,7 +55,7 @@ evfilt_user_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_user_knote_modify(struct filter *filt, struct knote *kn, +evfilt_user_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { unsigned int ffctrl; @@ -123,5 +123,5 @@ const struct filter evfilt_user = { evfilt_user_knote_modify, evfilt_user_knote_delete, evfilt_user_knote_enable, - evfilt_user_knote_disable, -}; \ No newline at end of file + evfilt_user_knote_disable, +}; diff --git a/vendor/libkqueue/test/benchmark/abtest b/vendor/libkqueue/test/benchmark/abtest index 7e6e00da3..5c189a0af 100755 --- a/vendor/libkqueue/test/benchmark/abtest +++ b/vendor/libkqueue/test/benchmark/abtest @@ -17,14 +17,14 @@ sub create_client { PeerAddr => '127.0.0.1', PeerPort => 8080, Proto => 'tcp', - ) + ) or die $!; push @CLIENT, $socket; } GetOptions("baseline" => \$BASELINE, "idle=i" => \$NCLIENT) or die; -for (my $i = 0; $i < $NCLIENT; $i++) { +for (my $i = 0; $i < $NCLIENT; $i++) { create_client(); } print "====> Created $NCLIENT idle connections <=====\n"; diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 29fb5a0bb..9922163a0 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -105,7 +105,7 @@ void kevent_update(int kqfd, struct kevent *kev); void _kevent_cmp(struct kevent *, struct kevent *, const char *, int); void -kevent_add(int kqfd, struct kevent *kev, +kevent_add(int kqfd, struct kevent *kev, uintptr_t ident, short filter, u_short flags, diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index e74f9ba2e..418b0ce81 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -19,7 +19,7 @@ extern int kqfd; /* Checks if any events are pending, which is an error. */ -void +void _test_no_kevents(int kqfd, const char *file, int line) { int nfds; @@ -142,7 +142,7 @@ kevent_to_str(struct kevent *kev) { char buf[512]; - snprintf(&buf[0], sizeof(buf), + snprintf(&buf[0], sizeof(buf), "[ident=%d, filter=%d, %s, %s, data=%d, udata=%p]", (u_int) kev->ident, kev->filter, @@ -165,7 +165,7 @@ kevent_update(int kqfd, struct kevent *kev) } void -kevent_add(int kqfd, struct kevent *kev, +kevent_add(int kqfd, struct kevent *kev, uintptr_t ident, short filter, u_short flags, @@ -173,7 +173,7 @@ kevent_add(int kqfd, struct kevent *kev, intptr_t data, void *udata) { - EV_SET(kev, ident, filter, flags, fflags, data, NULL); + EV_SET(kev, ident, filter, flags, fflags, data, NULL); if (kevent(kqfd, kev, 1, NULL, 0, NULL) < 0) { printf("Unable to add the following kevent:\n%s\n", kevent_to_str(kev)); @@ -185,14 +185,14 @@ void _kevent_cmp(struct kevent *k1, struct kevent *k2, const char *file, int line) { /* XXX- - Workaround for inconsistent implementation of kevent(2) + Workaround for inconsistent implementation of kevent(2) */ -#if defined (__FreeBSD_kernel__) || defined (__FreeBSD__) +#if defined (__FreeBSD_kernel__) || defined (__FreeBSD__) if (k1->flags & EV_ADD) k2->flags |= EV_ADD; #endif if (memcmp(k1, k2, sizeof(*k1)) != 0) { - printf("[%s:%d]: kevent_cmp() failed:\n expected %s\n but got %s\n", + printf("[%s:%d]: kevent_cmp() failed:\n expected %s\n but got %s\n", file, line, kevent_to_str(k1), kevent_to_str(k2)); abort(); } diff --git a/vendor/libkqueue/test/libdispatch/Makefile b/vendor/libkqueue/test/libdispatch/Makefile index f90b66eff..d66e36528 100644 --- a/vendor/libkqueue/test/libdispatch/Makefile +++ b/vendor/libkqueue/test/libdispatch/Makefile @@ -13,4 +13,4 @@ clean: rm -f *.o distclean: clean - rm -f disptest + rm -f disptest diff --git a/vendor/libkqueue/test/libdispatch/main.c b/vendor/libkqueue/test/libdispatch/main.c index 3f5fa167f..8904feb36 100644 --- a/vendor/libkqueue/test/libdispatch/main.c +++ b/vendor/libkqueue/test/libdispatch/main.c @@ -18,9 +18,9 @@ #include #include -#include -#include -#include +#include +#include +#include pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; int testnum; @@ -61,7 +61,7 @@ test_timer() dispatch_source_t timer; dispatch_time_t now; - timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, + timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_current_queue()); //NOTE: q_default doesn't work now = dispatch_walltime(DISPATCH_TIME_NOW, 0); dispatch_source_set_timer(timer, now, 1, 1); @@ -78,7 +78,7 @@ test_countdown(void) } -int +int main(int argc, char **argv) { while (argc) { diff --git a/vendor/libkqueue/test/lockstat.c b/vendor/libkqueue/test/lockstat.c index e08e67a50..0a5260c2e 100644 --- a/vendor/libkqueue/test/lockstat.c +++ b/vendor/libkqueue/test/lockstat.c @@ -47,7 +47,7 @@ int main() { struct foo x; pthread_t tid; void *rv; - + tracing_mutex_init(&x.foo_lock, NULL); tracing_mutex_lock(&x.foo_lock); tracing_mutex_assert(&x.foo_lock, MTX_LOCKED); diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index cb93dbe35..46f6efd38 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -23,7 +23,7 @@ */ static void create_socket_connection(int *client, int *server) -{ +{ struct sockaddr_in sain; socklen_t sa_len = sizeof(sain); int one = 1; @@ -34,10 +34,10 @@ create_socket_connection(int *client, int *server) memset(&sain, 0, sizeof(sain)); sain.sin_family = AF_INET; sain.sin_port = 0; - if ((srvr = socket(PF_INET, SOCK_STREAM, 0)) < 0) + if ((srvr = socket(PF_INET, SOCK_STREAM, 0)) < 0) err(1, "socket"); - if (setsockopt(srvr, SOL_SOCKET, SO_REUSEADDR, - (char *) &one, sizeof(one)) != 0) + if (setsockopt(srvr, SOL_SOCKET, SO_REUSEADDR, + (char *) &one, sizeof(one)) != 0) err(1, "setsockopt"); if (bind(srvr, (struct sockaddr *) &sain, sa_len) < 0) { printf("unable to bind to auto-assigned port\n"); @@ -54,11 +54,11 @@ create_socket_connection(int *client, int *server) sain.sin_port = htons(port); sain.sin_addr.s_addr = inet_addr("127.0.0.1"); if ((clnt = socket(AF_INET, SOCK_STREAM, 0)) < 0) - err(1, "clnt: socket"); + err(1, "clnt: socket"); if (connect(clnt, (struct sockaddr *) &sain, sa_len) < 0) - err(1, "clnt: connect"); + err(1, "clnt: connect"); if ((accepted = accept(srvr, NULL, 0)) < 0) - err(1, "srvr: accept"); + err(1, "srvr: accept"); *client = clnt; *server = accepted; @@ -155,7 +155,7 @@ test_kevent_socket_clear(struct test_context *ctx) kev.data = 2; #endif kevent_get(&ret, ctx->kqfd); - kevent_cmp(&kev, &ret); + kevent_cmp(&kev, &ret); /* We filled twice, but drain once. Edge-triggered would not generate additional events. @@ -192,7 +192,7 @@ test_kevent_socket_disable_and_enable(struct test_context *ctx) kev.flags = EV_ADD; kev.data = 1; kevent_get(&ret, ctx->kqfd); - kevent_cmp(&kev, &ret); + kevent_cmp(&kev, &ret); kevent_socket_drain(ctx); @@ -227,7 +227,7 @@ test_kevent_socket_oneshot(struct test_context *ctx) kevent_socket_fill(ctx); kev.data = 1; kevent_get(&ret, ctx->kqfd); - kevent_cmp(&kev, &ret); + kevent_cmp(&kev, &ret); test_no_kevents(ctx->kqfd); @@ -260,9 +260,9 @@ test_kevent_socket_listen_backlog(struct test_context *ctx) memset(&sain, 0, sizeof(sain)); sain.sin_family = AF_INET; sain.sin_port = 0; - if ((srvr = socket(PF_INET, SOCK_STREAM, 0)) < 0) + if ((srvr = socket(PF_INET, SOCK_STREAM, 0)) < 0) err(1, "socket()"); - if (setsockopt(srvr, SOL_SOCKET, SO_REUSEADDR, + if (setsockopt(srvr, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one)) != 0) err(1, "setsockopt()"); if (bind(srvr, (struct sockaddr *) &sain, sa_len) < 0) @@ -290,7 +290,7 @@ test_kevent_socket_listen_backlog(struct test_context *ctx) /* Verify that data=1 */ kev.data = 1; kevent_get(&ret, ctx->kqfd); - kevent_cmp(&kev, &ret); + kevent_cmp(&kev, &ret); test_no_kevents(ctx->kqfd); } @@ -309,7 +309,7 @@ test_kevent_socket_dispatch(struct test_context *ctx) kevent_socket_fill(ctx); kev.data = 1; kevent_get(&ret, ctx->kqfd); - kevent_cmp(&kev, &ret); + kevent_cmp(&kev, &ret); test_no_kevents(ctx->kqfd); /* Re-enable the kevent */ @@ -318,7 +318,7 @@ test_kevent_socket_dispatch(struct test_context *ctx) kev.data = 1; kev.flags = EV_ADD | EV_DISPATCH; /* FIXME: may not be portable */ kevent_get(&ret, ctx->kqfd); - kevent_cmp(&kev, &ret); + kevent_cmp(&kev, &ret); test_no_kevents(ctx->kqfd); /* Since the knote is disabled, the EV_DELETE operation succeeds. */ @@ -375,7 +375,7 @@ test_kevent_socket_eof(struct test_context *ctx) kev.flags |= EV_EOF; kevent_get(&ret, ctx->kqfd); - kevent_cmp(&kev, &ret); + kevent_cmp(&kev, &ret); /* Delete the watch */ kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_DELETE, 0, 0, &ctx->client_fd); @@ -402,7 +402,7 @@ test_kevent_regular_file(struct test_context *ctx) /* Set file position to EOF-1 */ ret.data--; if ((curpos = lseek(fd, ret.data, SEEK_SET)) != ret.data) { - printf("seek to %u failed with rv=%lu\n", + printf("seek to %u failed with rv=%lu\n", (unsigned int) ret.data, (unsigned long) curpos); abort(); } diff --git a/vendor/libkqueue/test/signal.c b/vendor/libkqueue/test/signal.c index 23a0edb63..f27e95194 100644 --- a/vendor/libkqueue/test/signal.c +++ b/vendor/libkqueue/test/signal.c @@ -29,7 +29,7 @@ test_kevent_signal_get(struct test_context *ctx) { struct kevent kev, ret; - kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); if (kill(getpid(), SIGUSR1) < 0) die("kill"); @@ -82,7 +82,7 @@ void test_kevent_signal_del(struct test_context *ctx) { struct kevent kev; - + /* Delete the kevent */ kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL); diff --git a/vendor/libkqueue/test/stress/Makefile b/vendor/libkqueue/test/stress/Makefile index 72efd08f0..e22484d0a 100644 --- a/vendor/libkqueue/test/stress/Makefile +++ b/vendor/libkqueue/test/stress/Makefile @@ -26,4 +26,4 @@ edit: $(EDITOR) $(SOURCES) distclean: clean - rm -f $(PROGRAM) + rm -f $(PROGRAM) diff --git a/vendor/libkqueue/test/stress/main.c b/vendor/libkqueue/test/stress/main.c index e0baeccc9..2e1617194 100644 --- a/vendor/libkqueue/test/stress/main.c +++ b/vendor/libkqueue/test/stress/main.c @@ -21,8 +21,8 @@ #include #include -#include -#include +#include +#include /* Number of threads to create */ static const int nthreads = 64; @@ -75,7 +75,7 @@ test_harness(void *arg) printf("thread %d done\n", id); } -int +int main(int argc, char **argv) { pthread_t tid[nthreads]; diff --git a/vendor/libkqueue/test/test.c b/vendor/libkqueue/test/test.c index 7882ee29c..242f3afef 100644 --- a/vendor/libkqueue/test/test.c +++ b/vendor/libkqueue/test/test.c @@ -108,6 +108,6 @@ testing_make_uid(void) if (id == INT_MAX) abort(); id++; - + return (id); } diff --git a/vendor/libkqueue/test/timer.c b/vendor/libkqueue/test/timer.c index e838a00e4..24db7c0a2 100644 --- a/vendor/libkqueue/test/timer.c +++ b/vendor/libkqueue/test/timer.c @@ -42,7 +42,7 @@ test_kevent_timer_get(struct test_context *ctx) kevent_add(ctx->kqfd, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL); kev.flags |= EV_CLEAR; - kev.data = 1; + kev.data = 1; kevent_get(&ret, ctx->kqfd); kevent_cmp(&kev, &ret); @@ -60,7 +60,7 @@ test_kevent_timer_oneshot(struct test_context *ctx) /* Retrieve the event */ kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT; - kev.data = 1; + kev.data = 1; kevent_get(&ret, ctx->kqfd); kevent_cmp(&kev, &ret); @@ -80,7 +80,7 @@ test_kevent_timer_periodic(struct test_context *ctx) /* Retrieve the event */ kev.flags = EV_ADD | EV_CLEAR; - kev.data = 1; + kev.data = 1; kevent_get(&ret, ctx->kqfd); kevent_cmp(&kev, &ret); @@ -112,7 +112,7 @@ test_kevent_timer_disable_and_enable(struct test_context *ctx) kevent_update(ctx->kqfd, &kev); kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT; - kev.data = 1; + kev.data = 1; kevent_get(&ret, ctx->kqfd); kevent_cmp(&kev, &ret); } @@ -129,7 +129,7 @@ test_kevent_timer_dispatch(struct test_context *ctx) /* Get one event */ kev.flags = EV_ADD | EV_CLEAR | EV_DISPATCH; - kev.data = 1; + kev.data = 1; kevent_get(&ret, ctx->kqfd); kevent_cmp(&kev, &ret); @@ -144,7 +144,7 @@ test_kevent_timer_dispatch(struct test_context *ctx) /* Get the next event */ sleep(1); kev.flags = EV_ADD | EV_CLEAR | EV_DISPATCH; - kev.data = 1; + kev.data = 1; kevent_get(&ret, ctx->kqfd); kevent_cmp(&kev, &ret); diff --git a/vendor/libkqueue/test/user.c b/vendor/libkqueue/test/user.c index 2f35cdcff..29ec077ae 100644 --- a/vendor/libkqueue/test/user.c +++ b/vendor/libkqueue/test/user.c @@ -36,8 +36,8 @@ test_kevent_user_get(struct test_context *ctx) test_no_kevents(ctx->kqfd); /* Add the event, and then trigger it */ - kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, NULL); - kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; @@ -56,8 +56,8 @@ test_kevent_user_get_hires(struct test_context *ctx) test_no_kevents(ctx->kqfd); /* Add the event, and then trigger it */ - kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, NULL); - kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; @@ -75,15 +75,15 @@ test_kevent_user_disable_and_enable(struct test_context *ctx) test_no_kevents(ctx->kqfd); - kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL); - kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_DISABLE, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_DISABLE, 0, 0, NULL); /* Trigger the event, but since it is disabled, nothing will happen. */ - kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); test_no_kevents(ctx->kqfd); - kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ENABLE, 0, 0, NULL); - kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ENABLE, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); kev.flags = EV_CLEAR; kev.fflags &= ~NOTE_FFCTRLMASK; @@ -100,7 +100,7 @@ test_kevent_user_oneshot(struct test_context *ctx) test_no_kevents(ctx->kqfd); kevent_add(ctx->kqfd, &kev, 2, EVFILT_USER, EV_ADD | EV_ONESHOT, 0, 0, NULL); - kevent_add(ctx->kqfd, &kev, 2, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + kevent_add(ctx->kqfd, &kev, 2, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); kev.flags = EV_ONESHOT; kev.fflags &= ~NOTE_FFCTRLMASK; diff --git a/vendor/libkqueue/test/vnode.c b/vendor/libkqueue/test/vnode.c index d4de569ff..222ee3df3 100644 --- a/vendor/libkqueue/test/vnode.c +++ b/vendor/libkqueue/test/vnode.c @@ -34,7 +34,7 @@ testfile_touch(const char *path) snprintf(&buf[0], sizeof(buf), "touch %s", path); if (system(buf) != 0) - die("system"); + die("system"); } static void @@ -44,7 +44,7 @@ testfile_write(const char *path) snprintf(&buf[0], sizeof(buf), "echo hi >> %s", path); if (system(buf) != 0) - die("system"); + die("system"); } static void @@ -60,10 +60,10 @@ testfile_rename(const char *path, int step) */ if (step == 0) { if (rename(path, buf) != 0) - err(1,"rename"); + err(1,"rename"); } else { if (rename(buf, path) != 0) - err(1,"rename"); + err(1,"rename"); } } @@ -78,7 +78,7 @@ test_kevent_vnode_add(struct test_context *ctx) if (ctx->vnode_fd < 0) err(1, "open of %s", ctx->testfile); - kevent_add(ctx->kqfd, &kev, ctx->vnode_fd, EVFILT_VNODE, EV_ADD, + kevent_add(ctx->kqfd, &kev, ctx->vnode_fd, EVFILT_VNODE, EV_ADD, NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME | NOTE_DELETE, 0, NULL); } @@ -127,9 +127,9 @@ test_kevent_vnode_note_attrib(struct test_context *ctx) if (nfds < 1) die("kevent"); if (kev.ident != ctx->vnode_fd || - kev.filter != EVFILT_VNODE || + kev.filter != EVFILT_VNODE || kev.fflags != NOTE_ATTRIB) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", test_id, (unsigned int)kev.ident, kev.filter, kev.flags); } @@ -147,9 +147,9 @@ test_kevent_vnode_note_rename(struct test_context *ctx) if (nfds < 1) die("kevent"); if (kev.ident != ctx->vnode_fd || - kev.filter != EVFILT_VNODE || + kev.filter != EVFILT_VNODE || kev.fflags != NOTE_RENAME) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", test_id, (unsigned int)kev.ident, kev.filter, kev.flags); testfile_rename(ctx->testfile, 1); @@ -190,9 +190,9 @@ test_kevent_vnode_disable_and_enable(struct test_context *ctx) if (nfds < 1) die("kevent"); if (kev.ident != ctx->vnode_fd || - kev.filter != EVFILT_VNODE || + kev.filter != EVFILT_VNODE || kev.fflags != NOTE_ATTRIB) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", test_id, (unsigned int)kev.ident, kev.filter, kev.flags); } @@ -213,9 +213,9 @@ test_kevent_vnode_dispatch(struct test_context *ctx) if (nfds < 1) die("kevent"); if (kev.ident != ctx->vnode_fd || - kev.filter != EVFILT_VNODE || + kev.filter != EVFILT_VNODE || kev.fflags != NOTE_ATTRIB) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", + err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", test_id, (unsigned int)kev.ident, kev.filter, kev.flags); /* Confirm that the watch is disabled automatically */ From 8bd34e87e32d9f09bd84b5bd7d3529a69972a53e Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 22 Feb 2019 16:23:19 +0800 Subject: [PATCH 0681/1120] Fix spurious debug message in knote_release. The real issue is that kn_create failed --- vendor/libkqueue/src/common/kevent.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 768b93a35..eb2483cc6 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -147,7 +147,11 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) kn->kn_kq = kq; assert(filt->kn_create); if (filt->kn_create(filt, kn) < 0) { + dbg_puts("kn_create failed"); + + kn->kn_flags |= KNFL_KNOTE_DELETED; knote_release(kn); + errno = EFAULT; return (-1); } From f8a94830195c7866e242167d2e31b021237917a1 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 22 Feb 2019 20:00:44 +0800 Subject: [PATCH 0682/1120] The default CMAKE_INSTALL_PREFIX is /share, set it to /usr on Linux --- vendor/libkqueue/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 992c8a37f..a385ac011 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -91,6 +91,12 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") src/solaris/timer.c src/solaris/user.c) elseif(CMAKE_SYSTEM_NAME STREQUAL Linux) + # + # Set the default prefix to something sane + # + if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set (CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "default install path" FORCE ) + endif() list(APPEND LIBKQUEUE_SOURCES src/posix/platform.c src/posix/platform.h From 2b04328b9bc7afad5e5999ec8c0800748632f7b5 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 22 Feb 2019 20:01:17 +0800 Subject: [PATCH 0683/1120] Set .so version to maintain compatibility with existing libkqueue packages --- vendor/libkqueue/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index a385ac011..447159c7a 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -127,6 +127,7 @@ endif() add_library(kqueue ${LIBRARY_TYPE} ${LIBKQUEUE_SOURCES} ${LIBKQUEUE_HEADERS}) set_target_properties(kqueue PROPERTIES DEBUG_POSTFIX "d") +set_target_properties(kqueue PROPERTIES SOVERSION 0) if(WIN32) target_compile_definitions(kqueue PRIVATE _USRDLL;_WINDLL) From 6f47abd700d8004fb0eb193f62a06228cdb65835 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 22 Feb 2019 20:02:04 +0800 Subject: [PATCH 0684/1120] Automatically append '64' to the library dir if we're building 64 bit libraries on linux --- vendor/libkqueue/CMakeLists.txt | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 447159c7a..9d4f21872 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -97,6 +97,16 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL Linux) if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set (CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "default install path" FORCE ) endif() + + # + # Set library directory correctly if we're building 64bit libraries + # + get_property(LIB64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS) + if ("${LIB64}" STREQUAL "TRUE") + set(LIB_SUFFIX 64) + else() + set(LIB_SUFFIX "") + endif() list(APPEND LIBKQUEUE_SOURCES src/posix/platform.c src/posix/platform.h @@ -166,7 +176,8 @@ configure_file("${CMAKE_SOURCE_DIR}/libkqueue.pc.in" # set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION ${CMAKE_INSTALL_FULL_MANDIR} ${CMAKE_INSTALL_FULL_MANDIR}/man2 - ${CMAKE_INSTALL_FULL_INCLUDEDIR}/sys) + ${CMAKE_INSTALL_FULL_INCLUDEDIR}/sys + ${CMAKE_INSTALL_FULL_LIBDIR}${LIB_SUFFIX}/pkgconfig) install(FILES "include/sys/event.h" @@ -176,7 +187,7 @@ install(FILES install(TARGETS kqueue DESTINATION - "${CMAKE_INSTALL_FULL_LIBDIR}" + "${CMAKE_INSTALL_FULL_LIBDIR}${LIB_SUFFIX}" COMPONENT libraries) install(FILES kqueue.2 @@ -186,7 +197,7 @@ install(FILES install(FILES "${CMAKE_BINARY_DIR}/libkqueue.pc" DESTINATION - "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig" + "${CMAKE_INSTALL_FULL_LIBDIR}${LIB_SUFFIX}/pkgconfig" COMPONENT pkgconfig) set(CPACK_PACKAGE_NAME ${PROJECT_NAME}) From d54c18731e112a4cba6bb705cc83ec4fd049a523 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Tue, 5 Mar 2019 19:48:18 -0500 Subject: [PATCH 0685/1120] * Install event.h in $INCLUDEDIR/kqueue/sys, rather than $INCLUDEDIR/sys * Add support for building native Debian packages using Docker --- vendor/libkqueue/CMakeLists.txt | 15 ++- vendor/libkqueue/ChangeLog | 7 ++ vendor/libkqueue/pkg/Dockerfile.debian | 13 +++ vendor/libkqueue/pkg/README.md | 17 +++ vendor/libkqueue/pkg/debian/changelog | 95 ++++++++++++++++ vendor/libkqueue/pkg/debian/compat | 1 + vendor/libkqueue/pkg/debian/control | 30 +++++ vendor/libkqueue/pkg/debian/copyright | 105 ++++++++++++++++++ .../pkg/debian/libkqueue-dev.install | 4 + .../libkqueue/pkg/debian/libkqueue0.install | 1 + vendor/libkqueue/pkg/debian/rules | 4 + vendor/libkqueue/pkg/debian/source/format | 1 + vendor/libkqueue/pkg/debian/symbols | 3 + 13 files changed, 292 insertions(+), 4 deletions(-) create mode 100644 vendor/libkqueue/pkg/Dockerfile.debian create mode 100644 vendor/libkqueue/pkg/README.md create mode 100644 vendor/libkqueue/pkg/debian/changelog create mode 100644 vendor/libkqueue/pkg/debian/compat create mode 100644 vendor/libkqueue/pkg/debian/control create mode 100644 vendor/libkqueue/pkg/debian/copyright create mode 100644 vendor/libkqueue/pkg/debian/libkqueue-dev.install create mode 100644 vendor/libkqueue/pkg/debian/libkqueue0.install create mode 100755 vendor/libkqueue/pkg/debian/rules create mode 100644 vendor/libkqueue/pkg/debian/source/format create mode 100644 vendor/libkqueue/pkg/debian/symbols diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 9d4f21872..427fffcf0 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -14,11 +14,16 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -# Note: In order for RPM packaging to work correctly version >= 3.8 is required -cmake_minimum_required(VERSION 3.8.0) +if(EXISTS "/etc/debian_version") + cmake_minimum_required(VERSION 3.7.2) +else() + # KLUDGE: assumes RPM here + # For RPM packaging to work correctly version >= 3.8 is required + cmake_minimum_required(VERSION 3.8.0) +endif() cmake_policy(SET CMP0063 OLD) -project(libkqueue VERSION 2.3.1 LANGUAGES C) +project(libkqueue VERSION 2.4.0 LANGUAGES C) enable_testing() set(CMAKE_C_VISIBILITY_PRESET hidden) @@ -182,7 +187,7 @@ set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION ${CMAKE_INSTALL_FULL_MANDIR} install(FILES "include/sys/event.h" DESTINATION - "${CMAKE_INSTALL_FULL_INCLUDEDIR}/sys" + "${CMAKE_INSTALL_FULL_INCLUDEDIR}/kqueue/sys" COMPONENT headers) install(TARGETS kqueue @@ -265,3 +270,5 @@ set(CPACK_DEB_COMPONENT_INSTALL ON) # Enable component based packagi set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) # Use default Debian package naming scheme include(CPack) + +add_custom_target(tarball git archive -o "libkqueue-${PROJECT_VERSION}.tar.gz" --prefix "libkqueue-${PROJECT_VERSION}/" HEAD) \ No newline at end of file diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index d9165ac2f..796291393 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,3 +1,10 @@ +Unreleased +------------------------------------------------------------------------ + + * Install event.h in $INCLUDEDIR/kqueue/sys, rather than $INCLUDEDIR/sys + + * Add support for building native Debian packages using Docker + 2019-02-06 v2.3.1 ------------------------------------------------------------------------ diff --git a/vendor/libkqueue/pkg/Dockerfile.debian b/vendor/libkqueue/pkg/Dockerfile.debian new file mode 100644 index 000000000..b8d3f32de --- /dev/null +++ b/vendor/libkqueue/pkg/Dockerfile.debian @@ -0,0 +1,13 @@ +FROM debian:sid +MAINTAINER mark@heily.com +RUN apt-get update && apt-get install -y build-essential +RUN apt-get install -y cmake debhelper +ARG project_version +RUN mkdir -p /tmp/libkqueue-${project_version} +COPY . /tmp/libkqueue-${project_version} +WORKDIR /tmp +RUN tar zcf libkqueue_${project_version}.orig.tar.gz libkqueue-${project_version} +COPY pkg/debian/ /tmp/libkqueue-${project_version}/debian/ +WORKDIR /tmp/libkqueue-${project_version} +RUN rm -f CMakeCache.txt + diff --git a/vendor/libkqueue/pkg/README.md b/vendor/libkqueue/pkg/README.md new file mode 100644 index 000000000..64134fde5 --- /dev/null +++ b/vendor/libkqueue/pkg/README.md @@ -0,0 +1,17 @@ +This directory contains native packaging scripts for various platforms. + +The Makefile could optionally be converted into a CMakeLists file. + +Non-working example: + + add_custom_target(tarball git archive -o "libkqueue-${PROJECT_VERSION}.tar.gz" --prefix "libkqueue-${PROJECT_VERSION}/" HEAD) + + add_custom_target(docker_image docker build -t libkqueue-build --build-arg "project_version=${PROJECT_VERSION}" . + DEPENDS tarball) + + add_custom_target(native_package docker run --rm -it libkqueue-deb dpkg-buildpackage -uc -us -sn + DEPENDS docker_image) + + add_custom_target(debug_package_build docker run --rm -it libkqueue-deb docker run --rm -it libkqueue-deb:latest dpkg-buildpackage -uc -us + DEPENDS docker_image) + diff --git a/vendor/libkqueue/pkg/debian/changelog b/vendor/libkqueue/pkg/debian/changelog new file mode 100644 index 000000000..592daeb1a --- /dev/null +++ b/vendor/libkqueue/pkg/debian/changelog @@ -0,0 +1,95 @@ +libkqueue (2.4.0-1) unstable; urgency=medium + + * New upstream release. + * Remove autoconf dependencies, as this project uses CMake. + * Remove all Debian patches, as they have been incorporated upstream. + + -- Mark Heily Wed, 18 Feb 2019 18:24:48 +0000 + +libkqueue (2.3.1-1) unstable; urgency=medium + + * New upstream release + + -- Mark Heily Wed, 06 Feb 2019 18:14:10 +0000 + +libkqueue (2.3.0-1) unstable; urgency=medium + + * New upstream release + + -- Mark Heily Tue, 15 Jan 2019 22:11:11 +0000 + +libkqueue (2.0.3-1.1) unstable; urgency=medium + + * Non maintainer upload. + * Fix build failures on 64bit architectures. Closes: #760302, #754376. + - Replacing preprocessor macro X86_64 to LP64 in knote.c, since + it is used to treat pointer rather than processor specifics (Fernando + Seiti Furusat). + + -- Matthias Klose Thu, 11 Sep 2014 13:52:07 +0200 + +libkqueue (2.0.3-1) unstable; urgency=low + + * New upstream release (closes: #741009) + + -- Mark Heily Sun, 09 Mar 2014 20:45:35 -0400 + +libkqueue (2.0.2-1) unstable; urgency=low + + * New upstream release (closes: #724170, #669572, #729591) + + -- Mark Heily Sun, 23 Feb 2014 16:04:08 -0500 + +libkqueue (1.0.4-2) unstable; urgency=low + * Integrate patches from Matthias Klose (Closes: #640029) + * Add -Wno-error=unused-result to CFLAGS + * Fix header checks for multiarch locations. + + -- Mark Heily Thu, 27 Oct 2011 20:58:03 -0400 + +libkqueue (1.0.4-1) unstable; urgency=low + + * Fix a FTBFS on 32-bit platforms caused by the use of /usr/lib64 + * Fix a lintian warning related to the copyright file + + -- Mark Heily Wed, 13 Jul 2011 20:52:41 -0400 + +libkqueue (1.0.3-1) unstable; urgency=low + + * New upstream release (Closes: #625639) + * Update control file with new website and standards version + * Simplify the debian/rules file using debhelper for everything + * Upgrade source/format to "3.0 (quilt)" + * Remove the debian/watch file + + -- Mark Heily Sat, 09 Jul 2011 18:56:19 -0400 + +libkqueue (0.9.2-2) unstable; urgency=low + + * Apply patch to fix a bug in EV_RECEIPT (Closes: #595648) + + -- Mark Heily Sun, 05 Sep 2010 13:57:45 -0400 + +libkqueue (0.9.2-1) unstable; urgency=low + + * New upstream release (Closes: #591818) + + -- Mark Heily Thu, 05 Aug 2010 23:31:18 -0400 + +libkqueue (0.9.1-1) unstable; urgency=low + + * New upstream release + + -- Mark Heily Wed, 04 Aug 2010 21:35:01 -0400 + +libkqueue (0.8-1) unstable; urgency=low + + * New upstream release + + -- Mark Heily Sun, 25 Jul 2010 10:09:35 -0400 + +libkqueue (0.7-1) unstable; urgency=low + + * Initial release (Closes: #576317) + + -- Mark Heily Sun, 28 Mar 2010 18:58:58 -0400 diff --git a/vendor/libkqueue/pkg/debian/compat b/vendor/libkqueue/pkg/debian/compat new file mode 100644 index 000000000..ec635144f --- /dev/null +++ b/vendor/libkqueue/pkg/debian/compat @@ -0,0 +1 @@ +9 diff --git a/vendor/libkqueue/pkg/debian/control b/vendor/libkqueue/pkg/debian/control new file mode 100644 index 000000000..dfc228196 --- /dev/null +++ b/vendor/libkqueue/pkg/debian/control @@ -0,0 +1,30 @@ +Source: libkqueue +Section: libs +Priority: optional +Maintainer: Mark Heily +Build-Depends: debhelper (>= 9) +Standards-Version: 3.9.5.0 +Vcs-Git: git://github.com/mheily/debian-packages.git -b libkqueue +Homepage: https://github.com/mheily/libkqueue/wiki + +Package: libkqueue0 +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: cross-platform library for kernel event notification + libkqueue is a portable userspace implementation of the kqueue(2) + kernel event notification mechanism found in FreeBSD and other BSD-based + operating systems. The library translates between the kevent structure + and the native kernel facilities of the host machine. + +Package: libkqueue-dev +Section: libdevel +Architecture: any +Depends: libkqueue0 (= ${binary:Version}), ${misc:Depends} +Description: Development files for libkqueue + Contains the header files, manpages, and static libraries for use in + developing applications that use the libkqueue library. + . + libkqueue is a portable userspace implementation of the kqueue(2) + kernel event notification mechanism found in FreeBSD and other BSD-based + operating systems. The library translates between the kevent structure + and the native kernel facilities of the host machine. diff --git a/vendor/libkqueue/pkg/debian/copyright b/vendor/libkqueue/pkg/debian/copyright new file mode 100644 index 000000000..5066ec1af --- /dev/null +++ b/vendor/libkqueue/pkg/debian/copyright @@ -0,0 +1,105 @@ +This package was debianized by Mark Heily on +Sun, 28 Mar 2010 18:58:58 -0400 + +It was downloaded from http://mark.heily.com/libkqueue/trunk/ + +Copyright: + + Copyright (C) 2009 Mark Heily + Copyright (c) 2000 Jonathan Lemon + Copyright 2002 Niels Provos + +License: + + Copyright (c) 2009 Mark Heily + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +include/sys/event.h is licensed: + + Copyright (c) 1999,2000,2001 Jonathan Lemon + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +src/common/tree.h is licensed: + + Copyright 2002 Niels Provos + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +The Debian packaging is: + + Copyright (C) 2010 Mark Heily + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + diff --git a/vendor/libkqueue/pkg/debian/libkqueue-dev.install b/vendor/libkqueue/pkg/debian/libkqueue-dev.install new file mode 100644 index 000000000..4efbacfe3 --- /dev/null +++ b/vendor/libkqueue/pkg/debian/libkqueue-dev.install @@ -0,0 +1,4 @@ +usr/lib/*/libkqueue.so +usr/lib/*/pkgconfig/libkqueue.pc +usr/include/kqueue/sys/event.h +usr/share/man/man2/* diff --git a/vendor/libkqueue/pkg/debian/libkqueue0.install b/vendor/libkqueue/pkg/debian/libkqueue0.install new file mode 100644 index 000000000..d55f15e28 --- /dev/null +++ b/vendor/libkqueue/pkg/debian/libkqueue0.install @@ -0,0 +1 @@ +usr/lib/*/lib*.so.0 diff --git a/vendor/libkqueue/pkg/debian/rules b/vendor/libkqueue/pkg/debian/rules new file mode 100755 index 000000000..050e29a63 --- /dev/null +++ b/vendor/libkqueue/pkg/debian/rules @@ -0,0 +1,4 @@ +#!/usr/bin/make -f + +%: + dh $@ --buildsystem=cmake diff --git a/vendor/libkqueue/pkg/debian/source/format b/vendor/libkqueue/pkg/debian/source/format new file mode 100644 index 000000000..163aaf8d8 --- /dev/null +++ b/vendor/libkqueue/pkg/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/vendor/libkqueue/pkg/debian/symbols b/vendor/libkqueue/pkg/debian/symbols new file mode 100644 index 000000000..0141b0fc0 --- /dev/null +++ b/vendor/libkqueue/pkg/debian/symbols @@ -0,0 +1,3 @@ +libkqueue.so.0 libkqueue0 #MINVER# + kevent@Base 2.0.2 + kqueue@Base 2.0.2 From 05753a5d0d1a5eaff516d962eb9284c55dc508ba Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 22 Mar 2019 14:36:30 +0700 Subject: [PATCH 0686/1120] Cleanup linux_get_descriptor_type and add documentation header There's no point in checking again if the FD was a socket, if we just determined it was a socket --- vendor/libkqueue/src/linux/platform.c | 66 +++++++++++++++++---------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index dd335b035..d358002d8 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -118,8 +118,8 @@ monitoring_thread_start(void *arg) return NULL; /* - * Now that thread is initialized, let kqueue init resume - */ + * Now that thread is initialized, let kqueue init resume + */ pthread_cond_broadcast(&monitoring_thread_cond); (void) pthread_mutex_unlock(&kq_mtx); @@ -547,6 +547,29 @@ linux_eventfd_descriptor(struct eventfd *e) return (e->ef_id); } +/** Determine what type of file descriptor the knote describes + * + * Sets the kn_flags field of the knote to one of: + * - KNFL_FILE FD is a regular file. + * - KNFL_PIPE FD is one end of a pipe. + * - KNFL_BLK FD is a block device. + * - KNFL_CHR FD is a character device. + * - KNFL_SOCKET_STREAM FD is a streaming socket(reliable connection-oriented byte streams). + * - KNFL_SOCKET_DGRAM FD is a datagram socket (unreliable connectionless messages). + * - KNFL_SOCKET_RDM FD is a reliable datagram socket (reliable connectionless messages). + * - KNFL_SOCKET_SEQPACKET FD is a sequenced packet socket (reliable connection-oriented messages). + * + * Additionally KNFL_SOCKET_* types may have the KNFL_SOCKET_PASSIVE flag set if they + * are never expected to return data, but only provide an indication of whether data is available. + * + * We currently check whether the socket is a 'listening' socket (SO_ACCEPTCONN) or has a BPF rule + * attached (SO_GET_FILTER) to determine if it's passive. + * + * @param[in] kn holding the file descriptor. + * @return + * - 0 on success. + * - -1 on failure. + */ int linux_get_descriptor_type(struct knote *kn) { @@ -563,43 +586,38 @@ linux_get_descriptor_type(struct knote *kn) dbg_perror("fstat(2)"); return (-1); } + switch (sb.st_mode & S_IFMT) { + default: + errno = EBADF; + dbg_perror("unknown fd type"); + return (-1); + case S_IFREG: dbg_printf("fd %d is a regular file\n", fd); kn->kn_flags |= KNFL_FILE; - break; + return (0); case S_IFIFO: dbg_printf("fd %d is a pipe\n", fd); kn->kn_flags |= KNFL_PIPE; - break; + return (0); case S_IFBLK: dbg_printf("fd %d is a block device\n", fd); kn->kn_flags |= KNFL_BLOCKDEV; - break; + return (0); case S_IFCHR: dbg_printf("fd %d is a character device\n", fd); kn->kn_flags |= KNFL_CHARDEV; - break; + return (0); case S_IFSOCK: dbg_printf("fd %d is a socket\n", fd); break; /* deferred type determination */ - - default: - errno = EBADF; - dbg_perror("unknown fd type"); - return -1; } - /* - * Test if the socket is active or passive. - */ - if (!S_ISSOCK(sb.st_mode)) - return (0); - /* * Determine socket type. */ @@ -636,6 +654,7 @@ linux_get_descriptor_type(struct knote *kn) dbg_perror("unknown socket type"); return (-1); } + slen = sizeof(lsock); lsock = 0; ret = getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &lsock, &slen); @@ -643,14 +662,13 @@ linux_get_descriptor_type(struct knote *kn) switch (errno) { case ENOTSOCK: /* same as lsock = 0 */ break; + default: dbg_perror("getsockopt(3)"); return (-1); } - } else { - if (lsock) - kn->kn_flags |= KNFL_SOCKET_PASSIVE; - } + } else if (lsock) + kn->kn_flags |= KNFL_SOCKET_PASSIVE; /* * Test if socket has a filter @@ -668,10 +686,8 @@ linux_get_descriptor_type(struct knote *kn) dbg_perror("getsockopt(3)"); return (-1); } - } else { - if (out_len) - kn->kn_flags |= KNFL_SOCKET_PASSIVE; - } + } else if (out_len) + kn->kn_flags |= KNFL_SOCKET_PASSIVE; return (0); } From e2fe4c5d52e57f4da84c252e5a0129d59356c865 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 22 Mar 2019 19:13:53 +0700 Subject: [PATCH 0687/1120] Add doxygen markup for event.h --- vendor/libkqueue/include/sys/event.h | 293 ++++++++++++++++----------- 1 file changed, 171 insertions(+), 122 deletions(-) diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index ccd1007dc..0f2927c2b 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -46,137 +46,186 @@ struct timespec; -#define EVFILT_READ (-1) -#define EVFILT_WRITE (-2) -#define EVFILT_AIO (-3) /* attached to aio requests */ -#define EVFILT_VNODE (-4) /* attached to vnodes */ -#define EVFILT_PROC (-5) /* attached to struct proc */ -#define EVFILT_SIGNAL (-6) /* attached to struct proc */ -#define EVFILT_TIMER (-7) /* timers */ -#define EVFILT_NETDEV (-8) /* network devices */ -#define EVFILT_FS (-9) /* filesystem events */ -#define EVFILT_LIO (-10) /* attached to lio requests */ -#define EVFILT_USER (-11) /* User events */ -#define EVFILT_SYSCOUNT 11 - -#define EV_SET(kevp_, a, b, c, d, e, f) do { \ - struct kevent *kevp = (kevp_); \ - (kevp)->ident = (a); \ - (kevp)->filter = (b); \ - (kevp)->flags = (c); \ - (kevp)->fflags = (d); \ - (kevp)->data = (e); \ - (kevp)->udata = (f); \ +/** Populate a kevent structure in the changelist + * + * @param[in] _kevp The kevent structure to populate. + * @param[in] _ident The unique identifier for this event. + * @param[in] _filter The unique identifier for this event. + * @param[in] _flags Filter specific flags. + * @param[in] _data Additional data for the filter. + * @param[in] _udata Opaque user data identifier. Not interpreted by libkqueue. + */ +#define EV_SET(_kevp, _ident, _filter, _flags, _fflags, _data, _udata) do { \ + struct kevent *kevp = (_kevp); \ + (kevp)->ident = (_ident); \ + (kevp)->filter = (_filter); \ + (kevp)->flags = (_flags); \ + (kevp)->fflags = (_fflags); \ + (kevp)->data = (_data); \ + (kevp)->udata = (_udata); \ } while(0) +/** Structure to hold an event registration or notification + * + * A list of kevent structures are passed in by the application as the changelist + * to set which notifications the application wishes to received. + * + * A list of kevent structures are passed back to the application as the eventlist + * to inform the application of events which occurred or filter states. + */ struct kevent { - uintptr_t ident; /* identifier for this event */ - short filter; /* filter for event */ - unsigned short flags; - unsigned int fflags; - intptr_t data; - void *udata; /* opaque user data identifier */ + uintptr_t ident; //!< The unique identifier for this event. + short filter; //!< The unique identifier for this event. + unsigned short flags; //!< One or more of the EV_* macros or'd together. + unsigned int fflags; //!< Filter specific flags. + intptr_t data; //!< Additional data for the filter. + void *udata; //!< Opaque user data identifier. }; -/* actions */ -#define EV_ADD 0x0001 /* add event to kq (implies enable) */ -#define EV_DELETE 0x0002 /* delete event from kq */ -#define EV_ENABLE 0x0004 /* enable event */ -#define EV_DISABLE 0x0008 /* disable event (not reported) */ - -/* flags */ -#define EV_ONESHOT 0x0010 /* only report one occurrence */ -#define EV_CLEAR 0x0020 /* clear event state after reporting */ -#define EV_RECEIPT 0x0040 /* force EV_ERROR on success, data=0 */ -#define EV_DISPATCH 0x0080 /* disable event after reporting */ - -#define EV_SYSFLAGS 0xF000 /* reserved by system */ -#define EV_FLAG1 0x2000 /* filter-specific flag */ - -/* returned values */ -#define EV_EOF 0x8000 /* EOF detected */ -#define EV_ERROR 0x4000 /* error, data contains errno */ - - /* - * data/hint flags/masks for EVFILT_USER - * - * On input, the top two bits of fflags specifies how the lower twenty four - * bits should be applied to the stored value of fflags. - * - * On output, the top two bits will always be set to NOTE_FFNOP and the - * remaining twenty four bits will contain the stored fflags value. - */ -#define NOTE_FFNOP 0x00000000 /* ignore input fflags */ -#define NOTE_FFAND 0x40000000 /* AND fflags */ -#define NOTE_FFOR 0x80000000 /* OR fflags */ -#define NOTE_FFCOPY 0xc0000000 /* copy fflags */ -#define NOTE_FFCTRLMASK 0xc0000000 /* masks for operations */ -#define NOTE_FFLAGSMASK 0x00ffffff - -#define NOTE_TRIGGER 0x01000000 /* Cause the event to be - triggered for output. */ - -/* - * data/hint flags for EVFILT_{READ|WRITE} +/** @name Filters + * + * @{ + */ +#define EVFILT_READ (-1) //!< Read I/O event. +#define EVFILT_WRITE (-2) //!< Write I/O event. +#define EVFILT_AIO (-3) //!< Attached to aio requests. +#define EVFILT_VNODE (-4) //!< Attached to vnodes. +#define EVFILT_PROC (-5) //!< attached to struct proc. +#define EVFILT_SIGNAL (-6) //!< Attached to struct proc. +#define EVFILT_TIMER (-7) //!< Timers. +#define EVFILT_NETDEV (-8) //!< Network devices. +#define EVFILT_FS (-9) //!< Filesystem events. +#define EVFILT_LIO (-10) //!< Attached to lio requests. +#define EVFILT_USER (-11) //!< User events. +#define EVFILT_SYSCOUNT 11 +/** @} */ + +/** @name Actions + * + * @{ + */ +#define EV_ADD 0x0001 //!< Add event to kq (implies enable). +#define EV_DELETE 0x0002 //!< Delete event from kq. +#define EV_ENABLE 0x0004 //!< Enable event. +#define EV_DISABLE 0x0008 //!< Disable event (not reported). +/** @} */ + +/** @name Flags + * + * @{ + */ +#define EV_ONESHOT 0x0010 //!< Only report one occurrence. +#define EV_CLEAR 0x0020 //!< Clear event state after reporting. +#define EV_RECEIPT 0x0040 //!< Force EV_ERROR on success, data=0. +#define EV_DISPATCH 0x0080 //!< Disable event after reporting. + +#define EV_SYSFLAGS 0xF000 //!< Reserved by system. +#define EV_FLAG1 0x2000 //!< Filter-specific flag. +/** @} */ + +/** @name Returned values + * + * @{ + */ +#define EV_EOF 0x8000 //!< EOF detected. +#define EV_ERROR 0x4000 //!< Error, data contains errno. +/** @} */ + +/** @name Data/hint flags/masks for EVFILT_USER + * + * On input, the top two bits of fflags specifies how the lower twenty four + * bits should be applied to the stored value of fflags. + * + * On output, the top two bits will always be set to NOTE_FFNOP and the + * remaining twenty four bits will contain the stored fflags value. + * @{ */ -#define NOTE_LOWAT 0x0001 /* low water mark */ -#undef NOTE_LOWAT /* Not supported on Linux */ +#define NOTE_FFNOP 0x00000000 //!< Ignore input fflags. +#define NOTE_FFAND 0x40000000 //!< AND fflags. +#define NOTE_FFOR 0x80000000 //!< OR fflags. +#define NOTE_FFCOPY 0xc0000000 //!< Copy fflags. +#define NOTE_FFCTRLMASK 0xc0000000 //!< Masks for operations. +#define NOTE_FFLAGSMASK 0x00ffffff + +#define NOTE_TRIGGER 0x01000000 //!< Cause the event to be triggered for output. +/** @} */ -/* - * data/hint flags for EVFILT_VNODE +/** @name Data/hint flags for EVFILT_{READ|WRITE} + * + * @{ */ -#define NOTE_DELETE 0x0001 /* vnode was removed */ -#define NOTE_WRITE 0x0002 /* data contents changed */ -#define NOTE_EXTEND 0x0004 /* size increased */ -#define NOTE_ATTRIB 0x0008 /* attributes changed */ -#define NOTE_LINK 0x0010 /* link count changed */ -#define NOTE_RENAME 0x0020 /* vnode was renamed */ -#define NOTE_REVOKE 0x0040 /* vnode access was revoked */ -#undef NOTE_REVOKE /* Not supported on Linux */ - -/* - * data/hint flags for EVFILT_PROC +#define NOTE_LOWAT 0x0001 //!< Low water mark. +#undef NOTE_LOWAT /* Not supported on Linux */ +/** @} */ + +/** @name Data/hint flags for EVFILT_VNODE + * + * @{ + */ +#define NOTE_DELETE 0x0001 //!< Vnode was removed. +#define NOTE_WRITE 0x0002 //!< Data contents changed. +#define NOTE_EXTEND 0x0004 //!< Size increased. +#define NOTE_ATTRIB 0x0008 //!< Attributes changed. +#define NOTE_LINK 0x0010 //!< Link count changed. +#define NOTE_RENAME 0x0020 //!< Vnode was renamed. +#define NOTE_REVOKE 0x0040 //!< Vnode access was revoked. +#undef NOTE_REVOKE /* Not supported on Linux */ +/** @} */ + +/** @name Data/hint flags for EVFILT_PROC + * + * @{ */ -#define NOTE_EXIT 0x80000000 /* process exited */ -#define NOTE_FORK 0x40000000 /* process forked */ -#define NOTE_EXEC 0x20000000 /* process exec'd */ -#define NOTE_PCTRLMASK 0xf0000000 /* mask for hint bits */ -#define NOTE_PDATAMASK 0x000fffff /* mask for pid */ - -/* additional flags for EVFILT_PROC */ -#define NOTE_TRACK 0x00000001 /* follow across forks */ -#define NOTE_TRACKERR 0x00000002 /* could not track child */ -#define NOTE_CHILD 0x00000004 /* am a child process */ - -/* - * data/hint flags for EVFILT_NETDEV +#define NOTE_EXIT 0x80000000 //!< Process exited. +#define NOTE_FORK 0x40000000 //!< Process forked. +#define NOTE_EXEC 0x20000000 //!< Process exec'd. +#define NOTE_PCTRLMASK 0xf0000000 //!< Mask for hint bits. +#define NOTE_PDATAMASK 0x000fffff //!< Mask for pid. +/** @} */ + +/** @name Additional flags for EVFILT_PROC + * + * @{ */ -#define NOTE_LINKUP 0x0001 /* link is up */ -#define NOTE_LINKDOWN 0x0002 /* link is down */ -#define NOTE_LINKINV 0x0004 /* link state is invalid */ - -/* KLUDGE: This is from on FreeBSD and is used by - the EVFILT_FS filter. */ -/* vfsquery flags */ -#define VQ_NOTRESP 0x0001 /* server down */ -#define VQ_NEEDAUTH 0x0002 /* server bad auth */ -#define VQ_LOWDISK 0x0004 /* we're low on space */ -#define VQ_MOUNT 0x0008 /* new filesystem arrived */ -#define VQ_UNMOUNT 0x0010 /* filesystem has left */ -#define VQ_DEAD 0x0020 /* filesystem is dead, needs force unmount */ -#define VQ_ASSIST 0x0040 /* filesystem needs assistance from external - program */ -#define VQ_NOTRESPLOCK 0x0080 /* server lockd down */ - -/* - * data/hint flags for EVFILT_TIMER as suported and defined in kevent64 +#define NOTE_TRACK 0x00000001 //!< Follow across forks. +#define NOTE_TRACKERR 0x00000002 //!< Could not track child. +#define NOTE_CHILD 0x00000004 //!< Am a child process. +/** @} */ + +/** @name Data/hint flags for EVFILT_NETDEV + * + * @{ */ -#define NOTE_SECONDS 0x0001 /* time specified in seconds */ -#define NOTE_USECONDS 0x0002 /* time specified in micro seconds */ -#define NOTE_NSECONDS 0x0004 /* time specified in nano seconds */ -#define NOTE_ABSOLUTE 0x0008 /* data is an absolute timeout */ +#define NOTE_LINKUP 0x0001 //!< Link is up. +#define NOTE_LINKDOWN 0x0002 //!< Link is down. +#define NOTE_LINKINV 0x0004 //!< Link state is invalid. +/** @} */ +/** @name vfsquery flags + * + * @note KLUDGE: This is from on FreeBSD and is used by the EVFILT_FS filter. + * + * @{ + */ +#define VQ_NOTRESP 0x0001 //!< Server down. +#define VQ_NEEDAUTH 0x0002 //!< server bad auth. +#define VQ_LOWDISK 0x0004 //!< we're low on space. +#define VQ_MOUNT 0x0008 //!< new filesystem arrived. +#define VQ_UNMOUNT 0x0010 //!< filesystem has left. +#define VQ_DEAD 0x0020 //!< filesystem is dead, needs force unmount. +#define VQ_ASSIST 0x0040 //!< filesystem needs assistance from external program. +#define VQ_NOTRESPLOCK 0x0080 //!< server lockd down. +/** @} */ +/** @name Data/hint flags for EVFILT_TIMER as suported and defined in kevent64 + * + * @{ + */ +#define NOTE_SECONDS 0x0001 //!< Time specified in seconds. +#define NOTE_USECONDS 0x0002 //!< Time specified in micro seconds. +#define NOTE_NSECONDS 0x0004 //!< Time specified in nano seconds. +#define NOTE_ABSOLUTE 0x0008 //!< Data is an absolute timeout. +/** @} */ #ifndef __KERNEL__ #ifdef __cplusplus @@ -199,8 +248,8 @@ kqueue(void); __declspec(dllexport) int kevent(int kq, const struct kevent *changelist, int nchanges, - struct kevent *eventlist, int nevents, - const struct timespec *timeout); + struct kevent *eventlist, int nevents, + const struct timespec *timeout); #ifdef MAKE_STATIC __declspec(dllexport) int @@ -210,8 +259,8 @@ libkqueue_init(); #else int kqueue(void); int kevent(int kq, const struct kevent *changelist, int nchanges, - struct kevent *eventlist, int nevents, - const struct timespec *timeout); + struct kevent *eventlist, int nevents, + const struct timespec *timeout); #ifdef MAKE_STATIC int libkqueue_init(); #endif From 93554c952a5f7a9a40eb5df9b6b4002cdbd1dbe5 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 22 Mar 2019 19:14:34 +0700 Subject: [PATCH 0688/1120] Add limited Doxygen markup for private.h --- vendor/libkqueue/src/common/private.h | 58 +++++++++++++++++++-------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 6939097b9..8e22b01bb 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -86,18 +86,19 @@ struct knote { unsigned int kn_flags; union { /* OLD */ - int pfd; /* Used by timerfd */ - int events; /* Used by socket */ + int pfd; //!< Used by timerfd. + int events; //!< Used by socket. struct { - nlink_t nlink; /* Used by vnode */ - off_t size; /* Used by vnode */ + nlink_t nlink; //!< Used by vnode. + off_t size; //!< Used by vnode. } vnode; - timer_t timerid; - struct sleepreq *sleepreq; /* Used by posix/timer.c */ - void *handle; /* Used by win32 filters */ + timer_t timerid; + struct sleepreq *sleepreq; //!< Used by posix/timer.c. + void *handle; //!< Used by win32 filters. } data; - struct kqueue* kn_kq; - volatile uint32_t kn_ref; + + struct kqueue *kn_kq; + volatile uint32_t kn_ref; #if defined(KNOTE_PLATFORM_SPECIFIC) KNOTE_PLATFORM_SPECIFIC; #endif @@ -112,6 +113,24 @@ struct knote { (ent)->kev.flags |= EV_DISABLE; \ } while (0/*CONSTCOND*/) +/** A filter within a kqueue notification channel + * + * Filters are discreet event notification facilities within a kqueue. + * Filters do not usually interact with each other, and maintain separate states. + * + * Filters handle notifications from different event sources. + * The EVFILT_READ filter, for example, provides notifications when an FD is + * readable, and EVFILT_SIGNAL filter provides notifications when a particular + * signal is received by the process/thread. + * + * Many of the fields in this struct are callbacks for functions which operate + * on the filer. + * + * Callbacks either change the state of the filter itself, or create new + * knotes associated with the filter. The knotes describe a filter-specific + * event the application is interested in receiving. + * + */ struct filter { short kf_id; @@ -137,7 +156,7 @@ struct filter { int kf_wfd; /* fd to write when an event occurs */ //----? - struct evfilt_data *kf_data; /* filter-specific data */ + struct evfilt_data *kf_data; /* filter-specific data */ RB_HEAD(knt, knote) kf_knote; pthread_rwlock_t kf_knote_mtx; struct kqueue *kf_kqueue; @@ -149,9 +168,16 @@ struct filter { /* Use this to declare a filter that is not implemented */ #define EVFILT_NOTIMPL { 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } +/** Structure representing a notification channel + * + * Structure used to track the events that an application is interesting + * in receiving notifications for. + */ struct kqueue { - int kq_id; - struct filter kq_filt[EVFILT_SYSCOUNT]; + int kq_id; //!< File descriptor used to identify this kqueue. + struct filter kq_filt[EVFILT_SYSCOUNT]; //!< Filters supported by the kqueue. Each + ///< kqueue maintains one filter state structure + ///< per filter type. fd_set kq_fds, kq_rfds; int kq_nfds; tracing_mutex_t kq_mtx; @@ -168,7 +194,7 @@ struct kqueue_vtable { // @param timespec can be given as timeout // @param int the number of events to wait for // @param kqueue the queue to wait on - int (*kevent_wait)(struct kqueue *, int, const struct timespec *); + int (*kevent_wait)(struct kqueue *, int, const struct timespec *); // @param kqueue the queue to look at // @param int The number of events that should be ready // @param kevent the structure to copy the events into @@ -207,13 +233,13 @@ int knote_disable(struct filter *, struct knote *); #define knote_get_filter(knt) &((knt)->kn_kq->kq_filt[(knt)->kev.filter]) int filter_lookup(struct filter **, struct kqueue *, short); -int filter_register_all(struct kqueue *); -void filter_unregister_all(struct kqueue *); +int filter_register_all(struct kqueue *); +void filter_unregister_all(struct kqueue *); const char *filter_name(short); int kevent_wait(struct kqueue *, const struct timespec *); int kevent_copyout(struct kqueue *, int, struct kevent *, int); -void kevent_free(struct kqueue *); +void kevent_free(struct kqueue *); const char *kevent_dump(const struct kevent *); struct kqueue * kqueue_lookup(int); int kqueue_validate(struct kqueue *); From 00e38f9393ddc216328bf3da1c0d6285f1e0f193 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 25 Mar 2019 13:02:20 +0700 Subject: [PATCH 0689/1120] Document debugging environmental variable --- vendor/libkqueue/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index 3d6d18cb5..2d69256a7 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -66,6 +66,13 @@ Running Unit Tests cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib -DENABLE_TESTING=YES make make test + +Debugging +--------- + +Ensure -DNDEBUG is *NOT* passed during compilation, otherwise all debug output will be disabled. + + KQUEUE_DEBUG=1 Building Applications --------------------- From 7af025c3a5b4bf22d368729062d8d137821fbfde Mon Sep 17 00:00:00 2001 From: Matt Rose Date: Tue, 2 Apr 2019 10:43:02 -0400 Subject: [PATCH 0690/1120] fix debian packaging to create shlibs file --- vendor/libkqueue/CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 427fffcf0..5be54e4d3 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -142,7 +142,7 @@ endif() add_library(kqueue ${LIBRARY_TYPE} ${LIBKQUEUE_SOURCES} ${LIBKQUEUE_HEADERS}) set_target_properties(kqueue PROPERTIES DEBUG_POSTFIX "d") -set_target_properties(kqueue PROPERTIES SOVERSION 0) +set_target_properties(kqueue PROPERTIES SOVERSION 1) if(WIN32) target_compile_definitions(kqueue PRIVATE _USRDLL;_WINDLL) @@ -268,7 +268,9 @@ set(CPACK_DEBIAN_DEVEL_PACKAGE_DEPENDS "${CPACK_PACKAGE_NAME} (= ${PROJECT_VERSI set(CPACK_DEB_COMPONENT_INSTALL ON) # Enable component based packaging (generate multiple packages) set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) # Use default Debian package naming scheme +set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) +set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON) include(CPack) -add_custom_target(tarball git archive -o "libkqueue-${PROJECT_VERSION}.tar.gz" --prefix "libkqueue-${PROJECT_VERSION}/" HEAD) \ No newline at end of file +add_custom_target(tarball git archive -o "libkqueue-${PROJECT_VERSION}.tar.gz" --prefix "libkqueue-${PROJECT_VERSION}/" HEAD) From 7d943aea32ec32ddaa3cc692bd0b7ba7cbdfe5e9 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 25 Mar 2019 14:30:20 +0700 Subject: [PATCH 0691/1120] s/\t/ /g Tabs to spaces --- vendor/libkqueue/src/linux/timer.c | 21 +++-- vendor/libkqueue/src/posix/signal.c | 38 ++++---- vendor/libkqueue/src/posix/timer.c | 8 +- vendor/libkqueue/src/solaris/signal.c | 36 ++++---- vendor/libkqueue/src/windows/platform.c | 18 ++-- vendor/libkqueue/src/windows/platform.h | 10 +-- vendor/libkqueue/src/windows/read.c | 18 ++-- vendor/libkqueue/src/windows/timer.c | 114 ++++++++++++------------ vendor/libkqueue/src/windows/user.c | 12 +-- 9 files changed, 139 insertions(+), 136 deletions(-) diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index b1a3bf175..7a210599e 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -85,27 +85,30 @@ itimerspec_dump(struct itimerspec *ts) static void convert_timedata_to_itimerspec(struct itimerspec *dst, long src, - unsigned int flags, int oneshot) + unsigned int flags, int oneshot) { time_t sec, nsec; - switch (flags & NOTE_TIMER_MASK) { - case NOTE_USECONDS: + switch (flags & NOTE_TIMER_MASK) { + case NOTE_USECONDS: sec = src / 1000000; nsec = (src % 1000000); break; - case NOTE_NSECONDS: + + case NOTE_NSECONDS: sec = src / 1000000000; nsec = (src % 1000000000); break; - case NOTE_SECONDS: + + case NOTE_SECONDS: sec = src; nsec = 0; break; - default: /* milliseconds */ + + default: /* milliseconds */ sec = src / 1000; nsec = (src % 1000) * 1000000; - } + } /* Set the interval */ if (oneshot) { @@ -164,8 +167,8 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) dbg_printf("created timerfd %d", tfd); convert_timedata_to_itimerspec(&ts, kn->kev.data, kn->kev.fflags, - kn->kev.flags & EV_ONESHOT); - flags = (kn->kev.fflags & NOTE_ABSOLUTE) ? TFD_TIMER_ABSTIME : 0; + kn->kev.flags & EV_ONESHOT); + flags = (kn->kev.fflags & NOTE_ABSOLUTE) ? TFD_TIMER_ABSTIME : 0; if (timerfd_settime(tfd, flags, &ts, NULL) < 0) { dbg_printf("timerfd_settime(2): %s", strerror(errno)); close(tfd); diff --git a/vendor/libkqueue/src/posix/signal.c b/vendor/libkqueue/src/posix/signal.c index e7a453db2..a6621082e 100644 --- a/vendor/libkqueue/src/posix/signal.c +++ b/vendor/libkqueue/src/posix/signal.c @@ -66,19 +66,19 @@ signal_handler(int sig) static int catch_signal(struct filter *filt, struct knote *kn) { - int sig; - struct sigaction sa; + int sig; + struct sigaction sa; sig = kn->kev.ident; - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = signal_handler; - sa.sa_flags |= SA_RESTART; - sigfillset(&sa.sa_mask); - - if (sigaction(kn->kev.ident, &sa, NULL) == -1) { - dbg_perror("sigaction"); - return (-1); - } + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = signal_handler; + sa.sa_flags |= SA_RESTART; + sigfillset(&sa.sa_mask); + + if (sigaction(kn->kev.ident, &sa, NULL) == -1) { + dbg_perror("sigaction"); + return (-1); + } /* FIXME: will clobber previous entry, if any */ pthread_mutex_lock(&sigtbl_mtx); sigtbl[kn->kev.ident].s_filt = filt; @@ -92,16 +92,16 @@ catch_signal(struct filter *filt, struct knote *kn) static int ignore_signal(int sig) { - struct sigaction sa; + struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = SIG_IGN; - sigemptyset(&sa.sa_mask); + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_IGN; + sigemptyset(&sa.sa_mask); - if (sigaction(sig, &sa, NULL) == -1) { - dbg_perror("sigaction"); - return (-1); - } + if (sigaction(sig, &sa, NULL) == -1) { + dbg_perror("sigaction"); + return (-1); + } pthread_mutex_lock(&sigtbl_mtx); sigtbl[sig].s_filt = NULL; sigtbl[sig].s_knote = NULL; diff --git a/vendor/libkqueue/src/posix/timer.c b/vendor/libkqueue/src/posix/timer.c index 01c1fe904..7eaeabdd0 100644 --- a/vendor/libkqueue/src/posix/timer.c +++ b/vendor/libkqueue/src/posix/timer.c @@ -59,7 +59,7 @@ sleeper_thread(void *arg) ssize_t cnt; bool cts = true; /* Clear To Send */ char buf[1]; - int rv; + int rv; #if 0 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); @@ -85,7 +85,7 @@ sleeper_thread(void *arg) /* Sleep */ dbg_printf("sleeping for %ld ms", (unsigned long) sr->interval); - rv = pthread_cond_timedwait(&sr->cond, &sr->mtx, &req); + rv = pthread_cond_timedwait(&sr->cond, &sr->mtx, &req); pthread_mutex_unlock(&sr->mtx); if (rv == 0) { /* _timer_delete() has requested that we terminate */ @@ -93,10 +93,10 @@ sleeper_thread(void *arg) break; } else if (rv != 0) { dbg_printf("rv=%d %s", rv, strerror(rv)); - if (rv == EINTR) + if (rv == EINTR) abort(); //FIXME should not happen - //ASSUME: rv == ETIMEDOUT + //ASSUME: rv == ETIMEDOUT } si.counter++; dbg_printf(" -------- sleep over (CTS=%d)----------", cts); diff --git a/vendor/libkqueue/src/solaris/signal.c b/vendor/libkqueue/src/solaris/signal.c index cd52e44a0..777a6087e 100644 --- a/vendor/libkqueue/src/solaris/signal.c +++ b/vendor/libkqueue/src/solaris/signal.c @@ -49,19 +49,19 @@ signal_handler(int sig) static int catch_signal(struct filter *filt, struct knote *kn) { - int sig; - struct sigaction sa; + int sig; + struct sigaction sa; sig = kn->kev.ident; - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = signal_handler; - sa.sa_flags |= SA_RESTART; - sigfillset(&sa.sa_mask); + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = signal_handler; + sa.sa_flags |= SA_RESTART; + sigfillset(&sa.sa_mask); - if (sigaction(kn->kev.ident, &sa, NULL) == -1) { - dbg_perror("sigaction"); - return (-1); - } + if (sigaction(kn->kev.ident, &sa, NULL) == -1) { + dbg_perror("sigaction"); + return (-1); + } pthread_mutex_lock(&sigtbl_mtx); sigtbl[sig].st_signum = sig; @@ -78,16 +78,16 @@ catch_signal(struct filter *filt, struct knote *kn) static int ignore_signal(int sig) { - struct sigaction sa; + struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = SIG_IGN; - sigemptyset(&sa.sa_mask); + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_IGN; + sigemptyset(&sa.sa_mask); - if (sigaction(sig, &sa, NULL) == -1) { - dbg_perror("sigaction"); - return (-1); - } + if (sigaction(sig, &sa, NULL) == -1) { + dbg_perror("sigaction"); + return (-1); + } dbg_printf("removed handler for signal %d", sig); return (0); diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index b09e108b1..73e81f252 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -70,10 +70,10 @@ windows_kqueue_init(struct kqueue *kq) } #endif - if(filter_register_all(kq) < 0) { - CloseHandle(kq->kq_iocp); - return (-1); - } + if(filter_register_all(kq) < 0) { + CloseHandle(kq->kq_iocp); + return (-1); + } return (0); } @@ -88,7 +88,7 @@ windows_kqueue_free(struct kqueue *kq) int windows_kevent_wait(struct kqueue *kq, int no, const struct timespec *timeout) { - int retval; + int retval; DWORD timeout_ms; BOOL success; @@ -134,7 +134,7 @@ windows_kevent_copyout(struct kqueue *kq, int nready, struct kevent *eventlist, int nevents) { struct filter *filt; - struct knote* kn; + struct knote* kn; int rv, nret; //FIXME: not true for EVFILT_IOCP @@ -166,17 +166,17 @@ windows_kevent_copyout(struct kqueue *kq, int nready, nret--; } - return nret; + return nret; } int windows_filter_init(struct kqueue *kq, struct filter *kf) { - kq->kq_filt_ref[kq->kq_filt_count] = (struct filter *) kf; + kq->kq_filt_ref[kq->kq_filt_count] = (struct filter *) kf; kq->kq_filt_count++; - return (0); + return (0); } void diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index caeba114f..8285f048e 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -55,9 +55,9 @@ * Additional members of struct kqueue */ #define KQUEUE_PLATFORM_SPECIFIC \ - HANDLE kq_iocp; \ - HANDLE kq_synthetic_event; \ - struct filter *kq_filt_ref[EVFILT_SYSCOUNT]; \ + HANDLE kq_iocp; \ + HANDLE kq_synthetic_event; \ + struct filter *kq_filt_ref[EVFILT_SYSCOUNT]; \ size_t kq_filt_count /* @@ -65,14 +65,14 @@ */ /* #define FILTER_PLATFORM_SPECIFIC \ - HANDLE kf_event_handle + HANDLE kf_event_handle */ /* * Additional members for struct knote */ #define KNOTE_PLATFORM_SPECIFIC \ - HANDLE kn_event_whandle + HANDLE kn_event_whandle /* * Some datatype forward declarations diff --git a/vendor/libkqueue/src/windows/read.c b/vendor/libkqueue/src/windows/read.c index 95a0c27fc..5898bc415 100644 --- a/vendor/libkqueue/src/windows/read.c +++ b/vendor/libkqueue/src/windows/read.c @@ -152,7 +152,7 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) kn->data.handle = evt; if (RegisterWaitForSingleObject(&kn->kn_event_whandle, evt, - evfilt_read_callback, kn, INFINITE, 0) == 0) { + evfilt_read_callback, kn, INFINITE, 0) == 0) { dbg_puts("RegisterWaitForSingleObject failed"); CloseHandle(evt); return (-1); @@ -174,14 +174,14 @@ evfilt_read_knote_delete(struct filter *filt, struct knote *kn) if (kn->data.handle == NULL || kn->kn_event_whandle == NULL) return (0); - if(!UnregisterWaitEx(kn->kn_event_whandle, INVALID_HANDLE_VALUE)) { - dbg_lasterror("UnregisterWait()"); - return (-1); - } - if (!WSACloseEvent(kn->data.handle)) { - dbg_wsalasterror("WSACloseEvent()"); - return (-1); - } + if(!UnregisterWaitEx(kn->kn_event_whandle, INVALID_HANDLE_VALUE)) { + dbg_lasterror("UnregisterWait()"); + return (-1); + } + if (!WSACloseEvent(kn->data.handle)) { + dbg_wsalasterror("WSACloseEvent()"); + return (-1); + } kn->data.handle = NULL; return (0); diff --git a/vendor/libkqueue/src/windows/timer.c b/vendor/libkqueue/src/windows/timer.c index 5d84a1d73..82cd30852 100644 --- a/vendor/libkqueue/src/windows/timer.c +++ b/vendor/libkqueue/src/windows/timer.c @@ -20,7 +20,7 @@ static void convert_msec_to_filetime(LARGE_INTEGER *dst, intptr_t src) { - dst->QuadPart = -((int64_t) src * 1000 * 10); + dst->QuadPart = -((int64_t) src * 1000 * 10); } static int @@ -30,61 +30,61 @@ ktimer_delete(struct filter *filt, struct knote *kn) if (kn->data.handle == NULL || kn->kn_event_whandle == NULL) return (0); - if(!UnregisterWaitEx(kn->kn_event_whandle, INVALID_HANDLE_VALUE)) { - dbg_lasterror("UnregisterWait()"); - return (-1); - } - - if (!CancelWaitableTimer(kn->data.handle)) { - dbg_lasterror("CancelWaitableTimer()"); - return (-1); - } - if (!CloseHandle(kn->data.handle)) { - dbg_lasterror("CloseHandle()"); - return (-1); - } - - if( !(kn->kev.flags & EV_ONESHOT) ) - knote_release(kn); - - kn->data.handle = NULL; - return (0); + if(!UnregisterWaitEx(kn->kn_event_whandle, INVALID_HANDLE_VALUE)) { + dbg_lasterror("UnregisterWait()"); + return (-1); + } + + if (!CancelWaitableTimer(kn->data.handle)) { + dbg_lasterror("CancelWaitableTimer()"); + return (-1); + } + if (!CloseHandle(kn->data.handle)) { + dbg_lasterror("CloseHandle()"); + return (-1); + } + + if( !(kn->kev.flags & EV_ONESHOT) ) + knote_release(kn); + + kn->data.handle = NULL; + return (0); } static VOID CALLBACK evfilt_timer_callback(void* param, BOOLEAN fired){ - struct knote* kn; - struct kqueue* kq; - - if(fired){ - dbg_puts("called, but timer did not fire - this case should never be reached"); - return; - } - - assert(param); - kn = (struct knote*)param; - - if(kn->kn_flags & KNFL_KNOTE_DELETED) { - dbg_puts("knote marked for deletion, skipping event"); - return; - } else { - kq = kn->kn_kq; - assert(kq); - - if (!PostQueuedCompletionStatus(kq->kq_iocp, 1, (ULONG_PTR) 0, (LPOVERLAPPED) kn)) { - dbg_lasterror("PostQueuedCompletionStatus()"); - return; - /* FIXME: need more extreme action */ - } + struct knote* kn; + struct kqueue* kq; + + if(fired){ + dbg_puts("called, but timer did not fire - this case should never be reached"); + return; + } + + assert(param); + kn = (struct knote*)param; + + if(kn->kn_flags & KNFL_KNOTE_DELETED) { + dbg_puts("knote marked for deletion, skipping event"); + return; + } else { + kq = kn->kn_kq; + assert(kq); + + if (!PostQueuedCompletionStatus(kq->kq_iocp, 1, (ULONG_PTR) 0, (LPOVERLAPPED) kn)) { + dbg_lasterror("PostQueuedCompletionStatus()"); + return; + /* FIXME: need more extreme action */ + } #if DEADWOOD - evt_signal(kq->kq_loop, EVT_WAKEUP, kn); + evt_signal(kq->kq_loop, EVT_WAKEUP, kn); #endif - } - if(kn->kev.flags & EV_ONESHOT) { - struct filter* filt; - if( filter_lookup(&filt, kq, kn->kev.filter) ) - dbg_perror("filter_lookup()"); - knote_release(kn); - } + } + if(kn->kev.flags & EV_ONESHOT) { + struct filter* filt; + if( filter_lookup(&filt, kq, kn->kev.filter) ) + dbg_perror("filter_lookup()"); + knote_release(kn); + } } int @@ -102,21 +102,21 @@ int evfilt_timer_copyout(struct kevent* dst, struct knote* src, void* ptr) { memcpy(dst, &src->kev, sizeof(struct kevent)); - // TODO: Timer error handling + // TODO: Timer error handling /* We have no way to determine the number of times the timer triggered, thus we assume it was only once */ dst->data = 1; - return (0); + return (0); } int evfilt_timer_knote_create(struct filter *filt, struct knote *kn) { HANDLE th; - LARGE_INTEGER liDueTime; + LARGE_INTEGER liDueTime; kn->kev.flags |= EV_CLEAR; @@ -129,7 +129,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) convert_msec_to_filetime(&liDueTime, kn->kev.data); - // XXX-FIXME add completion routine to this call + // XXX-FIXME add completion routine to this call if (!SetWaitableTimer(th, &liDueTime, (LONG)( (kn->kev.flags & EV_ONESHOT) ? 0 : kn->kev.data ), NULL, NULL, FALSE)) { dbg_lasterror("SetWaitableTimer()"); CloseHandle(th); @@ -137,8 +137,8 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) } kn->data.handle = th; - RegisterWaitForSingleObject(&kn->kn_event_whandle, th, evfilt_timer_callback, kn, INFINITE, 0); - knote_retain(kn); + RegisterWaitForSingleObject(&kn->kn_event_whandle, th, evfilt_timer_callback, kn, INFINITE, 0); + knote_retain(kn); return (0); } diff --git a/vendor/libkqueue/src/windows/user.c b/vendor/libkqueue/src/windows/user.c index fa0b3d481..e3a8885eb 100644 --- a/vendor/libkqueue/src/windows/user.c +++ b/vendor/libkqueue/src/windows/user.c @@ -45,13 +45,13 @@ evfilt_user_copyout(struct kevent* dst, struct knote* src, void* ptr) if (src->kev.flags & EV_DISPATCH) src->kev.fflags &= ~NOTE_TRIGGER; - return (0); + return (0); } int evfilt_user_knote_create(struct filter *filt, struct knote *kn) { - return (0); + return (0); } int @@ -87,10 +87,10 @@ evfilt_user_knote_modify(struct filter *filt, struct knote *kn, if ((!(kn->kev.flags & EV_DISABLE)) && kev->fflags & NOTE_TRIGGER) { kn->kev.fflags |= NOTE_TRIGGER; - if (!PostQueuedCompletionStatus(kn->kn_kq->kq_iocp, 1, (ULONG_PTR) 0, (LPOVERLAPPED) kn)) { - dbg_lasterror("PostQueuedCompletionStatus()"); - return (-1); - } + if (!PostQueuedCompletionStatus(kn->kn_kq->kq_iocp, 1, (ULONG_PTR) 0, (LPOVERLAPPED) kn)) { + dbg_lasterror("PostQueuedCompletionStatus()"); + return (-1); + } } return (0); From ebc756924b75b038ee7902d04f8310ec04412fca Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 31 Mar 2019 15:19:05 -0400 Subject: [PATCH 0692/1120] Ignore ctags file --- vendor/libkqueue/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/.gitignore b/vendor/libkqueue/.gitignore index d0b4a3281..725956cf9 100644 --- a/vendor/libkqueue/.gitignore +++ b/vendor/libkqueue/.gitignore @@ -14,6 +14,7 @@ cmake_install.cmake install_manifest*.txt kqueue-*.deb libkqueue.so +tags test/CMakeCache.txt test/CMakeFiles/ test/cmake_install.cmake From 49b4cd9a0b6ddf57536411f7c3cd3ddb0d25d1bc Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 31 Mar 2019 15:25:09 -0400 Subject: [PATCH 0693/1120] Bump Vagrantfile to Bionic This gets us the cmake version we need to build libkqueue --- vendor/libkqueue/Vagrantfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/Vagrantfile b/vendor/libkqueue/Vagrantfile index 33cbbdd71..f8d1dc4a5 100644 --- a/vendor/libkqueue/Vagrantfile +++ b/vendor/libkqueue/Vagrantfile @@ -12,7 +12,7 @@ Vagrant.configure("2") do |config| # Every Vagrant development environment requires a box. You can search for # boxes at https://atlas.hashicorp.com/search. - config.vm.box = "ubuntu/xenial64" + config.vm.box = "ubuntu/bionic64" # Disable automatic box update checking. If you disable this, then # boxes will only be checked for updates when the user runs From cfa048f42103e0a530bbac192f2a64c44ca8e569 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 2 Apr 2019 14:40:05 -0400 Subject: [PATCH 0694/1120] Ignore all versions of libkqueue.so --- vendor/libkqueue/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/.gitignore b/vendor/libkqueue/.gitignore index 725956cf9..3e6cea916 100644 --- a/vendor/libkqueue/.gitignore +++ b/vendor/libkqueue/.gitignore @@ -13,7 +13,7 @@ _CPack_Packages/ cmake_install.cmake install_manifest*.txt kqueue-*.deb -libkqueue.so +libkqueue.so* tags test/CMakeCache.txt test/CMakeFiles/ From 7c6cd12b8ea78860484fcb7a2b875ccb5985cbf5 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 2 Apr 2019 15:18:03 -0400 Subject: [PATCH 0695/1120] Use shorter buffer for proc path --- vendor/libkqueue/src/linux/platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index d358002d8..f2101c4ae 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -737,9 +737,9 @@ epoll_update(int op, struct filter *filt, struct knote *kn, struct epoll_event * int linux_fd_to_path(char *buf, size_t bufsz, int fd) { - char path[1024]; //TODO: Maxpathlen, etc. + char path[51]; // 6 + 20 + 4 + 20 + 1 - if (snprintf(&path[0], sizeof(path), "/proc/%d/fd/%d", getpid(), fd) < 0) + if (snprintf(path, sizeof(path), "/proc/%d/fd/%d", getpid(), fd) < 0) return (-1); memset(buf, 0, bufsz); From 3fba14720d7d308e840ac7f381fb8bf45438bc9e Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 8 May 2019 19:55:05 -0400 Subject: [PATCH 0696/1120] Use RB_FOREACH_SAFE in knote_free_all so we don't get SEGVs when kqueues are cleaned up I guess this wasn't found before because kqueues _were not_ cleaned up. --- vendor/libkqueue/src/common/knote.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 0fbfb6408..6d7b802e7 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -149,10 +149,10 @@ knote_get_by_data(struct filter *filt, intptr_t data) int knote_free_all(struct filter *filt) { - struct knote *kn; + struct knote *kn, *tmp; pthread_rwlock_rdlock(&filt->kf_knote_mtx); - RB_FOREACH(kn, knt, &filt->kf_knote) { + RB_FOREACH_SAFE(kn, knt, &filt->kf_knote, tmp) { /* Check return code */ filt->kn_delete(filt, kn); From 01bb92c23b3dfcbc0393c40910cf6de55366e592 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sat, 18 Jan 2020 10:27:21 -0500 Subject: [PATCH 0697/1120] Detect raw sockets --- vendor/libkqueue/src/common/private.h | 4 +++- vendor/libkqueue/src/linux/platform.c | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 8e22b01bb..3c2efe62d 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -75,11 +75,13 @@ struct eventfd { #define KNFL_SOCKET_DGRAM (1U << 6U) #define KNFL_SOCKET_RDM (1U << 7U) #define KNFL_SOCKET_SEQPACKET (1U << 8U) +#define KNFL_SOCKET_RAW (1U << 9U) #define KNFL_KNOTE_DELETED (1U << 31U) #define KNFL_SOCKET (KNFL_SOCKET_STREAM |\ KNFL_SOCKET_DGRAM |\ KNFL_SOCKET_RDM |\ - KNFL_SOCKET_SEQPACKET) + KNFL_SOCKET_SEQPACKET |\ + KNFL_SOCKET_RAW) struct knote { struct kevent kev; diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index f2101c4ae..c78f207e6 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -649,6 +649,11 @@ linux_get_descriptor_type(struct knote *kn) kn->kn_flags |= KNFL_SOCKET_SEQPACKET; break; + case SOCK_RAW: + dbg_printf("fd %d is a raw socket\n", fd); + kn->kn_flags |= KNFL_SOCKET_RAW; + break; + default: errno = EBADF; dbg_perror("unknown socket type"); From b9d9c176a86d8bf804f8d0ba8b3a4856f60b7e97 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sat, 18 Jan 2020 20:52:50 -0500 Subject: [PATCH 0698/1120] Update comment --- vendor/libkqueue/src/linux/platform.c | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index c78f207e6..cc6e52dab 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -558,6 +558,7 @@ linux_eventfd_descriptor(struct eventfd *e) * - KNFL_SOCKET_DGRAM FD is a datagram socket (unreliable connectionless messages). * - KNFL_SOCKET_RDM FD is a reliable datagram socket (reliable connectionless messages). * - KNFL_SOCKET_SEQPACKET FD is a sequenced packet socket (reliable connection-oriented messages). + * - KNFL_SOCKET_RAW FD is a raw socket as documented in raw(7). * * Additionally KNFL_SOCKET_* types may have the KNFL_SOCKET_PASSIVE flag set if they * are never expected to return data, but only provide an indication of whether data is available. From 249014596b79ca9838c9014922c64924f3288f29 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 28 Jan 2020 16:42:14 -0700 Subject: [PATCH 0699/1120] Use high-resolution wait on Linux for timeouts finer than a millisecond --- vendor/libkqueue/src/linux/platform.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index cc6e52dab..cb060b06e 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -386,8 +386,9 @@ linux_kevent_wait( { int timeout, nret; - /* Use a high-resolution syscall if the timeout value is less than one millisecond. */ - if (ts != NULL && ts->tv_sec == 0 && ts->tv_nsec > 0 && ts->tv_nsec < 1000000) { + /* Use a high-resolution syscall if the timeout value's tv_nsec value has a resolution + * finer than a millisecond. */ + if (ts != NULL && (ts->tv_nsec % 1000000 != 0)) { nret = linux_kevent_wait_hires(kq, ts); if (nret <= 0) return (nret); From 954836e2551b76c62ec3f1cc7035f1a8ccaff041 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 30 Jan 2020 15:36:40 -0500 Subject: [PATCH 0700/1120] Fix illegal access on the cleanup pipe under linux Closes #70 --- vendor/libkqueue/src/linux/platform.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index cb060b06e..b6c7911a8 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -290,6 +290,8 @@ linux_kqueue_cleanup(struct kqueue *kq) { char buffer; ssize_t ret; + int pipefd; + filter_unregister_all(kq); if (kq->epollfd > 0) { close(kq->epollfd); @@ -314,12 +316,13 @@ linux_kqueue_cleanup(struct kqueue *kq) dbg_puts("Unexpected data available on kqueue FD"); } - if (kq->pipefd[0] > 0) { - close(kq->pipefd[0]); + pipefd = kq->pipefd[0]; + if (pipefd > 0) { + close(pipefd); kq->pipefd[0] = -1; } - fd_map[kq->pipefd[0]] = 0; + fd_map[pipefd] = 0; /* Decrement kqueue counter */ kqueue_cnt--; From c05f474cec7359d368a9586cbe60703ee334aa0f Mon Sep 17 00:00:00 2001 From: WqyJh <781345688@qq.com> Date: Mon, 25 May 2020 19:19:21 +0800 Subject: [PATCH 0701/1120] Fix kevent_add() failed on CentOS 6 kevent_add() was failed on CentOS 6.8 due to error of getsockopt(SO_GET_FILTER) in linux_get_descriptor_type(). The SO_GET_FILTER option was introduced since Linux kernel 3.8, which would be defined as SO_ATTACH_FILTER in src/linux/platform.c, causing the getsockopt() failed. --- vendor/libkqueue/src/linux/platform.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index b6c7911a8..1e69f66d9 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -20,9 +20,6 @@ #include #include "../common/private.h" -#ifndef SO_GET_FILTER -#define SO_GET_FILTER SO_ATTACH_FILTER -#endif //XXX-FIXME TEMP const struct filter evfilt_proc = EVFILT_NOTIMPL; @@ -581,7 +578,6 @@ linux_get_descriptor_type(struct knote *kn) socklen_t slen; struct stat sb; int ret, lsock, stype; - socklen_t out_len; const int fd = (int)kn->kev.ident; /* @@ -680,13 +676,14 @@ linux_get_descriptor_type(struct knote *kn) } else if (lsock) kn->kn_flags |= KNFL_SOCKET_PASSIVE; +#ifdef SO_GET_FILTER /* * Test if socket has a filter * pcap file descriptors need to be considered as passive sockets as * SIOCINQ always returns 0 even if data is available. * Looking at SO_GET_FILTER is a good way of doing this. */ - out_len = 0; + socklen_t out_len = 0; ret = getsockopt(fd, SOL_SOCKET, SO_GET_FILTER, NULL, &out_len); if (ret < 0) { switch (errno) { @@ -698,6 +695,7 @@ linux_get_descriptor_type(struct knote *kn) } } else if (out_len) kn->kn_flags |= KNFL_SOCKET_PASSIVE; +#endif /* SO_GET_FILTER */ return (0); } From 32d32032185303d08ffb20e37c31a7f90537a7d5 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 25 May 2020 08:47:30 -0500 Subject: [PATCH 0702/1120] Formatting changes --- vendor/libkqueue/src/linux/platform.c | 39 ++++++++++++++------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 1e69f66d9..9a6fe5996 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -677,24 +677,27 @@ linux_get_descriptor_type(struct knote *kn) kn->kn_flags |= KNFL_SOCKET_PASSIVE; #ifdef SO_GET_FILTER - /* - * Test if socket has a filter - * pcap file descriptors need to be considered as passive sockets as - * SIOCINQ always returns 0 even if data is available. - * Looking at SO_GET_FILTER is a good way of doing this. - */ - socklen_t out_len = 0; - ret = getsockopt(fd, SOL_SOCKET, SO_GET_FILTER, NULL, &out_len); - if (ret < 0) { - switch (errno) { - case ENOTSOCK: /* same as lsock = 0 */ - break; - default: - dbg_perror("getsockopt(3)"); - return (-1); - } - } else if (out_len) - kn->kn_flags |= KNFL_SOCKET_PASSIVE; + { + socklen_t out_len = 0; + + /* + * Test if socket has a filter + * pcap file descriptors need to be considered as passive sockets as + * SIOCINQ always returns 0 even if data is available. + * Looking at SO_GET_FILTER is a good way of doing this. + */ + ret = getsockopt(fd, SOL_SOCKET, SO_GET_FILTER, NULL, &out_len); + if (ret < 0) { + switch (errno) { + case ENOTSOCK: /* same as lsock = 0 */ + break; + default: + dbg_perror("getsockopt(3)"); + return (-1); + } + } else if (out_len) + kn->kn_flags |= KNFL_SOCKET_PASSIVE; + } #endif /* SO_GET_FILTER */ return (0); From ba826c38e1b88cff01114c7deaf87e6a4c9a8afb Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 7 Jun 2020 13:01:48 -0500 Subject: [PATCH 0703/1120] Use field names when initialising filters, and fix issue in src/posix/proc.c where evfilt_proc_copyin was assigned to the wrong field --- vendor/libkqueue/src/common/private.h | 2 +- vendor/libkqueue/src/linux/proc.c | 16 ++++++-------- vendor/libkqueue/src/linux/read.c | 16 ++++++-------- vendor/libkqueue/src/linux/signal.c | 16 ++++++-------- vendor/libkqueue/src/linux/timer.c | 16 ++++++-------- vendor/libkqueue/src/linux/user.c | 16 ++++++-------- vendor/libkqueue/src/linux/vnode.c | 16 ++++++-------- vendor/libkqueue/src/linux/write.c | 16 ++++++-------- vendor/libkqueue/src/posix/proc.c | 12 +++++----- vendor/libkqueue/src/posix/signal.c | 18 +++++++-------- vendor/libkqueue/src/posix/timer.c | 18 +++++++-------- vendor/libkqueue/src/posix/user.c | 18 +++++++-------- vendor/libkqueue/src/solaris/signal.c | 16 ++++++-------- vendor/libkqueue/src/solaris/socket.c | 32 ++++++++++++--------------- vendor/libkqueue/src/solaris/timer.c | 18 +++++++-------- vendor/libkqueue/src/solaris/user.c | 16 ++++++-------- vendor/libkqueue/src/windows/read.c | 16 ++++++-------- vendor/libkqueue/src/windows/timer.c | 18 +++++++-------- vendor/libkqueue/src/windows/user.c | 18 +++++++-------- 19 files changed, 145 insertions(+), 169 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 3c2efe62d..657b137a9 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -168,7 +168,7 @@ struct filter { }; /* Use this to declare a filter that is not implemented */ -#define EVFILT_NOTIMPL { 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } +#define EVFILT_NOTIMPL { .kf_id = 0 } /** Structure representing a notification channel * diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index 4c9cba657..c2a49148b 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -231,13 +231,11 @@ evfilt_proc_knote_disable(struct filter *filt, struct knote *kn) } const struct filter evfilt_proc_DEADWOOD = { - 0, //XXX-FIXME broken: EVFILT_PROC, - evfilt_proc_init, - evfilt_proc_destroy, - evfilt_proc_copyout, - evfilt_proc_knote_create, - evfilt_proc_knote_modify, - evfilt_proc_knote_delete, - evfilt_proc_knote_enable, - evfilt_proc_knote_disable, + .kf_id = 0, //XXX-FIXME broken: EVFILT_PROC, + .kf_copyout = evfilt_proc_copyout, + .kn_create = evfilt_proc_knote_create, + .kn_modify = evfilt_proc_knote_modify, + .kn_delete = evfilt_proc_knote_delete, + .kn_enable = evfilt_proc_knote_enable, + .kn_disable = evfilt_proc_knote_disable, }; diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index efb712245..da56a36d5 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -274,13 +274,11 @@ evfilt_read_knote_disable(struct filter *filt, struct knote *kn) } const struct filter evfilt_read = { - EVFILT_READ, - NULL, - NULL, - evfilt_read_copyout, - evfilt_read_knote_create, - evfilt_read_knote_modify, - evfilt_read_knote_delete, - evfilt_read_knote_enable, - evfilt_read_knote_disable, + .kf_id = EVFILT_READ, + .kf_copyout = evfilt_read_copyout, + .kn_create = evfilt_read_knote_create, + .kn_modify = evfilt_read_knote_modify, + .kn_delete = evfilt_read_knote_delete, + .kn_enable = evfilt_read_knote_enable, + .kn_disable = evfilt_read_knote_disable, }; diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index 4766b524d..2e23c238a 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -206,13 +206,11 @@ evfilt_signal_knote_disable(struct filter *filt, struct knote *kn) const struct filter evfilt_signal = { - EVFILT_SIGNAL, - NULL, - NULL, - evfilt_signal_copyout, - evfilt_signal_knote_create, - evfilt_signal_knote_modify, - evfilt_signal_knote_delete, - evfilt_signal_knote_enable, - evfilt_signal_knote_disable, + .kf_id = EVFILT_SIGNAL, + .kf_copyout = evfilt_signal_copyout, + .kn_create = evfilt_signal_knote_create, + .kn_modify = evfilt_signal_knote_modify, + .kn_delete = evfilt_signal_knote_delete, + .kn_enable = evfilt_signal_knote_enable, + .kn_disable = evfilt_signal_knote_disable, }; diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 7a210599e..31eb62018 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -235,13 +235,11 @@ evfilt_timer_knote_disable(struct filter *filt, struct knote *kn) } const struct filter evfilt_timer = { - EVFILT_TIMER, - NULL, - NULL, - evfilt_timer_copyout, - evfilt_timer_knote_create, - evfilt_timer_knote_modify, - evfilt_timer_knote_delete, - evfilt_timer_knote_enable, - evfilt_timer_knote_disable, + .kf_id = EVFILT_TIMER, + .kf_copyout = evfilt_timer_copyout, + .kn_create = evfilt_timer_knote_create, + .kn_modify = evfilt_timer_knote_modify, + .kn_delete = evfilt_timer_knote_delete, + .kn_enable = evfilt_timer_knote_enable, + .kn_disable = evfilt_timer_knote_disable, }; diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index cb7cb1b88..6c53e8318 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -221,13 +221,11 @@ linux_evfilt_user_knote_disable(struct filter *filt, struct knote *kn) } const struct filter evfilt_user = { - EVFILT_USER, - NULL, - NULL, - linux_evfilt_user_copyout, - linux_evfilt_user_knote_create, - linux_evfilt_user_knote_modify, - linux_evfilt_user_knote_delete, - linux_evfilt_user_knote_enable, - linux_evfilt_user_knote_disable, + .kf_id = EVFILT_USER, + .kf_copyout = linux_evfilt_user_copyout, + .kn_create = linux_evfilt_user_knote_create, + .kn_modify = linux_evfilt_user_knote_modify, + .kn_delete = linux_evfilt_user_knote_delete, + .kn_enable = linux_evfilt_user_knote_enable, + .kn_disable = linux_evfilt_user_knote_disable, }; diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index c275e4a6c..137cea5b9 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -294,13 +294,11 @@ evfilt_vnode_knote_disable(struct filter *filt, struct knote *kn) } const struct filter evfilt_vnode = { - EVFILT_VNODE, - NULL, - NULL, - evfilt_vnode_copyout, - evfilt_vnode_knote_create, - evfilt_vnode_knote_modify, - evfilt_vnode_knote_delete, - evfilt_vnode_knote_enable, - evfilt_vnode_knote_disable, + .kf_id = EVFILT_VNODE, + .kf_copyout = evfilt_vnode_copyout, + .kn_create = evfilt_vnode_knote_create, + .kn_modify = evfilt_vnode_knote_modify, + .kn_delete = evfilt_vnode_knote_delete, + .kn_enable = evfilt_vnode_knote_enable, + .kn_disable = evfilt_vnode_knote_disable, }; diff --git a/vendor/libkqueue/src/linux/write.c b/vendor/libkqueue/src/linux/write.c index e31b93f6d..09ad80530 100644 --- a/vendor/libkqueue/src/linux/write.c +++ b/vendor/libkqueue/src/linux/write.c @@ -129,13 +129,11 @@ evfilt_write_knote_disable(struct filter *filt, struct knote *kn) } const struct filter evfilt_write = { - EVFILT_WRITE, - NULL, - NULL, - evfilt_write_copyout, - evfilt_write_knote_create, - evfilt_write_knote_modify, - evfilt_write_knote_delete, - evfilt_write_knote_enable, - evfilt_write_knote_disable, + .kf_id = EVFILT_WRITE, + .kf_copyout = evfilt_write_copyout, + .kn_create = evfilt_write_knote_create, + .kn_modify = evfilt_write_knote_modify, + .kn_delete = evfilt_write_knote_delete, + .kn_enable = evfilt_write_knote_enable, + .kn_disable = evfilt_write_knote_disable, }; diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 64e53e068..9c4feeb25 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -130,7 +130,7 @@ evfilt_proc_destroy(struct filter *filt) } int -evfilt_proc_copyin(struct filter *filt, +evfilt_proc_create(struct filter *filt, struct knote *dst, const struct kevent *src) { if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) { @@ -182,9 +182,9 @@ evfilt_proc_copyout(struct filter *filt, } const struct filter evfilt_proc = { - EVFILT_PROC, - evfilt_proc_init, - evfilt_proc_destroy, - evfilt_proc_copyin, - evfilt_proc_copyout, + .kf_id = EVFILT_PROC, + .kf_init = evfilt_proc_init, + .kf_destroy = evfilt_proc_destroy, + .kf_copyout = evfilt_proc_copyout, + .kn_create = evfilt_proc_create, }; diff --git a/vendor/libkqueue/src/posix/signal.c b/vendor/libkqueue/src/posix/signal.c index a6621082e..dac284cba 100644 --- a/vendor/libkqueue/src/posix/signal.c +++ b/vendor/libkqueue/src/posix/signal.c @@ -214,13 +214,13 @@ evfilt_signal_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) } const struct filter evfilt_signal = { - EVFILT_SIGNAL, - evfilt_signal_init, - evfilt_signal_destroy, - evfilt_signal_copyout, - evfilt_signal_knote_create, - evfilt_signal_knote_modify, - evfilt_signal_knote_delete, - evfilt_signal_knote_enable, - evfilt_signal_knote_disable, + .kf_id = EVFILT_SIGNAL, + .kf_init = evfilt_signal_init, + .kf_destroy = evfilt_signal_destroy, + .kf_copyout = evfilt_signal_copyout, + .kn_create = evfilt_signal_knote_create, + .kn_modify = evfilt_signal_knote_modify, + .kn_delete = evfilt_signal_knote_delete, + .kn_enable = evfilt_signal_knote_enable, + .kn_disable = evfilt_signal_knote_disable, }; diff --git a/vendor/libkqueue/src/posix/timer.c b/vendor/libkqueue/src/posix/timer.c index 7eaeabdd0..2afa28bb2 100644 --- a/vendor/libkqueue/src/posix/timer.c +++ b/vendor/libkqueue/src/posix/timer.c @@ -315,13 +315,13 @@ evfilt_timer_knote_disable(struct filter *filt, struct knote *kn) } const struct filter evfilt_timer = { - EVFILT_TIMER, - evfilt_timer_init, - evfilt_timer_destroy, - evfilt_timer_copyout, - evfilt_timer_knote_create, - evfilt_timer_knote_modify, - evfilt_timer_knote_delete, - evfilt_timer_knote_enable, - evfilt_timer_knote_disable, + .kf_id = EVFILT_TIMER, + .kf_init = evfilt_timer_init, + .kf_destroy = evfilt_timer_destroy, + .kf_copyout = evfilt_timer_copyout, + .kn_create = evfilt_timer_knote_create, + .kn_modify = evfilt_timer_knote_modify, + .kn_delete = evfilt_timer_knote_delete, + .kn_enable = evfilt_timer_knote_enable, + .kn_disable = evfilt_timer_knote_disable, }; diff --git a/vendor/libkqueue/src/posix/user.c b/vendor/libkqueue/src/posix/user.c index 497254b6c..6e13ea98f 100644 --- a/vendor/libkqueue/src/posix/user.c +++ b/vendor/libkqueue/src/posix/user.c @@ -152,15 +152,15 @@ posix_evfilt_user_knote_disable(struct filter *filt, struct knote *kn) /* FIXME: this conflicts with the struct in linux/platform.c const struct filter evfilt_user = { - EVFILT_USER, - evfilt_user_init, - evfilt_user_destroy, - evfilt_user_copyout, - evfilt_user_knote_create, - evfilt_user_knote_modify, - evfilt_user_knote_delete, - evfilt_user_knote_enable, - evfilt_user_knote_disable, + .kf_id = EVFILT_USER, + .kf_init = evfilt_user_init, + .kf_destroy = evfilt_user_destroy, + .kf_copyout = evfilt_user_copyout, + .kn_create = evfilt_user_knote_create, + .kn_modify = evfilt_user_knote_modify, + .kn_delete = evfilt_user_knote_delete, + .kn_enable = evfilt_user_knote_enable, + .kn_disable = evfilt_user_knote_disable, }; */ diff --git a/vendor/libkqueue/src/solaris/signal.c b/vendor/libkqueue/src/solaris/signal.c index 777a6087e..5a79e5da6 100644 --- a/vendor/libkqueue/src/solaris/signal.c +++ b/vendor/libkqueue/src/solaris/signal.c @@ -156,13 +156,11 @@ evfilt_signal_copyout(struct kevent *dst, struct knote *src, void *ptr) } const struct filter evfilt_signal = { - EVFILT_SIGNAL, - NULL, - NULL, - evfilt_signal_copyout, - evfilt_signal_knote_create, - evfilt_signal_knote_modify, - evfilt_signal_knote_delete, - evfilt_signal_knote_enable, - evfilt_signal_knote_disable, + .kf_id = EVFILT_SIGNAL, + .kf_copyout = evfilt_signal_copyout, + .kn_create = evfilt_signal_knote_create, + .kn_modify = evfilt_signal_knote_modify, + .kn_delete = evfilt_signal_knote_delete, + .kn_enable = evfilt_signal_knote_enable, + .kn_disable = evfilt_signal_knote_disable, }; diff --git a/vendor/libkqueue/src/solaris/socket.c b/vendor/libkqueue/src/solaris/socket.c index e04a707c0..faed786b2 100644 --- a/vendor/libkqueue/src/solaris/socket.c +++ b/vendor/libkqueue/src/solaris/socket.c @@ -138,25 +138,21 @@ evfilt_socket_copyout(struct kevent *dst, struct knote *src, void *ptr) } const struct filter evfilt_read = { - EVFILT_READ, - NULL, - NULL, - evfilt_socket_copyout, - evfilt_socket_knote_create, - evfilt_socket_knote_modify, - evfilt_socket_knote_delete, - evfilt_socket_knote_enable, - evfilt_socket_knote_disable, + .kf_id = EVFILT_READ, + .kf_copyout = evfilt_socket_copyout, + .kn_create = evfilt_socket_knote_create, + .kn_modify = evfilt_socket_knote_modify, + .kn_delete = evfilt_socket_knote_delete, + .kn_enable = evfilt_socket_knote_enable, + .kn_disable = evfilt_socket_knote_disable, }; const struct filter evfilt_write = { - EVFILT_WRITE, - NULL, - NULL, - evfilt_socket_copyout, - evfilt_socket_knote_create, - evfilt_socket_knote_modify, - evfilt_socket_knote_delete, - evfilt_socket_knote_enable, - evfilt_socket_knote_disable, + .kf_id = EVFILT_WRITE, + .kf_copyout = evfilt_socket_copyout, + .kn_create = evfilt_socket_knote_create, + .kn_modify = evfilt_socket_knote_modify, + .kn_delete = evfilt_socket_knote_delete, + .kn_enable = evfilt_socket_knote_enable, + .kn_disable = evfilt_socket_knote_disable, }; diff --git a/vendor/libkqueue/src/solaris/timer.c b/vendor/libkqueue/src/solaris/timer.c index 9d0b5acfc..c19f5cd52 100644 --- a/vendor/libkqueue/src/solaris/timer.c +++ b/vendor/libkqueue/src/solaris/timer.c @@ -176,13 +176,13 @@ evfilt_timer_knote_disable(struct filter *filt, struct knote *kn) } const struct filter evfilt_timer = { - EVFILT_TIMER, - evfilt_timer_init, - evfilt_timer_destroy, - evfilt_timer_copyout, - evfilt_timer_knote_create, - evfilt_timer_knote_modify, - evfilt_timer_knote_delete, - evfilt_timer_knote_enable, - evfilt_timer_knote_disable, + .kf_id = EVFILT_TIMER, + .kf_init = evfilt_timer_init, + .kf_destroy = evfilt_timer_destroy, + .kf_copyout = evfilt_timer_copyout, + .kn_create = evfilt_timer_knote_create, + .kn_modify = evfilt_timer_knote_modify, + .kn_delete = evfilt_timer_knote_delete, + .kn_enable = evfilt_timer_knote_enable, + .kn_disable = evfilt_timer_knote_disable, }; diff --git a/vendor/libkqueue/src/solaris/user.c b/vendor/libkqueue/src/solaris/user.c index 03dac44c4..ac25dfa8a 100644 --- a/vendor/libkqueue/src/solaris/user.c +++ b/vendor/libkqueue/src/solaris/user.c @@ -124,13 +124,11 @@ evfilt_user_knote_disable(struct filter *filt UNUSED, struct knote *kn UNUSED) } const struct filter evfilt_user = { - EVFILT_USER, - NULL, - NULL, - evfilt_user_copyout, - evfilt_user_knote_create, - evfilt_user_knote_modify, - evfilt_user_knote_delete, - evfilt_user_knote_enable, - evfilt_user_knote_disable, + .kf_id = EVFILT_USER, + .kf_copyout = evfilt_user_copyout, + .kn_create = evfilt_user_knote_create, + .kn_modify = evfilt_user_knote_modify, + .kn_delete = evfilt_user_knote_delete, + .kn_enable = evfilt_user_knote_enable, + .kn_disable = evfilt_user_knote_disable, }; diff --git a/vendor/libkqueue/src/windows/read.c b/vendor/libkqueue/src/windows/read.c index 5898bc415..4b0685d35 100644 --- a/vendor/libkqueue/src/windows/read.c +++ b/vendor/libkqueue/src/windows/read.c @@ -200,13 +200,11 @@ evfilt_read_knote_disable(struct filter *filt, struct knote *kn) } const struct filter evfilt_read = { - EVFILT_READ, - NULL, - NULL, - evfilt_read_copyout, - evfilt_read_knote_create, - evfilt_read_knote_modify, - evfilt_read_knote_delete, - evfilt_read_knote_enable, - evfilt_read_knote_disable, + .kf_id = EVFILT_READ, + .kf_copyout = evfilt_read_copyout, + .kn_create = evfilt_read_knote_create, + .kn_modify = evfilt_read_knote_modify, + .kn_delete = evfilt_read_knote_delete, + .kn_enable = evfilt_read_knote_enable, + .kn_disable = evfilt_read_knote_disable, }; diff --git a/vendor/libkqueue/src/windows/timer.c b/vendor/libkqueue/src/windows/timer.c index 82cd30852..167af703e 100644 --- a/vendor/libkqueue/src/windows/timer.c +++ b/vendor/libkqueue/src/windows/timer.c @@ -169,13 +169,13 @@ evfilt_timer_knote_disable(struct filter *filt, struct knote *kn) } const struct filter evfilt_timer = { - EVFILT_TIMER, - evfilt_timer_init, - evfilt_timer_destroy, - evfilt_timer_copyout, - evfilt_timer_knote_create, - evfilt_timer_knote_modify, - evfilt_timer_knote_delete, - evfilt_timer_knote_enable, - evfilt_timer_knote_disable, + .kf_id = EVFILT_TIMER, + .kf_init = evfilt_timer_init, + .kf_destroy = evfilt_timer_destroy, + .kf_copyout = evfilt_timer_copyout, + .kn_create = evfilt_timer_knote_create, + .kn_modify = evfilt_timer_knote_modify, + .kn_delete = evfilt_timer_knote_delete, + .kn_enable = evfilt_timer_knote_enable, + .kn_disable = evfilt_timer_knote_disable, }; diff --git a/vendor/libkqueue/src/windows/user.c b/vendor/libkqueue/src/windows/user.c index e3a8885eb..b036d9729 100644 --- a/vendor/libkqueue/src/windows/user.c +++ b/vendor/libkqueue/src/windows/user.c @@ -115,13 +115,13 @@ evfilt_user_knote_disable(struct filter *filt, struct knote *kn) } const struct filter evfilt_user = { - EVFILT_USER, - evfilt_user_init, - evfilt_user_destroy, - evfilt_user_copyout, - evfilt_user_knote_create, - evfilt_user_knote_modify, - evfilt_user_knote_delete, - evfilt_user_knote_enable, - evfilt_user_knote_disable, + .kf_id = EVFILT_USER, + .kf_init = evfilt_user_init, + .kf_destroy = evfilt_user_destroy, + .kf_copyout = evfilt_user_copyout, + .kn_create = evfilt_user_knote_create, + .kn_modify = evfilt_user_knote_modify, + .kn_delete = evfilt_user_knote_delete, + .kn_enable = evfilt_user_knote_enable, + .kn_disable = evfilt_user_knote_disable, }; From c54a106044dc5623a25c039c57907e906dbd0af2 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 8 Jun 2020 13:32:02 -0500 Subject: [PATCH 0704/1120] Add doxygen header for filter_lookup --- vendor/libkqueue/src/common/filter.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index ae97f8a27..67bb63d75 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -132,6 +132,15 @@ filter_unregister_all(struct kqueue *kq) memset(&kq->kq_filt[0], 0, sizeof(kq->kq_filt)); } +/** Lookup filters in the array of filters registered for kq + * + * @param[out] filt the specified ID resolves to. + * @param[in] kq to lookup the filter in. + * @param[in] id of the filter to lookup. + * @return + * - 0 on success. + * - -1 on failure (filter not implemented). + */ int filter_lookup(struct filter **filt, struct kqueue *kq, short id) { From dec3db6e3cfdde7c17a201763dcf25ba927a68c7 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 8 Jun 2020 13:32:30 -0500 Subject: [PATCH 0705/1120] Remove some DEADWOOD --- vendor/libkqueue/src/common/filter.c | 18 +++--------------- vendor/libkqueue/src/common/knote.c | 20 -------------------- vendor/libkqueue/src/common/private.h | 1 - 3 files changed, 3 insertions(+), 36 deletions(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index 67bb63d75..e6be5c47e 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -69,21 +69,9 @@ filter_register(struct kqueue *kq, short filter, const struct filter *src) } } -#if DEADWOOD - /* Add the filter's event descriptor to the main fdset */ - if (dst->kf_pfd > 0) { - FD_SET(dst->kf_pfd, &kq->kq_fds); - if (dst->kf_pfd > kq->kq_nfds) - kq->kq_nfds = dst->kf_pfd; - dbg_printf("fds: added %d (nfds=%d)", dst->kf_pfd, kq->kq_nfds); - } - dbg_printf("filter %d (%s) registered", filter, filter_name(filter)); -#endif - - /* FIXME: should totally remove const from src */ - if (kqops.filter_init != NULL - && kqops.filter_init(kq, dst) < 0) - return (-1); + /* FIXME: should totally remove const from src */ + if ((kqops.filter_init != NULL) && (kqops.filter_init(kq, dst) < 0)) + return (-1); return (0); } diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 6d7b802e7..bf522fa61 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -127,26 +127,6 @@ knote_lookup(struct filter *filt, uintptr_t ident) return (ent); } -#if DEADWOOD -struct knote * -knote_get_by_data(struct filter *filt, intptr_t data) -{ - struct knote *kn; - - pthread_rwlock_rdlock(&filt->kf_knote_mtx); - RB_FOREACH(kn, knt, &filt->kf_knote) { - if (data == kn->kev.data) - break; - } - if (kn != NULL) { - knote_retain(kn); - } - pthread_rwlock_unlock(&filt->kf_knote_mtx); - - return (kn); -} -#endif - int knote_free_all(struct filter *filt) { struct knote *kn, *tmp; diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 657b137a9..09b78cf1e 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -224,7 +224,6 @@ extern const struct kqueue_vtable kqops; */ int knote_free_all(struct filter *filt); struct knote * knote_lookup(struct filter *, uintptr_t); -//DEADWOOD: struct knote * knote_get_by_data(struct filter *filt, intptr_t); struct knote * knote_new(void); #define knote_retain(kn) atomic_inc(&kn->kn_ref) void knote_release(struct knote *); From 75c9b95fb9d9d5e94f72b12ba98af433cee9fdf2 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 8 Jun 2020 20:19:48 -0500 Subject: [PATCH 0706/1120] Change filter registration function so that it takes the kf_id from the filter --- vendor/libkqueue/src/common/filter.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index e6be5c47e..4e9576fd8 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -32,13 +32,18 @@ extern const struct filter evfilt_timer; extern const struct filter evfilt_user; static int -filter_register(struct kqueue *kq, short filter, const struct filter *src) +filter_register(struct kqueue *kq, const struct filter *src) { struct filter *dst; unsigned int filt; int rv = 0; - filt = (-1 * filter) - 1; + /* + * This filter is not implemented, see EVFILT_NOTIMPL. + */ + if (src->kf_id == 0) return (0); + + filt = (-1 * src->kf_id) - 1; /* flip sign, and convert to array offset */ if (filt >= EVFILT_SYSCOUNT) return (-1); @@ -83,13 +88,13 @@ filter_register_all(struct kqueue *kq) FD_ZERO(&kq->kq_fds); rv = 0; - rv += filter_register(kq, EVFILT_READ, &evfilt_read); - rv += filter_register(kq, EVFILT_WRITE, &evfilt_write); - rv += filter_register(kq, EVFILT_SIGNAL, &evfilt_signal); - rv += filter_register(kq, EVFILT_VNODE, &evfilt_vnode); - rv += filter_register(kq, EVFILT_PROC, &evfilt_proc); - rv += filter_register(kq, EVFILT_TIMER, &evfilt_timer); - rv += filter_register(kq, EVFILT_USER, &evfilt_user); + rv += filter_register(kq, &evfilt_read); + rv += filter_register(kq, &evfilt_write); + rv += filter_register(kq, &evfilt_signal); + rv += filter_register(kq, &evfilt_vnode); + rv += filter_register(kq, &evfilt_proc); + rv += filter_register(kq, &evfilt_timer); + rv += filter_register(kq, &evfilt_user); kq->kq_nfds++; if (rv != 0) { filter_unregister_all(kq); From 8323e002885618eb3c6c713391386c702b50f7ce Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Tue, 9 Jun 2020 11:43:27 -0300 Subject: [PATCH 0707/1120] platform.c: Prevent potential dead-lock in linux_kqueue_init() --- vendor/libkqueue/src/linux/platform.c | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 9a6fe5996..d1795cc1b 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -245,6 +245,7 @@ linux_kqueue_init(struct kqueue *kq) sig_owner.pid = monitoring_tid; if (fcntl(kq->pipefd[0], F_SETOWN_EX, &sig_owner) < 0) { dbg_perror("failed settting F_SETOWN"); + (void) pthread_mutex_unlock(&kq_mtx); goto error; } From 9a663ea5e27d2f0102394c4063d75c18f1ea4944 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 8 Jun 2020 20:28:03 -0500 Subject: [PATCH 0708/1120] Change field indentation in struct filter --- vendor/libkqueue/src/common/private.h | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 09b78cf1e..7ba5248d4 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -134,28 +134,29 @@ struct knote { * */ struct filter { - short kf_id; + short kf_id; //!< EVFILT_* facility this filter provides. /* filter operations */ - int (*kf_init)(struct filter *); - void (*kf_destroy)(struct filter *); - int (*kf_copyout)(struct kevent *, struct knote *, void *); + int (*kf_init)(struct filter *); + void (*kf_destroy)(struct filter *); + int (*kf_copyout)(struct kevent *, struct knote *, void *); /* knote operations */ - int (*kn_create)(struct filter *, struct knote *); - int (*kn_modify)(struct filter *, struct knote *, + + int (*kn_create)(struct filter *, struct knote *); + int (*kn_modify)(struct filter *, struct knote *, const struct kevent *); - int (*kn_delete)(struct filter *, struct knote *); - int (*kn_enable)(struct filter *, struct knote *); - int (*kn_disable)(struct filter *, struct knote *); + int (*kn_delete)(struct filter *, struct knote *); + int (*kn_enable)(struct filter *, struct knote *); + int (*kn_disable)(struct filter *, struct knote *); struct eventfd kf_efd; /* Used by user.c */ //MOVE TO POSIX? - int kf_pfd; /* fd to poll(2) for readiness */ - int kf_wfd; /* fd to write when an event occurs */ + int kf_pfd; /* fd to poll(2) for readiness */ + int kf_wfd; /* fd to write when an event occurs */ //----? struct evfilt_data *kf_data; /* filter-specific data */ From 46fdb81e8454e34f4ce9d4fc2355a2cbeaa1989b Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Tue, 9 Jun 2020 16:20:27 -0300 Subject: [PATCH 0709/1120] platform.c: Fix slightly deadlock in thread_start() --- vendor/libkqueue/src/linux/platform.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index d1795cc1b..a2a275da3 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -105,14 +105,17 @@ monitoring_thread_start(void *arg) monitoring_tid = syscall(SYS_gettid); fd_map = calloc(nb_max_fd, sizeof(unsigned int)); - - if (fd_map == NULL) + if (fd_map == NULL) { + error: + (void) pthread_mutex_unlock(&kq_mtx); return NULL; + } fd_cleanup_cnt = calloc(nb_max_fd, sizeof(unsigned int)); - - if (fd_cleanup_cnt == NULL) - return NULL; + if (fd_cleanup_cnt == NULL){ + free(fd_map); + goto error; + } /* * Now that thread is initialized, let kqueue init resume From 0ad2be94d6cfc55e415d2ade2593f636e68f2d7c Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Tue, 9 Jun 2020 16:43:30 -0300 Subject: [PATCH 0710/1120] vnode: Fix missing inotify_rm_watch() --- vendor/libkqueue/src/linux/vnode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 137cea5b9..617de0050 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -158,6 +158,7 @@ add_watch(struct filter *filt, struct knote *kn) return (0); errout: + inotify_rm_watch(ifd, kn->kev.data); kn->kdata.kn_inotifyfd = -1; (void) close(ifd); return (-1); From b6a5c950815376cdd6ff68280fc14e0833b9838f Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 9 Jun 2020 14:25:52 -0500 Subject: [PATCH 0711/1120] s/fastpath/likely/g s/slowpath/unlikely/g same as Linux and everywhere else which uses these macros --- vendor/libkqueue/src/common/kevent.c | 2 +- vendor/libkqueue/src/common/map.c | 10 +++++----- vendor/libkqueue/src/linux/platform.c | 4 ++-- vendor/libkqueue/src/posix/platform.h | 4 ++-- vendor/libkqueue/src/windows/platform.c | 4 ++-- vendor/libkqueue/src/windows/platform.h | 8 ++++---- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index eb2483cc6..cd9d13f8c 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -281,7 +281,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, if (nevents > 0) { rv = kqops.kevent_wait(kq, nevents, timeout); dbg_printf("kqops.kevent_wait returned %d", rv); - if (fastpath(rv > 0)) { + if (likely(rv > 0)) { kqueue_lock(kq); rv = kqops.kevent_copyout(kq, rv, eventlist, nevents); kqueue_unlock(kq); diff --git a/vendor/libkqueue/src/common/map.c b/vendor/libkqueue/src/common/map.c index d3f2153c7..65c13c4b1 100644 --- a/vendor/libkqueue/src/common/map.c +++ b/vendor/libkqueue/src/common/map.c @@ -54,7 +54,7 @@ map_new(size_t len) int map_insert(struct map *m, int idx, void *ptr) { - if (slowpath(idx < 0 || idx > (int)m->len)) + if (unlikely(idx < 0 || idx > (int)m->len)) return (-1); if (atomic_ptr_cas(&(m->data[idx]), 0, ptr) == NULL) { @@ -71,7 +71,7 @@ map_insert(struct map *m, int idx, void *ptr) int map_remove(struct map *m, int idx, void *ptr) { - if (slowpath(idx < 0 || idx > (int)m->len)) + if (unlikely(idx < 0 || idx > (int)m->len)) return (-1); if (atomic_ptr_cas(&(m->data[idx]), ptr, 0) == NULL) { @@ -88,7 +88,7 @@ map_replace(struct map *m, int idx, void *oldp, void *newp) { void *tmp; - if (slowpath(idx < 0 || idx > (int)m->len)) + if (unlikely(idx < 0 || idx > (int)m->len)) return (-1); tmp = atomic_ptr_cas(&(m->data[idx]), oldp, newp); @@ -106,7 +106,7 @@ map_replace(struct map *m, int idx, void *oldp, void *newp) void * map_lookup(struct map *m, int idx) { - if (slowpath(idx < 0 || idx > (int)m->len)) + if (unlikely(idx < 0 || idx > (int)m->len)) return (NULL); return m->data[idx]; @@ -118,7 +118,7 @@ map_delete(struct map *m, int idx) void *oval; void *nval; - if (slowpath(idx < 0 || idx > (int)m->len)) + if (unlikely(idx < 0 || idx > (int)m->len)) return ((void *)-1); /* Hopefully we aren't racing with another thread, but you never know.. */ diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index d1795cc1b..e5bcdbc69 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -429,7 +429,7 @@ linux_kevent_copyout(struct kqueue *kq, int nready, kn = (struct knote *) ev->data.ptr; filt = &kq->kq_filt[~(kn->kev.filter)]; rv = filt->kf_copyout(eventlist, kn, ev); - if (slowpath(rv < 0)) { + if (unlikely(rv < 0)) { dbg_puts("knote_copyout failed"); /* XXX-FIXME: hard to handle this without losing events */ abort(); @@ -447,7 +447,7 @@ linux_kevent_copyout(struct kqueue *kq, int nready, /* If an empty kevent structure is returned, the event is discarded. */ /* TODO: add these semantics to windows + solaris platform.c */ - if (fastpath(eventlist->filter != 0)) { + if (likely(eventlist->filter != 0)) { eventlist++; } else { dbg_puts("spurious wakeup, discarding event"); diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index cc800b4a6..2ad8f92f3 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -33,8 +33,8 @@ /* * GCC-compatible branch prediction macros */ -#define fastpath(x) __builtin_expect((x), 1) -#define slowpath(x) __builtin_expect((x), 0) +#define likely(x) __builtin_expect((x), 1) +#define unlikely(x) __builtin_expect((x), 0) /* * GCC-compatible attributes diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 73e81f252..4f098162a 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -141,7 +141,7 @@ windows_kevent_copyout(struct kqueue *kq, int nready, kn = (struct knote *) iocp_buf.overlap; filt = &kq->kq_filt[~(kn->kev.filter)]; rv = filt->kf_copyout(eventlist, kn, &iocp_buf); - if (slowpath(rv < 0)) { + if (unlikely(rv < 0)) { dbg_puts("knote_copyout failed"); /* XXX-FIXME: hard to handle this without losing events */ abort(); @@ -159,7 +159,7 @@ windows_kevent_copyout(struct kqueue *kq, int nready, knote_delete(filt, kn); //TODO: Error checking /* If an empty kevent structure is returned, the event is discarded. */ - if (fastpath(eventlist->filter != 0)) { + if (likely(eventlist->filter != 0)) { eventlist++; } else { dbg_puts("spurious wakeup, discarding event"); diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 8285f048e..d2b3af456 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -96,11 +96,11 @@ int windows_get_descriptor_type(struct knote *); * GCC-compatible branch prediction macros */ #ifdef __GNUC__ -# define fastpath(x) __builtin_expect((x), 1) -# define slowpath(x) __builtin_expect((x), 0) +# define likely(x) __builtin_expect((x), 1) +# define unlikely(x) __builtin_expect((x), 0) #else -# define fastpath(x) (x) -# define slowpath(x) (x) +# define likely(x) (x) +# define unlikely(x) (x) #endif /* Function visibility macros */ From 8d15780e8ccf15869e7d04b972ccc8958a6e0f3d Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 9 Jun 2020 14:52:40 -0500 Subject: [PATCH 0712/1120] Initialise kqueue_vtable using field names - It makes it much easier when spulunking through the code, as you can easily identify where those callbacks are called without referring to the struct definition. - It allows struct field order to be modified without fixing up the struct initialises - No more useless NULLs --- vendor/libkqueue/src/linux/platform.c | 20 +++++++++----------- vendor/libkqueue/src/solaris/platform.c | 20 +++++++++----------- vendor/libkqueue/src/windows/platform.c | 12 ++++++------ 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index e5bcdbc69..75dbd924b 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -59,17 +59,15 @@ static unsigned int *fd_map; static unsigned int *fd_cleanup_cnt; const struct kqueue_vtable kqops = { - linux_kqueue_init, - linux_kqueue_free, - linux_kevent_wait, - linux_kevent_copyout, - NULL, - NULL, - linux_eventfd_init, - linux_eventfd_close, - linux_eventfd_raise, - linux_eventfd_lower, - linux_eventfd_descriptor + .kqueue_init = linux_kqueue_init, + .kqueue_free = linux_kqueue_free, + .kevent_wait = linux_kevent_wait, + .kevent_copyout = linux_kevent_copyout, + .eventfd_init = linux_eventfd_init, + .eventfd_close = linux_eventfd_close, + .eventfd_raise = linux_eventfd_raise, + .eventfd_lower = linux_eventfd_lower, + .eventfd_descriptor = linux_eventfd_descriptor, }; static bool diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index 6f2864ac3..57bbd6038 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -229,15 +229,13 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, const struct kqueue_vtable kqops = { - solaris_kqueue_init, - solaris_kqueue_free, - solaris_kevent_wait, - solaris_kevent_copyout, - NULL, - NULL, - posix_eventfd_init, - posix_eventfd_close, - posix_eventfd_raise, - posix_eventfd_lower, - posix_eventfd_descriptor + .kqueue_init = solaris_kqueue_init, + .kqueue_free = solaris_kqueue_free, + .kevent_wait = solaris_kevent_wait, + .kevent_copyout = solaris_kevent_copyout, + .eventfd_init = posix_eventfd_init, + .eventfd_close = posix_eventfd_close, + .eventfd_raise = posix_eventfd_raise, + .eventfd_lower = posix_eventfd_lower, + .eventfd_descriptor = posix_eventfd_descriptor, }; diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 4f098162a..e5483de6a 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -35,12 +35,12 @@ const struct filter evfilt_signal = EVFILT_NOTIMPL; const struct filter evfilt_write = EVFILT_NOTIMPL; const struct kqueue_vtable kqops = { - windows_kqueue_init, - windows_kqueue_free, - windows_kevent_wait, - windows_kevent_copyout, - windows_filter_init, - windows_filter_free, + .kqueue_init = windows_kqueue_init, + .kqueue_free = windows_kqueue_free, + .kevent_wait = windows_kevent_wait, + .kevent_copyout = windows_kevent_copyout, + .filter_init = windows_filter_init, + .filter_free = windows_filter_free }; int From c0314e1225f794e3dcf3416aa75202686f67b4fb Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Tue, 9 Jun 2020 17:22:58 -0300 Subject: [PATCH 0713/1120] read.c: Fix missing close() --- vendor/libkqueue/src/linux/proc.c | 2 +- vendor/libkqueue/src/linux/read.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index c2a49148b..8d7b61a13 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -105,7 +105,7 @@ wait_thread(void *arg) dbg_printf("write(2): %s", strerror(errno)); /* TODO: set filter error flag */ break; - } + } } } diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index da56a36d5..6e8ace036 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -190,6 +190,7 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_eventfd, &ev) < 0) { dbg_printf("epoll_ctl(2): %s", strerror(errno)); + (void) close(evfd); return (-1); } From 36a73e8cc0d5a6dafc154bfab7b9cf72a1c0da5d Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Tue, 9 Jun 2020 17:38:54 -0300 Subject: [PATCH 0714/1120] build: Allow set CMAKE_BUILD_TYPE It allows to build in debug mode like: e.g: cmake -DCMAKE_BUILD_TYPE=Debug ... --- vendor/libkqueue/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 5be54e4d3..9bddc01f5 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -30,7 +30,10 @@ set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD 99) -set(CMAKE_BUILD_TYPE RelWithDebInfo) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE RelWithDebInfo) +endif() option(STATIC_KQUEUE "build libkqueue as static library" OFF) From 513f07cdc9d389c45d4560081fb3aabf49c9dc6b Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 9 Jun 2020 15:53:46 -0500 Subject: [PATCH 0715/1120] Make it a proper debug build when running the unit tests --- vendor/libkqueue/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index 2d69256a7..1eeeeb538 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -63,7 +63,7 @@ Xcode (project) Running Unit Tests ------------------ - cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib -DENABLE_TESTING=YES + cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib -DENABLE_TESTING=YES -DCMAKE_BUILD_TYPE=Debug make make test From 15f8e3d17b460d0e7e53de5ec95bebf8c7e9b70f Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 9 Jun 2020 15:55:16 -0500 Subject: [PATCH 0716/1120] Update README.md --- vendor/libkqueue/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index 1eeeeb538..9f4e07395 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -70,7 +70,10 @@ Running Unit Tests Debugging --------- -Ensure -DNDEBUG is *NOT* passed during compilation, otherwise all debug output will be disabled. +For best results add `-DCMAKE_BUILD_TYPE=Debug` to your cmake invocation. +At a minimum ensure -DNDEBUG is *NOT* passed during compilation, otherwise all debug output will be disabled. + +The environmental variable `KQUEUE_DEBUG` can then be set to enable debug output from libkqueue. KQUEUE_DEBUG=1 From 6b0d0eeda77ff3749f876f590876320a6c5b1cea Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 9 Jun 2020 15:24:24 -0500 Subject: [PATCH 0717/1120] Use a more obvious name for the function which returns the epoll fd from the kq --- vendor/libkqueue/src/linux/platform.c | 6 +++--- vendor/libkqueue/src/linux/platform.h | 2 +- vendor/libkqueue/src/solaris/platform.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 03f83d4d6..32c58ba46 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -352,7 +352,7 @@ linux_kevent_wait_hires( dbg_printf("waiting for events (timeout=%ld sec %ld nsec)", timeout->tv_sec, timeout->tv_nsec); - fds.fd = kqueue_epfd(kq); + fds.fd = kqueue_epoll_fd(kq); fds.events = POLLIN; n = ppoll(&fds, 1, timeout, NULL); @@ -363,7 +363,7 @@ linux_kevent_wait_hires( dbg_printf("waiting for events (timeout=%ld sec %ld nsec)", timeout->tv_sec, timeout->tv_nsec); - epfd = kqueue_epfd(kq); + epfd = kqueue_epoll_fd(kq); FD_ZERO(&fds); FD_SET(epfd, &fds); n = pselect(epfd + 1, &fds, NULL , NULL, timeout, NULL); @@ -406,7 +406,7 @@ linux_kevent_wait( } dbg_puts("waiting for events"); - nret = epoll_wait(kqueue_epfd(kq), &epevt[0], nevents, timeout); + nret = epoll_wait(kqueue_epoll_fd(kq), &epevt[0], nevents, timeout); if (nret < 0) { dbg_perror("epoll_wait"); return (-1); diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index ec037df3a..15fb03cce 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -54,7 +54,7 @@ extern long int syscall (long int __sysno, ...); #endif /* Convenience macros to access the epoll descriptor for the kqueue */ -#define kqueue_epfd(kq) ((kq)->epollfd) +#define kqueue_epoll_fd(kq) ((kq)->epollfd) #define filter_epfd(filt) ((filt)->kf_kqueue->epollfd) /* diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index 81d95af65..ec35b518e 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -41,7 +41,7 @@ #define X_PORT_SOURCE_USER 102 /* Convenience macros to access the event port descriptor for the kqueue */ -#define kqueue_epfd(kq) ((kq)->kq_id) +#define kqueue_epoll_fd(kq) ((kq)->kq_id) #define filter_epfd(filt) ((filt)->kf_kqueue->kq_id) void solaris_kqueue_free(struct kqueue *); From c8a3261e2336778486c245c6eb7218d68c1c1d90 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Tue, 9 Jun 2020 18:49:09 -0300 Subject: [PATCH 0718/1120] test: It should be passed only for the linker --- vendor/libkqueue/test/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/vendor/libkqueue/test/CMakeLists.txt b/vendor/libkqueue/test/CMakeLists.txt index 01339fcc4..363c025fe 100644 --- a/vendor/libkqueue/test/CMakeLists.txt +++ b/vendor/libkqueue/test/CMakeLists.txt @@ -43,9 +43,7 @@ if(WIN32) target_compile_options(libkqueue-test PRIVATE -Wno-unused-variable) endif() elseif(UNIX) - target_compile_options(libkqueue-test - PRIVATE - -rdynamic) + target_link_libraries(libkqueue-test PRIVATE -rdynamic) endif() target_link_libraries(libkqueue-test PRIVATE From 9de7e67296fd0b8994be22e62bc41e6724ea3e7c Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 9 Jun 2020 15:32:23 -0500 Subject: [PATCH 0719/1120] Fix strange redundant method of passing a pointer to the start of an array Maybe it's to explicitly mark these things as being arrays... Unsure. I'm willing to bet it'll cause compiler errors with arr[static ] though. --- vendor/libkqueue/kqlite/kqlite.c | 10 +++++----- vendor/libkqueue/src/common/kevent.c | 16 ++++++++-------- vendor/libkqueue/src/linux/platform.c | 10 +++++----- vendor/libkqueue/src/linux/read.c | 2 +- vendor/libkqueue/src/linux/vnode.c | 2 +- vendor/libkqueue/src/posix/signal.c | 2 +- vendor/libkqueue/src/solaris/platform.c | 20 ++++++++++---------- vendor/libkqueue/test/kevent.c | 2 +- vendor/libkqueue/test/main.c | 6 +++--- vendor/libkqueue/test/read.c | 2 +- vendor/libkqueue/test/vnode.c | 6 +++--- 11 files changed, 39 insertions(+), 39 deletions(-) diff --git a/vendor/libkqueue/kqlite/kqlite.c b/vendor/libkqueue/kqlite/kqlite.c index 0a665c555..c441e1671 100644 --- a/vendor/libkqueue/kqlite/kqlite.c +++ b/vendor/libkqueue/kqlite/kqlite.c @@ -438,7 +438,7 @@ int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, } else { epev_wait_max = nevents; } - epev_cnt = epoll_wait(kq->epfd, &epev_buf[0], epev_wait_max, eptimeout); + epev_cnt = epoll_wait(kq->epfd, epev_buf, epev_wait_max, eptimeout); if (epev_cnt < 0) { return (-1); //FIXME: handle timeout } @@ -493,9 +493,9 @@ epoll_event_to_str(struct epoll_event *evt) #define EPEVT_DUMP(attrib) \ if (evt->events & attrib) \ - strcat(&buf[0], #attrib" "); + strcat(buf, #attrib" "); - snprintf(&buf[0], 128, " { data = %p, events = ", evt->data.ptr); + snprintf(buf, 128, " { data = %p, events = ", evt->data.ptr); EPEVT_DUMP(EPOLLIN); EPEVT_DUMP(EPOLLOUT); #if defined(HAVE_EPOLLRDHUP) @@ -503,9 +503,9 @@ epoll_event_to_str(struct epoll_event *evt) #endif EPEVT_DUMP(EPOLLONESHOT); EPEVT_DUMP(EPOLLET); - strcat(&buf[0], "}\n"); + strcat(buf, "}\n"); - return (&buf[0]); + return (buf); #undef EPEVT_DUMP } #endif diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index cd9d13f8c..628155328 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -33,9 +33,9 @@ kevent_filter_dump(const struct kevent *kev) { static __thread char buf[64]; - snprintf(&buf[0], sizeof(buf), "%d (%s)", + snprintf(buf, sizeof(buf), "%d (%s)", kev->filter, filter_name(kev->filter)); - return ((const char *) &buf[0]); + return ((const char *) buf); } static const char * @@ -45,7 +45,7 @@ kevent_fflags_dump(const struct kevent *kev) #define KEVFFL_DUMP(attrib) \ if (kev->fflags & attrib) \ - strncat((char *) &buf[0], #attrib" ", 64); + strncat((char *) buf, #attrib" ", 64); snprintf(buf, sizeof(buf), "fflags=0x%04x (", kev->fflags); if (kev->filter == EVFILT_VNODE) { @@ -68,7 +68,7 @@ kevent_fflags_dump(const struct kevent *kev) #undef KEVFFL_DUMP - return ((const char *) &buf[0]); + return ((const char *) buf); } static const char * @@ -78,7 +78,7 @@ kevent_flags_dump(const struct kevent *kev) #define KEVFL_DUMP(attrib) \ if (kev->flags & attrib) \ - strncat((char *) &buf[0], #attrib" ", 64); + strncat((char *) buf, #attrib" ", 64); snprintf(buf, sizeof(buf), "flags=0x%04x (", kev->flags); KEVFL_DUMP(EV_ADD); @@ -95,7 +95,7 @@ kevent_flags_dump(const struct kevent *kev) #undef KEVFL_DUMP - return ((const char *) &buf[0]); + return ((const char *) buf); } const char * @@ -103,7 +103,7 @@ kevent_dump(const struct kevent *kev) { static __thread char buf[2147]; - snprintf((char *) &buf[0], sizeof(buf), + snprintf((char *) buf, sizeof(buf), "{ ident=%d, filter=%s, %s, %s, data=%d, udata=%p }", (u_int) kev->ident, kevent_filter_dump(kev), @@ -112,7 +112,7 @@ kevent_dump(const struct kevent *kev) (int) kev->data, kev->udata); - return ((const char *) &buf[0]); + return ((const char *) buf); } static int diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 32c58ba46..232f1e102 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -406,7 +406,7 @@ linux_kevent_wait( } dbg_puts("waiting for events"); - nret = epoll_wait(kqueue_epoll_fd(kq), &epevt[0], nevents, timeout); + nret = epoll_wait(kqueue_epoll_fd(kq), epevt, nevents, timeout); if (nret < 0) { dbg_perror("epoll_wait"); return (-1); @@ -715,9 +715,9 @@ epoll_event_dump(struct epoll_event *evt) #define EPEVT_DUMP(attrib) \ if (evt->events & attrib) \ - strcat(&buf[0], #attrib" "); + strcat(buf, #attrib" "); - snprintf(&buf[0], 128, " { data = %p, events = ", evt->data.ptr); + snprintf(buf, 128, " { data = %p, events = ", evt->data.ptr); EPEVT_DUMP(EPOLLIN); EPEVT_DUMP(EPOLLOUT); #if defined(HAVE_EPOLLRDHUP) @@ -725,9 +725,9 @@ epoll_event_dump(struct epoll_event *evt) #endif EPEVT_DUMP(EPOLLONESHOT); EPEVT_DUMP(EPOLLET); - strcat(&buf[0], "}\n"); + strcat(buf, "}\n"); - return (&buf[0]); + return (buf); #undef EPEVT_DUMP } diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index 6e8ace036..d66ee75ad 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -90,7 +90,7 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) return (-1); } src->kdata.kn_inotifyfd = inofd; - if (linux_fd_to_path(&path[0], sizeof(path), src->kev.ident) < 0) + if (linux_fd_to_path(path, sizeof(path), src->kev.ident) < 0) return (-1); if (inotify_add_watch(inofd, path, IN_ATTRIB) < 0) { dbg_perror("inotify_add_watch"); diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 617de0050..ca0cec5bf 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -109,7 +109,7 @@ add_watch(struct filter *filt, struct knote *kn) uint32_t mask; /* Convert the fd to a pathname */ - if (linux_fd_to_path(&path[0], sizeof(path), kn->kev.ident) < 0) + if (linux_fd_to_path(path, sizeof(path), kn->kev.ident) < 0) return (-1); /* Convert the fflags to the inotify mask */ diff --git a/vendor/libkqueue/src/posix/signal.c b/vendor/libkqueue/src/posix/signal.c index dac284cba..399e1f0b0 100644 --- a/vendor/libkqueue/src/posix/signal.c +++ b/vendor/libkqueue/src/posix/signal.c @@ -183,7 +183,7 @@ evfilt_signal_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) port_event_dequeue(&pe, filt->kf_kqueue); s = (struct sentry *) pe.portev_user; - sig = s - &sigtbl[0]; + sig = s - sigtbl; #else kqops.eventfd_lower(sig_eventfd); sig = 1; //XXX-FIXME totally broken, workaround just to compile diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index 57bbd6038..3c302d388 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -35,9 +35,9 @@ poll_events_dump(short events) #define _PL_DUMP(attrib) \ if (events == attrib) \ - strcat(&buf[0], " "#attrib); + strcat(buf, " "#attrib); - snprintf(&buf[0], 512, "events = %hd 0x%o (", events, events); + snprintf(buf, 512, "events = %hd 0x%o (", events, events); _PL_DUMP(POLLIN); _PL_DUMP(POLLPRI); _PL_DUMP(POLLOUT); @@ -47,9 +47,9 @@ poll_events_dump(short events) _PL_DUMP(POLLERR); _PL_DUMP(POLLHUP); _PL_DUMP(POLLNVAL); - strcat(&buf[0], ")"); + strcat(buf, ")"); - return (&buf[0]); + return (buf); #undef _PL_DUMP } @@ -60,15 +60,15 @@ port_event_dump(port_event_t *evt) static __thread char buf[512]; if (evt == NULL) { - snprintf(&buf[0], sizeof(buf), "NULL ?!?!\n"); + snprintf(buf, sizeof(buf), "NULL ?!?!\n"); goto out; } #define PE_DUMP(attrib) \ if (evt->portev_source == attrib) \ - strcat(&buf[0], #attrib); + strcat(buf, #attrib); - snprintf(&buf[0], 512, + snprintf(buf, 512, " { object = %u, user = %p, %s, source = %d (", (unsigned int) evt->portev_object, evt->portev_user, @@ -79,11 +79,11 @@ port_event_dump(port_event_t *evt) PE_DUMP(PORT_SOURCE_TIMER); PE_DUMP(PORT_SOURCE_USER); PE_DUMP(PORT_SOURCE_ALERT); - strcat(&buf[0], ") }"); + strcat(buf, ") }"); #undef PE_DUMP out: - return (&buf[0]); + return (buf); } #endif /* !NDEBUG */ @@ -124,7 +124,7 @@ solaris_kevent_wait( reset_errno(); dbg_puts("waiting for events"); - rv = port_getn(kq->kq_id, &evbuf[0], 1, &nget, (struct timespec *) ts); + rv = port_getn(kq->kq_id, evbuf, 1, &nget, (struct timespec *) ts); dbg_printf("rv=%d errno=%d (%s) nget=%d", rv, errno, strerror(errno), nget); if ((rv < 0) && (nget < 1)) { diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index 418b0ce81..f871b899b 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -142,7 +142,7 @@ kevent_to_str(struct kevent *kev) { char buf[512]; - snprintf(&buf[0], sizeof(buf), + snprintf(buf, sizeof(buf), "[ident=%d, filter=%d, %s, %s, data=%d, udata=%p]", (u_int) kev->ident, kev->filter, diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 12e444f8f..b355569e5 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -212,7 +212,7 @@ run_iteration(struct test_context *ctx) { struct unit_test *test; - for (test = &ctx->tests[0]; test->ut_name != NULL; test++) { + for (test = ctx->tests; test->ut_name != NULL; test++) { if (test->ut_enabled) test->ut_func(ctx); } @@ -332,14 +332,14 @@ main(int argc, char **argv) /* If specific tests are requested, disable all tests by default */ if (optind < argc) { - for (test = &tests[0]; test->ut_name != NULL; test++) { + for (test = tests; test->ut_name != NULL; test++) { test->ut_enabled = 0; } } for (i = optind; i < argc; i++) { match = 0; arg = argv[i]; - for (test = &tests[0]; test->ut_name != NULL; test++) { + for (test = tests; test->ut_name != NULL; test++) { if (strcmp(arg, test->ut_name) == 0) { test->ut_enabled = 1; match = 1; diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 46f6efd38..eb76f8f1e 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -70,7 +70,7 @@ kevent_socket_drain(struct test_context *ctx) char buf[1]; /* Drain the read buffer, then make sure there are no more events. */ - if (recv(ctx->client_fd, &buf[0], 1, 0) < 1) + if (recv(ctx->client_fd, buf, 1, 0) < 1) die("recv(2)"); } diff --git a/vendor/libkqueue/test/vnode.c b/vendor/libkqueue/test/vnode.c index 222ee3df3..74f001811 100644 --- a/vendor/libkqueue/test/vnode.c +++ b/vendor/libkqueue/test/vnode.c @@ -32,7 +32,7 @@ testfile_touch(const char *path) { char buf[1024]; - snprintf(&buf[0], sizeof(buf), "touch %s", path); + snprintf(buf, sizeof(buf), "touch %s", path); if (system(buf) != 0) die("system"); } @@ -42,7 +42,7 @@ testfile_write(const char *path) { char buf[1024]; - snprintf(&buf[0], sizeof(buf), "echo hi >> %s", path); + snprintf(buf, sizeof(buf), "echo hi >> %s", path); if (system(buf) != 0) die("system"); } @@ -52,7 +52,7 @@ testfile_rename(const char *path, int step) { char buf[1024]; - snprintf(&buf[0], sizeof(buf), "%s.tmp", path); + snprintf(buf, sizeof(buf), "%s.tmp", path); /* XXX-FIXME use of 'step' conceals a major memory corruption when the file is renamed twice. To replicate, remove "if step" conditional so From b62e192312b91f97ffac99e586a311a61a797dca Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 9 Jun 2020 18:04:53 -0500 Subject: [PATCH 0720/1120] Use NUM_ELEMENTS macro when iterating over tables Compiler will flag an error if they're converted to heap allocated arrays, and it ensures we never walk off the end if code refactoring makes the array bigger/smaller than the macro we're using for the upper bound. --- vendor/libkqueue/kern/kqueue.c | 2 +- vendor/libkqueue/src/common/filter.c | 4 ++-- vendor/libkqueue/src/common/private.h | 5 +++++ vendor/libkqueue/src/linux/platform.c | 4 ++-- vendor/libkqueue/src/posix/kevent.c | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/kern/kqueue.c b/vendor/libkqueue/kern/kqueue.c index 4c2bc383d..69d3baab4 100644 --- a/vendor/libkqueue/kern/kqueue.c +++ b/vendor/libkqueue/kern/kqueue.c @@ -145,7 +145,7 @@ static int kqueue_open (struct inode *inode, struct file *file) return -1; } spin_lock_init(&kq->kq_lock); - for (i = 0; i < EVFILT_SYSCOUNT; i++) + for (i = 0; i < NUM_ELEMENTS(kq->kq_filt); i++) kq->kq_filt[i].kf_note = RB_ROOT; file->private_data = kq; diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index 4e9576fd8..e862bbd48 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -110,7 +110,7 @@ filter_unregister_all(struct kqueue *kq) { int i; - for (i = 0; i < EVFILT_SYSCOUNT; i++) { + for (i = 0; i < NUM_ELEMENTS(kq->kq_filt); i++) { if (kq->kq_filt[i].kf_id == 0) continue; @@ -173,7 +173,7 @@ filter_name(short filt) }; id = ~filt; - if (id < 0 || id >= EVFILT_SYSCOUNT) + if (id < 0 || id >= NUM_ELEMENTS(fname)) return "EVFILT_INVALID"; else return fname[id]; diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 7ba5248d4..668680a2f 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -49,6 +49,11 @@ struct evfilt_data; # error Unknown platform #endif +/** Convenience macros + * + */ +#define NUM_ELEMENTS(_t) (sizeof((_t)) / sizeof(*(_t))) + #include "debug.h" /* Workaround for Android */ diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 232f1e102..9329b04e2 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -256,7 +256,7 @@ linux_kqueue_init(struct kqueue *kq) //might be useful in posix /* Add each filter's pollable descriptor to the epollset */ - for (i = 0; i < EVFILT_SYSCOUNT; i++) { + for (i = 0; i < NUM_ELEMENTS(kq->kq_filt); i++) { filt = &kq->kq_filt[i]; if (filt->kf_id == 0) @@ -681,7 +681,7 @@ linux_get_descriptor_type(struct knote *kn) #ifdef SO_GET_FILTER { socklen_t out_len = 0; - + /* * Test if socket has a filter * pcap file descriptors need to be considered as passive sockets as diff --git a/vendor/libkqueue/src/posix/kevent.c b/vendor/libkqueue/src/posix/kevent.c index 96be0b8aa..99e386609 100644 --- a/vendor/libkqueue/src/posix/kevent.c +++ b/vendor/libkqueue/src/posix/kevent.c @@ -56,7 +56,7 @@ posix_kevent_copyout(struct kqueue *kq, int nready, int i, rv, nret; nret = 0; - for (i = 0; (i < EVFILT_SYSCOUNT && nready > 0 && nevents > 0); i++) { + for (i = 0; (i < NUM_ELEMENTS(kq->kq_filt) && nready > 0 && nevents > 0); i++) { // dbg_printf("eventlist: n = %d nevents = %d", nready, nevents); filt = &kq->kq_filt[i]; // dbg_printf("pfd[%d] = %d", i, filt->kf_pfd); From 48a5325cc91fa4b6f605bbf8c2c8fc6f6610621f Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 9 Jun 2020 18:07:22 -0500 Subject: [PATCH 0721/1120] s/epfd/epoll_fd/g shortened names are a barrier to entry to people unfamiliar with the code --- vendor/libkqueue/kqlite/kqlite.c | 22 +++++++++++----------- vendor/libkqueue/src/linux/platform.c | 10 +++++----- vendor/libkqueue/src/linux/platform.h | 4 ++-- vendor/libkqueue/src/linux/read.c | 2 +- vendor/libkqueue/src/linux/signal.c | 14 +++++++------- vendor/libkqueue/src/linux/timer.c | 4 ++-- vendor/libkqueue/src/linux/user.c | 4 ++-- vendor/libkqueue/src/linux/vnode.c | 4 ++-- vendor/libkqueue/src/solaris/platform.h | 2 +- vendor/libkqueue/src/solaris/signal.c | 2 +- vendor/libkqueue/src/solaris/socket.c | 6 +++--- vendor/libkqueue/src/solaris/timer.c | 2 +- vendor/libkqueue/src/solaris/user.c | 2 +- 13 files changed, 39 insertions(+), 39 deletions(-) diff --git a/vendor/libkqueue/kqlite/kqlite.c b/vendor/libkqueue/kqlite/kqlite.c index c441e1671..744f311a2 100644 --- a/vendor/libkqueue/kqlite/kqlite.c +++ b/vendor/libkqueue/kqlite/kqlite.c @@ -64,7 +64,7 @@ struct kqueue { #if defined(USE_KQUEUE) int kqfd; /* kqueue(2) descriptor */ #elif defined(USE_EPOLL) - int epfd; /* epoll */ + int epoll_fd; /* epoll */ int inofd; /* inotify */ int sigfd; /* signalfd */ int timefd; /* timerfd */ @@ -159,30 +159,30 @@ kq_init(void) sigemptyset(&kq->sigmask); kq->sigfd = signalfd(-1, &kq->sigmask, 0); kq->inofd = inotify_init(); - kq->epfd = epoll_create(10); + kq->epoll_fd = epoll_create(10); kq->readfd = epoll_create(10); kq->writefd = epoll_create(10); kq->timefd = timerfd_create(CLOCK_MONOTONIC, 0); - if (kq->sigfd < 0 || kq->inofd < 0 || kq->epfd < 0 + if (kq->sigfd < 0 || kq->inofd < 0 || kq->epoll_fd < 0 || kq->readfd < 0 || kq->writefd < 0 || kq->timefd < 0) goto errout; /* Add the signalfd descriptor to the epollset */ epev.events = EPOLLIN; epev.data.u32 = EVFILT_SIGNAL; - if (epoll_ctl(kq->epfd, EPOLL_CTL_ADD, kq->sigfd, &epev) < 0) + if (epoll_ctl(kq->epoll_fd, EPOLL_CTL_ADD, kq->sigfd, &epev) < 0) goto errout; /* Add the readfd descriptor to the epollset */ epev.events = EPOLLIN; epev.data.u32 = EVFILT_READ; - if (epoll_ctl(kq->epfd, EPOLL_CTL_ADD, kq->readfd, &epev) < 0) + if (epoll_ctl(kq->epoll_fd, EPOLL_CTL_ADD, kq->readfd, &epev) < 0) goto errout; /* Add the writefd descriptor to the epollset */ epev.events = EPOLLIN; epev.data.u32 = EVFILT_WRITE; - if (epoll_ctl(kq->epfd, EPOLL_CTL_ADD, kq->writefd, &epev) < 0) + if (epoll_ctl(kq->epoll_fd, EPOLL_CTL_ADD, kq->writefd, &epev) < 0) goto errout; /* Add the inotify descriptor to the epollset */ @@ -193,7 +193,7 @@ kq_init(void) epev.events = EPOLLIN; epev.data.u32 = 1; utarray_push_back(kq->kev, kev); - if (epoll_ctl(kq->epfd, EPOLL_CTL_ADD, kq->inofd, &epev) < 0) + if (epoll_ctl(kq->epoll_fd, EPOLL_CTL_ADD, kq->inofd, &epev) < 0) goto errout; */ @@ -218,7 +218,7 @@ kq_free(kqueue_t kq) #elif defined(USE_EPOLL) close(kq->sigfd); close(kq->inofd); - close(kq->epfd); + close(kq->epoll_fd); close(kq->readfd); close(kq->writefd); close(kq->timefd); @@ -296,7 +296,7 @@ kq_add(kqueue_t kq, const struct kevent *ev) case EVFILT_VNODE: epev.events = EPOLLIN; - rv = epoll_ctl(kq->epfd, EPOLL_CTL_ADD, ev->ident, &epev); + rv = epoll_ctl(kq->epoll_fd, EPOLL_CTL_ADD, ev->ident, &epev); rv = -1; break; @@ -344,7 +344,7 @@ kq_delete(kqueue_t kq, const struct kevent *ev) switch (ev->ident) { case EVFILT_READ: case EVFILT_WRITE: - rv = epoll_ctl(kq->epfd, EPOLL_CTL_DEL, ev->ident, &epev); + rv = epoll_ctl(kq->epoll_fd, EPOLL_CTL_DEL, ev->ident, &epev); break; case EVFILT_VNODE: @@ -438,7 +438,7 @@ int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, } else { epev_wait_max = nevents; } - epev_cnt = epoll_wait(kq->epfd, epev_buf, epev_wait_max, eptimeout); + epev_cnt = epoll_wait(kq->epoll_fd, epev_buf, epev_wait_max, eptimeout); if (epev_cnt < 0) { return (-1); //FIXME: handle timeout } diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 9329b04e2..720b3d290 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -357,16 +357,16 @@ linux_kevent_wait_hires( n = ppoll(&fds, 1, timeout, NULL); #else - int epfd; + int epoll_fd; fd_set fds; dbg_printf("waiting for events (timeout=%ld sec %ld nsec)", timeout->tv_sec, timeout->tv_nsec); - epfd = kqueue_epoll_fd(kq); + epoll_fd = kqueue_epoll_fd(kq); FD_ZERO(&fds); - FD_SET(epfd, &fds); - n = pselect(epfd + 1, &fds, NULL , NULL, timeout, NULL); + FD_SET(epoll_fd, &fds); + n = pselect(epoll_fd + 1, &fds, NULL , NULL, timeout, NULL); #endif if (n < 0) { @@ -736,7 +736,7 @@ epoll_update(int op, struct filter *filt, struct knote *kn, struct epoll_event * { dbg_printf("op=%d fd=%d events=%s", op, (int)kn->kev.ident, epoll_event_dump(ev)); - if (epoll_ctl(filter_epfd(filt), op, kn->kev.ident, ev) < 0) { + if (epoll_ctl(filter_epoll_fd(filt), op, kn->kev.ident, ev) < 0) { dbg_printf("epoll_ctl(2): %s", strerror(errno)); return (-1); } diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 15fb03cce..f74394369 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -55,7 +55,7 @@ extern long int syscall (long int __sysno, ...); /* Convenience macros to access the epoll descriptor for the kqueue */ #define kqueue_epoll_fd(kq) ((kq)->epollfd) -#define filter_epfd(filt) ((filt)->kf_kqueue->epollfd) +#define filter_epoll_fd(filt) ((filt)->kf_kqueue->epollfd) /* * Additional members of struct filter @@ -66,7 +66,7 @@ extern long int syscall (long int __sysno, ...); * Additional members of struct knote */ #define KNOTE_PLATFORM_SPECIFIC \ - int kn_epollfd; /* A copy of filter->epfd */ \ + int kn_epollfd; /* A copy of filter->epoll_fd */ \ int kn_registered; /* Is FD registered with epoll */ \ union { \ int kn_timerfd; \ diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index d66ee75ad..a0d2e4b08 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -174,7 +174,7 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) if (kn->kn_flags & KNFL_FILE) { int evfd; - kn->kn_epollfd = filter_epfd(filt); + kn->kn_epollfd = filter_epoll_fd(filt); evfd = eventfd(0, 0); if (evfd < 0) { dbg_perror("eventfd(2)"); diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index 2e23c238a..f8f76acbe 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -61,7 +61,7 @@ signalfd_reset(int sigfd) } static int -signalfd_add(int epfd, int sigfd, void *ptr) +signalfd_add(int epoll_fd, int sigfd, void *ptr) { struct epoll_event ev; int rv; @@ -70,7 +70,7 @@ signalfd_add(int epfd, int sigfd, void *ptr) memset(&ev, 0, sizeof(ev)); ev.events = EPOLLIN; ev.data.ptr = ptr; - rv = epoll_ctl(epfd, EPOLL_CTL_ADD, sigfd, &ev); + rv = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sigfd, &ev); if (rv < 0) { dbg_perror("epoll_ctl(2)"); return (-1); @@ -80,7 +80,7 @@ signalfd_add(int epfd, int sigfd, void *ptr) } static int -signalfd_create(int epfd, void *ptr, int signum) +signalfd_create(int epoll_fd, void *ptr, int signum) { static int flags = SFD_NONBLOCK; sigset_t sigmask; @@ -109,10 +109,10 @@ signalfd_create(int epfd, void *ptr, int signum) signalfd_reset(sigfd); - if (signalfd_add(epfd, sigfd, ptr) < 0) + if (signalfd_add(epoll_fd, sigfd, ptr) < 0) goto errout; - dbg_printf("added sigfd %d to epfd %d (signum=%d)", sigfd, epfd, signum); + dbg_printf("added sigfd %d to epoll_fd %d (signum=%d)", sigfd, epoll_fd, signum); return (sigfd); @@ -144,7 +144,7 @@ evfilt_signal_knote_create(struct filter *filt, struct knote *kn) { int fd; - fd = signalfd_create(filter_epfd(filt), kn, kn->kev.ident); + fd = signalfd_create(filter_epoll_fd(filt), kn, kn->kev.ident); if (fd > 0) { kn->kev.flags |= EV_CLEAR; kn->kdata.kn_signalfd = fd; @@ -174,7 +174,7 @@ evfilt_signal_knote_delete(struct filter *filt, struct knote *kn) if (kn->kdata.kn_signalfd == -1) return (0); - if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_DEL, sigfd, NULL) < 0) { + if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, sigfd, NULL) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); } diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 31eb62018..7cf894410 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -181,7 +181,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) ev.events |= EPOLLONESHOT; ev.data.ptr = kn; - if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_ADD, tfd, &ev) < 0) { + if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_ADD, tfd, &ev) < 0) { dbg_printf("epoll_ctl(2): %d", errno); close(tfd); return (-1); @@ -209,7 +209,7 @@ evfilt_timer_knote_delete(struct filter *filt, struct knote *kn) if (kn->data.pfd == -1) return (0); - if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_DEL, kn->data.pfd, NULL) < 0) { + if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, kn->data.pfd, NULL) < 0) { dbg_printf("epoll_ctl(2): %s", strerror(errno)); rv = -1; } diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index 6c53e8318..151078800 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -130,7 +130,7 @@ linux_evfilt_user_knote_create(struct filter *filt, struct knote *kn) memset(&ev, 0, sizeof(ev)); ev.events = EPOLLIN; ev.data.ptr = kn; - if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_ADD, evfd, &ev) < 0) { + if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_ADD, evfd, &ev) < 0) { dbg_perror("epoll_ctl(2)"); goto errout; } @@ -190,7 +190,7 @@ linux_evfilt_user_knote_modify(struct filter *filt UNUSED, struct knote *kn, int linux_evfilt_user_knote_delete(struct filter *filt, struct knote *kn) { - if (kn->kn_registered && epoll_ctl(filter_epfd(filt), EPOLL_CTL_DEL, + if (kn->kn_registered && epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, kn->kdata.kn_eventfd, NULL) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index ca0cec5bf..274c2c2f9 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -148,7 +148,7 @@ add_watch(struct filter *filt, struct knote *kn) memset(&ev, 0, sizeof(ev)); ev.events = EPOLLIN; ev.data.ptr = kn; - if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_ADD, ifd, &ev) < 0) { + if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_ADD, ifd, &ev) < 0) { dbg_perror("epoll_ctl(2)"); goto errout; } @@ -171,7 +171,7 @@ delete_watch(struct filter *filt, struct knote *kn) if (ifd < 0) return (0); - if (epoll_ctl(filter_epfd(filt), EPOLL_CTL_DEL, ifd, NULL) < 0) { + if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, ifd, NULL) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); } diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index ec35b518e..4afa85008 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -42,7 +42,7 @@ /* Convenience macros to access the event port descriptor for the kqueue */ #define kqueue_epoll_fd(kq) ((kq)->kq_id) -#define filter_epfd(filt) ((filt)->kf_kqueue->kq_id) +#define filter_epoll_fd(filt) ((filt)->kf_kqueue->kq_id) void solaris_kqueue_free(struct kqueue *); int solaris_kqueue_init(struct kqueue *); diff --git a/vendor/libkqueue/src/solaris/signal.c b/vendor/libkqueue/src/solaris/signal.c index 5a79e5da6..9ef04682c 100644 --- a/vendor/libkqueue/src/solaris/signal.c +++ b/vendor/libkqueue/src/solaris/signal.c @@ -65,7 +65,7 @@ catch_signal(struct filter *filt, struct knote *kn) pthread_mutex_lock(&sigtbl_mtx); sigtbl[sig].st_signum = sig; - sigtbl[sig].st_port = filter_epfd(filt); + sigtbl[sig].st_port = filter_epoll_fd(filt); sigtbl[sig].st_count = 0; memcpy(&sigtbl[sig].st_kev, &kn->kev, sizeof(struct kevent)); pthread_mutex_unlock(&sigtbl_mtx); diff --git a/vendor/libkqueue/src/solaris/socket.c b/vendor/libkqueue/src/solaris/socket.c index faed786b2..621f57c1a 100644 --- a/vendor/libkqueue/src/solaris/socket.c +++ b/vendor/libkqueue/src/solaris/socket.c @@ -48,9 +48,9 @@ evfilt_socket_knote_create(struct filter *filt, struct knote *kn) return (-1); } - dbg_printf("port_associate kq fd %d with actual fd %ld", filter_epfd(filt), kn->kev.ident); + dbg_printf("port_associate kq fd %d with actual fd %ld", filter_epoll_fd(filt), kn->kev.ident); - rv = port_associate(filter_epfd(filt), PORT_SOURCE_FD, kn->kev.ident, + rv = port_associate(filter_epoll_fd(filt), PORT_SOURCE_FD, kn->kev.ident, events, kn); if (rv < 0) { dbg_perror("port_associate(2)"); @@ -79,7 +79,7 @@ evfilt_socket_knote_delete(struct filter *filt, struct knote *kn) return (0); */ - if (port_dissociate(filter_epfd(filt), PORT_SOURCE_FD, kn->kev.ident) < 0) { + if (port_dissociate(filter_epoll_fd(filt), PORT_SOURCE_FD, kn->kev.ident) < 0) { dbg_perror("port_dissociate(2)"); return (-1); } diff --git a/vendor/libkqueue/src/solaris/timer.c b/vendor/libkqueue/src/solaris/timer.c index c19f5cd52..a7e922905 100644 --- a/vendor/libkqueue/src/solaris/timer.c +++ b/vendor/libkqueue/src/solaris/timer.c @@ -119,7 +119,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) kn->kev.flags |= EV_CLEAR; - pn.portnfy_port = filter_epfd(filt); + pn.portnfy_port = filter_epoll_fd(filt); pn.portnfy_user = (void *) kn; se.sigev_notify = SIGEV_PORT; diff --git a/vendor/libkqueue/src/solaris/user.c b/vendor/libkqueue/src/solaris/user.c index ac25dfa8a..f2d0bdcd0 100644 --- a/vendor/libkqueue/src/solaris/user.c +++ b/vendor/libkqueue/src/solaris/user.c @@ -97,7 +97,7 @@ evfilt_user_knote_modify(struct filter *filt, struct knote *kn, if ((!(kn->kev.flags & EV_DISABLE)) && kev->fflags & NOTE_TRIGGER) { kn->kev.fflags |= NOTE_TRIGGER; - return (port_send(filter_epfd(filt), X_PORT_SOURCE_USER, kn)); + return (port_send(filter_epoll_fd(filt), X_PORT_SOURCE_USER, kn)); } return (0); From 8a10e27bce5798e738bfbf49adc10328b2fd16e3 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Wed, 10 Jun 2020 17:13:46 -0300 Subject: [PATCH 0722/1120] build: Don't append 'd' to the library in debug mode --- vendor/libkqueue/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 9bddc01f5..f1018f986 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -144,7 +144,6 @@ else() endif() add_library(kqueue ${LIBRARY_TYPE} ${LIBKQUEUE_SOURCES} ${LIBKQUEUE_HEADERS}) -set_target_properties(kqueue PROPERTIES DEBUG_POSTFIX "d") set_target_properties(kqueue PROPERTIES SOVERSION 1) if(WIN32) From ac4d9aafbc45125ed9e41379d0ac1e0fa93b2539 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 9 Jun 2020 18:46:52 -0500 Subject: [PATCH 0723/1120] Formatting --- vendor/libkqueue/src/common/knote.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index bf522fa61..aa8346c89 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -41,10 +41,10 @@ RB_GENERATE(knt, knote, kn_entries, knote_cmp) struct knote * knote_new(void) { - struct knote *res; + struct knote *res; res = calloc(1, sizeof(struct knote)); - if (res == NULL) + if (res == NULL) return (NULL); res->kn_ref = 1; @@ -57,7 +57,7 @@ knote_release(struct knote *kn) { assert (kn->kn_ref > 0); - if (atomic_dec(&kn->kn_ref) == 0) { + if (atomic_dec(&kn->kn_ref) == 0) { if (kn->kn_flags & KNFL_KNOTE_DELETED) { dbg_printf("freeing knote at %p", kn); free(kn); From 0dce9ec833a1b033fb5b2159e5a25c578b1b572b Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 9 Jun 2020 19:05:01 -0500 Subject: [PATCH 0724/1120] We need the write lock when freeing knotes, not that it really matters --- vendor/libkqueue/src/common/knote.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index aa8346c89..51b280d77 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -131,7 +131,7 @@ int knote_free_all(struct filter *filt) { struct knote *kn, *tmp; - pthread_rwlock_rdlock(&filt->kf_knote_mtx); + pthread_rwlock_wrlock(&filt->kf_knote_mtx); RB_FOREACH_SAFE(kn, knt, &filt->kf_knote, tmp) { /* Check return code */ filt->kn_delete(filt, kn); From 0db6b80224ad852ba6c28d16e40fda982f41f871 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Thu, 11 Jun 2020 14:55:27 -0300 Subject: [PATCH 0725/1120] build: Don't append 'd' to tests in debug mode --- vendor/libkqueue/test/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/vendor/libkqueue/test/CMakeLists.txt b/vendor/libkqueue/test/CMakeLists.txt index 363c025fe..2c8161978 100644 --- a/vendor/libkqueue/test/CMakeLists.txt +++ b/vendor/libkqueue/test/CMakeLists.txt @@ -54,9 +54,6 @@ if(WIN32) PRIVATE Ws2_32) endif() -set_target_properties(libkqueue-test - PROPERTIES - DEBUG_POSTFIX "d") add_test(NAME libkqueue-test COMMAND libkqueue-test) From 8e5d4b3ae40ddd4429d88316fa3974d38c396d46 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Thu, 11 Jun 2020 15:07:29 -0300 Subject: [PATCH 0726/1120] Add *.deb items to .gitignore --- vendor/libkqueue/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/.gitignore b/vendor/libkqueue/.gitignore index 3e6cea916..e8a6cd10a 100644 --- a/vendor/libkqueue/.gitignore +++ b/vendor/libkqueue/.gitignore @@ -2,6 +2,7 @@ config.h *.pc *.log +*.deb CMakeCache.txt CMakeFiles/ CPackConfig.cmake @@ -12,7 +13,6 @@ Testing/ _CPack_Packages/ cmake_install.cmake install_manifest*.txt -kqueue-*.deb libkqueue.so* tags test/CMakeCache.txt From 5bd9ef5e68646e52d7cd0c4f87a349da12ddcc6e Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 11 Jun 2020 13:12:51 -0500 Subject: [PATCH 0727/1120] Remove spurious newlines in debug output --- vendor/libkqueue/src/linux/platform.c | 20 ++++++++++---------- vendor/libkqueue/src/linux/read.c | 2 +- vendor/libkqueue/src/windows/read.c | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 720b3d290..30ef16d96 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -597,27 +597,27 @@ linux_get_descriptor_type(struct knote *kn) return (-1); case S_IFREG: - dbg_printf("fd %d is a regular file\n", fd); + dbg_printf("fd %d is a regular file", fd); kn->kn_flags |= KNFL_FILE; return (0); case S_IFIFO: - dbg_printf("fd %d is a pipe\n", fd); + dbg_printf("fd %d is a pipe", fd); kn->kn_flags |= KNFL_PIPE; return (0); case S_IFBLK: - dbg_printf("fd %d is a block device\n", fd); + dbg_printf("fd %d is a block device", fd); kn->kn_flags |= KNFL_BLOCKDEV; return (0); case S_IFCHR: - dbg_printf("fd %d is a character device\n", fd); + dbg_printf("fd %d is a character device", fd); kn->kn_flags |= KNFL_CHARDEV; return (0); case S_IFSOCK: - dbg_printf("fd %d is a socket\n", fd); + dbg_printf("fd %d is a socket", fd); break; /* deferred type determination */ } @@ -633,27 +633,27 @@ linux_get_descriptor_type(struct knote *kn) } switch (stype) { case SOCK_STREAM: - dbg_printf("fd %d is a stream socket\n", fd); + dbg_printf("fd %d is a stream socket", fd); kn->kn_flags |= KNFL_SOCKET_STREAM; break; case SOCK_DGRAM: - dbg_printf("fd %d is a datagram socket\n", fd); + dbg_printf("fd %d is a datagram socket", fd); kn->kn_flags |= KNFL_SOCKET_DGRAM; break; case SOCK_RDM: - dbg_printf("fd %d is a reliable datagram socket\n", fd); + dbg_printf("fd %d is a reliable datagram socket", fd); kn->kn_flags |= KNFL_SOCKET_RDM; break; case SOCK_SEQPACKET: - dbg_printf("fd %d is a sequenced and reliable datagram socket\n", fd); + dbg_printf("fd %d is a sequenced and reliable datagram socket", fd); kn->kn_flags |= KNFL_SOCKET_SEQPACKET; break; case SOCK_RAW: - dbg_printf("fd %d is a raw socket\n", fd); + dbg_printf("fd %d is a raw socket", fd); kn->kn_flags |= KNFL_SOCKET_RAW; break; diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index a0d2e4b08..edbfcb1a4 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -49,7 +49,7 @@ get_eof_offset(int fd) sb.st_size = 1; } - dbg_printf("curpos=%zu size=%zu\n", (size_t)curpos, (size_t)sb.st_size); + dbg_printf("curpos=%zu size=%zu", (size_t)curpos, (size_t)sb.st_size); return (sb.st_size - curpos); //FIXME: can overflow } diff --git a/vendor/libkqueue/src/windows/read.c b/vendor/libkqueue/src/windows/read.c index 4b0685d35..6e4c7b98c 100644 --- a/vendor/libkqueue/src/windows/read.c +++ b/vendor/libkqueue/src/windows/read.c @@ -81,7 +81,7 @@ get_eof_offset(int fd) sb.st_size = 1; } - dbg_printf("curpos=%zu size=%zu\n", curpos, sb.st_size); + dbg_printf("curpos=%zu size=%zu", curpos, sb.st_size); return (sb.st_size - curpos); //FIXME: can overflow } #endif From 417c6ab1c5b72c7d99d3862cbabdba6a0867bb22 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 11 Jun 2020 16:31:00 -0500 Subject: [PATCH 0728/1120] Bump to C11 so we get _Generics, proper atomics, and compound literals --- vendor/libkqueue/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index f1018f986..4bf9e81e2 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -29,7 +29,7 @@ enable_testing() set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_C_STANDARD_REQUIRED ON) -set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD 11) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE RelWithDebInfo) From 06d587196b0ab36d91bfdb948bb9fce52783eede Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Mon, 20 Jan 2020 14:51:13 -0500 Subject: [PATCH 0729/1120] Add a unit test for issue #59 --- vendor/libkqueue/test/read.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index eb76f8f1e..50d5f239b 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -424,6 +424,34 @@ test_kevent_regular_file(struct test_context *ctx) close(fd); } +/* Test transitioning a socket from EVFILT_WRITE to EVFILT_READ */ +void +test_transition_from_write_to_read(struct test_context *ctx) +{ + struct kevent kev, ret; + int kqfd; + int sd[2]; + + (void) ctx; + if ((kqfd = kqueue()) < 0) + err(1, "kqueue"); + + if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sd)) + err(1, "socketpair"); + + EV_SET(&kev, sd[0], EVFILT_WRITE, EV_ADD, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1,"kevent"); + + EV_SET(&kev, sd[0], EVFILT_READ, EV_ADD, 0, 0, NULL); + if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + err(1,"kevent"); + + close(sd[0]); + close(sd[1]); + close(kqfd); +} + void test_evfilt_read(struct test_context *ctx) { @@ -444,4 +472,9 @@ test_evfilt_read(struct test_context *ctx) test(kevent_regular_file, ctx); close(ctx->client_fd); close(ctx->server_fd); + + create_socket_connection(&ctx->client_fd, &ctx->server_fd); + test(transition_from_write_to_read, ctx); + close(ctx->client_fd); + close(ctx->server_fd); } From 09e110d4e48aaf7233b6a2ad99398031bb9f5906 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 11 Jun 2020 16:41:54 -0500 Subject: [PATCH 0730/1120] Keep a separate state tree for file descriptors inserted into epoll to avoid conflicts between EVFILT_READ and EVFILT_WRITE Closes #29 Closes #59 There's more work required, but at least this fixes the outstanding issues. Known limitations: - Need to verify correct behaviour of EV_DISPATCH when both filters are registered for events. This now needs to be implemented internally by libkqueue instead of relying on EPOLLET, as EPOLLET applies to both EPOLLIN and EPOLLOUT. - If the number of events we are to return does not have sufficient space for at least two entries when polling an FD registered for both read and write events, the write event will be lost. We can fix this by implementing a linked list of pending events we return before calling the platform's wait function. Will probably copy the dlist implementation from FreeRADIUS across, as it's been well tested, and is a header only implementation like the current rbtree. A dlist is needed to store entries for EVFILT_PROC anyway, which is the next filter that needs major attention. --- vendor/libkqueue/src/common/kevent.c | 4 +- vendor/libkqueue/src/common/private.h | 21 +- vendor/libkqueue/src/linux/platform.c | 543 ++++++++++++++++++++++---- vendor/libkqueue/src/linux/platform.h | 121 +++++- vendor/libkqueue/src/linux/read.c | 51 +-- vendor/libkqueue/src/linux/signal.c | 13 +- vendor/libkqueue/src/linux/timer.c | 11 +- vendor/libkqueue/src/linux/user.c | 7 +- vendor/libkqueue/src/linux/vnode.c | 7 +- vendor/libkqueue/src/linux/write.c | 37 +- 10 files changed, 645 insertions(+), 170 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 628155328..fa9bd5078 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -177,12 +177,12 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) rv = knote_delete(filt, kn); dbg_printf("knote_delete returned %d", rv); } else if (src->flags & EV_DISABLE) { - kn->kev.flags |= EV_DISABLE; rv = filt->kn_disable(filt, kn); + if (rv == 0) kn->kev.flags |= EV_DISABLE; dbg_printf("kn_disable returned %d", rv); } else if (src->flags & EV_ENABLE) { - kn->kev.flags &= ~EV_DISABLE; rv = filt->kn_enable(filt, kn); + if (rv == 0) kn->kev.flags &= ~EV_DISABLE; dbg_printf("kn_enable returned %d", rv); } else if (src->flags & EV_ADD || src->flags == 0 || src->flags & EV_RECEIPT) { kn->kev.udata = src->udata; diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 668680a2f..0c2762a1f 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -139,7 +139,7 @@ struct knote { * */ struct filter { - short kf_id; //!< EVFILT_* facility this filter provides. + short kf_id; //!< EVFILT_* facility this filter provides. /* filter operations */ @@ -151,20 +151,19 @@ struct filter { int (*kn_create)(struct filter *, struct knote *); - int (*kn_modify)(struct filter *, struct knote *, - const struct kevent *); + int (*kn_modify)(struct filter *, struct knote *, const struct kevent *); int (*kn_delete)(struct filter *, struct knote *); int (*kn_enable)(struct filter *, struct knote *); int (*kn_disable)(struct filter *, struct knote *); - struct eventfd kf_efd; /* Used by user.c */ + struct eventfd kf_efd; //!< Used by user.c //MOVE TO POSIX? - int kf_pfd; /* fd to poll(2) for readiness */ - int kf_wfd; /* fd to write when an event occurs */ + int kf_pfd; //!< fd to poll(2) for readiness + int kf_wfd; //!< fd to write when an event occurs //----? - struct evfilt_data *kf_data; /* filter-specific data */ + struct evfilt_data *kf_data; //!< filter-specific data */ RB_HEAD(knt, knote) kf_knote; pthread_rwlock_t kf_knote_mtx; struct kqueue *kf_kqueue; @@ -182,10 +181,10 @@ struct filter { * in receiving notifications for. */ struct kqueue { - int kq_id; //!< File descriptor used to identify this kqueue. - struct filter kq_filt[EVFILT_SYSCOUNT]; //!< Filters supported by the kqueue. Each - ///< kqueue maintains one filter state structure - ///< per filter type. + int kq_id; //!< File descriptor used to identify this kqueue. + struct filter kq_filt[EVFILT_SYSCOUNT]; //!< Filters supported by the kqueue. Each + ///< kqueue maintains one filter state structure + ///< per filter type. fd_set kq_fds, kq_rfds; int kq_nfds; tracing_mutex_t kq_mtx; diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 30ef16d96..c22f348ad 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -28,7 +28,7 @@ const struct filter evfilt_proc = EVFILT_NOTIMPL; * Per-thread epoll event buffer used to ferry data between * kevent_wait() and kevent_copyout(). */ -static __thread struct epoll_event epevt[MAX_KEVENT]; +static __thread struct epoll_event epoll_events[MAX_KEVENT]; extern pthread_mutex_t kq_mtx; /* @@ -212,7 +212,7 @@ linux_kqueue_init(struct kqueue *kq) } if (filter_register_all(kq) < 0) { - error: + error: close(kq->epollfd); close(kq->pipefd[0]); close(kq->pipefd[1]); @@ -381,10 +381,7 @@ linux_kevent_wait_hires( } int -linux_kevent_wait( - struct kqueue *kq, - int nevents, - const struct timespec *ts) +linux_kevent_wait(struct kqueue *kq, int nevents, const struct timespec *ts) { int timeout, nret; @@ -406,7 +403,7 @@ linux_kevent_wait( } dbg_puts("waiting for events"); - nret = epoll_wait(kqueue_epoll_fd(kq), epevt, nevents, timeout); + nret = epoll_wait(kqueue_epoll_fd(kq), epoll_events, nevents, timeout); if (nret < 0) { dbg_perror("epoll_wait"); return (-1); @@ -415,50 +412,134 @@ linux_kevent_wait( return (nret); } +static inline int linux_kevent_copyout_ev(struct kevent **el_p, struct epoll_event *ev, + struct filter *filt, struct knote *kn) +{ + int rv; + struct kevent *el = *el_p; + + rv = filt->kf_copyout(el, kn, ev); + if (unlikely(rv < 0)) { + dbg_puts("knote_copyout failed"); + assert(0); + return rv; + } + + /* + * Advance to the next el entry + */ + if (likely(el->filter != 0)) { + (*el_p)++; + } else { + dbg_puts("spurious wakeup, discarding event"); + } + + /* + * Certain flags cause the associated knote to be deleted + * or disabled. + */ + if (el->flags & EV_DISPATCH) + knote_disable(filt, kn); //FIXME: Error checking + if (el->flags & EV_ONESHOT) { + knote_delete(filt, kn); //FIXME: Error checking + } + + return rv; +} + int -linux_kevent_copyout(struct kqueue *kq, int nready, - struct kevent *eventlist, int nevents UNUSED) +linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int nevents) { - struct epoll_event *ev; - struct filter *filt; - struct knote *kn; - int i, nret, rv; + struct kevent *el_p = el, *el_end = el + nevents; + int i; - nret = nready; for (i = 0; i < nready; i++) { - ev = &epevt[i]; - kn = (struct knote *) ev->data.ptr; - filt = &kq->kq_filt[~(kn->kev.filter)]; - rv = filt->kf_copyout(eventlist, kn, ev); - if (unlikely(rv < 0)) { - dbg_puts("knote_copyout failed"); - /* XXX-FIXME: hard to handle this without losing events */ - abort(); + struct epoll_event *ev = &epoll_events[i]; /* Thread local storage populated in linux_kevent_wait */ + struct epoll_udata *epoll_udata = ev->data.ptr; + int rv; + + if (!epoll_udata) { + dbg_puts("event has no filter, skipping..."); + continue; } + switch (epoll_udata->ud_type) { /* - * Certain flags cause the associated knote to be deleted - * or disabled. + * epoll event is associated with a single filter + * so we just have the one knote. */ - if (eventlist->flags & EV_DISPATCH) - knote_disable(filt, kn); //FIXME: Error checking - if (eventlist->flags & EV_ONESHOT) { - knote_delete(filt, kn); //FIXME: Error checking + case EPOLL_UDATA_KNOTE: + { + struct knote *kn = epoll_udata->ud_kn; + + if (el_p >= el_end) { + oos: + dbg_printf("no more available kevent slots, used %zu", el_p - el); + goto done; + } + + rv = linux_kevent_copyout_ev(&el_p, ev, &kq->kq_filt[~(kn->kev.filter)], kn); + if (rv < 0) goto done; } + break; - /* If an empty kevent structure is returned, the event is discarded. */ - /* TODO: add these semantics to windows + solaris platform.c */ - if (likely(eventlist->filter != 0)) { - eventlist++; - } else { - dbg_puts("spurious wakeup, discarding event"); - nret--; + /* + * epoll event is associated with one filter for + * reading and one filter for writing. + */ + case EPOLL_UDATA_FD_STATE: + { + struct fd_state *fds = epoll_udata->ud_fds; + struct knote *kn; + + /* + * FD is readable + */ + if (ev->events & EPOLLIN) { + if (el_p >= el_end) goto oos; + + kn = fds->fds_read; + + /* + * We shouldn't receive events we didn't register for + * This assume's the Linux's epoll implementation isn't + * complete garbage... so um... this assert may need + * to be removed later. + */ + assert(kn); + + rv = linux_kevent_copyout_ev(&el_p, ev, &kq->kq_filt[~(kn->kev.filter)], kn); + if (rv < 0) goto done; + } + + /* + * FD is writable + */ + if (ev->events & EPOLLOUT) { + if (el_p >= el_end) goto oos; + + kn = fds->fds_write; + + assert(kn); /* We shouldn't receive events we didn't request */ + + rv = linux_kevent_copyout_ev(&el_p, ev, &kq->kq_filt[~(kn->kev.filter)], kn); + if (rv < 0) goto done; + } + } + break; + + /* + * Bad udata value. Maybe use after free? + */ + default: + assert(0); + return (-1); } } - return (nret); +done: + return el_p - el; } - int linux_eventfd_init(struct eventfd *e) { @@ -496,17 +577,17 @@ linux_eventfd_raise(struct eventfd *e) counter = 1; if (write(e->ef_id, &counter, sizeof(counter)) < 0) { switch (errno) { - case EAGAIN: - /* Not considered an error */ - break; + case EAGAIN: + /* Not considered an error */ + break; - case EINTR: - rv = -EINTR; - break; + case EINTR: + rv = -EINTR; + break; - default: - dbg_printf("write(2): %s", strerror(errno)); - rv = -1; + default: + dbg_printf("write(2): %s", strerror(errno)); + rv = -1; } } return (rv); @@ -524,17 +605,17 @@ linux_eventfd_lower(struct eventfd *e) n = read(e->ef_id, &cur, sizeof(cur)); if (n < 0) { switch (errno) { - case EAGAIN: - /* Not considered an error */ - break; + case EAGAIN: + /* Not considered an error */ + break; - case EINTR: - rv = -EINTR; - break; + case EINTR: + rv = -EINTR; + break; - default: - dbg_printf("read(2): %s", strerror(errno)); - rv = -1; + default: + dbg_printf("read(2): %s", strerror(errno)); + rv = -1; } } else if (n != sizeof(cur)) { dbg_puts("short read"); @@ -705,19 +786,34 @@ linux_get_descriptor_type(struct knote *kn) return (0); } -char * -epoll_event_dump(struct epoll_event *evt) +char *epoll_event_op_dump(int op) +{ + static __thread char buf[14]; + + buf[0] = '\0'; + +#define EPOP_DUMP(attrib) \ + if (op == attrib) { \ + strcpy(buf, #attrib); \ + return buf; \ + } + + EPOP_DUMP(EPOLL_CTL_MOD); + EPOP_DUMP(EPOLL_CTL_ADD); + EPOP_DUMP(EPOLL_CTL_DEL); + + return buf; +} + +char *epoll_event_flags_dump(int events) { static __thread char buf[128]; - if (evt == NULL) - return "(null)"; + buf[0] = '\0'; #define EPEVT_DUMP(attrib) \ - if (evt->events & attrib) \ - strcat(buf, #attrib" "); + if (events & attrib) strcat(buf, #attrib" "); - snprintf(buf, 128, " { data = %p, events = ", evt->data.ptr); EPEVT_DUMP(EPOLLIN); EPEVT_DUMP(EPOLLOUT); #if defined(HAVE_EPOLLRDHUP) @@ -725,22 +821,335 @@ epoll_event_dump(struct epoll_event *evt) #endif EPEVT_DUMP(EPOLLONESHOT); EPEVT_DUMP(EPOLLET); - strcat(buf, "}\n"); + + if (buf[0] != '\0') buf[strlen(buf) - 1] = '\0'; /* Trim trailing space */ + + return buf; +} + +char * +epoll_event_dump(struct epoll_event *evt) +{ + static __thread char buf[128]; + + if (evt == NULL) + return "(null)"; + + snprintf(buf, sizeof(buf), "{ data = %p, events = %s }", evt->data.ptr, epoll_event_flags_dump(evt->events)); return (buf); #undef EPEVT_DUMP } + + +/** Determine if two fd state entries are equal + * + * @param[in] a first entry. + * @param[in] b second entry. + * @return + * - 0 if fd is equal. + * - 1 if fd_a > fd_b + * - -1 if fd_a < fd_b + */ +static int +epoll_fd_state_cmp(struct fd_state *a, struct fd_state *b) +{ + return (a->fds_fd > b->fds_fd) - (a->fds_fd < b->fds_fd); /* branchless comparison */ +} + +/** Create type specific rbtree functions + * + */ +RB_GENERATE(fd_st, fd_state, fds_entries, epoll_fd_state_cmp) + +/** Determine current fd_state/knote associations + * + * @param[in,out] fds_p to query. If *fds_p is NULL and + * kn->kn_fds is NULL, we attempt a + * lookup based on the FD associated with + * the kn. + * @param[in] kn to return EPOLLIN|EPOLLOUT flags for. + * @param[in] disabled if true, only disabled knotes will + * be included in the set. + * if false, only enabled knotes will + * be included in the set. + * @return + * - EPOLLIN if the FD has a read knote associated with it. + * - EPOLLOUT if the FD has a write knote associated with it. + */ +int epoll_fd_state(struct fd_state **fds_p, struct knote *kn, bool disabled) +{ + int state = 0; + int fd = kn->kev.ident; + struct fd_state *fds = *fds_p; + + if (!fds) { + fds = kn->kn_fds; + if(fds) dbg_printf("fd_state: from-kn fd=%i", fd); + } + if (!fds) { + dbg_printf("fd_state: find fd=%i", fd); + + fds = RB_FIND(fd_st, &kn->kn_kq->kq_fd_st, &(struct fd_state){ .fds_fd = fd }); + if (!fds) return (0); + } + + *fds_p = fds; + + if (fds->fds_read && (disabled == ((kn->kev.flags & EV_DISABLE) != 0))) state |= EPOLLIN; + if (fds->fds_write && (disabled == ((kn->kev.flags & EV_DISABLE) != 0))) state |= EPOLLOUT; + + return state; +} + +/** Associate a knote with the fd_state + * + * @param[in,out] fds_p to modify knote associations for. + * If *fds_p is NULL and kn->kn_fds is + * NULL, we attempt a lookup based on + * the FD associated with the kn. + * @param[in] kn to add FD tracking entry for. + * @param[in] ev the file descriptor was registered for, + * either EPOLLIN or EPOLLOUT. + * @return + * - 0 on success. + * - -1 on failure. + */ +int epoll_fd_state_mod(struct fd_state **fds_p, struct knote *kn, int ev) +{ + struct kqueue *kq = kn->kn_kq; + int fd = kn->kev.ident; + struct fd_state *fds = *fds_p; + + assert(ev & (EPOLLIN | EPOLLOUT)); + + /* + * The kqueue_lock around copyin and copyout + * operations means we don't need mutexes + * around tree access. + * + * Only one thread can be copying in or copying + * out at a time. + * + * The only potential issue we have were + * modifying the tree in kevent_wait + * (which we're not). + */ + if (!fds) fds = kn->kn_fds; + if (!fds) { + /* + * Also used as an initialiser if we can't find + * an existing fd_state. + */ + struct fd_state query = { .fds_fd = fd }; + + fds = RB_FIND(fd_st, &kq->kq_fd_st, &query); + if (!fds) { + dbg_printf("fd_state: new fd=%i events=0x%04x (%s)", fd, ev, epoll_event_flags_dump(ev)); + + fds = malloc(sizeof(struct fd_state)); + if (!fds) return (-1); + + *fds = query; + FDS_UDATA(fds); /* Prepare for insertion into epoll */ + RB_INSERT(fd_st, &kq->kq_fd_st, fds); + + } else { + mod: + dbg_printf("fd_state: mod fd=%i events=0x%04x (%s)", fd, ev, epoll_event_flags_dump(ev)); + } + } else goto mod; + + /* + * Place the knote in the correct slot. + */ + if (ev & EPOLLIN) { + assert(!fds->fds_read || (fds->fds_read == kn)); + fds->fds_read = kn; + } + if (ev & EPOLLOUT) { + assert(!fds->fds_write || (fds->fds_write == kn)); + fds->fds_write = kn; + } + + kn->kn_fds = fds; + *fds_p = fds; + + return (0); +} + +/** Disassociate a knote from an fd_ev possibly freeing the fd_ev + * + * @param[in] kn to remove FD tracking entry for. + * @param[in] ev the file descriptor was de-registered for, + * either EPOLLIN or EPOLLOUT. + */ +void epoll_fd_state_del(struct fd_state **fds_p, struct knote *kn, int ev) +{ + struct fd_state *fds = kn->kn_fds; + struct kqueue *kq = kn->kn_kq; + int fd; + + assert(ev & (EPOLLIN | EPOLLOUT)); + assert(fds); /* There ~must~ be an entry else something has gone horribly wrong */ + assert(!*fds_p || (*fds_p == kn->kn_fds)); + + fd = fds->fds_fd; + + /* + * copyin/copyout lock means we don't need + * to protect operations here. + */ + if (ev & EPOLLIN) { + assert(fds->fds_read); + fds->fds_read = NULL; + } + + if (ev & EPOLLOUT) { + assert(fds->fds_write); + fds->fds_write = NULL; + } + + if (!fds->fds_read && !fds->fds_write) { + dbg_printf("fd_state: rm fd=%i", fd); + RB_REMOVE(fd_st, &kq->kq_fd_st, fds); + free(fds); + *fds_p = NULL; + } else { + dbg_printf("fd_state: mod fd=%i events=0x%04x (%s)", fd, ev, epoll_event_flags_dump(ev)); + } + kn->kn_fds = NULL; +} + int -epoll_update(int op, struct filter *filt, struct knote *kn, struct epoll_event *ev) +epoll_update(int op, struct filter *filt, struct knote *kn, int ev, bool delete) { - dbg_printf("op=%d fd=%d events=%s", op, (int)kn->kev.ident, - epoll_event_dump(ev)); - if (epoll_ctl(filter_epoll_fd(filt), op, kn->kev.ident, ev) < 0) { + struct fd_state *fds = NULL; + int have_ev, want, want_ev; + int opn; + int fd; + + fd = kn->kev.ident; + +#define EV_EPOLLINOUT(_x) ((_x) & (EPOLLIN | EPOLLOUT)) + + if (kn->kev.flags & EV_DISABLE) dbg_printf("fd=%i kn is disabled", fd); + + /* + * Determine the current state of the file descriptor + * and see if we need to make changes. + */ + have_ev = epoll_fd_state(&fds, kn, false); /* ...enabled only */ + + dbg_printf("fd=%i have_ev=0x%04x (%s)", fd, have_ev, epoll_event_flags_dump(have_ev)); + switch (op) { + case EPOLL_CTL_ADD: + want = have_ev | ev; /* This also preserves other option flags */ + break; + + case EPOLL_CTL_DEL: + want = have_ev & ~ev; /* No options for delete */ + + /* + * If we're performing a delete we need + * to check for previously disabled + * knotes that may now be being deleted. + */ + if (delete) { + int to_delete; + + to_delete = epoll_fd_state(&fds, kn, true); /* ...disabled only */ + dbg_printf("fd=%i disabled_ev=0x%04x (%s)", fd, to_delete, epoll_event_flags_dump(to_delete)); + to_delete &= EV_EPOLLINOUT(ev); + + if (to_delete) { + dbg_printf("fd=%i ev=%i removing disabled fd state", fd, op); + epoll_fd_state_del(&fds, kn, to_delete); + } + } + break; + + case EPOLL_CTL_MOD: + want = ev; /* We assume the caller knows what its doing... */ + + if (delete) { + int to_delete; + + to_delete = epoll_fd_state(&fds, kn, true); /* ...disabled only */ + dbg_printf("fd=%i disabled_ev=0x%04x (%s)", fd, to_delete, epoll_event_flags_dump(to_delete)); + to_delete &= ~ev; + + if (to_delete) { + dbg_printf("fd=%i ev=%i removing disabled fd state", fd, op); + epoll_fd_state_del(&fds, kn, to_delete); + } + } + break; + + default: + assert(0); + return (-1); + } + + /* + * We only want the read/write flags for comparisons. + */ + want_ev = EV_EPOLLINOUT(want); + if (!have_ev && want_ev) { /* There's no events registered and we want some */ + opn = EPOLL_CTL_ADD; + epoll_fd_state_mod(&fds, kn, want_ev & ~have_ev); + } + else if (have_ev && !want_ev) /* We have events registered but don't want any */ + opn = EPOLL_CTL_DEL; + else if (have_ev != want_ev) /* There's events but they're not what we want */ + opn = EPOLL_CTL_MOD; + else + return (0); + + dbg_printf("fd=%i op=0x%04x (%s) opn=0x%04x (%s) %s", + fd, + op, epoll_event_op_dump(op), + opn, epoll_event_op_dump(opn), + epoll_event_dump(EPOLL_EV_FDS(want, fds))); + + if (epoll_ctl(filter_epoll_fd(filt), opn, fd, EPOLL_EV_FDS(want, fds)) < 0) { dbg_printf("epoll_ctl(2): %s", strerror(errno)); + + if (opn == EPOLL_CTL_ADD) epoll_fd_state_del(&fds, kn, want_ev & ~have_ev); + return (-1); } + /* + * Only change fd state for del and mod on success + * we need to 'add' before so that we get the fd_state + * structure to pass in to epoll. + */ + switch (opn) { + case EPOLL_CTL_DEL: + if (delete) { + dbg_printf("fd=%i ev=%i removing fd state", fd, op); + epoll_fd_state_del(&fds, kn, have_ev & ~want_ev); /* We rely on the caller to mark the knote as disabled */ + } + break; + + case EPOLL_CTL_MOD: + { + int add, del; + + add = want_ev & ~have_ev; + del = have_ev & ~want_ev; + + if (add) epoll_fd_state_mod(&fds, kn, add); + if (del && delete) { + dbg_printf("fd=%i ev=%i removing fd state", fd, op); + epoll_fd_state_del(&fds, kn, del); /* We rely on the caller to mark the knote as disabled */ + } + } + break; + } + return (0); } diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index f74394369..ae95d5eb9 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -13,7 +13,6 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - #ifndef _KQUEUE_LINUX_PLATFORM_H #define _KQUEUE_LINUX_PLATFORM_H @@ -57,30 +56,118 @@ extern long int syscall (long int __sysno, ...); #define kqueue_epoll_fd(kq) ((kq)->epollfd) #define filter_epoll_fd(filt) ((filt)->kf_kqueue->epollfd) -/* - * Additional members of struct filter +/** Macro for populating the kn udata structure + * + * @param[in] _kn to populate. */ -#undef FILTER_PLATFORM_SPECIFIC +#define KN_UDATA(_kn) ((_kn)->kn_udata = (struct epoll_udata){ .ud_type = EPOLL_UDATA_KNOTE, .ud_kn = _kn }) -/* - * Additional members of struct knote +/** Macro for populating the fds udata structure + * + * @param[in] _fds to populate. + */ +#define FDS_UDATA(_fds) ((_fds)->fds_udata = (struct epoll_udata){ .ud_type = EPOLL_UDATA_FD_STATE, .ud_fds = _fds }) + +/** Macro for building a temporary kn epoll_event + * + * @param[in] _events One or more event flags EPOLLIN, EPOLLOUT etc... + * @param[in] _kn to associate with the event. Is used to + * determine the correct filter to notify + * if the event fires. + */ +#define EPOLL_EV_KN(_events, _kn) &(struct epoll_event){ .events = _events, .data = { .ptr = &(_kn)->kn_udata } } + +/** Macro for building a temporary fds epoll_event + * + * @param[in] _events One or more event flags EPOLLIN, EPOLLOUT etc... + * @param[in] _fds File descriptor state to associate with the + * event. Is used during event demuxing to inform + * multiple filters of read/write events on the fd. + */ +#define EPOLL_EV_FDS(_events, _fds) &(struct epoll_event){ .events = _events, .data = { .ptr = &(_fds)->fds_udata } } + +/** Macro for building a temporary epoll_event + * + * @param[in] _events One or more event flags EPOLLIN, EPOLLOUT etc... + */ +#define EPOLL_EV(_events) &(struct epoll_event){ .events = _events } + +/** What type of udata is in the event loop + * + */ +enum epoll_udata_type { + EPOLL_UDATA_KNOTE = 0x01, //!< Udata is a pointer to a knote. + EPOLL_UDATA_FD_STATE = 0x02 //!< Udata is a pointer to a fd state structure. +}; + +/** Common structure that's provided as the epoll data.ptr + * + * Where an epoll event is associated with a single filter we pass in + * a knote. When the epoll event is associated with multiple filters + * we pass in an fd_state struct. + * + * This structure is common to both, and allows us to determine the + * type of structure associated with the epoll event. + */ +struct epoll_udata { + union { + struct knote *ud_kn; //!< Pointer back to the containing knote. + struct fd_state *ud_fds; //!< Pointer back to the containing fd_state. + }; + enum epoll_udata_type ud_type; //!< Which union member to use. +}; + +/** Holds cross-filter information for file descriptors + * + * Epoll will not allow the same file descriptor to be inserted + * twice into the same event loop. + * + * To make epoll work reliably, we need to mux and demux the events + * created by the filters interested in read/write events. + * This structure records the read and write knotes. + * + * Unfortunately this has the side effect of not allowing flags like + * EPOLLET + * + * We use the fact that fds_read/fds_write are nonnull to determine + * if the FD has already been registered for a particular event when + * we get a request to update epoll. + */ +struct fd_state { + RB_ENTRY(fd_state) fds_entries; //!< Entry in the RB tree. + int fds_fd; //!< File descriptor this entry relates to. + struct knote *fds_read; //!< Knote that should be informed of read events. + struct knote *fds_write; //!< Knote that should be informed of write events. + struct epoll_udata fds_udata; //!< Common struct passed to epoll +}; + +/** Additional members of struct filter + * + */ +#define FILTER_PLATFORM_SPECIFIC + +/** Additional members of struct knote + * */ #define KNOTE_PLATFORM_SPECIFIC \ - int kn_epollfd; /* A copy of filter->epoll_fd */ \ - int kn_registered; /* Is FD registered with epoll */ \ + int kn_epollfd; /* A copy of filter->epoll_fd */ \ + int kn_registered; /* Is FD registered with epoll */ \ + struct fd_state *kn_fds; /* File descriptor's registration state */ \ union { \ int kn_timerfd; \ int kn_signalfd; \ int kn_inotifyfd; \ int kn_eventfd; \ - } kdata + } kdata; \ + struct epoll_udata kn_udata /* Common struct passed to epoll */ -/* - * Additional members of struct kqueue +/** Additional members of struct kqueue + * */ #define KQUEUE_PLATFORM_SPECIFIC \ - int epollfd; /* Main epoll FD */ \ - int pipefd[2]; /* FD for pipe that catches close */ \ + int epollfd; /* Main epoll FD */ \ + int pipefd[2]; /* FD for pipe that catches close */ \ + RB_HEAD(fd_st, fd_state) kq_fd_st; /* EVFILT_READ/EVFILT_WRITE fd state */ \ struct epoll_event kq_plist[MAX_KEVENT]; \ size_t kq_nplist @@ -105,7 +192,13 @@ int linux_fd_to_path(char *, size_t, int); /* epoll-related functions */ -int epoll_update(int, struct filter *, struct knote *, struct epoll_event *); +char * epoll_event_op_dump(int); +char * epoll_event_flags_dump(int); char * epoll_event_dump(struct epoll_event *); +int epoll_fd_state(struct fd_state **, struct knote *, bool); +int epoll_fd_state_init(struct fd_state **, struct knote *, int); +void epoll_fd_state_free(struct fd_state **, struct knote *, int); + +int epoll_update(int op, struct filter *filt, struct knote *kn, int ev, bool delete); #endif /* ! _KQUEUE_LINUX_PLATFORM_H */ diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index edbfcb1a4..07ff0c99a 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -150,8 +150,6 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) int evfilt_read_knote_create(struct filter *filt, struct knote *kn) { - struct epoll_event ev; - if (linux_get_descriptor_type(kn) < 0) return (-1); @@ -161,19 +159,26 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) #else kn->data.events = EPOLLIN; #endif - if (kn->kev.flags & EV_ONESHOT || kn->kev.flags & EV_DISPATCH) - kn->data.events |= EPOLLONESHOT; if (kn->kev.flags & EV_CLEAR) kn->data.events |= EPOLLET; - memset(&ev, 0, sizeof(ev)); - ev.events = kn->data.events; - ev.data.ptr = kn; - /* Special case: for regular files, add a surrogate eventfd that is always readable */ if (kn->kn_flags & KNFL_FILE) { int evfd; + /* + * We only set oneshot for cases where we're not going to + * be using EPOLL_CTL_MOD. + * + * We rely on the common code disabling the event after + * it's fired once. + * + * See this SO post for details: + * https://stackoverflow.com/questions/59517961/how-should-i-use-epoll-to-read-and-write-from-the-same-fd + */ + if (kn->kev.flags & EV_ONESHOT || kn->kev.flags & EV_DISPATCH) + kn->data.events |= EPOLLONESHOT; + kn->kn_epollfd = filter_epoll_fd(filt); evfd = eventfd(0, 0); if (evfd < 0) { @@ -188,7 +193,8 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) kn->kdata.kn_eventfd = evfd; - if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_eventfd, &ev) < 0) { + KN_UDATA(kn); /* populate this knote's kn_udata field */ + if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_eventfd, EPOLL_EV_KN(kn->data.events, kn)) < 0) { dbg_printf("epoll_ctl(2): %s", strerror(errno)); (void) close(evfd); return (-1); @@ -199,7 +205,7 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) return (0); } - return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); + return epoll_update(EPOLL_CTL_ADD, filt, kn, kn->data.events, false); } int @@ -215,9 +221,6 @@ evfilt_read_knote_modify(struct filter *filt, struct knote *kn, int evfilt_read_knote_delete(struct filter *filt, struct knote *kn) { - if (kn->kev.flags & EV_DISABLE) - return (0); - if ((kn->kn_flags & KNFL_FILE) && (kn->kdata.kn_eventfd != -1)) { if (kn->kn_registered && epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kdata.kn_eventfd, NULL) < 0) { dbg_perror("epoll_ctl(2)"); @@ -227,36 +230,24 @@ evfilt_read_knote_delete(struct filter *filt, struct knote *kn) (void) close(kn->kdata.kn_eventfd); kn->kdata.kn_eventfd = -1; return (0); - } else { - return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); } - // clang will complain about not returning a value otherwise - return (-1); + return epoll_update(EPOLL_CTL_DEL, filt, kn, EPOLLIN, true); } int evfilt_read_knote_enable(struct filter *filt, struct knote *kn) { - struct epoll_event ev; - - memset(&ev, 0, sizeof(ev)); - ev.events = kn->data.events; - ev.data.ptr = kn; - if (kn->kn_flags & KNFL_FILE) { - if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_eventfd, &ev) < 0) { + if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_eventfd, EPOLL_EV_KN(kn->data.events, kn)) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); } kn->kn_registered = 1; return (0); - } else { - return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); } - // clang will complain about not returning a value otherwise - return (-1); + return epoll_update(EPOLL_CTL_ADD, filt, kn, kn->data.events, false); } int @@ -269,9 +260,9 @@ evfilt_read_knote_disable(struct filter *filt, struct knote *kn) } kn->kn_registered = 1; return (0); - } else { - return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); } + + return epoll_update(EPOLL_CTL_DEL, filt, kn, EPOLLIN, false); } const struct filter evfilt_read = { diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index f8f76acbe..c855a8de0 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -61,16 +61,13 @@ signalfd_reset(int sigfd) } static int -signalfd_add(int epoll_fd, int sigfd, void *ptr) +signalfd_add(int epoll_fd, int sigfd, struct knote *kn) { - struct epoll_event ev; int rv; /* Add the signalfd to the kqueue's epoll descriptor set */ - memset(&ev, 0, sizeof(ev)); - ev.events = EPOLLIN; - ev.data.ptr = ptr; - rv = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sigfd, &ev); + KN_UDATA(kn); /* populate this knote's kn_udata field */ + rv = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sigfd, EPOLL_EV_KN(EPOLLIN, kn)); if (rv < 0) { dbg_perror("epoll_ctl(2)"); return (-1); @@ -80,7 +77,7 @@ signalfd_add(int epoll_fd, int sigfd, void *ptr) } static int -signalfd_create(int epoll_fd, void *ptr, int signum) +signalfd_create(int epoll_fd, struct knote *kn, int signum) { static int flags = SFD_NONBLOCK; sigset_t sigmask; @@ -109,7 +106,7 @@ signalfd_create(int epoll_fd, void *ptr, int signum) signalfd_reset(sigfd); - if (signalfd_add(epoll_fd, sigfd, ptr) < 0) + if (signalfd_add(epoll_fd, sigfd, kn) < 0) goto errout; dbg_printf("added sigfd %d to epoll_fd %d (signum=%d)", sigfd, epoll_fd, signum); diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 7cf894410..50997ca7d 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -152,10 +152,10 @@ evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr) int evfilt_timer_knote_create(struct filter *filt, struct knote *kn) { - struct epoll_event ev; struct itimerspec ts; int tfd; int flags; + int events; kn->kev.flags |= EV_CLEAR; @@ -175,13 +175,12 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) return (-1); } - memset(&ev, 0, sizeof(ev)); - ev.events = EPOLLIN | EPOLLET; + events = EPOLLIN | EPOLLET; if (kn->kev.flags & (EV_ONESHOT | EV_DISPATCH)) - ev.events |= EPOLLONESHOT; + events |= EPOLLONESHOT; - ev.data.ptr = kn; - if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_ADD, tfd, &ev) < 0) { + KN_UDATA(kn); /* populate this knote's kn_udata field */ + if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_ADD, tfd, EPOLL_EV_KN(events, kn)) < 0) { dbg_printf("epoll_ctl(2): %d", errno); close(tfd); return (-1); diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index 151078800..98b8f53c1 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -116,7 +116,6 @@ linux_evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSE int linux_evfilt_user_knote_create(struct filter *filt, struct knote *kn) { - struct epoll_event ev; int evfd; /* Create an eventfd */ @@ -127,10 +126,8 @@ linux_evfilt_user_knote_create(struct filter *filt, struct knote *kn) } /* Add the eventfd to the epoll set */ - memset(&ev, 0, sizeof(ev)); - ev.events = EPOLLIN; - ev.data.ptr = kn; - if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_ADD, evfd, &ev) < 0) { + KN_UDATA(kn); /* populate this knote's kn_udata field */ + if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_ADD, evfd, EPOLL_EV_KN(EPOLLIN, kn)) < 0) { dbg_perror("epoll_ctl(2)"); goto errout; } diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 274c2c2f9..0c48245f5 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -103,7 +103,6 @@ get_one_event(struct inotify_event *dst, size_t len, int inofd) static int add_watch(struct filter *filt, struct knote *kn) { - struct epoll_event ev; int ifd; char path[PATH_MAX]; uint32_t mask; @@ -145,10 +144,8 @@ add_watch(struct filter *filt, struct knote *kn) } /* Add the inotify fd to the epoll set */ - memset(&ev, 0, sizeof(ev)); - ev.events = EPOLLIN; - ev.data.ptr = kn; - if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_ADD, ifd, &ev) < 0) { + KN_UDATA(kn); /* populate this knote's kn_udata field */ + if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_ADD, ifd, EPOLL_EV_KN(EPOLLIN, kn)) < 0) { dbg_perror("epoll_ctl(2)"); goto errout; } diff --git a/vendor/libkqueue/src/linux/write.c b/vendor/libkqueue/src/linux/write.c index 09ad80530..44170e4f5 100644 --- a/vendor/libkqueue/src/linux/write.c +++ b/vendor/libkqueue/src/linux/write.c @@ -67,8 +67,6 @@ evfilt_write_copyout(struct kevent *dst, struct knote *src, void *ptr) int evfilt_write_knote_create(struct filter *filt, struct knote *kn) { - struct epoll_event ev; - if (linux_get_descriptor_type(kn) < 0) return (-1); @@ -77,18 +75,22 @@ evfilt_write_knote_create(struct filter *filt, struct knote *kn) return (-1); } - /* Convert the kevent into an epoll_event */ + /* + * Convert the kevent into an epoll_event + */ kn->data.events = EPOLLOUT; - if (kn->kev.flags & EV_ONESHOT || kn->kev.flags & EV_DISPATCH) - kn->data.events |= EPOLLONESHOT; + + /* + * For EV_ONESHOT, EV_DISPATCH we rely on common code + * disabling/deleting the event after it's fired once. + * + * See this SO post for details: + * https://stackoverflow.com/questions/59517961/how-should-i-use-epoll-to-read-and-write-from-the-same-fd + */ if (kn->kev.flags & EV_CLEAR) kn->data.events |= EPOLLET; - memset(&ev, 0, sizeof(ev)); - ev.events = kn->data.events; - ev.data.ptr = kn; - - return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); + return epoll_update(EPOLL_CTL_ADD, filt, kn, kn->data.events, false); } int @@ -104,28 +106,19 @@ evfilt_write_knote_modify(struct filter *filt, struct knote *kn, int evfilt_write_knote_delete(struct filter *filt, struct knote *kn) { - if (kn->kev.flags & EV_DISABLE) - return (0); - else - return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); + return epoll_update(EPOLL_CTL_DEL, filt, kn, EPOLLOUT, true); } int evfilt_write_knote_enable(struct filter *filt, struct knote *kn) { - struct epoll_event ev; - - memset(&ev, 0, sizeof(ev)); - ev.events = kn->data.events; - ev.data.ptr = kn; - - return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); + return epoll_update(EPOLL_CTL_ADD, filt, kn, kn->data.events, false); } int evfilt_write_knote_disable(struct filter *filt, struct knote *kn) { - return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); + return epoll_update(EPOLL_CTL_DEL, filt, kn, EPOLLOUT, false); } const struct filter evfilt_write = { From 49816c6c50cbef6d11e0eb807c050dd63ccb7925 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 11 Jun 2020 16:45:29 -0500 Subject: [PATCH 0731/1120] Minor cleanup for non-debug builds on GCC --- vendor/libkqueue/src/linux/platform.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index c22f348ad..9b3622f69 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -989,14 +989,11 @@ void epoll_fd_state_del(struct fd_state **fds_p, struct knote *kn, int ev) { struct fd_state *fds = kn->kn_fds; struct kqueue *kq = kn->kn_kq; - int fd; assert(ev & (EPOLLIN | EPOLLOUT)); assert(fds); /* There ~must~ be an entry else something has gone horribly wrong */ assert(!*fds_p || (*fds_p == kn->kn_fds)); - fd = fds->fds_fd; - /* * copyin/copyout lock means we don't need * to protect operations here. @@ -1012,12 +1009,12 @@ void epoll_fd_state_del(struct fd_state **fds_p, struct knote *kn, int ev) } if (!fds->fds_read && !fds->fds_write) { - dbg_printf("fd_state: rm fd=%i", fd); + dbg_printf("fd_state: rm fd=%i", fds->fds_fd); RB_REMOVE(fd_st, &kq->kq_fd_st, fds); free(fds); *fds_p = NULL; } else { - dbg_printf("fd_state: mod fd=%i events=0x%04x (%s)", fd, ev, epoll_event_flags_dump(ev)); + dbg_printf("fd_state: mod fd=%i events=0x%04x (%s)", fds->fds_fd, ev, epoll_event_flags_dump(ev)); } kn->kn_fds = NULL; } From bfd2ff4889632345555802d5a8aa25b64a751460 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 11 Jun 2020 16:55:22 -0500 Subject: [PATCH 0732/1120] tabs to spaces... --- vendor/libkqueue/kern/kqueue.c | 8 ++-- vendor/libkqueue/src/common/filter.c | 2 +- vendor/libkqueue/src/common/kevent.c | 4 +- vendor/libkqueue/src/common/kqueue.c | 12 +++--- vendor/libkqueue/src/common/map.c | 14 +++---- vendor/libkqueue/src/common/private.h | 18 ++++----- vendor/libkqueue/src/linux/platform.c | 24 ++++++------ vendor/libkqueue/test/kevent.c | 12 +++--- vendor/libkqueue/test/libdispatch/main.c | 50 ++++++++++++------------ vendor/libkqueue/test/main.c | 8 ++-- vendor/libkqueue/test/read.c | 6 +-- vendor/libkqueue/test/test.c | 8 ++-- vendor/libkqueue/test/user.c | 2 +- vendor/libkqueue/test/vnode.c | 2 +- 14 files changed, 85 insertions(+), 85 deletions(-) diff --git a/vendor/libkqueue/kern/kqueue.c b/vendor/libkqueue/kern/kqueue.c index 69d3baab4..29a74ca31 100644 --- a/vendor/libkqueue/kern/kqueue.c +++ b/vendor/libkqueue/kern/kqueue.c @@ -63,11 +63,11 @@ static ssize_t kqueue_write(struct file *file, const char __user *buf, struct file_operations fops = { .owner = THIS_MODULE, - .ioctl = kqueue_ioctl, - .open = kqueue_open, + .ioctl = kqueue_ioctl, + .open = kqueue_open, .release = kqueue_release, - .read = kqueue_read, - .write = kqueue_write, + .read = kqueue_read, + .write = kqueue_write, }; struct kfilter { diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index e862bbd48..1f6fcac39 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -121,7 +121,7 @@ filter_unregister_all(struct kqueue *kq) if (kqops.filter_free != NULL) kqops.filter_free(kq, &kq->kq_filt[i]); - } + } memset(&kq->kq_filt[0], 0, sizeof(kq->kq_filt)); } diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index fa9bd5078..ee43325d3 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -78,7 +78,7 @@ kevent_flags_dump(const struct kevent *kev) #define KEVFL_DUMP(attrib) \ if (kev->flags & attrib) \ - strncat((char *) buf, #attrib" ", 64); + strncat((char *) buf, #attrib" ", 64); snprintf(buf, sizeof(buf), "flags=0x%04x (", kev->flags); KEVFL_DUMP(EV_ADD); @@ -299,7 +299,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, dbg_printf("(%u) returning %d events", myid, rv); for (n = 0; n < rv; n++) { - dbg_printf("(%u) eventlist[%d] = %s", myid, n, kevent_dump(&eventlist[n])); + dbg_printf("(%u) eventlist[%d] = %s", myid, n, kevent_dump(&eventlist[n])); } } #endif diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 29f1c0716..0e8116b9a 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -77,12 +77,12 @@ libkqueue_init(void) #endif # if defined(_WIN32) && !defined(__GNUC__) - /* Enable heap surveillance */ - { - int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ); - tmpFlag |= _CRTDBG_CHECK_ALWAYS_DF; - _CrtSetDbgFlag(tmpFlag); - } + /* Enable heap surveillance */ + { + int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ); + tmpFlag |= _CRTDBG_CHECK_ALWAYS_DF; + _CrtSetDbgFlag(tmpFlag); + } # endif /* _WIN32 */ } #endif diff --git a/vendor/libkqueue/src/common/map.c b/vendor/libkqueue/src/common/map.c index 65c13c4b1..80aa8af86 100644 --- a/vendor/libkqueue/src/common/map.c +++ b/vendor/libkqueue/src/common/map.c @@ -30,13 +30,13 @@ map_new(size_t len) if (dst == NULL) return (NULL); #ifdef _WIN32 - dst->data = calloc(len, sizeof(void*)); - if(dst->data == NULL) { - dbg_perror("calloc()"); - free(dst); - return NULL; - } - dst->len = len; + dst->data = calloc(len, sizeof(void*)); + if(dst->data == NULL) { + dbg_perror("calloc()"); + free(dst); + return NULL; + } + dst->len = len; #else dst->data = mmap(NULL, len * sizeof(void *), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_NORESERVE | MAP_ANON, -1, 0); diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 0c2762a1f..7fae7ff86 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -139,7 +139,7 @@ struct knote { * */ struct filter { - short kf_id; //!< EVFILT_* facility this filter provides. + short kf_id; //!< EVFILT_* facility this filter provides. /* filter operations */ @@ -156,14 +156,14 @@ struct filter { int (*kn_enable)(struct filter *, struct knote *); int (*kn_disable)(struct filter *, struct knote *); - struct eventfd kf_efd; //!< Used by user.c + struct eventfd kf_efd; //!< Used by user.c //MOVE TO POSIX? - int kf_pfd; //!< fd to poll(2) for readiness - int kf_wfd; //!< fd to write when an event occurs + int kf_pfd; //!< fd to poll(2) for readiness + int kf_wfd; //!< fd to write when an event occurs //----? - struct evfilt_data *kf_data; //!< filter-specific data */ + struct evfilt_data *kf_data; //!< filter-specific data */ RB_HEAD(knt, knote) kf_knote; pthread_rwlock_t kf_knote_mtx; struct kqueue *kf_kqueue; @@ -181,10 +181,10 @@ struct filter { * in receiving notifications for. */ struct kqueue { - int kq_id; //!< File descriptor used to identify this kqueue. - struct filter kq_filt[EVFILT_SYSCOUNT]; //!< Filters supported by the kqueue. Each - ///< kqueue maintains one filter state structure - ///< per filter type. + int kq_id; //!< File descriptor used to identify this kqueue. + struct filter kq_filt[EVFILT_SYSCOUNT]; //!< Filters supported by the kqueue. Each + ///< kqueue maintains one filter state structure + ///< per filter type. fd_set kq_fds, kq_rfds; int kq_nfds; tracing_mutex_t kq_mtx; diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 9b3622f69..2efc1c799 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -790,26 +790,26 @@ char *epoll_event_op_dump(int op) { static __thread char buf[14]; - buf[0] = '\0'; + buf[0] = '\0'; #define EPOP_DUMP(attrib) \ - if (op == attrib) { \ - strcpy(buf, #attrib); \ - return buf; \ - } + if (op == attrib) { \ + strcpy(buf, #attrib); \ + return buf; \ + } - EPOP_DUMP(EPOLL_CTL_MOD); - EPOP_DUMP(EPOLL_CTL_ADD); - EPOP_DUMP(EPOLL_CTL_DEL); + EPOP_DUMP(EPOLL_CTL_MOD); + EPOP_DUMP(EPOLL_CTL_ADD); + EPOP_DUMP(EPOLL_CTL_DEL); - return buf; + return buf; } char *epoll_event_flags_dump(int events) { static __thread char buf[128]; - buf[0] = '\0'; + buf[0] = '\0'; #define EPEVT_DUMP(attrib) \ if (events & attrib) strcat(buf, #attrib" "); @@ -822,7 +822,7 @@ char *epoll_event_flags_dump(int events) EPEVT_DUMP(EPOLLONESHOT); EPEVT_DUMP(EPOLLET); - if (buf[0] != '\0') buf[strlen(buf) - 1] = '\0'; /* Trim trailing space */ + if (buf[0] != '\0') buf[strlen(buf) - 1] = '\0'; /* Trim trailing space */ return buf; } @@ -885,7 +885,7 @@ int epoll_fd_state(struct fd_state **fds_p, struct knote *kn, bool disabled) struct fd_state *fds = *fds_p; if (!fds) { - fds = kn->kn_fds; + fds = kn->kn_fds; if(fds) dbg_printf("fd_state: from-kn fd=%i", fd); } if (!fds) { diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index f871b899b..602f2adc0 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -75,15 +75,15 @@ kevent_fflags_dump(struct kevent *kev) #define KEVFFL_DUMP(attrib) \ if (kev->fflags & attrib) \ - strncat(buf, #attrib" ", 64); + strncat(buf, #attrib" ", 64); if ((buf = calloc(1, 1024)) == NULL) - abort(); + abort(); /* Not every filter has meaningful fflags */ if (kev->filter != EVFILT_VNODE) { - snprintf(buf, 1024, "fflags = %d", kev->fflags); - return (buf); + snprintf(buf, 1024, "fflags = %d", kev->fflags); + return (buf); } snprintf(buf, 1024, "fflags = %d (", kev->fflags); @@ -111,10 +111,10 @@ kevent_flags_dump(struct kevent *kev) #define KEVFL_DUMP(attrib) \ if (kev->flags & attrib) \ - strncat(buf, #attrib" ", 64); + strncat(buf, #attrib" ", 64); if ((buf = calloc(1, 1024)) == NULL) - abort(); + abort(); snprintf(buf, 1024, "flags = %d (", kev->flags); KEVFL_DUMP(EV_ADD); diff --git a/vendor/libkqueue/test/libdispatch/main.c b/vendor/libkqueue/test/libdispatch/main.c index 8904feb36..e22ff5e57 100644 --- a/vendor/libkqueue/test/libdispatch/main.c +++ b/vendor/libkqueue/test/libdispatch/main.c @@ -30,26 +30,26 @@ void test_countdown(void); void say_hello(void *arg) { - puts("hello"); - test_countdown(); + puts("hello"); + test_countdown(); } void final_countdown(void *arg, size_t count) { - static int europe = 10; + static int europe = 10; - if (europe == 0) { - printf("It's the final countdown..\n"); - exit(0); - } else { - printf("%d.. ", europe); - fflush(stdout); - } + if (europe == 0) { + printf("It's the final countdown..\n"); + exit(0); + } else { + printf("%d.. ", europe); + fflush(stdout); + } - pthread_mutex_lock(&mtx); - europe--; - pthread_mutex_unlock(&mtx); + pthread_mutex_lock(&mtx); + europe--; + pthread_mutex_unlock(&mtx); } /* Adapted from: @@ -58,23 +58,23 @@ final_countdown(void *arg, size_t count) void test_timer() { - dispatch_source_t timer; - dispatch_time_t now; + dispatch_source_t timer; + dispatch_time_t now; timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, - dispatch_get_current_queue()); //NOTE: q_default doesn't work - now = dispatch_walltime(DISPATCH_TIME_NOW, 0); - dispatch_source_set_timer(timer, now, 1, 1); - dispatch_source_set_event_handler_f(timer, say_hello); - puts("starting timer\n"); + dispatch_get_current_queue()); //NOTE: q_default doesn't work + now = dispatch_walltime(DISPATCH_TIME_NOW, 0); + dispatch_source_set_timer(timer, now, 1, 1); + dispatch_source_set_event_handler_f(timer, say_hello); + puts("starting timer\n"); } void test_countdown(void) { - dispatch_apply_f(15, - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), - NULL, final_countdown); + dispatch_apply_f(15, + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), + NULL, final_countdown); } @@ -90,9 +90,9 @@ main(int argc, char **argv) argc--; } - test_timer(); + test_timer(); - dispatch_main(); + dispatch_main(); printf("\n---\n" "+OK All %d tests completed.\n", testnum - 1); return (0); diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index b355569e5..b550d293a 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -62,8 +62,8 @@ static void test_peer_close_detection(void *unused) { #ifdef _WIN32 - return; - //FIXME + return; + //FIXME #else int sockfd[2]; char buf[1]; @@ -292,9 +292,9 @@ main(int argc, char **argv) #if FIXME { "proc", 1, test_evfilt_proc }, #endif - { "timer", 1, test_evfilt_timer }, + { "timer", 1, test_evfilt_timer }, #ifndef _WIN32 - { "vnode", 1, test_evfilt_vnode }, + { "vnode", 1, test_evfilt_vnode }, #endif #ifdef EVFILT_USER { "user", 1, test_evfilt_user }, diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 50d5f239b..c04d80c52 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -35,10 +35,10 @@ create_socket_connection(int *client, int *server) sain.sin_family = AF_INET; sain.sin_port = 0; if ((srvr = socket(PF_INET, SOCK_STREAM, 0)) < 0) - err(1, "socket"); + err(1, "socket"); if (setsockopt(srvr, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one)) != 0) - err(1, "setsockopt"); + err(1, "setsockopt"); if (bind(srvr, (struct sockaddr *) &sain, sa_len) < 0) { printf("unable to bind to auto-assigned port\n"); err(1, "bind-1"); @@ -47,7 +47,7 @@ create_socket_connection(int *client, int *server) err(1, "getsockname-1"); port = ntohs(sain.sin_port); if (listen(srvr, 100) < 0) - err(1, "listen"); + err(1, "listen"); /* Simulate a client connecting to the server */ sain.sin_family = AF_INET; diff --git a/vendor/libkqueue/test/test.c b/vendor/libkqueue/test/test.c index 242f3afef..65e0a0754 100644 --- a/vendor/libkqueue/test/test.c +++ b/vendor/libkqueue/test/test.c @@ -32,13 +32,13 @@ static void error_handler(int signum) { #if defined(__linux__) && (defined(__GLIBC__) && !defined(__UCLIBC__)) - void *buf[32]; + void *buf[32]; /* FIXME: the symbols aren't printing */ - printf("***** ERROR: Program received signal %d *****\n", signum); - backtrace_symbols_fd(buf, sizeof(buf) / sizeof(void *), 2); + printf("***** ERROR: Program received signal %d *****\n", signum); + backtrace_symbols_fd(buf, sizeof(buf) / sizeof(void *), 2); #else - printf("***** ERROR: Program received signal %d *****\n", signum); + printf("***** ERROR: Program received signal %d *****\n", signum); #endif exit(1); } diff --git a/vendor/libkqueue/test/user.c b/vendor/libkqueue/test/user.c index 29ec077ae..f9c76c35e 100644 --- a/vendor/libkqueue/test/user.c +++ b/vendor/libkqueue/test/user.c @@ -173,7 +173,7 @@ test_kevent_user_dispatch(struct test_context *ctx) kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_DELETE, 0, 0, NULL); test_no_kevents(ctx->kqfd); } -#endif /* EV_DISPATCH */ +#endif /* EV_DISPATCH */ void test_evfilt_user(struct test_context *ctx) diff --git a/vendor/libkqueue/test/vnode.c b/vendor/libkqueue/test/vnode.c index 74f001811..13de091f6 100644 --- a/vendor/libkqueue/test/vnode.c +++ b/vendor/libkqueue/test/vnode.c @@ -235,7 +235,7 @@ test_kevent_vnode_dispatch(struct test_context *ctx) /* Delete the watch */ kevent_add(ctx->kqfd, &kev, ctx->vnode_fd, EVFILT_VNODE, EV_DELETE, NOTE_ATTRIB, 0, NULL); } -#endif /* EV_DISPATCH */ +#endif /* EV_DISPATCH */ void test_evfilt_vnode(struct test_context *ctx) From a1d0ae7493a12427074d81771d7d160383e64bf4 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Thu, 11 Jun 2020 18:40:31 -0300 Subject: [PATCH 0733/1120] kqueue() Fix memory leak --- vendor/libkqueue/src/common/kqueue.c | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 0e8116b9a..28e01385b 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -167,6 +167,7 @@ kqueue(void) if (map_insert(kqmap, kq->kq_id, kq) < 0) { dbg_puts("map insertion failed"); kqops.kqueue_free(kq); + free(kq); return (-1); } From 4075907abf7d0b5289c49f3ba7eb5dfb4eafaaea Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Thu, 11 Jun 2020 18:45:47 -0300 Subject: [PATCH 0734/1120] kqueue() Fix dead-lock --- vendor/libkqueue/src/common/kqueue.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 28e01385b..3c3560b71 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -150,6 +150,8 @@ kqueue(void) tracing_mutex_init(&kq->kq_mtx, NULL); if (kqops.kqueue_init(kq) < 0) { + error: + tracing_mutex_destroy(&kq->kq_mtx); free(kq); return (-1); } @@ -167,8 +169,8 @@ kqueue(void) if (map_insert(kqmap, kq->kq_id, kq) < 0) { dbg_puts("map insertion failed"); kqops.kqueue_free(kq); - free(kq); - return (-1); + pthread_mutex_unlock(&kq_mtx); + goto error; } pthread_mutex_unlock(&kq_mtx); From 6cfec454c651c2e102c9e4d5fbc38cb4b47dec47 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Fri, 12 Jun 2020 14:44:45 -0300 Subject: [PATCH 0735/1120] Add sanitizer debug targets (#84) * Add sanitizer debug targets Now we have the below new debug build targets -DENABLE_ASAN=YES - Address Sanitizer -DENABLE_LSAN=YES - Leak Sanitizer -DENABLE_UBSAN=YES - Undefined Behaviour Sanitizer --- vendor/libkqueue/CMakeLists.txt | 42 +++++++++++++++++++++++++++++++++ vendor/libkqueue/README.md | 12 +++++++--- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 4bf9e81e2..1f14150ff 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -35,6 +35,48 @@ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE RelWithDebInfo) endif() +# +# Address Sanitize +# +if(ENABLE_ASAN) + # + # -fsanitize=address - Build with address sanitizer support + # -fno-omit-frame-pointer - Always keep the frame pointer in a register + # -fno-optimize-sibling-calls - Don't optimize away tail recursion. + # + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer -fno-optimize-sibling-calls") + list(APPEND DEBUG_FSANITIZERFLAGS "address") +endif() + +# +# LeakSanitizer +# +if(ENABLE_LSAN) + # + # -fsanitize=leak - Build with lsan support + # + list(APPEND DEBUG_FSANITIZERFLAGS "leak") +endif() + +# +# UndefinedBehaviour +# +if(ENABLE_UBSAN) + # + # -fsanitize=undefined - Build with ubsan support + # -fno-omit-frame-pointer - Always keep the frame pointer in a register + # + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-sanitize-recover=undefined -fno-omit-frame-pointer") + set(CMAKE_LD_FLAGS_DEBUG "${CMAKE_LD_FLAGS_DEBUG} -fno-sanitize-recover=undefined") + list(APPEND DEBUG_FSANITIZERFLAGS "undefined") +endif() + +if(DEBUG_FSANITIZERFLAGS) + string (REPLACE ";" "," DEBUG_FSANITIZERFLAGS "${DEBUG_FSANITIZERFLAGS}") + set(CMAKE_C_FLAGS_DEBUG "-fsanitize=${DEBUG_FSANITIZERFLAGS} ${CMAKE_C_FLAGS_DEBUG}") + set(CMAKE_LD_FLAGS_DEBUG "-fsanitize=${DEBUG_FSANITIZERFLAGS} ${CMAKE_LD_FLAGS_DEBUG}") +endif() + option(STATIC_KQUEUE "build libkqueue as static library" OFF) set(CMAKE_THREAD_PREFER_PTHREAD TRUE) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index 9f4e07395..3d40ded9a 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -70,10 +70,16 @@ Running Unit Tests Debugging --------- -For best results add `-DCMAKE_BUILD_TYPE=Debug` to your cmake invocation. -At a minimum ensure -DNDEBUG is *NOT* passed during compilation, otherwise all debug output will be disabled. +For best results add `-DCMAKE_BUILD_TYPE=Debug` to your cmake invocation, this will disable optimisation +and add debugging symbols to ensure your debugger produces usable output, it also enables asserts. -The environmental variable `KQUEUE_DEBUG` can then be set to enable debug output from libkqueue. +When building under clang and some later versions of GCC, you can add the following flags: + +- `-DENABLE_ASAN=YES`, enables address sansitizer (detects use after free issues, and out of bounds accesses). +- `-DENABLE_LSAN=YES`, enables leak sanitizer (detects memory leaks). +- `-DENABLE_UBSAN=YES`, enables undefined behaviour sanitizer (detects misaligned accesses, interger wrap, divide by zero etc...). + +The environmental variable `KQUEUE_DEBUG` can then be set to enable debug output from libkqueue and the test utility. KQUEUE_DEBUG=1 From f7870e3c6d8feb49e1c1ed92a1b0a8d5f822bb11 Mon Sep 17 00:00:00 2001 From: "konstantin.gusarov" Date: Wed, 3 Apr 2019 13:05:52 +0300 Subject: [PATCH 0736/1120] More Windows-related updates --- vendor/libkqueue/CMakeLists.txt | 8 +++++++- vendor/libkqueue/config.h.in | 1 + vendor/libkqueue/src/common/kqueue.c | 2 ++ vendor/libkqueue/src/windows/platform.h | 2 ++ vendor/libkqueue/test/common.h | 2 +- vendor/libkqueue/test/test.c | 1 - 6 files changed, 13 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 1f14150ff..1611d3954 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -90,6 +90,7 @@ include(GNUInstallDirs) check_include_files(sys/signalfd.h HAVE_SYS_SIGNALFD_H) check_include_files(sys/timerfd.h HAVE_SYS_TIMERFD_H) check_include_files(sys/eventfd.h HAVE_SYS_EVENTFD_H) +check_include_files(sys/types.h HAVE_SYS_TYPES_H) if(ENABLE_TESTING) check_include_files(err.h HAVE_ERR_H) endif() @@ -204,7 +205,12 @@ if(CMAKE_C_COMPILER_ID MATCHES GNU) target_compile_options(kqueue PRIVATE -Wall -Werror) endif() if(MINGW AND CMAKE_C_COMPILER_ID MATCHES GNU) - target_compile_options(kqueue PRIVATE -march=i486) + #TODO: is it needed at all? + if (CMAKE_SIZEOF_VOID_P EQUAL 4) + target_compile_options(kqueue PRIVATE -march=i486) + elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) + target_compile_options(kqueue PRIVATE -march=x86-64) + endif () endif() if(WIN32) diff --git a/vendor/libkqueue/config.h.in b/vendor/libkqueue/config.h.in index cec3300ed..57352ee6e 100644 --- a/vendor/libkqueue/config.h.in +++ b/vendor/libkqueue/config.h.in @@ -3,6 +3,7 @@ #cmakedefine01 HAVE_SYS_TIMERFD_H #cmakedefine01 HAVE_SYS_EVENTFD_H #cmakedefine01 HAVE_ERR_H +#cmakedefine01 HAVE_SYS_TYPES_H #cmakedefine01 HAVE_EPOLLRDHUP #cmakedefine01 HAVE_NOTE_TRUNCATE diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 3c3560b71..714a90ef7 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -137,6 +137,8 @@ kqueue(void) sleep(1); } } + + pthread_mutex_init(&kq_mtx, NULL); #else (void) pthread_mutex_lock(&kq_mtx); (void) pthread_once(&kq_is_initialized, libkqueue_init); diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index d2b3af456..934e7fac8 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -122,7 +122,9 @@ typedef int nlink_t; typedef int timer_t; typedef int pthread_t; typedef int sigset_t; +#ifndef HAVE_SYS_TYPES_H typedef int pid_t; +#endif #ifndef __GNUC__ # define __thread __declspec(thread) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 9922163a0..353bf6e94 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -39,6 +39,7 @@ #include #include +#include "config.h" #ifndef _WIN32 #include #include @@ -48,7 +49,6 @@ #include #include #include -#include "config.h" #include #else # include "include/sys/event.h" diff --git a/vendor/libkqueue/test/test.c b/vendor/libkqueue/test/test.c index 65e0a0754..a56b77528 100644 --- a/vendor/libkqueue/test/test.c +++ b/vendor/libkqueue/test/test.c @@ -19,7 +19,6 @@ #endif #include #include -#include #include "common.h" From 0eab70e81c1db96a9b759445ef07106eb7a9171e Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 12 Jun 2020 14:32:39 -0500 Subject: [PATCH 0737/1120] Fix inclusion of execinfo.h --- vendor/libkqueue/test/test.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/test/test.c b/vendor/libkqueue/test/test.c index a56b77528..81d918c44 100644 --- a/vendor/libkqueue/test/test.c +++ b/vendor/libkqueue/test/test.c @@ -13,32 +13,31 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include #if defined(__linux__) && (defined(__GLIBC__) && !defined(__UCLIBC__)) -#include +# include #endif -#include -#include #include "common.h" static int testnum = 1; static int error_flag = 1; -/* FIXME: not portable beyond linux */ #ifndef _WIN32 static void error_handler(int signum) { -#if defined(__linux__) && (defined(__GLIBC__) && !defined(__UCLIBC__)) +# if defined(__linux__) && (defined(__GLIBC__) && !defined(__UCLIBC__)) void *buf[32]; /* FIXME: the symbols aren't printing */ printf("***** ERROR: Program received signal %d *****\n", signum); backtrace_symbols_fd(buf, sizeof(buf) / sizeof(void *), 2); -#else +# else printf("***** ERROR: Program received signal %d *****\n", signum); -#endif +# endif exit(1); } #endif /* ! _WIN32 */ From df9d26a6237163dabbc372bebb666c3b0d3b4973 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 12 Jun 2020 14:33:42 -0500 Subject: [PATCH 0738/1120] Print flags for more filters --- vendor/libkqueue/src/common/kevent.c | 37 +++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index ee43325d3..0e5e48435 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -42,29 +42,50 @@ static const char * kevent_fflags_dump(const struct kevent *kev) { static __thread char buf[1024]; + size_t len; #define KEVFFL_DUMP(attrib) \ if (kev->fflags & attrib) \ strncat((char *) buf, #attrib" ", 64); snprintf(buf, sizeof(buf), "fflags=0x%04x (", kev->fflags); - if (kev->filter == EVFILT_VNODE) { + switch (kev->filter) { + case EVFILT_VNODE: KEVFFL_DUMP(NOTE_DELETE); KEVFFL_DUMP(NOTE_WRITE); KEVFFL_DUMP(NOTE_EXTEND); KEVFFL_DUMP(NOTE_ATTRIB); KEVFFL_DUMP(NOTE_LINK); KEVFFL_DUMP(NOTE_RENAME); - } else if (kev->filter == EVFILT_USER) { + break; + + case EVFILT_USER: KEVFFL_DUMP(NOTE_FFNOP); KEVFFL_DUMP(NOTE_FFAND); KEVFFL_DUMP(NOTE_FFOR); KEVFFL_DUMP(NOTE_FFCOPY); KEVFFL_DUMP(NOTE_TRIGGER); - } else { - buf[0] = ' '; + break; + + case EVFILT_READ: + case EVFILT_WRITE: +#ifdef NOTE_LOWAT + KEVFFL_DUMP(NOTE_LOWAT); +#endif + break; + + case EVFILT_PROC: + KEVFFL_DUMP(NOTE_EXIT); + KEVFFL_DUMP(NOTE_FORK); + KEVFFL_DUMP(NOTE_EXEC); + break; + + default: + break; } - buf[strlen(buf) - 1] = ')'; + len = strlen(buf); + if (buf[len - 1] == ' ') buf[len - 1] = '\0'; /* Trim trailing space */ + strcat(buf, ")"); #undef KEVFFL_DUMP @@ -75,6 +96,7 @@ static const char * kevent_flags_dump(const struct kevent *kev) { static __thread char buf[1024]; + size_t len; #define KEVFL_DUMP(attrib) \ if (kev->flags & attrib) \ @@ -91,7 +113,10 @@ kevent_flags_dump(const struct kevent *kev) KEVFL_DUMP(EV_ERROR); KEVFL_DUMP(EV_DISPATCH); KEVFL_DUMP(EV_RECEIPT); - buf[strlen(buf) - 1] = ')'; + + len = strlen(buf); + if (buf[len - 1] == ' ') buf[len - 1] = '\0'; /* Trim trailing space */ + strcat(buf, ")"); #undef KEVFL_DUMP From fdae7506b0cb84612db8f387fdfa447abeefa4eb Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 12 Jun 2020 16:11:48 -0500 Subject: [PATCH 0739/1120] Don't leak kqfd in the test harness --- vendor/libkqueue/test/stress/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/test/stress/main.c b/vendor/libkqueue/test/stress/main.c index 2e1617194..7164d2bd6 100644 --- a/vendor/libkqueue/test/stress/main.c +++ b/vendor/libkqueue/test/stress/main.c @@ -73,6 +73,8 @@ test_harness(void *arg) printf("thread %d round %d / %d\n", id, i, nrounds); } printf("thread %d done\n", id); + + close(kqfd); } int From 0beeb5c392f25e046e63090e27d75fb25c3737f1 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Thu, 11 Jun 2020 15:29:49 -0300 Subject: [PATCH 0740/1120] Enhance the Travis build * Builds against GCC and CLANG in Debug and Release mode. * Upgrade to Ubuntu 18.04 --- vendor/libkqueue/.travis.yml | 45 +++++++++++++++++++----- vendor/libkqueue/scripts/travis/build.sh | 39 ++++++++++++++++++++ 2 files changed, 75 insertions(+), 9 deletions(-) create mode 100755 vendor/libkqueue/scripts/travis/build.sh diff --git a/vendor/libkqueue/.travis.yml b/vendor/libkqueue/.travis.yml index 4c65e7d8f..2b4b0482a 100644 --- a/vendor/libkqueue/.travis.yml +++ b/vendor/libkqueue/.travis.yml @@ -2,21 +2,48 @@ language: c compiler: - clang - gcc -dist: trusty +cache: + apt: true +dist: bionic env: global: + - KQUEUE_DEBUG="yes" - M_PERTURB=0x42 + - CTEST_OUTPUT_ON_FAILURE=1 + - ASAN_OPTIONS="symbolize=1 detect_leaks=1 detect_stack_use_after_return=1" + - LSAN_OPTIONS="fast_unwind_on_malloc=0:malloc_context_size=50" + matrix: + - BUILD_TYPE=Release + - BUILD_TYPE=Debug ENABLE_ASAN=NO ENABLE_LSAN=NO ENABLE_UBSAN=NO + - BUILD_TYPE=Debug ENABLE_ASAN=YES ENABLE_LSAN=YES ENABLE_UBSAN=YES addons: apt: + config: + retries: true + sources: + - sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main' + key_url: https://apt.llvm.org/llvm-snapshot.gpg.key + # For newer GCC + - ubuntu-toolchain-r-test packages: - - doxygen + - build-essential + - clang-10 + - debhelper + - devscripts + - dh-make + - fakeroot + - gcc-7 + - gccgo-7 + - gdb + # Needed for llvm-symbolizer + - llvm-10 before_install: -- $CC --version +- if [ "${CC}" == 'gcc' ]; then sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 9999 && sudo update-alternatives --config gcc; fi +- if [ "${CC}" == 'clang' ]; then sudo rm -rf /usr/local/clang-*; fi +- if [ "${CC}" == 'clang' ]; then sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-10 9999 && sudo update-alternatives --config clang; fi +- if [ "${CC}" == 'clang' ]; then sudo update-alternatives --install /usr/bin/llvm-symbolizer llvm-symbolizer /usr/bin/llvm-symbolizer-10 9999 && sudo update-alternatives --config llvm-symbolizer; fi before_script: -# Cmake that ships with Trusty (v3.2.2) is too old, we need at least v3.4.3 -- mkdir /tmp/cmake && wget -O cmake.sh https://cmake.org/files/v3.10/cmake-3.10.0-Linux-x86_64.sh && chmod +x cmake.sh && ./cmake.sh --prefix=/tmp/cmake --skip-license -- /tmp/cmake/bin/cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib -DENABLE_TESTING=YES ./ -- make -j2 -- /tmp/cmake/bin/cpack -G DEB +- ./scripts/travis/build.sh script: -- make test +- make ARGS="-V" test + diff --git a/vendor/libkqueue/scripts/travis/build.sh b/vendor/libkqueue/scripts/travis/build.sh new file mode 100755 index 000000000..79bc8110b --- /dev/null +++ b/vendor/libkqueue/scripts/travis/build.sh @@ -0,0 +1,39 @@ +#!/bin/bash -e +# Author: Jorge Pereira +# + +function fatal() { + echo "$0: ERROR: $@" + exit 1 +} + +if [[ ! "${BUILD_TYPE}" =~ Debug|Release ]]; then + fatal "The 'BUILD_TYPE' should be 'Debug' or 'Release'." +fi + +if ! cmake . -G "Unix Makefiles" \ + -DCMAKE_INSTALL_PREFIX="/usr" \ + -DCMAKE_INSTALL_LIBDIR="lib" \ + -DCMAKE_VERBOSE_MAKEFILE:BOOL="ON" \ + -DENABLE_TESTING="YES" \ + -DENABLE_ASAN="${DENABLE_ASAN:-YES}" \ + -DENABLE_LSAN="${DENABLE_LSAN:-YES}" \ + -DENABLE_UBSAN="${DENABLE_UBSAN:-YES}" \ + -DCMAKE_BUILD_TYPE="${BUILD_TYPE}"; then + fatal "Failed during cmake build configuration" +fi + +# +# Build the libkqueue +# +echo "Starting compilation" +if ! make -j8; then + fatal "Failed during compilation" +fi + +# +# Build the *.deb packages +# +if ! cpack -G DEB; then + fatal "Failed when building debian packages" +fi From 65a5f88469f78910c162f01f121cda508d1141e8 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Thu, 11 Jun 2020 15:29:49 -0300 Subject: [PATCH 0741/1120] travis: Fix typo --- vendor/libkqueue/.travis.yml | 2 +- vendor/libkqueue/scripts/travis/build.sh | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/.travis.yml b/vendor/libkqueue/.travis.yml index 2b4b0482a..265d6e82c 100644 --- a/vendor/libkqueue/.travis.yml +++ b/vendor/libkqueue/.travis.yml @@ -14,7 +14,7 @@ env: - LSAN_OPTIONS="fast_unwind_on_malloc=0:malloc_context_size=50" matrix: - BUILD_TYPE=Release - - BUILD_TYPE=Debug ENABLE_ASAN=NO ENABLE_LSAN=NO ENABLE_UBSAN=NO + - BUILD_TYPE=Debug - BUILD_TYPE=Debug ENABLE_ASAN=YES ENABLE_LSAN=YES ENABLE_UBSAN=YES addons: apt: diff --git a/vendor/libkqueue/scripts/travis/build.sh b/vendor/libkqueue/scripts/travis/build.sh index 79bc8110b..612caa25d 100755 --- a/vendor/libkqueue/scripts/travis/build.sh +++ b/vendor/libkqueue/scripts/travis/build.sh @@ -16,9 +16,9 @@ if ! cmake . -G "Unix Makefiles" \ -DCMAKE_INSTALL_LIBDIR="lib" \ -DCMAKE_VERBOSE_MAKEFILE:BOOL="ON" \ -DENABLE_TESTING="YES" \ - -DENABLE_ASAN="${DENABLE_ASAN:-YES}" \ - -DENABLE_LSAN="${DENABLE_LSAN:-YES}" \ - -DENABLE_UBSAN="${DENABLE_UBSAN:-YES}" \ + -DENABLE_ASAN="${ENABLE_ASAN:-NO}" \ + -DENABLE_LSAN="${ENABLE_LSAN:-NO}" \ + -DENABLE_UBSAN="${ENABLE_UBSAN:-NO}" \ -DCMAKE_BUILD_TYPE="${BUILD_TYPE}"; then fatal "Failed during cmake build configuration" fi From 49be0aeefc46e42cd4a1a0d8066dfc51be006599 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 13 Jun 2020 20:10:44 -0500 Subject: [PATCH 0742/1120] Remove deadwood that pobably won't be useful in POSIX, and definitely isn't useful for Linux --- vendor/libkqueue/src/linux/platform.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 2efc1c799..d7d0198c2 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -252,28 +252,6 @@ linux_kqueue_init(struct kqueue *kq) (void) pthread_mutex_unlock(&kq_mtx); - #if DEADWOOD - //might be useful in posix - - /* Add each filter's pollable descriptor to the epollset */ - for (i = 0; i < NUM_ELEMENTS(kq->kq_filt); i++) { - filt = &kq->kq_filt[i]; - - if (filt->kf_id == 0) - continue; - - memset(&ev, 0, sizeof(ev)); - ev.events = EPOLLIN; - ev.data.ptr = filt; - - if (epoll_ctl(kq->kq_id, EPOLL_CTL_ADD, filt->kf_pfd, &ev) < 0) { - dbg_perror("epoll_ctl(2)"); - close(kq->kq_id); - return (-1); - } - } -#endif - return (0); } From ffa4ddaa5976e731eaa7041235d72a54c4b5e5d0 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 15 Jun 2020 09:12:07 -0500 Subject: [PATCH 0743/1120] Add more notes on how the monitoring thread is supposed to work --- vendor/libkqueue/src/linux/platform.c | 37 ++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index d7d0198c2..cdc7020fd 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -20,6 +20,8 @@ #include #include "../common/private.h" +#define MONITORING_THREAD_SIGNAL (SIGRTMIN + 1) + //XXX-FIXME TEMP const struct filter evfilt_proc = EVFILT_NOTIMPL; @@ -96,7 +98,7 @@ monitoring_thread_start(void *arg) pthread_sigmask(SIG_BLOCK, &monitoring_sig_set, NULL); sigemptyset(&monitoring_sig_set); - sigaddset(&monitoring_sig_set, SIGRTMIN + 1); + sigaddset(&monitoring_sig_set, MONITORING_THREAD_SIGNAL); (void) pthread_mutex_lock(&kq_mtx); @@ -194,6 +196,7 @@ int linux_kqueue_init(struct kqueue *kq) { struct f_owner_ex sig_owner; + int flags; kq->epollfd = epoll_create(1); if (kq->epollfd < 0) { @@ -202,9 +205,12 @@ linux_kqueue_init(struct kqueue *kq) } /* - * The standard behaviour when closing a kqueue fd is for the underlying resources to be freed. - * In order to catch the close on the libkqueue fd, we use a pipe and return the write end as kq_id. - * Closing the end will cause the pipe to be close which will be caught by the monitoring thread. + * The standard behaviour when closing a kqueue fd is + * for the underlying resources to be freed. + * In order to catch the close on the libkqueue fd, + * we use a pipe and return the write end as kq_id. + * Closing the end will cause the pipe to be close which + * will be caught by the monitoring thread. */ if (pipe(kq->pipefd)) { close(kq->epollfd); @@ -221,12 +227,26 @@ linux_kqueue_init(struct kqueue *kq) kq->kq_id = kq->pipefd[1]; - if (fcntl(kq->pipefd[0], F_SETFL, fcntl(kq->pipefd[0], F_GETFL, 0) | O_ASYNC) < 0) { + /* + * Setting O_ASYNC means a signal (SIGIO) will be sent + * whenever I/O is possible OR when the other end of the + * pipe has been closed. + */ + flags = fcntl(kq->pipefd[0], F_GETFL, 0); + if (fcntl(kq->pipefd[0], F_SETFL, flags | O_ASYNC) < 0) { dbg_perror("failed setting O_ASYNC"); goto error; } - if (fcntl(kq->pipefd[0], F_SETSIG, SIGRTMIN + 1) < 0) { + /* + * SIGIO may be used by the application, so we use F_SETSIG + * to change the signal sent to one in the realtime range + * which are all user defined. + * + * We may want to make this configurable at runtime later + * so we won't conflict with the application. + */ + if (fcntl(kq->pipefd[0], F_SETSIG, MONITORING_THREAD_SIGNAL) < 0) { dbg_perror("failed settting F_SETSIG"); goto error; } @@ -242,6 +262,11 @@ linux_kqueue_init(struct kqueue *kq) /* Increment kqueue counter */ kqueue_cnt++; + /* + * Finally, ensure that signals generated by I/O operations + * on the FD get dispatch to the monitoring thread, and + * not anywhere else. + */ sig_owner.type = F_OWNER_TID; sig_owner.pid = monitoring_tid; if (fcntl(kq->pipefd[0], F_SETOWN_EX, &sig_owner) < 0) { From 66f43808ad6ccf6de847236ac88b78b96b048b4b Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 15 Jun 2020 09:25:00 -0500 Subject: [PATCH 0744/1120] add more debugging to kqueue cleanup code to try and determine the reason it's not reliably cleaning up kqueues fix monitoring thread re-init --- vendor/libkqueue/src/linux/platform.c | 146 ++++++++++++++++---------- 1 file changed, 88 insertions(+), 58 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index cdc7020fd..fdd6ccabb 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -76,18 +76,75 @@ static bool linux_kqueue_cleanup(struct kqueue *kq); unsigned int get_fd_limit(void); + +static bool end_monitoring_thread = false; + +static void +monitoring_thread_kq_cleanup(int signal_fd) +{ + int fd; + struct kqueue *kq; + + (void) pthread_mutex_lock(&kq_mtx); + /* + * Signal is received for read side of pipe + * Get FD for write side as it's the kqueue identifier + */ + fd = fd_map[signal_fd]; + if (!fd) { + /* Should not happen */ + dbg_printf("got signal for unknown FD %i", fd); + goto check_count; + } + + kq = kqueue_lookup(fd); + if (!kq) { + /* Should not happen */ + dbg_printf("no kqueue associated with FD %i", fd); + goto check_count; + } + + /* If kqueue instance for this FD hasn't been cleaned yet */ + if (fd_cleanup_cnt[kq->kq_id] == 0) { + dbg_printf("cleanup count for kqueue FD %u is 0, cleaning up...", kq->kq_id); + linux_kqueue_cleanup(kq); + + /* Decrement cleanup counter as signal handler has been run for this FD */ + fd_cleanup_cnt[kq->kq_id]--; + } else { + dbg_printf("cleanup count for kqueue FD %u is %u, skipping...", kq->kq_id, fd_cleanup_cnt[kq->kq_id]); + } + +check_count: + /* + * Stop thread if all kqueues have been closed + */ + if (kqueue_cnt == 0) { + dbg_printf("monitoring thread %u exiting", monitoring_tid); + + end_monitoring_thread = true; + + /* Reset so that thread can be restarted */ + monitoring_thread_initialized = PTHREAD_ONCE_INIT; + + /* Free thread resources */ + free(fd_map); + free(fd_cleanup_cnt); + } + + (void) pthread_mutex_unlock(&kq_mtx); +} + /* * Monitoring thread that loops on waiting for signals to be received */ static void * -monitoring_thread_start(void *arg) +monitoring_thread_loop(void *arg) { - short end_thread = 0; int res = 0; siginfo_t info; - int fd; int nb_max_fd; - struct kqueue *kq; + sigset_t monitoring_sig_set; nb_max_fd = get_fd_limit(); @@ -102,8 +159,12 @@ monitoring_thread_start(void *arg) (void) pthread_mutex_lock(&kq_mtx); + end_monitoring_thread = false; /* reset */ + monitoring_tid = syscall(SYS_gettid); + dbg_printf("monitoring thread %u started", monitoring_tid); + fd_map = calloc(nb_max_fd, sizeof(unsigned int)); if (fd_map == NULL) { error: @@ -125,57 +186,15 @@ monitoring_thread_start(void *arg) pthread_detach(pthread_self()); - while (!end_thread) { + while (!end_monitoring_thread) { /* * Wait for signal notifying us that a change has occured on the pipe * It's not possible to only listen on FD close but no other operation * should be performed on the kqueue. */ res = sigwaitinfo(&monitoring_sig_set, &info); - if( res != -1 ) { - (void) pthread_mutex_lock(&kq_mtx); - /* - * Signal is received for read side of pipe - * Get FD for write side as it's the kqueue identifier - */ - fd = fd_map[info.si_fd]; - if (fd) { - kq = kqueue_lookup(fd); - if (kq) { - /* If kqueue instance for this FD hasn't been cleaned yet */ - if (fd_cleanup_cnt[kq->kq_id] == 0) { - linux_kqueue_cleanup(kq); - } - - /* Decrement cleanup counter as signal handler has been run for this FD */ - fd_cleanup_cnt[kq->kq_id]--; - } else { - /* Should not happen */ - dbg_puts("Failed to lookup FD"); - } - } else { - /* Should not happen */ - dbg_puts("Got signal from unknown FD"); - } - - /* - * Stop thread if all kqueues have been closed - */ - if (kqueue_cnt == 0) { - end_thread = 1; - - /* Reset so that thread can be restarted */ - monitoring_thread_initialized = PTHREAD_ONCE_INIT; - - /* Free thread resources */ - free(fd_map); - free(fd_cleanup_cnt); - } - - (void) pthread_mutex_unlock(&kq_mtx); - } else { - dbg_perror("sigwait()"); - } + if (res != -1) + monitoring_thread_kq_cleanup(info.si_fd); } return NULL; @@ -184,7 +203,7 @@ monitoring_thread_start(void *arg) static void linux_kqueue_start_thread() { - if (pthread_create(&monitoring_thread, NULL, &monitoring_thread_start, NULL)) { + if (pthread_create(&monitoring_thread, NULL, &monitoring_thread_loop, NULL)) { dbg_perror("linux_kqueue_start_thread failure"); } @@ -234,7 +253,7 @@ linux_kqueue_init(struct kqueue *kq) */ flags = fcntl(kq->pipefd[0], F_GETFL, 0); if (fcntl(kq->pipefd[0], F_SETFL, flags | O_ASYNC) < 0) { - dbg_perror("failed setting O_ASYNC"); + dbg_printf("failed setting O_ASYNC on FD %i: %s", kq->pipefd[0], strerror(errno)); goto error; } @@ -247,20 +266,27 @@ linux_kqueue_init(struct kqueue *kq) * so we won't conflict with the application. */ if (fcntl(kq->pipefd[0], F_SETSIG, MONITORING_THREAD_SIGNAL) < 0) { - dbg_perror("failed settting F_SETSIG"); + dbg_printf("failed settting F_SETSIG on FD %i: %s", kq->pipefd[0], strerror(errno)); goto error; } (void) pthread_mutex_lock(&kq_mtx); + /* + * Increment kqueue counter - must be incremented before + * starting the monitoring thread in case there's a spurious + * wakeup and the thread immediately checks that there + * are no kqueues, and exits. + */ + kqueue_cnt++; + /* Start monitoring thread during first initialization */ (void) pthread_once(&monitoring_thread_initialized, linux_kqueue_start_thread); /* Update pipe FD map */ fd_map[kq->pipefd[0]] = kq->pipefd[1]; - /* Increment kqueue counter */ - kqueue_cnt++; + dbg_printf("there are now %u active kqueue(s)", kqueue_cnt); /* * Finally, ensure that signals generated by I/O operations @@ -270,10 +296,12 @@ linux_kqueue_init(struct kqueue *kq) sig_owner.type = F_OWNER_TID; sig_owner.pid = monitoring_tid; if (fcntl(kq->pipefd[0], F_SETOWN_EX, &sig_owner) < 0) { - dbg_perror("failed settting F_SETOWN"); + dbg_printf("failed settting F_SETOWN to TID %u on FD %i: %s", monitoring_tid, kq->pipefd[0], strerror(errno)); + kqueue_cnt--; (void) pthread_mutex_unlock(&kq_mtx); goto error; } + dbg_printf("kqueue FD %i now monitored", kq->pipefd[0]); (void) pthread_mutex_unlock(&kq_mtx); @@ -315,7 +343,7 @@ linux_kqueue_cleanup(struct kqueue *kq) } else if (ret > 0) { // Shouldn't happen unless data is written to kqueue FD // Ignore write and continue with close - dbg_puts("Unexpected data available on kqueue FD"); + dbg_puts("unexpected data available on kqueue FD"); } pipefd = kq->pipefd[0]; @@ -328,6 +356,7 @@ linux_kqueue_cleanup(struct kqueue *kq) /* Decrement kqueue counter */ kqueue_cnt--; + dbg_printf("cleaned up kqueue %i, there are now %u active kqueue(s)", pipefd, kqueue_cnt); return true; } @@ -336,9 +365,10 @@ void linux_kqueue_free(struct kqueue *kq) { /* Increment cleanup counter as cleanup is being performed outside signal handler */ - if (linux_kqueue_cleanup(kq)) + if (linux_kqueue_cleanup(kq)) { fd_cleanup_cnt[kq->kq_id]++; - else /* Reset counter as FD had already been cleaned */ + dbg_printf("cleanup count for kqueue FD %u increased to %u", kq->kq_id, fd_cleanup_cnt[kq->kq_id]); + } else /* Reset counter as FD had already been cleaned */ fd_cleanup_cnt[kq->kq_id] = 0; free(kq); From 74894b5b177473e126f7a8c556803015134772a8 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 15 Jun 2020 11:01:41 -0500 Subject: [PATCH 0745/1120] Fix use after free issue in decrementing kq reference counts --- vendor/libkqueue/src/linux/platform.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index fdd6ccabb..a3e63e4e6 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -105,14 +105,14 @@ monitoring_thread_kq_cleanup(int signal_fd) } /* If kqueue instance for this FD hasn't been cleaned yet */ - if (fd_cleanup_cnt[kq->kq_id] == 0) { - dbg_printf("cleanup count for kqueue FD %u is 0, cleaning up...", kq->kq_id); + if (fd_cleanup_cnt[fd] == 0) { + dbg_printf("cleanup count for kqueue FD %u is 0, cleaning up...", fd); linux_kqueue_cleanup(kq); /* Decrement cleanup counter as signal handler has been run for this FD */ - fd_cleanup_cnt[kq->kq_id]--; + fd_cleanup_cnt[fd]--; } else { - dbg_printf("cleanup count for kqueue FD %u is %u, skipping...", kq->kq_id, fd_cleanup_cnt[kq->kq_id]); + dbg_printf("cleanup count for kqueue FD %u is %u, skipping...", fd, fd_cleanup_cnt[fd]); } check_count: From a319be7c24457cf98520418ceff875a6ebfa8016 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 15 Jun 2020 11:01:51 -0500 Subject: [PATCH 0746/1120] Better debugging --- vendor/libkqueue/src/linux/platform.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index a3e63e4e6..ba5d3e729 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -327,6 +327,7 @@ linux_kqueue_cleanup(struct kqueue *kq) close(kq->epollfd); kq->epollfd = -1; } else { + dbg_puts("epollfd already closed, not performing cleanup"); // Don't do cleanup if epollfd has already been closed return false; } @@ -356,7 +357,7 @@ linux_kqueue_cleanup(struct kqueue *kq) /* Decrement kqueue counter */ kqueue_cnt--; - dbg_printf("cleaned up kqueue %i, there are now %u active kqueue(s)", pipefd, kqueue_cnt); + dbg_printf("cleaned up kqueue FD %i, there are now %u active kqueue(s)", pipefd, kqueue_cnt); return true; } @@ -367,7 +368,7 @@ linux_kqueue_free(struct kqueue *kq) /* Increment cleanup counter as cleanup is being performed outside signal handler */ if (linux_kqueue_cleanup(kq)) { fd_cleanup_cnt[kq->kq_id]++; - dbg_printf("cleanup count for kqueue FD %u increased to %u", kq->kq_id, fd_cleanup_cnt[kq->kq_id]); + dbg_printf("cleanup count for kqueue FD %i increased to %u", kq->kq_id, fd_cleanup_cnt[kq->kq_id]); } else /* Reset counter as FD had already been cleaned */ fd_cleanup_cnt[kq->kq_id] = 0; From b5253f543eb25db77f2a54a35401328cbfa08bb9 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 15 Jun 2020 14:28:33 -0500 Subject: [PATCH 0747/1120] Use -1 as the uninitialised value in the fd_map --- vendor/libkqueue/src/linux/platform.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index ba5d3e729..b973f7fb2 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -51,7 +51,7 @@ static unsigned int kqueue_cnt = 0; * Map for kqueue pipes where index is the read side (for which signals are received) * and value is the write side that gets closed and corresponds to the kqueue id. */ -static unsigned int *fd_map; +static int *fd_map; /* * Map kqueue id to counter for kq cleanups. @@ -91,7 +91,7 @@ monitoring_thread_kq_cleanup(int signal_fd) * Get FD for write side as it's the kqueue identifier */ fd = fd_map[signal_fd]; - if (!fd) { + if (fd < 0) { /* Should not happen */ dbg_printf("got signal for unknown FD %i", fd); goto check_count; @@ -165,12 +165,14 @@ monitoring_thread_loop(void *arg) dbg_printf("monitoring thread %u started", monitoring_tid); - fd_map = calloc(nb_max_fd, sizeof(unsigned int)); + fd_map = calloc(nb_max_fd, sizeof(int)); if (fd_map == NULL) { error: (void) pthread_mutex_unlock(&kq_mtx); return NULL; } + for (i = 0; i < nb_max_fd; i++) + fd_map[i] = -1; fd_cleanup_cnt = calloc(nb_max_fd, sizeof(unsigned int)); if (fd_cleanup_cnt == NULL){ @@ -353,7 +355,7 @@ linux_kqueue_cleanup(struct kqueue *kq) kq->pipefd[0] = -1; } - fd_map[pipefd] = 0; + fd_map[pipefd] = -1; /* Decrement kqueue counter */ kqueue_cnt--; From bb962ad324d3bbd73b25f6a19662a63228e2c9a1 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 15 Jun 2020 23:14:56 -0500 Subject: [PATCH 0748/1120] Fix file descriptor leaks in read tests --- vendor/libkqueue/src/linux/platform.c | 1 + vendor/libkqueue/test/common.h | 1 + vendor/libkqueue/test/read.c | 16 +++++++++++----- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index b973f7fb2..5b3a403af 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -144,6 +144,7 @@ monitoring_thread_loop(void *arg) int res = 0; siginfo_t info; int nb_max_fd; + int i; sigset_t monitoring_sig_set; diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 353bf6e94..6f39011a5 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -74,6 +74,7 @@ struct test_context { /* EVFILT_READ and EVFILT_WRITE */ int client_fd; int server_fd; + int listen_fd; /* EVFILT_VNODE */ int vnode_fd; diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index c04d80c52..62a81a948 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -22,7 +22,7 @@ * Create a connected TCP socket. */ static void -create_socket_connection(int *client, int *server) +create_socket_connection(int *client_fd, int *server_fd, int *listen_fd) { struct sockaddr_in sain; socklen_t sa_len = sizeof(sain); @@ -60,8 +60,9 @@ create_socket_connection(int *client, int *server) if ((accepted = accept(srvr, NULL, 0)) < 0) err(1, "srvr: accept"); - *client = clnt; - *server = accepted; + *client_fd = clnt; + *server_fd = accepted; + *listen_fd = srvr; } static void @@ -292,6 +293,9 @@ test_kevent_socket_listen_backlog(struct test_context *ctx) kevent_get(&ret, ctx->kqfd); kevent_cmp(&kev, &ret); test_no_kevents(ctx->kqfd); + + close(clnt); + close(srvr); } #ifdef EV_DISPATCH @@ -455,7 +459,7 @@ test_transition_from_write_to_read(struct test_context *ctx) void test_evfilt_read(struct test_context *ctx) { - create_socket_connection(&ctx->client_fd, &ctx->server_fd); + create_socket_connection(&ctx->client_fd, &ctx->server_fd, &ctx->listen_fd); test(kevent_socket_add, ctx); test(kevent_socket_del, ctx); @@ -472,9 +476,11 @@ test_evfilt_read(struct test_context *ctx) test(kevent_regular_file, ctx); close(ctx->client_fd); close(ctx->server_fd); + close(ctx->listen_fd); - create_socket_connection(&ctx->client_fd, &ctx->server_fd); + create_socket_connection(&ctx->client_fd, &ctx->server_fd, &ctx->listen_fd); test(transition_from_write_to_read, ctx); close(ctx->client_fd); close(ctx->server_fd); + close(ctx->listen_fd); } From 9bdbd24a9d8d4ebe53cf6ef36a2b4ae7939e0d30 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Tue, 16 Jun 2020 11:03:41 -0300 Subject: [PATCH 0749/1120] Append version to generated library It is helpful to know which version is in filesystem --- vendor/libkqueue/CMakeLists.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 1611d3954..a3ed29082 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -14,6 +14,8 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # +set(PROJECT_VERSION 2.4.0) + if(EXISTS "/etc/debian_version") cmake_minimum_required(VERSION 3.7.2) else() @@ -23,7 +25,9 @@ else() endif() cmake_policy(SET CMP0063 OLD) -project(libkqueue VERSION 2.4.0 LANGUAGES C) +project(libkqueue VERSION ${PROJECT_VERSION} + LANGUAGES C) + enable_testing() set(CMAKE_C_VISIBILITY_PRESET hidden) @@ -187,7 +191,7 @@ else() endif() add_library(kqueue ${LIBRARY_TYPE} ${LIBKQUEUE_SOURCES} ${LIBKQUEUE_HEADERS}) -set_target_properties(kqueue PROPERTIES SOVERSION 1) +set_target_properties(kqueue PROPERTIES SOVERSION ${PROJECT_VERSION}) if(WIN32) target_compile_definitions(kqueue PRIVATE _USRDLL;_WINDLL) From c8e8d42713d6fa65c8fd981da22b8f2dae619a06 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Tue, 16 Jun 2020 11:05:02 -0300 Subject: [PATCH 0750/1120] Add libkqueue version header --- vendor/libkqueue/.gitignore | 1 + vendor/libkqueue/CMakeLists.txt | 4 ++- vendor/libkqueue/include/sys/event.h | 1 + .../include/sys/libkqueue_version.h.in | 28 +++++++++++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 vendor/libkqueue/include/sys/libkqueue_version.h.in diff --git a/vendor/libkqueue/.gitignore b/vendor/libkqueue/.gitignore index e8a6cd10a..202092736 100644 --- a/vendor/libkqueue/.gitignore +++ b/vendor/libkqueue/.gitignore @@ -19,3 +19,4 @@ test/CMakeCache.txt test/CMakeFiles/ test/cmake_install.cmake test/libkqueue-test +include/sys/libkqueue_version.h diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index a3ed29082..3d6910340 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -27,6 +27,8 @@ cmake_policy(SET CMP0063 OLD) project(libkqueue VERSION ${PROJECT_VERSION} LANGUAGES C) +configure_file(include/sys/libkqueue_version.h.in + include/sys/libkqueue_version.h @ONLY) enable_testing() @@ -239,7 +241,7 @@ set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION ${CMAKE_INSTALL_FULL_MANDIR} ${CMAKE_INSTALL_FULL_LIBDIR}${LIB_SUFFIX}/pkgconfig) install(FILES - "include/sys/event.h" + "include/sys/event.h" "include/sys/libkqueue_version.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/kqueue/sys" COMPONENT headers) diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index 0f2927c2b..ceebcb3ba 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -41,6 +41,7 @@ #else # include #endif +# include #define LIBKQUEUE 1 #endif diff --git a/vendor/libkqueue/include/sys/libkqueue_version.h.in b/vendor/libkqueue/include/sys/libkqueue_version.h.in new file mode 100644 index 000000000..356c390d2 --- /dev/null +++ b/vendor/libkqueue/include/sys/libkqueue_version.h.in @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _LIBKQUEUE_VERSION_H +#define _LIBKQUEUE_VERSION_H + +#define LIBKQUEUE_VERSION ((@PROJECT_VERSION_MAJOR@ << 16) | (@PROJECT_VERSION_MINOR@ << 8) | (@PROJECT_VERSION_PATCH@)) + +#define LIBKQUEUE_VERSION_STRING "@PROJECT_VERSION@" + +#define LIBKQUEUE_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ +#define LIBKQUEUE_VERSION_MINOR @PROJECT_VERSION_MINOR@ +#define LIBKQUEUE_VERSION_PATCH @PROJECT_VERSION_PATCH@ + +#endif /* ! _LIBKQUEUE_VERSION_H */ From 8bf663cb5b57ea4324d30495d033385b21526a00 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 15 Jun 2020 23:19:21 -0500 Subject: [PATCH 0751/1120] Always close the kq in test_ev_receipt --- vendor/libkqueue/test/main.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index b550d293a..0be3bb77d 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -197,14 +197,11 @@ test_ev_receipt(void *unused) EV_SET(&kev, SIGUSR2, EVFILT_SIGNAL, EV_ADD | EV_RECEIPT, 0, 0, NULL); if (kevent(kq, &kev, 1, &kev, 1, NULL) < 0) die("kevent"); - - /* TODO: check the receipt */ - - close(kq); #else memset(&kev, 0, sizeof(kev)); puts("Skipped -- EV_RECEIPT is not available or running on Win32"); #endif + close(kq); } void From 11f87c61b880ad1db820bf563f8e76eb002c4b0d Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 16 Jun 2020 17:41:42 -0500 Subject: [PATCH 0752/1120] More tab/space fixes --- vendor/libkqueue/kern/test.c | 6 +- vendor/libkqueue/kqlite/kqlite.c | 4 +- vendor/libkqueue/kqlite/lite.h | 113 +++++++++++++++---------------- 3 files changed, 61 insertions(+), 62 deletions(-) diff --git a/vendor/libkqueue/kern/test.c b/vendor/libkqueue/kern/test.c index 89e51f7ae..1c936b71d 100644 --- a/vendor/libkqueue/kern/test.c +++ b/vendor/libkqueue/kern/test.c @@ -40,13 +40,13 @@ main(int argc, char **argv) int x; x = 1; - if (ioctl(fd, 1234, (char *) &x) < 0) + if (ioctl(fd, 1234, (char *) &x) < 0) err(1, "ioctl"); x = 2; - if (ioctl(fd, 1234, (char *) &x) < 0) + if (ioctl(fd, 1234, (char *) &x) < 0) err(1, "ioctl"); #endif - if (write(fd, &kev, sizeof(kev)) < 0) + if (write(fd, &kev, sizeof(kev)) < 0) err(1, "write"); close(fd); diff --git a/vendor/libkqueue/kqlite/kqlite.c b/vendor/libkqueue/kqlite/kqlite.c index 744f311a2..128558a9a 100644 --- a/vendor/libkqueue/kqlite/kqlite.c +++ b/vendor/libkqueue/kqlite/kqlite.c @@ -397,8 +397,8 @@ _get_signal(struct kevent *dst, kqueue_t kq) /* Equivalent to kevent() */ int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, - struct kevent *eventlist, int nevents, - const struct timespec *timeout) + struct kevent *eventlist, int nevents, + const struct timespec *timeout) { int rv = 0; struct kevent *dst; diff --git a/vendor/libkqueue/kqlite/lite.h b/vendor/libkqueue/kqlite/lite.h index 2e368cd6e..ba34dd7be 100644 --- a/vendor/libkqueue/kqlite/lite.h +++ b/vendor/libkqueue/kqlite/lite.h @@ -38,43 +38,43 @@ #include #include -#define EV_SET(kevp_, a, b, c, d, e, f) do { \ - struct kevent *kevp = (kevp_); \ - (kevp)->ident = (a); \ - (kevp)->filter = (b); \ - (kevp)->flags = (c); \ - (kevp)->fflags = (d); \ - (kevp)->data = (e); \ - (kevp)->udata = (f); \ +#define EV_SET(kevp_, a, b, c, d, e, f) do { \ + struct kevent *kevp = (kevp_); \ + (kevp)->ident = (a); \ + (kevp)->filter = (b); \ + (kevp)->flags = (c); \ + (kevp)->fflags = (d); \ + (kevp)->data = (e); \ + (kevp)->udata = (f); \ } while(0) struct kevent { - uintptr_t ident; /* identifier for this event */ - short filter; /* filter for event */ - unsigned short flags; - unsigned int fflags; - intptr_t data; - void *udata; /* opaque user data identifier */ + uintptr_t ident; /* identifier for this event */ + short filter; /* filter for event */ + unsigned short flags; + unsigned int fflags; + intptr_t data; + void *udata; /* opaque user data identifier */ }; /* actions */ -#define EV_ADD 0x0001 /* add event to kq (implies enable) */ -#define EV_DELETE 0x0002 /* delete event from kq */ -#define EV_ENABLE 0x0004 /* enable event */ -#define EV_DISABLE 0x0008 /* disable event (not reported) */ +#define EV_ADD 0x0001 /* add event to kq (implies enable) */ +#define EV_DELETE 0x0002 /* delete event from kq */ +#define EV_ENABLE 0x0004 /* enable event */ +#define EV_DISABLE 0x0008 /* disable event (not reported) */ /* flags */ -#define EV_ONESHOT 0x0010 /* only report one occurrence */ -#define EV_CLEAR 0x0020 /* clear event state after reporting */ -#define EV_RECEIPT 0x0040 /* force EV_ERROR on success, data=0 */ -#define EV_DISPATCH 0x0080 /* disable event after reporting */ +#define EV_ONESHOT 0x0010 /* only report one occurrence */ +#define EV_CLEAR 0x0020 /* clear event state after reporting */ +#define EV_RECEIPT 0x0040 /* force EV_ERROR on success, data=0 */ +#define EV_DISPATCH 0x0080 /* disable event after reporting */ -#define EV_SYSFLAGS 0xF000 /* reserved by system */ -#define EV_FLAG1 0x2000 /* filter-specific flag */ +#define EV_SYSFLAGS 0xF000 /* reserved by system */ +#define EV_FLAG1 0x2000 /* filter-specific flag */ /* returned values */ -#define EV_EOF 0x8000 /* EOF detected */ -#define EV_ERROR 0x4000 /* error, data contains errno */ +#define EV_EOF 0x8000 /* EOF detected */ +#define EV_ERROR 0x4000 /* error, data contains errno */ /* * data/hint flags/masks for EVFILT_USER @@ -85,54 +85,53 @@ struct kevent { * On output, the top two bits will always be set to NOTE_FFNOP and the * remaining twenty four bits will contain the stored fflags value. */ -#define NOTE_FFNOP 0x00000000 /* ignore input fflags */ -#define NOTE_FFAND 0x40000000 /* AND fflags */ -#define NOTE_FFOR 0x80000000 /* OR fflags */ -#define NOTE_FFCOPY 0xc0000000 /* copy fflags */ -#define NOTE_FFCTRLMASK 0xc0000000 /* masks for operations */ -#define NOTE_FFLAGSMASK 0x00ffffff +#define NOTE_FFNOP 0x00000000 /* ignore input fflags */ +#define NOTE_FFAND 0x40000000 /* AND fflags */ +#define NOTE_FFOR 0x80000000 /* OR fflags */ +#define NOTE_FFCOPY 0xc0000000 /* copy fflags */ +#define NOTE_FFCTRLMASK 0xc0000000 /* masks for operations */ +#define NOTE_FFLAGSMASK 0x00ffffff -#define NOTE_TRIGGER 0x01000000 /* Cause the event to be - triggered for output. */ +#define NOTE_TRIGGER 0x01000000 /* Cause the event to be triggered for output. */ /* * data/hint flags for EVFILT_{READ|WRITE} */ -#define NOTE_LOWAT 0x0001 /* low water mark */ -#undef NOTE_LOWAT /* Not supported on Linux */ +#define NOTE_LOWAT 0x0001 /* low water mark */ +#undef NOTE_LOWAT /* Not supported on Linux */ /* * data/hint flags for EVFILT_VNODE */ -#define NOTE_DELETE 0x0001 /* vnode was removed */ -#define NOTE_WRITE 0x0002 /* data contents changed */ -#define NOTE_EXTEND 0x0004 /* size increased */ -#define NOTE_ATTRIB 0x0008 /* attributes changed */ -#define NOTE_LINK 0x0010 /* link count changed */ -#define NOTE_RENAME 0x0020 /* vnode was renamed */ -#define NOTE_REVOKE 0x0040 /* vnode access was revoked */ -#undef NOTE_REVOKE /* Not supported on Linux */ +#define NOTE_DELETE 0x0001 /* vnode was removed */ +#define NOTE_WRITE 0x0002 /* data contents changed */ +#define NOTE_EXTEND 0x0004 /* size increased */ +#define NOTE_ATTRIB 0x0008 /* attributes changed */ +#define NOTE_LINK 0x0010 /* link count changed */ +#define NOTE_RENAME 0x0020 /* vnode was renamed */ +#define NOTE_REVOKE 0x0040 /* vnode access was revoked */ +#undef NOTE_REVOKE /* Not supported on Linux */ /* * data/hint flags for EVFILT_PROC */ -#define NOTE_EXIT 0x80000000 /* process exited */ -#define NOTE_FORK 0x40000000 /* process forked */ -#define NOTE_EXEC 0x20000000 /* process exec'd */ -#define NOTE_PCTRLMASK 0xf0000000 /* mask for hint bits */ -#define NOTE_PDATAMASK 0x000fffff /* mask for pid */ +#define NOTE_EXIT 0x80000000 /* process exited */ +#define NOTE_FORK 0x40000000 /* process forked */ +#define NOTE_EXEC 0x20000000 /* process exec'd */ +#define NOTE_PCTRLMASK 0xf0000000 /* mask for hint bits */ +#define NOTE_PDATAMASK 0x000fffff /* mask for pid */ /* additional flags for EVFILT_PROC */ -#define NOTE_TRACK 0x00000001 /* follow across forks */ -#define NOTE_TRACKERR 0x00000002 /* could not track child */ -#define NOTE_CHILD 0x00000004 /* am a child process */ +#define NOTE_TRACK 0x00000001 /* follow across forks */ +#define NOTE_TRACKERR 0x00000002 /* could not track child */ +#define NOTE_CHILD 0x00000004 /* am a child process */ /* * data/hint flags for EVFILT_NETDEV */ -#define NOTE_LINKUP 0x0001 /* link is up */ -#define NOTE_LINKDOWN 0x0002 /* link is down */ -#define NOTE_LINKINV 0x0004 /* link state is invalid */ +#define NOTE_LINKUP 0x0001 /* link is up */ +#define NOTE_LINKDOWN 0x0002 /* link is down */ +#define NOTE_LINKINV 0x0004 /* link state is invalid */ /* Linux supports a subset of these filters. */ #define EVFILT_READ (0) @@ -155,8 +154,8 @@ void kq_free(kqueue_t kq); /* Equivalent to kevent() */ int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, - struct kevent *eventlist, int nevents, - const struct timespec *timeout); + struct kevent *eventlist, int nevents, + const struct timespec *timeout); /* Dispatch kevents using multiple threads */ void kq_dispatch(kqueue_t, void (*)(kqueue_t, struct kevent)); From 0eff42f786d3e75bc9f704eb009a7c7b8b73787f Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 16 Jun 2020 17:51:07 -0500 Subject: [PATCH 0753/1120] Add back interface to allow freeing of kqueues by platform specific-code Always free the kq in the common code --- vendor/libkqueue/src/common/kqueue.c | 41 +++++++++++++++++++------ vendor/libkqueue/src/common/private.h | 2 ++ vendor/libkqueue/src/linux/platform.c | 1 - vendor/libkqueue/src/windows/platform.c | 1 - 4 files changed, 33 insertions(+), 12 deletions(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 714a90ef7..3a51ae80d 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -104,18 +104,43 @@ kqueue_cmp(struct kqueue *a, struct kqueue *b) { return memcmp(&a->kq_id, &b->kq_id, sizeof(int)); } +#endif /* Must hold the kqtree_mtx when calling this */ void kqueue_free(struct kqueue *kq) { - RB_REMOVE(kqt, &kqtree, kq); + dbg_printf("freeing kqueue %p, fd=%d", kq, kq->kq_id); + + /* + * Ensure the current map entry points to + * this kqueue. We don't want to remove + * the entry for another kqueue. + */ + if (map_lookup(kqmap, kq->kq_id) == kq) + map_delete(kqmap, kq->kq_id); + filter_unregister_all(kq); kqops.kqueue_free(kq); + tracing_mutex_destroy(&kq->kq_mtx); free(kq); } -#endif +void +kqueue_free_by_id(int id) +{ + struct kqueue *kq; + + kq = map_delete(kqmap, id); + if (!kq) return; + + dbg_printf("freeing kqueue %p, fd=%d", kq, kq->kq_id); + + filter_unregister_all(kq); + kqops.kqueue_free(kq); + tracing_mutex_destroy(&kq->kq_mtx); + free(kq); +} struct kqueue * kqueue_lookup(int kq) @@ -127,7 +152,6 @@ int VISIBLE kqueue(void) { struct kqueue *kq; - struct kqueue *tmp; #ifdef _WIN32 if (InterlockedCompareExchange(&kq_init_begin, 0, 1) == 0) { @@ -158,19 +182,16 @@ kqueue(void) return (-1); } - dbg_printf("created kqueue, fd=%d", kq->kq_id); + dbg_printf("alloced kqueue %p, fd=%d", kq, kq->kq_id); /* Delete and insert should be atomic */ (void) pthread_mutex_lock(&kq_mtx); - tmp = map_delete(kqmap, kq->kq_id); - if (tmp != NULL) { - kqops.kqueue_free(tmp); - } + kqueue_free_by_id(kq->kq_id); /* Free any old map entries */ if (map_insert(kqmap, kq->kq_id, kq) < 0) { - dbg_puts("map insertion failed"); - kqops.kqueue_free(kq); + dbg_printf("map insertion failed, freeing kqueue %p, fd=%d", kq, kq->kq_id); + filter_unregister_all(kq); pthread_mutex_unlock(&kq_mtx); goto error; } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 7fae7ff86..40ad95e54 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -248,6 +248,8 @@ int kevent_copyout(struct kqueue *, int, struct kevent *, int); void kevent_free(struct kqueue *); const char *kevent_dump(const struct kevent *); struct kqueue * kqueue_lookup(int); +void kqueue_free(struct kqueue *); +void kqueue_free_by_id(int id); int kqueue_validate(struct kqueue *); struct map *map_new(size_t); diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 5b3a403af..cc33dc492 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -375,7 +375,6 @@ linux_kqueue_free(struct kqueue *kq) } else /* Reset counter as FD had already been cleaned */ fd_cleanup_cnt[kq->kq_id] = 0; - free(kq); } static int diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index e5483de6a..df93a82df 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -82,7 +82,6 @@ void windows_kqueue_free(struct kqueue *kq) { CloseHandle(kq->kq_iocp); - free(kq); } int From b2fd21a3660556d2d4310443d61a66f7550509ef Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 16 Jun 2020 17:51:56 -0500 Subject: [PATCH 0754/1120] s/cleanup_cnt/use_cnt/g --- vendor/libkqueue/src/linux/platform.c | 28 +++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index cc33dc492..8309cc839 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -55,10 +55,10 @@ static int *fd_map; /* * Map kqueue id to counter for kq cleanups. - * When cleanup counter is at 0, cleanup can be performed by signal handler. + * When use counter is at 0, cleanup can be performed by signal handler. * Otherwise, it means cleanup was already performed for this FD in linux_kqueue_free. */ -static unsigned int *fd_cleanup_cnt; +static unsigned int *fd_use_cnt; const struct kqueue_vtable kqops = { .kqueue_init = linux_kqueue_init, @@ -105,14 +105,14 @@ monitoring_thread_kq_cleanup(int signal_fd) } /* If kqueue instance for this FD hasn't been cleaned yet */ - if (fd_cleanup_cnt[fd] == 0) { - dbg_printf("cleanup count for kqueue FD %u is 0, cleaning up...", fd); + if (fd_use_cnt[fd] == 0) { + dbg_printf("use count for kqueue FD %u is 0, cleaning up...", fd); linux_kqueue_cleanup(kq); - /* Decrement cleanup counter as signal handler has been run for this FD */ - fd_cleanup_cnt[fd]--; + /* Decrement use counter as signal handler has been run for this FD */ + fd_use_cnt[fd]--; } else { - dbg_printf("cleanup count for kqueue FD %u is %u, skipping...", fd, fd_cleanup_cnt[fd]); + dbg_printf("use count for kqueue FD %u is %u, skipping...", fd, fd_use_cnt[fd]); } check_count: @@ -129,7 +129,7 @@ monitoring_thread_kq_cleanup(int signal_fd) /* Free thread resources */ free(fd_map); - free(fd_cleanup_cnt); + free(fd_use_cnt); } (void) pthread_mutex_unlock(&kq_mtx); @@ -175,8 +175,8 @@ monitoring_thread_loop(void *arg) for (i = 0; i < nb_max_fd; i++) fd_map[i] = -1; - fd_cleanup_cnt = calloc(nb_max_fd, sizeof(unsigned int)); - if (fd_cleanup_cnt == NULL){ + fd_use_cnt = calloc(nb_max_fd, sizeof(unsigned int)); + if (fd_use_cnt == NULL){ free(fd_map); goto error; } @@ -368,12 +368,12 @@ linux_kqueue_cleanup(struct kqueue *kq) void linux_kqueue_free(struct kqueue *kq) { - /* Increment cleanup counter as cleanup is being performed outside signal handler */ + /* Increment use counter as cleanup is being performed outside signal handler */ if (linux_kqueue_cleanup(kq)) { - fd_cleanup_cnt[kq->kq_id]++; - dbg_printf("cleanup count for kqueue FD %i increased to %u", kq->kq_id, fd_cleanup_cnt[kq->kq_id]); + fd_use_cnt[kq->kq_id]++; + dbg_printf("use count for kqueue FD %i increased to %u", kq->kq_id, fd_use_cnt[kq->kq_id]); } else /* Reset counter as FD had already been cleaned */ - fd_cleanup_cnt[kq->kq_id] = 0; + fd_use_cnt[kq->kq_id] = 0; } From 0b4a09004045479149049250ce1399884c1bc14d Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 16 Jun 2020 18:00:43 -0500 Subject: [PATCH 0755/1120] Use a separate mutex for starting the monitor thread There's a potential race with the old code where if multiple threads were calling kqueue_init, the thread that got the mutex after the thread that called pthread_cond_wait, could have been the monitor thread, OR another thread performing kqueue_init, in which case the fd_map array would have been NULL, and we'd have gotten a NULL pointer deref. --- vendor/libkqueue/src/linux/platform.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 8309cc839..5596a784d 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -85,7 +85,6 @@ monitoring_thread_kq_cleanup(int signal_fd) int fd; struct kqueue *kq; - (void) pthread_mutex_lock(&kq_mtx); /* * Signal is received for read side of pipe * Get FD for write side as it's the kqueue identifier @@ -158,8 +157,6 @@ monitoring_thread_loop(void *arg) sigemptyset(&monitoring_sig_set); sigaddset(&monitoring_sig_set, MONITORING_THREAD_SIGNAL); - (void) pthread_mutex_lock(&kq_mtx); - end_monitoring_thread = false; /* reset */ monitoring_tid = syscall(SYS_gettid); @@ -169,7 +166,6 @@ monitoring_thread_loop(void *arg) fd_map = calloc(nb_max_fd, sizeof(int)); if (fd_map == NULL) { error: - (void) pthread_mutex_unlock(&kq_mtx); return NULL; } for (i = 0; i < nb_max_fd; i++) @@ -184,9 +180,7 @@ monitoring_thread_loop(void *arg) /* * Now that thread is initialized, let kqueue init resume */ - pthread_cond_broadcast(&monitoring_thread_cond); - (void) pthread_mutex_unlock(&kq_mtx); - + pthread_cond_signal(&monitoring_thread_cond); pthread_detach(pthread_self()); while (!end_monitoring_thread) { @@ -204,14 +198,19 @@ monitoring_thread_loop(void *arg) } static void -linux_kqueue_start_thread() +linux_kqueue_start_thread(void) { + static pthread_mutex_t mt_mtx = PTHREAD_MUTEX_INITIALIZER; + + pthread_mutex_lock(&mt_mtx); + if (pthread_create(&monitoring_thread, NULL, &monitoring_thread_loop, NULL)) { dbg_perror("linux_kqueue_start_thread failure"); } /* Wait for thread creating to be done as we need monitoring_tid to be available */ - pthread_cond_wait(&monitoring_thread_cond, &kq_mtx); + pthread_cond_wait(&monitoring_thread_cond, &mt_mtx); + pthread_mutex_unlock(&mt_mtx); } int From 1817940f0981b0bbffe9886d0d50e52fecbeefde Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 16 Jun 2020 18:04:34 -0500 Subject: [PATCH 0756/1120] Don't remove entries from fd_map We need them to process delayed signals --- vendor/libkqueue/src/linux/platform.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 5596a784d..eaa407180 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -50,6 +50,9 @@ static unsigned int kqueue_cnt = 0; /* * Map for kqueue pipes where index is the read side (for which signals are received) * and value is the write side that gets closed and corresponds to the kqueue id. + * + * @note Values in the fd_map are never cleared, as we still need to decrement + * fd_use_cnt when signals for a particular FD are received. */ static int *fd_map; @@ -168,8 +171,8 @@ monitoring_thread_loop(void *arg) error: return NULL; } - for (i = 0; i < nb_max_fd; i++) - fd_map[i] = -1; + for (i = 0; i < nb_max_fd; i++) + fd_map[i] = -1; fd_use_cnt = calloc(nb_max_fd, sizeof(unsigned int)); if (fd_use_cnt == NULL){ @@ -355,8 +358,6 @@ linux_kqueue_cleanup(struct kqueue *kq) kq->pipefd[0] = -1; } - fd_map[pipefd] = -1; - /* Decrement kqueue counter */ kqueue_cnt--; dbg_printf("cleaned up kqueue FD %i, there are now %u active kqueue(s)", pipefd, kqueue_cnt); From a473bb20b13f9976e68d439dc37d314edbbee029 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 16 Jun 2020 18:10:40 -0500 Subject: [PATCH 0757/1120] Make debug messages more constent and easily parseable in linux/platform.c --- vendor/libkqueue/src/linux/platform.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index eaa407180..a5f0255e4 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -95,26 +95,26 @@ monitoring_thread_kq_cleanup(int signal_fd) fd = fd_map[signal_fd]; if (fd < 0) { /* Should not happen */ - dbg_printf("got signal for unknown FD %i", fd); + dbg_printf("got signal for unknown FD, fd=%i", fd); goto check_count; } kq = kqueue_lookup(fd); if (!kq) { /* Should not happen */ - dbg_printf("no kqueue associated with FD %i", fd); + dbg_printf("no kqueue associated, fd=%i", fd); goto check_count; } /* If kqueue instance for this FD hasn't been cleaned yet */ if (fd_use_cnt[fd] == 0) { - dbg_printf("use count for kqueue FD %u is 0, cleaning up...", fd); + dbg_printf("kqueue fd=%u, use_count=%u, cleaning up...", fd, fd_use_cnt[fd]); linux_kqueue_cleanup(kq); /* Decrement use counter as signal handler has been run for this FD */ fd_use_cnt[fd]--; } else { - dbg_printf("use count for kqueue FD %u is %u, skipping...", fd, fd_use_cnt[fd]); + dbg_printf("kqueue fd=%u, use_count=%u, skipping...", fd, fd_use_cnt[fd]); } check_count: @@ -122,7 +122,7 @@ monitoring_thread_kq_cleanup(int signal_fd) * Stop thread if all kqueues have been closed */ if (kqueue_cnt == 0) { - dbg_printf("monitoring thread %u exiting", monitoring_tid); + dbg_printf("monitoring thread tid=%u exiting", monitoring_tid); end_monitoring_thread = true; @@ -164,7 +164,7 @@ monitoring_thread_loop(void *arg) monitoring_tid = syscall(SYS_gettid); - dbg_printf("monitoring thread %u started", monitoring_tid); + dbg_printf("monitoring thread tid=%u started", monitoring_tid); fd_map = calloc(nb_max_fd, sizeof(int)); if (fd_map == NULL) { @@ -258,7 +258,7 @@ linux_kqueue_init(struct kqueue *kq) */ flags = fcntl(kq->pipefd[0], F_GETFL, 0); if (fcntl(kq->pipefd[0], F_SETFL, flags | O_ASYNC) < 0) { - dbg_printf("failed setting O_ASYNC on FD %i: %s", kq->pipefd[0], strerror(errno)); + dbg_printf("failed setting O_ASYNC fd=%i: %s", kq->pipefd[0], strerror(errno)); goto error; } @@ -271,7 +271,7 @@ linux_kqueue_init(struct kqueue *kq) * so we won't conflict with the application. */ if (fcntl(kq->pipefd[0], F_SETSIG, MONITORING_THREAD_SIGNAL) < 0) { - dbg_printf("failed settting F_SETSIG on FD %i: %s", kq->pipefd[0], strerror(errno)); + dbg_printf("failed settting F_SETSIG fd=%i: %s", kq->pipefd[0], strerror(errno)); goto error; } @@ -301,12 +301,12 @@ linux_kqueue_init(struct kqueue *kq) sig_owner.type = F_OWNER_TID; sig_owner.pid = monitoring_tid; if (fcntl(kq->pipefd[0], F_SETOWN_EX, &sig_owner) < 0) { - dbg_printf("failed settting F_SETOWN to TID %u on FD %i: %s", monitoring_tid, kq->pipefd[0], strerror(errno)); + dbg_printf("failed settting F_SETOWN, tid=%u fd=%i: %s", monitoring_tid, kq->pipefd[0], strerror(errno)); kqueue_cnt--; (void) pthread_mutex_unlock(&kq_mtx); goto error; } - dbg_printf("kqueue FD %i now monitored", kq->pipefd[0]); + dbg_printf("kqueue now monitored kq=%p fd=%i", kq, kq->pipefd[0]); (void) pthread_mutex_unlock(&kq_mtx); From d1ba3784190ad18617dbd331202de7ec66957b34 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 16 Jun 2020 18:55:08 -0500 Subject: [PATCH 0758/1120] Fixup uses of knote_free which doesn't exist anymore and rename knote_free_all to be knote_delete_all for consistency --- vendor/libkqueue/src/common/filter.c | 2 +- vendor/libkqueue/src/common/knote.c | 2 +- vendor/libkqueue/src/common/private.h | 2 +- vendor/libkqueue/src/linux/proc.c | 2 +- vendor/libkqueue/src/posix/proc.c | 2 +- vendor/libkqueue/src/posix/signal.c | 2 +- vendor/libkqueue/src/posix/timer.c | 2 +- vendor/libkqueue/src/solaris/user.c | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index 1f6fcac39..96112f743 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -117,7 +117,7 @@ filter_unregister_all(struct kqueue *kq) if (kq->kq_filt[i].kf_destroy != NULL) kq->kq_filt[i].kf_destroy(&kq->kq_filt[i]); - knote_free_all(&kq->kq_filt[i]); + knote_delete_all(&kq->kq_filt[i]); if (kqops.filter_free != NULL) kqops.filter_free(kq, &kq->kq_filt[i]); diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 51b280d77..70b4a3525 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -127,7 +127,7 @@ knote_lookup(struct filter *filt, uintptr_t ident) return (ent); } -int knote_free_all(struct filter *filt) +int knote_delete_all(struct filter *filt) { struct knote *kn, *tmp; diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 40ad95e54..261ea0790 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -227,7 +227,7 @@ extern const struct kqueue_vtable kqops; /* * knote internal API */ -int knote_free_all(struct filter *filt); +int knote_delete_all(struct filter *filt); struct knote * knote_lookup(struct filter *, uintptr_t); struct knote * knote_new(void); #define knote_retain(kn) atomic_inc(&kn->kn_ref) diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index 8d7b61a13..c9fa4f21b 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -179,7 +179,7 @@ evfilt_proc_copyout(struct filter *filt, KNOTE_DISABLE(kn); } if (kn->kev.flags & EV_ONESHOT) { - knote_free(filt, kn); + knote_delete(filt, kn); } else { kn->kev.data = 0; //why?? } diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 9c4feeb25..54966e229 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -167,7 +167,7 @@ evfilt_proc_copyout(struct filter *filt, #if FIXME /* XXX - NEED TO use safe foreach instead */ if (kn->kev.flags & EV_ONESHOT) - knote_free(kn); + knote_delete(filt, kn); #endif if (++nevents > maxevents) diff --git a/vendor/libkqueue/src/posix/signal.c b/vendor/libkqueue/src/posix/signal.c index 399e1f0b0..b7aaa74c9 100644 --- a/vendor/libkqueue/src/posix/signal.c +++ b/vendor/libkqueue/src/posix/signal.c @@ -206,7 +206,7 @@ evfilt_signal_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) KNOTE_DISABLE(kn); } else if (kn->kev.flags & EV_ONESHOT) { ignore_signal(kn->kev.ident); - knote_free(filt, kn); + knote_delete(filt, kn); } #endif diff --git a/vendor/libkqueue/src/posix/timer.c b/vendor/libkqueue/src/posix/timer.c index 2afa28bb2..d52d23dc2 100644 --- a/vendor/libkqueue/src/posix/timer.c +++ b/vendor/libkqueue/src/posix/timer.c @@ -268,7 +268,7 @@ evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) _timer_delete(kn); } else if (kn->kev.flags & EV_ONESHOT) { _timer_delete(kn); - knote_free(filt, kn); + knote_delete(filt, kn); } #endif diff --git a/vendor/libkqueue/src/solaris/user.c b/vendor/libkqueue/src/solaris/user.c index f2d0bdcd0..3d3407960 100644 --- a/vendor/libkqueue/src/solaris/user.c +++ b/vendor/libkqueue/src/solaris/user.c @@ -40,7 +40,7 @@ evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) KNOTE_DISABLE(src); src->kev.fflags &= ~NOTE_TRIGGER; } else if (src->kev.flags & EV_ONESHOT) { - knote_free(filt, src); + knote_delete(filt, src); } */ From 6d49bf67840cb28d985a11df01d94f131d15626c Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Tue, 16 Jun 2020 15:18:03 -0300 Subject: [PATCH 0759/1120] Add variables for commit hash and build time --- vendor/libkqueue/CMakeLists.txt | 7 +++++++ vendor/libkqueue/include/sys/libkqueue_version.h.in | 3 +++ 2 files changed, 10 insertions(+) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 3d6910340..ae913c689 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -25,6 +25,13 @@ else() endif() cmake_policy(SET CMP0063 OLD) +# Both variables used in include/sys/libkqueue_version.h.in +string(TIMESTAMP PROJECT_VERSION_DATE "%b %d %Y at %H:%M:%S") + +execute_process(COMMAND git rev-parse --short=8 HEAD + OUTPUT_VARIABLE LIBKQUEUE_VERSION_COMMIT + OUTPUT_STRIP_TRAILING_WHITESPACE) + project(libkqueue VERSION ${PROJECT_VERSION} LANGUAGES C) configure_file(include/sys/libkqueue_version.h.in diff --git a/vendor/libkqueue/include/sys/libkqueue_version.h.in b/vendor/libkqueue/include/sys/libkqueue_version.h.in index 356c390d2..a0b087c4a 100644 --- a/vendor/libkqueue/include/sys/libkqueue_version.h.in +++ b/vendor/libkqueue/include/sys/libkqueue_version.h.in @@ -25,4 +25,7 @@ #define LIBKQUEUE_VERSION_MINOR @PROJECT_VERSION_MINOR@ #define LIBKQUEUE_VERSION_PATCH @PROJECT_VERSION_PATCH@ +#define LIBKQUEUE_VERSION_DATE "@PROJECT_VERSION_DATE@" +#cmakedefine LIBKQUEUE_VERSION_COMMIT "@LIBKQUEUE_VERSION_COMMIT@" + #endif /* ! _LIBKQUEUE_VERSION_H */ From bcef632fce829d3fe1b730e14ad9e84e3e8e4891 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 16 Jun 2020 19:51:42 -0500 Subject: [PATCH 0760/1120] Add debugging function to figure out of an FD is registered int he event loop --- vendor/libkqueue/src/linux/platform.c | 25 +++++++++++++++++++++++++ vendor/libkqueue/src/linux/platform.h | 1 + 2 files changed, 26 insertions(+) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index a5f0255e4..8d1c9cb7c 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -1055,6 +1055,31 @@ void epoll_fd_state_del(struct fd_state **fds_p, struct knote *kn, int ev) kn->kn_fds = NULL; } +bool +epoll_fd_registered(struct filter *filt, struct knote *kn) +{ + struct fd_state *fds = NULL; + int fd = kn->kev.ident; + int have_ev; + + /* + * The vast majority of the time if the knote + * has already been removed then kn->kn_fds + * will be false. + */ + if (!kn->kn_fds) return false; /* No file descriptor state, can't be in epoll */ + + have_ev = epoll_fd_state(&fds, kn, false); /* ...enabled only */ + if (!have_ev) return false; + + /* + * This *SHOULD* be a noop if the FD is already + * registered. + */ + if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_MOD, fd, EPOLL_EV_FDS(have_ev, fds)) < 0) return false; + + return true; +} int epoll_update(int op, struct filter *filt, struct knote *kn, int ev, bool delete) { diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index ae95d5eb9..2aaf30ce9 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -200,5 +200,6 @@ int epoll_fd_state(struct fd_state **, struct knote *, bool); int epoll_fd_state_init(struct fd_state **, struct knote *, int); void epoll_fd_state_free(struct fd_state **, struct knote *, int); +bool epoll_fd_registered(struct filter *filt, struct knote *kn); int epoll_update(int op, struct filter *filt, struct knote *kn, int ev, bool delete); #endif /* ! _KQUEUE_LINUX_PLATFORM_H */ From bc17add269f69272807a271f53638c0ae4136868 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 16 Jun 2020 19:52:46 -0500 Subject: [PATCH 0761/1120] Cleanup fds on mod or delete which was going to remove the knote anyway --- vendor/libkqueue/src/linux/platform.c | 32 ++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 8d1c9cb7c..fabd101fb 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -877,8 +877,6 @@ epoll_event_dump(struct epoll_event *evt) #undef EPEVT_DUMP } - - /** Determine if two fd state entries are equal * * @param[in] a first entry. @@ -1174,7 +1172,35 @@ epoll_update(int op, struct filter *filt, struct knote *kn, int ev, bool delete) if (epoll_ctl(filter_epoll_fd(filt), opn, fd, EPOLL_EV_FDS(want, fds)) < 0) { dbg_printf("epoll_ctl(2): %s", strerror(errno)); - if (opn == EPOLL_CTL_ADD) epoll_fd_state_del(&fds, kn, want_ev & ~have_ev); + switch (opn) { + case EPOLL_CTL_ADD: + epoll_fd_state_del(&fds, kn, want_ev & ~have_ev); + break; + + case EPOLL_CTL_DEL: + case EPOLL_CTL_MOD: + /* + * File descriptor went away and we weren't notified + * not necessarily an error. + */ + if (errno == EBADF) { + int kn_ev = 0; + + if (kn == fds->fds_read) { + kn_ev = EPOLLIN; + } else if (kn == fds->fds_write) { + kn_ev = EPOLLOUT; + } + kn_ev &= ~want_ev; /* If it wasn't wanted... */ + + if (kn_ev) { + dbg_printf("clearing fd=%i fds=%p ev=%s", fds, fd, epoll_event_flags_dump(kn_ev)); + epoll_fd_state_del(&fds, kn, kn_ev); + return (0); + } + } + break; + } return (-1); } From 45e498f7083377a8326b5feaf6ad3c86fb6417c2 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 16 Jun 2020 19:53:21 -0500 Subject: [PATCH 0762/1120] Make sure we got the monitoring thread's TID --- vendor/libkqueue/src/linux/platform.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index fabd101fb..c4006cf9d 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -293,6 +293,8 @@ linux_kqueue_init(struct kqueue *kq) dbg_printf("there are now %u active kqueue(s)", kqueue_cnt); + assert(monitoring_tid != 0); + /* * Finally, ensure that signals generated by I/O operations * on the FD get dispatch to the monitoring thread, and From ad9a49682c4eb64b2f88ed688253c19b5e5035ef Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 16 Jun 2020 22:44:29 -0500 Subject: [PATCH 0763/1120] Fix the majority of LSAN's complaints There still appears to be FD leaks somewhere --- vendor/libkqueue/src/linux/platform.c | 116 ++++++++++++++++++++------ 1 file changed, 92 insertions(+), 24 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index c4006cf9d..554324644 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -14,8 +14,9 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -# define _GNU_SOURCE -# include +#define _GNU_SOURCE +#include +#include #include #include #include "../common/private.h" @@ -63,6 +64,8 @@ static int *fd_map; */ static unsigned int *fd_use_cnt; +static int nb_max_fd; + const struct kqueue_vtable kqops = { .kqueue_init = linux_kqueue_init, .kqueue_free = linux_kqueue_free, @@ -83,7 +86,7 @@ unsigned int get_fd_limit(void); static bool end_monitoring_thread = false; static void -monitoring_thread_kq_cleanup(int signal_fd) +monitoring_thread_kq_cleanup(int signal_fd, bool ignore_use_count) { int fd; struct kqueue *kq; @@ -106,34 +109,79 @@ monitoring_thread_kq_cleanup(int signal_fd) goto check_count; } - /* If kqueue instance for this FD hasn't been cleaned yet */ - if (fd_use_cnt[fd] == 0) { + /* + * If kqueue instance for this FD hasn't been cleaned yet + * + * The issue the fd_use_cnt array prevents, is where kqueue + * allocates a KQ, and takes the opportunity to cleanup an + * old KQ instance, and this happens before the monitoring + * thread is woken up to reap the KQ itself. + * + * If the KQ has already been freed, we don't want to do + * anything here, as that will destroy the newly allocated + * KQ that shares an identifier with the old KQ. + * + * It's a counter because multiple signals may be queued. + */ + if (ignore_use_count || (fd_use_cnt[fd] == 0)) { dbg_printf("kqueue fd=%u, use_count=%u, cleaning up...", fd, fd_use_cnt[fd]); - linux_kqueue_cleanup(kq); - - /* Decrement use counter as signal handler has been run for this FD */ - fd_use_cnt[fd]--; + kqueue_free(kq); } else { dbg_printf("kqueue fd=%u, use_count=%u, skipping...", fd, fd_use_cnt[fd]); } check_count: + /* + * Forcefully cleaning up like this breaks use counting + * so we reset the use count to 0, and don't allow it to + * go below 0 if we later receive delayed signals. + */ + if (ignore_use_count) { + fd_use_cnt[fd] = 0; + } else if (fd_use_cnt[fd] > 0) { + fd_use_cnt[fd]--; /* Decrement use counter as signal handler has been run for this FD */ + } + /* * Stop thread if all kqueues have been closed */ - if (kqueue_cnt == 0) { - dbg_printf("monitoring thread tid=%u exiting", monitoring_tid); + if (kqueue_cnt == 0) end_monitoring_thread = true; +} - end_monitoring_thread = true; +static void +monitoring_thread_cleanup(void *arg) +{ + int i; - /* Reset so that thread can be restarted */ - monitoring_thread_initialized = PTHREAD_ONCE_INIT; + /* Reset so that thread can be restarted */ + monitoring_thread_initialized = PTHREAD_ONCE_INIT; - /* Free thread resources */ - free(fd_map); - free(fd_use_cnt); + /* + * + */ + for (i = 0; i < nb_max_fd; i++) { + if (fd_use_cnt[i] > 0) { + int fd; + + fd = fd_map[i]; + dbg_printf("Checking fd=%i, fd=%i", i, fd); + if (fcntl(fd, F_GETFD) < 0) { + dbg_printf("forcefully cleaning up fd=%i use_count=%u: %s", + fd, fd_use_cnt[fd], strerror(errno)); + fd_use_cnt[fd] = 0; + monitoring_thread_kq_cleanup(i, true); + fd_use_cnt[fd] = 0; + } + } } + dbg_printf("monitoring thread %u exiting", monitoring_tid); + /* Free thread resources */ + free(fd_map); + fd_map = NULL; + free(fd_use_cnt); + fd_use_cnt = NULL; + (void) pthread_mutex_unlock(&kq_mtx); } @@ -145,7 +193,7 @@ monitoring_thread_loop(void *arg) { int res = 0; siginfo_t info; - int nb_max_fd; + int i; sigset_t monitoring_sig_set; @@ -186,16 +234,28 @@ monitoring_thread_loop(void *arg) pthread_cond_signal(&monitoring_thread_cond); pthread_detach(pthread_self()); - while (!end_monitoring_thread) { + pthread_cleanup_push(monitoring_thread_cleanup, NULL) + while (true) { /* * Wait for signal notifying us that a change has occured on the pipe * It's not possible to only listen on FD close but no other operation * should be performed on the kqueue. */ res = sigwaitinfo(&monitoring_sig_set, &info); - if (res != -1) - monitoring_thread_kq_cleanup(info.si_fd); + (void) pthread_mutex_lock(&kq_mtx); + if (res != -1) { + dbg_printf("freeing kqueue due to closure, fd=%i", fd_map[info.si_fd]); + monitoring_thread_kq_cleanup(info.si_fd, false); + } else { + dbg_perror("sigwaitinfo returned early"); + } + + if (end_monitoring_thread) + break; + + (void) pthread_mutex_unlock(&kq_mtx); } + pthread_cleanup_pop(true); return NULL; } @@ -238,6 +298,7 @@ linux_kqueue_init(struct kqueue *kq) */ if (pipe(kq->pipefd)) { close(kq->epollfd); + kq->epollfd = -1; return (-1); } @@ -245,7 +306,9 @@ linux_kqueue_init(struct kqueue *kq) error: close(kq->epollfd); close(kq->pipefd[0]); + kq->pipefd[0] = -1; close(kq->pipefd[1]); + kq->pipefd[1] = -1; return (-1); } @@ -329,7 +392,6 @@ linux_kqueue_cleanup(struct kqueue *kq) ssize_t ret; int pipefd; - filter_unregister_all(kq); if (kq->epollfd > 0) { close(kq->epollfd); kq->epollfd = -1; @@ -367,6 +429,13 @@ linux_kqueue_cleanup(struct kqueue *kq) return true; } +/** Explicitly free the kqueue + * + * This is only called from the public kqueue function when a map + * slot is going to be re-used, so it's an indicator that the + * KQ fd is in use, and we shouldn't attempt to free it if we + * receive a signal in the monitoring thread. + */ void linux_kqueue_free(struct kqueue *kq) { @@ -376,7 +445,6 @@ linux_kqueue_free(struct kqueue *kq) dbg_printf("use count for kqueue FD %i increased to %u", kq->kq_id, fd_use_cnt[kq->kq_id]); } else /* Reset counter as FD had already been cleaned */ fd_use_cnt[kq->kq_id] = 0; - } static int @@ -1196,7 +1264,7 @@ epoll_update(int op, struct filter *filt, struct knote *kn, int ev, bool delete) kn_ev &= ~want_ev; /* If it wasn't wanted... */ if (kn_ev) { - dbg_printf("clearing fd=%i fds=%p ev=%s", fds, fd, epoll_event_flags_dump(kn_ev)); + dbg_printf("clearing fd=%i fds=%p ev=%s", fd, fds, epoll_event_flags_dump(kn_ev)); epoll_fd_state_del(&fds, kn, kn_ev); return (0); } From 57e13e4a17f142fa659ea98153263487320d76ef Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 17 Jun 2020 13:33:25 -0500 Subject: [PATCH 0764/1120] Don't leak ctx->vnode_fd --- vendor/libkqueue/test/vnode.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/test/vnode.c b/vendor/libkqueue/test/vnode.c index 13de091f6..365cd9a46 100644 --- a/vendor/libkqueue/test/vnode.c +++ b/vendor/libkqueue/test/vnode.c @@ -269,4 +269,6 @@ test_evfilt_vnode(struct test_context *ctx) /* TODO: test r590 corner case where a descriptor is closed and the associated knote is automatically freed. */ unlink(ctx->testfile); + close(ctx->vnode_fd); + ctx->vnode_fd = -1; } From 67f5695f8aca1f82b9090e81a3e515d5a91bb58b Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 17 Jun 2020 18:35:50 -0500 Subject: [PATCH 0765/1120] Don't leak one end of the pipe in test_dead_peer_detection --- vendor/libkqueue/test/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 0be3bb77d..95e6e60f4 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -86,6 +86,7 @@ test_peer_close_detection(void *unused) if (recv(sockfd[0], buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT) != 0) die("failed to detect peer shutdown"); } + close(sockfd[0]); #endif } From 4b3dc393c375be8dfc8efd6ec307574091406fe0 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 17 Jun 2020 19:04:37 -0500 Subject: [PATCH 0766/1120] Always close the eventfd file descriptor, even if it's not in epoll --- vendor/libkqueue/src/linux/user.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index 98b8f53c1..e5d65c376 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -187,20 +187,25 @@ linux_evfilt_user_knote_modify(struct filter *filt UNUSED, struct knote *kn, int linux_evfilt_user_knote_delete(struct filter *filt, struct knote *kn) { - if (kn->kn_registered && epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, - kn->kdata.kn_eventfd, NULL) < 0) { - dbg_perror("epoll_ctl(2)"); - return (-1); + int rv = 0; + + if (kn->kn_registered) { + rv = epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, kn->kdata.kn_eventfd, NULL); + if (rv < 0) { + dbg_perror("epoll_ctl(2)"); + } else { + dbg_printf("removed eventfd fd=%d from the epollfd", kn->kdata.kn_eventfd); + } } + kn->kn_registered = 0; if (close(kn->kdata.kn_eventfd) < 0) { dbg_perror("close(2)"); return (-1); } - dbg_printf("removed eventfd %d from the epollfd", kn->kdata.kn_eventfd); kn->kdata.kn_eventfd = -1; - return (0); + return rv; } int From f580a133caaa0aa83b192daa32c71f88ac363065 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 17 Jun 2020 19:04:55 -0500 Subject: [PATCH 0767/1120] More debugging messages and code tidying in user.c --- vendor/libkqueue/src/linux/user.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index e5d65c376..c910e81df 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -122,26 +122,26 @@ linux_evfilt_user_knote_create(struct filter *filt, struct knote *kn) evfd = eventfd(0, 0); if (evfd < 0) { dbg_perror("eventfd"); - goto errout; +error: + if (evfd >= 0) close(evfd); + kn->kdata.kn_eventfd = -1; + kn->kn_registered = 0; + return (-1); } + dbg_printf("created eventfd fd=%i", evfd); + /* Add the eventfd to the epoll set */ KN_UDATA(kn); /* populate this knote's kn_udata field */ if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_ADD, evfd, EPOLL_EV_KN(EPOLLIN, kn)) < 0) { dbg_perror("epoll_ctl(2)"); - goto errout; + goto error; } kn->kdata.kn_eventfd = evfd; kn->kn_registered = 1; return (0); - -errout: - (void) close(evfd); - kn->kdata.kn_eventfd = -1; - kn->kn_registered = 0; - return (-1); } int From bb07d745932169baa7ccea6ef261d531074f35a2 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 18 Jun 2020 16:53:39 -0500 Subject: [PATCH 0768/1120] More debug message standardisation, indentation fixes, etc... --- vendor/libkqueue/src/common/filter.c | 4 +- vendor/libkqueue/src/common/kevent.c | 26 +++---- vendor/libkqueue/src/common/knote.c | 96 ++++++++++++++----------- vendor/libkqueue/src/common/kqueue.c | 8 +-- vendor/libkqueue/src/common/map.c | 18 +++-- vendor/libkqueue/src/common/private.h | 63 ++++++++-------- vendor/libkqueue/src/linux/platform.c | 60 ++++++++-------- vendor/libkqueue/src/linux/proc.c | 2 +- vendor/libkqueue/src/linux/read.c | 2 +- vendor/libkqueue/src/linux/signal.c | 14 ++-- vendor/libkqueue/src/linux/timer.c | 4 +- vendor/libkqueue/src/linux/user.c | 14 ++-- vendor/libkqueue/src/linux/vnode.c | 2 +- vendor/libkqueue/src/solaris/socket.c | 5 +- vendor/libkqueue/src/solaris/timer.c | 4 +- vendor/libkqueue/src/windows/platform.c | 6 +- vendor/libkqueue/src/windows/timer.c | 2 +- 17 files changed, 171 insertions(+), 159 deletions(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index 96112f743..bc738e0cf 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -138,14 +138,14 @@ int filter_lookup(struct filter **filt, struct kqueue *kq, short id) { if (~id < 0 || ~id >= EVFILT_SYSCOUNT) { - dbg_printf("invalid id: id %d ~id %d", id, (~id)); + dbg_printf("filt=%d inv_filt=%d - invalid id", id, (~id)); errno = EINVAL; *filt = NULL; return (-1); } *filt = &kq->kq_filt[~id]; if ((*filt)->kf_copyout == NULL) { - dbg_printf("filter %s is not implemented", filter_name(id)); + dbg_printf("filt=%d - filt_name=%s not implemented", id, filter_name(id)); errno = ENOSYS; *filt = NULL; return (-1); diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 0e5e48435..b6632848e 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -129,7 +129,7 @@ kevent_dump(const struct kevent *kev) static __thread char buf[2147]; snprintf((char *) buf, sizeof(buf), - "{ ident=%d, filter=%s, %s, %s, data=%d, udata=%p }", + "{ ident=%i, filter=%s, %s, %s, data=%d, udata=%p }", (u_int) kev->ident, kevent_filter_dump(kev), kevent_flags_dump(kev), @@ -159,7 +159,6 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) dbg_printf("src=%s", kevent_dump(src)); kn = knote_lookup(filt, src->ident); - dbg_printf("knote_lookup: ident %d == %p", (int)src->ident, kn); if (kn == NULL) { if (src->flags & EV_ADD) { if ((kn = knote_new()) == NULL) { @@ -181,7 +180,7 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) return (-1); } knote_insert(filt, kn); - dbg_printf("created kevent %s", kevent_dump(src)); + dbg_printf("kn=%p - created knote %s", kn, kevent_dump(src)); /* XXX- FIXME Needs to be handled in kn_create() to prevent races */ if (src->flags & EV_DISABLE) { @@ -192,27 +191,24 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) return (0); } else { - dbg_printf("no entry found for ident=%u", (unsigned int)src->ident); + dbg_printf("ident=%u - no knote found", (unsigned int)src->ident); errno = ENOENT; return (-1); } + } else { + dbg_printf("kn=%p - resolved ident=%i to knote", kn, (int)src->ident); } if (src->flags & EV_DELETE) { rv = knote_delete(filt, kn); - dbg_printf("knote_delete returned %d", rv); } else if (src->flags & EV_DISABLE) { - rv = filt->kn_disable(filt, kn); - if (rv == 0) kn->kev.flags |= EV_DISABLE; - dbg_printf("kn_disable returned %d", rv); + rv = knote_disable(filt, kn); } else if (src->flags & EV_ENABLE) { - rv = filt->kn_enable(filt, kn); - if (rv == 0) kn->kev.flags &= ~EV_DISABLE; - dbg_printf("kn_enable returned %d", rv); + rv = knote_enable(filt, kn); } else if (src->flags & EV_ADD || src->flags == 0 || src->flags & EV_RECEIPT) { kn->kev.udata = src->udata; rv = filt->kn_modify(filt, kn, src); - dbg_printf("kn_modify returned %d", rv); + dbg_printf("kn=%p - kn_modify rv=%d", kn, rv); } return (rv); @@ -276,7 +272,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, #ifndef NDEBUG if (DEBUG_KQUEUE) { myid = atomic_inc(&_kevent_counter); - dbg_printf("--- kevent %u --- (nchanges = %d, nevents = %d)", myid, nchanges, nevents); + dbg_printf("--- kevent %u --- (nchanges = %d nevents = %d)", myid, nchanges, nevents); } #endif @@ -287,7 +283,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, kqueue_lock(kq); rv = kevent_copyin(kq, changelist, nchanges, eventlist, nevents); kqueue_unlock(kq); - dbg_printf("(%u) changelist: rv=%d", myid, rv); + dbg_printf("(%u) kevent_copyin rv=%d", myid, rv); if (rv < 0) goto out; if (rv > 0) { @@ -305,7 +301,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, nevents = MAX_KEVENT; if (nevents > 0) { rv = kqops.kevent_wait(kq, nevents, timeout); - dbg_printf("kqops.kevent_wait returned %d", rv); + dbg_printf("kqops.kevent_wait rv=%i", rv); if (likely(rv > 0)) { kqueue_lock(kq); rv = kqops.kevent_copyout(kq, rv, eventlist, nevents); diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 70b4a3525..09bb76704 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -59,13 +59,13 @@ knote_release(struct knote *kn) if (atomic_dec(&kn->kn_ref) == 0) { if (kn->kn_flags & KNFL_KNOTE_DELETED) { - dbg_printf("freeing knote at %p", kn); + dbg_printf("kn=%p - freeing", kn); free(kn); } else { - dbg_puts("this should never happen"); + dbg_puts("kn=%p - attempted to free knote without marking it as deleted"); } } else { - dbg_printf("decrementing refcount of knote %p rc=%d", kn, kn->kn_ref); + dbg_printf("kn=%p rc=%d - decrementing refcount", kn, kn->kn_ref); } } @@ -77,39 +77,6 @@ knote_insert(struct filter *filt, struct knote *kn) pthread_rwlock_unlock(&filt->kf_knote_mtx); } -int -knote_delete(struct filter *filt, struct knote *kn) -{ - struct knote query; - struct knote *tmp; - - if (kn->kn_flags & KNFL_KNOTE_DELETED) { - dbg_puts("ERROR: double deletion detected"); - return (-1); - } - - /* - * Verify that the knote wasn't removed by another - * thread before we acquired the knotelist lock. - */ - query.kev.ident = kn->kev.ident; - pthread_rwlock_wrlock(&filt->kf_knote_mtx); - tmp = RB_FIND(knt, &filt->kf_knote, &query); - if (tmp == kn) { - RB_REMOVE(knt, &filt->kf_knote, kn); - } - pthread_rwlock_unlock(&filt->kf_knote_mtx); - - if (filt->kn_delete(filt, kn) < 0) - return (-1); - - kn->kn_flags |= KNFL_KNOTE_DELETED; - - knote_release(kn); - - return (0); -} - struct knote * knote_lookup(struct filter *filt, uintptr_t ident) { @@ -122,8 +89,6 @@ knote_lookup(struct filter *filt, uintptr_t ident) ent = RB_FIND(knt, &filt->kf_knote, &query); pthread_rwlock_unlock(&filt->kf_knote_mtx); - dbg_printf("id=%" PRIuPTR " ent=%p", ident, ent); - return (ent); } @@ -144,15 +109,62 @@ int knote_delete_all(struct filter *filt) return (0); } +int +knote_delete(struct filter *filt, struct knote *kn) +{ + struct knote query; + struct knote *tmp; + int rv; + + dbg_printf("kn=%p - calling kn_delete", kn); + if (kn->kn_flags & KNFL_KNOTE_DELETED) { + dbg_printf("kn=%p - double deletion detected", kn); + return (-1); + } + + /* + * Verify that the knote wasn't removed by another + * thread before we acquired the knotelist lock. + */ + query.kev.ident = kn->kev.ident; + pthread_rwlock_wrlock(&filt->kf_knote_mtx); + tmp = RB_FIND(knt, &filt->kf_knote, &query); + if (tmp == kn) { + RB_REMOVE(knt, &filt->kf_knote, kn); + } + pthread_rwlock_unlock(&filt->kf_knote_mtx); + + rv = filt->kn_delete(filt, kn); + dbg_printf("kn=%p - kn_delete rv=%i", kn, rv); + + kn->kn_flags |= KNFL_KNOTE_DELETED; + knote_release(kn); + + return (rv); +} + int knote_disable(struct filter *filt, struct knote *kn) { + int rv = 0; + assert(!(kn->kev.flags & EV_DISABLE)); - filt->kn_disable(filt, kn); //TODO: Error checking - KNOTE_DISABLE(kn); - return (0); + dbg_printf("kn=%p - calling kn_disable", kn); + rv = filt->kn_disable(filt, kn); + dbg_printf("kn=%p - kn_disable rv=%i", kn, rv); + if (rv == 0) KNOTE_DISABLE(kn); + return (rv); } -//TODO: knote_enable() +int +knote_enable(struct filter *filt, struct knote *kn) +{ + int rv = 0; + dbg_printf("kn=%p - calling kn_enable", kn); + rv = filt->kn_enable(filt, kn); + dbg_printf("kn=%p - kn_enable rv=%i", kn, rv); + if (rv == 0) KNOTE_ENABLE(kn); + return (rv); +} diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 3a51ae80d..81afebd6c 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -110,7 +110,7 @@ kqueue_cmp(struct kqueue *a, struct kqueue *b) void kqueue_free(struct kqueue *kq) { - dbg_printf("freeing kqueue %p, fd=%d", kq, kq->kq_id); + dbg_printf("kq=%p - freeing", kq); /* * Ensure the current map entry points to @@ -134,7 +134,7 @@ kqueue_free_by_id(int id) kq = map_delete(kqmap, id); if (!kq) return; - dbg_printf("freeing kqueue %p, fd=%d", kq, kq->kq_id); + dbg_printf("kq=%p - freeing", kq); filter_unregister_all(kq); kqops.kqueue_free(kq); @@ -182,7 +182,7 @@ kqueue(void) return (-1); } - dbg_printf("alloced kqueue %p, fd=%d", kq, kq->kq_id); + dbg_printf("kq=%p - alloced with fd=%d", kq, kq->kq_id); /* Delete and insert should be atomic */ (void) pthread_mutex_lock(&kq_mtx); @@ -190,7 +190,7 @@ kqueue(void) kqueue_free_by_id(kq->kq_id); /* Free any old map entries */ if (map_insert(kqmap, kq->kq_id, kq) < 0) { - dbg_printf("map insertion failed, freeing kqueue %p, fd=%d", kq, kq->kq_id); + dbg_printf("kq=%p - map insertion failed, freeing", kq); filter_unregister_all(kq); pthread_mutex_unlock(&kq_mtx); goto error; diff --git a/vendor/libkqueue/src/common/map.c b/vendor/libkqueue/src/common/map.c index 80aa8af86..ca8ebd961 100644 --- a/vendor/libkqueue/src/common/map.c +++ b/vendor/libkqueue/src/common/map.c @@ -58,12 +58,11 @@ map_insert(struct map *m, int idx, void *ptr) return (-1); if (atomic_ptr_cas(&(m->data[idx]), 0, ptr) == NULL) { - dbg_printf("inserted %p in location %d", ptr, idx); + dbg_printf("idx=%i - inserted ptr=%p into map", idx, ptr); return (0); } else { - dbg_printf("tried to insert a value into a non-empty location %d (value=%p)", - idx, - m->data[idx]); + dbg_printf("idx=%i - tried to insert ptr=%p into a non-empty location (cur_ptr=%p)", + idx, ptr, m->data[idx]); return (-1); } } @@ -75,10 +74,10 @@ map_remove(struct map *m, int idx, void *ptr) return (-1); if (atomic_ptr_cas(&(m->data[idx]), ptr, 0) == NULL) { - dbg_printf("removed %p from location %d", ptr, idx); + dbg_printf("idx=%i - removed ptr=%p from map", idx, ptr); return (0); } else { - dbg_printf("removal failed: location %d does not contain value %p", idx, m->data[idx]); + dbg_printf("idx=%i - removal failed, ptr=%p != cur_ptr=%p", idx, ptr, m->data[idx]); return (-1); } } @@ -93,12 +92,11 @@ map_replace(struct map *m, int idx, void *oldp, void *newp) tmp = atomic_ptr_cas(&(m->data[idx]), oldp, newp); if (tmp == oldp) { - dbg_printf("replaced value %p in location %d with value %p", - oldp, idx, newp); + dbg_printf("idx=%i - replaced item in map with ptr=%p", idx, newp); + return (0); } else { - dbg_printf("item in location %d does not match expected value %p", - idx, oldp); + dbg_printf("idx=%i - replace failed, ptr=%p != cur_ptr=%p", idx, newp, m->data[idx]); return (-1); } } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 261ea0790..b30e60e8f 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -227,38 +227,43 @@ extern const struct kqueue_vtable kqops; /* * knote internal API */ -int knote_delete_all(struct filter *filt); -struct knote * knote_lookup(struct filter *, uintptr_t); -struct knote * knote_new(void); +int knote_delete_all(struct filter *filt); +struct knote *knote_lookup(struct filter *, uintptr_t); +struct knote *knote_new(void); + #define knote_retain(kn) atomic_inc(&kn->kn_ref) -void knote_release(struct knote *); -void knote_insert(struct filter *, struct knote *); -int knote_delete(struct filter *, struct knote *); -int knote_init(void); -int knote_disable(struct filter *, struct knote *); + +void knote_release(struct knote *); +void knote_insert(struct filter *, struct knote *); +int knote_delete(struct filter *, struct knote *); +int knote_init(void); +int knote_disable(struct filter *, struct knote *); +int knote_enable(struct filter *, struct knote *); + #define knote_get_filter(knt) &((knt)->kn_kq->kq_filt[(knt)->kev.filter]) -int filter_lookup(struct filter **, struct kqueue *, short); -int filter_register_all(struct kqueue *); -void filter_unregister_all(struct kqueue *); -const char *filter_name(short); - -int kevent_wait(struct kqueue *, const struct timespec *); -int kevent_copyout(struct kqueue *, int, struct kevent *, int); -void kevent_free(struct kqueue *); -const char *kevent_dump(const struct kevent *); -struct kqueue * kqueue_lookup(int); -void kqueue_free(struct kqueue *); -void kqueue_free_by_id(int id); -int kqueue_validate(struct kqueue *); - -struct map *map_new(size_t); -int map_insert(struct map *, int, void *); -int map_remove(struct map *, int, void *); -int map_replace(struct map *, int, void *, void *); -void *map_lookup(struct map *, int); -void *map_delete(struct map *, int); -void map_free(struct map *); +int filter_lookup(struct filter **, struct kqueue *, short); +int filter_register_all(struct kqueue *); +void filter_unregister_all(struct kqueue *); +const char *filter_name(short); + +unsigned int get_fd_limit(void); +int kevent_wait(struct kqueue *, const struct timespec *); +int kevent_copyout(struct kqueue *, int, struct kevent *, int); +void kevent_free(struct kqueue *); +const char *kevent_dump(const struct kevent *); +struct kqueue *kqueue_lookup(int); +void kqueue_free(struct kqueue *); +void kqueue_free_by_id(int id); +int kqueue_validate(struct kqueue *); + +struct map *map_new(size_t); +int map_insert(struct map *, int, void *); +int map_remove(struct map *, int, void *); +int map_replace(struct map *, int, void *, void *); +void *map_lookup(struct map *, int); +void *map_delete(struct map *, int); +void map_free(struct map *); /* DEADWOOD: No longer needed due to the un-smerging of POSIX and Linux diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 554324644..37d922eb1 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -81,8 +81,6 @@ const struct kqueue_vtable kqops = { static bool linux_kqueue_cleanup(struct kqueue *kq); -unsigned int get_fd_limit(void); - static bool end_monitoring_thread = false; static void @@ -98,14 +96,14 @@ monitoring_thread_kq_cleanup(int signal_fd, bool ignore_use_count) fd = fd_map[signal_fd]; if (fd < 0) { /* Should not happen */ - dbg_printf("got signal for unknown FD, fd=%i", fd); + dbg_printf("fd=%i - not a known FD", fd); goto check_count; } kq = kqueue_lookup(fd); if (!kq) { /* Should not happen */ - dbg_printf("no kqueue associated, fd=%i", fd); + dbg_printf("fd=%i - no kqueue associated", fd); goto check_count; } @@ -124,10 +122,10 @@ monitoring_thread_kq_cleanup(int signal_fd, bool ignore_use_count) * It's a counter because multiple signals may be queued. */ if (ignore_use_count || (fd_use_cnt[fd] == 0)) { - dbg_printf("kqueue fd=%u, use_count=%u, cleaning up...", fd, fd_use_cnt[fd]); + dbg_printf("kq=%p - fd=%i use_count=%u cleaning up...", kq, fd, fd_use_cnt[fd]); kqueue_free(kq); } else { - dbg_printf("kqueue fd=%u, use_count=%u, skipping...", fd, fd_use_cnt[fd]); + dbg_printf("kq=%p - fd=%i use_count=%u skipping...", kq, fd, fd_use_cnt[fd]); } check_count: @@ -156,17 +154,14 @@ monitoring_thread_cleanup(void *arg) /* Reset so that thread can be restarted */ monitoring_thread_initialized = PTHREAD_ONCE_INIT; - /* - * - */ for (i = 0; i < nb_max_fd; i++) { if (fd_use_cnt[i] > 0) { int fd; fd = fd_map[i]; - dbg_printf("Checking fd=%i, fd=%i", i, fd); + dbg_printf("Checking rfd=%i wfd=%i", i, fd); if (fcntl(fd, F_GETFD) < 0) { - dbg_printf("forcefully cleaning up fd=%i use_count=%u: %s", + dbg_printf("fd=%i - forcefully cleaning up, use_count=%u: %s", fd, fd_use_cnt[fd], strerror(errno)); fd_use_cnt[fd] = 0; monitoring_thread_kq_cleanup(i, true); @@ -175,7 +170,7 @@ monitoring_thread_cleanup(void *arg) } } - dbg_printf("monitoring thread %u exiting", monitoring_tid); + dbg_printf("tid=%u - monitoring thread exiting", monitoring_tid); /* Free thread resources */ free(fd_map); fd_map = NULL; @@ -212,7 +207,7 @@ monitoring_thread_loop(void *arg) monitoring_tid = syscall(SYS_gettid); - dbg_printf("monitoring thread tid=%u started", monitoring_tid); + dbg_printf("tid=%u - monitoring thread started", monitoring_tid); fd_map = calloc(nb_max_fd, sizeof(int)); if (fd_map == NULL) { @@ -244,7 +239,7 @@ monitoring_thread_loop(void *arg) res = sigwaitinfo(&monitoring_sig_set, &info); (void) pthread_mutex_lock(&kq_mtx); if (res != -1) { - dbg_printf("freeing kqueue due to closure, fd=%i", fd_map[info.si_fd]); + dbg_printf("fd=%i - freeing kqueue due to fd closure", fd_map[info.si_fd]); monitoring_thread_kq_cleanup(info.si_fd, false); } else { dbg_perror("sigwaitinfo returned early"); @@ -321,7 +316,7 @@ linux_kqueue_init(struct kqueue *kq) */ flags = fcntl(kq->pipefd[0], F_GETFL, 0); if (fcntl(kq->pipefd[0], F_SETFL, flags | O_ASYNC) < 0) { - dbg_printf("failed setting O_ASYNC fd=%i: %s", kq->pipefd[0], strerror(errno)); + dbg_printf("fd=%i - failed setting FSETFL O_ASYNC (%i): %s", kq->pipefd[0], flags, strerror(errno)); goto error; } @@ -334,7 +329,8 @@ linux_kqueue_init(struct kqueue *kq) * so we won't conflict with the application. */ if (fcntl(kq->pipefd[0], F_SETSIG, MONITORING_THREAD_SIGNAL) < 0) { - dbg_printf("failed settting F_SETSIG fd=%i: %s", kq->pipefd[0], strerror(errno)); + dbg_printf("fd=%i - failed settting F_SETSIG sig=%u: %s", + kq->pipefd[0], MONITORING_THREAD_SIGNAL, strerror(errno)); goto error; } @@ -354,7 +350,7 @@ linux_kqueue_init(struct kqueue *kq) /* Update pipe FD map */ fd_map[kq->pipefd[0]] = kq->pipefd[1]; - dbg_printf("there are now %u active kqueue(s)", kqueue_cnt); + dbg_printf("active_kqueues=%u", kqueue_cnt); assert(monitoring_tid != 0); @@ -366,12 +362,12 @@ linux_kqueue_init(struct kqueue *kq) sig_owner.type = F_OWNER_TID; sig_owner.pid = monitoring_tid; if (fcntl(kq->pipefd[0], F_SETOWN_EX, &sig_owner) < 0) { - dbg_printf("failed settting F_SETOWN, tid=%u fd=%i: %s", monitoring_tid, kq->pipefd[0], strerror(errno)); + dbg_printf("fd=%i - failed settting F_SETOWN to tid=%u: %s", monitoring_tid, kq->pipefd[0], strerror(errno)); kqueue_cnt--; (void) pthread_mutex_unlock(&kq_mtx); goto error; } - dbg_printf("kqueue now monitored kq=%p fd=%i", kq, kq->pipefd[0]); + dbg_printf("kq=%p - monitoring fd=%i for closure", kq, kq->pipefd[0]); (void) pthread_mutex_unlock(&kq_mtx); @@ -424,7 +420,7 @@ linux_kqueue_cleanup(struct kqueue *kq) /* Decrement kqueue counter */ kqueue_cnt--; - dbg_printf("cleaned up kqueue FD %i, there are now %u active kqueue(s)", pipefd, kqueue_cnt); + dbg_printf("kq=%p - cleaned up kqueue, active_kqueues=%u", kq, kqueue_cnt); return true; } @@ -442,7 +438,7 @@ linux_kqueue_free(struct kqueue *kq) /* Increment use counter as cleanup is being performed outside signal handler */ if (linux_kqueue_cleanup(kq)) { fd_use_cnt[kq->kq_id]++; - dbg_printf("use count for kqueue FD %i increased to %u", kq->kq_id, fd_use_cnt[kq->kq_id]); + dbg_printf("kq=%p - increased fd=%i use_count=%u", kq, kq->kq_id, fd_use_cnt[kq->kq_id]); } else /* Reset counter as FD had already been cleaned */ fd_use_cnt[kq->kq_id] = 0; } @@ -784,27 +780,27 @@ linux_get_descriptor_type(struct knote *kn) return (-1); case S_IFREG: - dbg_printf("fd %d is a regular file", fd); + dbg_printf("fd=%i is a regular file", fd); kn->kn_flags |= KNFL_FILE; return (0); case S_IFIFO: - dbg_printf("fd %d is a pipe", fd); + dbg_printf("fd=%i is a pipe", fd); kn->kn_flags |= KNFL_PIPE; return (0); case S_IFBLK: - dbg_printf("fd %d is a block device", fd); + dbg_printf("fd=%i is a block device", fd); kn->kn_flags |= KNFL_BLOCKDEV; return (0); case S_IFCHR: - dbg_printf("fd %d is a character device", fd); + dbg_printf("fd=%i is a character device", fd); kn->kn_flags |= KNFL_CHARDEV; return (0); case S_IFSOCK: - dbg_printf("fd %d is a socket", fd); + dbg_printf("fd=%i is a socket", fd); break; /* deferred type determination */ } @@ -820,27 +816,27 @@ linux_get_descriptor_type(struct knote *kn) } switch (stype) { case SOCK_STREAM: - dbg_printf("fd %d is a stream socket", fd); + dbg_printf("fd=%i is a stream socket", fd); kn->kn_flags |= KNFL_SOCKET_STREAM; break; case SOCK_DGRAM: - dbg_printf("fd %d is a datagram socket", fd); + dbg_printf("fd=%i is a datagram socket", fd); kn->kn_flags |= KNFL_SOCKET_DGRAM; break; case SOCK_RDM: - dbg_printf("fd %d is a reliable datagram socket", fd); + dbg_printf("fd=%i is a reliable datagram socket", fd); kn->kn_flags |= KNFL_SOCKET_RDM; break; case SOCK_SEQPACKET: - dbg_printf("fd %d is a sequenced and reliable datagram socket", fd); + dbg_printf("fd=%i is a sequenced and reliable datagram socket", fd); kn->kn_flags |= KNFL_SOCKET_SEQPACKET; break; case SOCK_RAW: - dbg_printf("fd %d is a raw socket", fd); + dbg_printf("fd=%i is a raw socket", fd); kn->kn_flags |= KNFL_SOCKET_RAW; break; @@ -1160,7 +1156,7 @@ epoll_update(int op, struct filter *filt, struct knote *kn, int ev, bool delete) #define EV_EPOLLINOUT(_x) ((_x) & (EPOLLIN | EPOLLOUT)) - if (kn->kev.flags & EV_DISABLE) dbg_printf("fd=%i kn is disabled", fd); + if (kn->kev.flags & EV_DISABLE) dbg_printf("fd=%i kn=%p is disabled", fd, kn); /* * Determine the current state of the file descriptor diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index c9fa4f21b..60ea5d1b6 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -72,7 +72,7 @@ wait_thread(void *arg) continue; } - dbg_puts(" waitid(2) returned"); + dbg_puts("waitid(2) returned"); if (errno == EINTR) continue; dbg_perror("waitid(2)"); diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index 07ff0c99a..a108e16a3 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -107,7 +107,7 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) return (0); } - dbg_printf("epoll: %s", epoll_event_dump(ev)); + dbg_printf("epoll_ev=%s", epoll_event_dump(ev)); memcpy(dst, &src->kev, sizeof(*dst)); #if defined(HAVE_EPOLLRDHUP) if (ev->events & EPOLLRDHUP || ev->events & EPOLLHUP) diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index c855a8de0..bf8182041 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -109,7 +109,7 @@ signalfd_create(int epoll_fd, struct knote *kn, int signum) if (signalfd_add(epoll_fd, sigfd, kn) < 0) goto errout; - dbg_printf("added sigfd %d to epoll_fd %d (signum=%d)", sigfd, epoll_fd, signum); + dbg_printf("sig_fd=%d - sigfd added to epoll_fd=%d (signum=%d)", sigfd, epoll_fd, signum); return (sigfd); @@ -166,16 +166,20 @@ int evfilt_signal_knote_delete(struct filter *filt, struct knote *kn) { const int sigfd = kn->kdata.kn_signalfd; + int rv = 0; /* Needed so that delete() can be called after disable() */ if (kn->kdata.kn_signalfd == -1) return (0); - if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, sigfd, NULL) < 0) { + rv = epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, sigfd, NULL); + if (rv < 0) { dbg_perror("epoll_ctl(2)"); - return (-1); + } else { + dbg_printf("sig_fd=%i - removed from epoll_fd=%i", sigfd, filter_epoll_fd(filt)); } + dbg_printf("sig_fd=%d - closed", sigfd); if (close(sigfd) < 0) { dbg_perror("close(2)"); return (-1); @@ -184,20 +188,18 @@ evfilt_signal_knote_delete(struct filter *filt, struct knote *kn) /* NOTE: This does not call sigprocmask(3) to unblock the signal. */ kn->kdata.kn_signalfd = -1; - return (0); + return (rv); } int evfilt_signal_knote_enable(struct filter *filt, struct knote *kn) { - dbg_printf("enabling ident %u", (unsigned int) kn->kev.ident); return evfilt_signal_knote_create(filt, kn); } int evfilt_signal_knote_disable(struct filter *filt, struct knote *kn) { - dbg_printf("disabling ident %u", (unsigned int) kn->kev.ident); return evfilt_signal_knote_delete(filt, kn); } diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 50997ca7d..abbb9d8fb 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -164,7 +164,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) dbg_printf("timerfd_create(2): %s", strerror(errno)); return (-1); } - dbg_printf("created timerfd %d", tfd); + dbg_printf("timer_fd=%i - created", tfd); convert_timedata_to_itimerspec(&ts, kn->kev.data, kn->kev.fflags, kn->kev.flags & EV_ONESHOT); @@ -212,6 +212,8 @@ evfilt_timer_knote_delete(struct filter *filt, struct knote *kn) dbg_printf("epoll_ctl(2): %s", strerror(errno)); rv = -1; } + + dbg_printf("timer_fd=%i - closed", kn->data.pfd); if (close(kn->data.pfd) < 0) { dbg_printf("close(2): %s", strerror(errno)); rv = -1; diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index c910e81df..2dfbb72c1 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -36,7 +36,7 @@ eventfd_raise(int evfd) uint64_t counter; int rv = 0; - dbg_puts("raising event level"); + dbg_printf("event_fd=%i - raising event level", evfd); counter = 1; if (write(evfd, &counter, sizeof(counter)) < 0) { switch (errno) { @@ -65,7 +65,7 @@ eventfd_lower(int evfd) int rv = 0; /* Reset the counter */ - dbg_puts("lowering event level"); + dbg_printf("event_fd=%i - lowering event level", evfd); n = read(evfd, &cur, sizeof(cur)); if (n < 0) { switch (errno) { @@ -129,7 +129,7 @@ linux_evfilt_user_knote_create(struct filter *filt, struct knote *kn) return (-1); } - dbg_printf("created eventfd fd=%i", evfd); + dbg_printf("event_fd=%i - created", evfd); /* Add the eventfd to the epoll set */ KN_UDATA(kn); /* populate this knote's kn_udata field */ @@ -145,8 +145,7 @@ linux_evfilt_user_knote_create(struct filter *filt, struct knote *kn) } int -linux_evfilt_user_knote_modify(struct filter *filt UNUSED, struct knote *kn, - const struct kevent *kev) +linux_evfilt_user_knote_modify(struct filter *filt UNUSED, struct knote *kn, const struct kevent *kev) { unsigned int ffctrl; unsigned int fflags; @@ -194,11 +193,14 @@ linux_evfilt_user_knote_delete(struct filter *filt, struct knote *kn) if (rv < 0) { dbg_perror("epoll_ctl(2)"); } else { - dbg_printf("removed eventfd fd=%d from the epollfd", kn->kdata.kn_eventfd); + dbg_printf("event_fd=%i - removed from epoll_fd=%i", + kn->kdata.kn_eventfd, filter_epoll_fd(filt)); } } kn->kn_registered = 0; + + dbg_printf("event_fd=%i - closed", kn->kdata.kn_eventfd); if (close(kn->kdata.kn_eventfd) < 0) { dbg_perror("close(2)"); return (-1); diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 0c48245f5..233482d06 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -135,7 +135,7 @@ add_watch(struct filter *filt, struct knote *kn) } /* Add the watch */ - dbg_printf("inotify_add_watch(2); inofd=%d, %s, path=%s", + dbg_printf("inotify_add_watch(2); inofd=%d flags=%s path=%s", ifd, inotify_mask_dump(mask), path); kn->kev.data = inotify_add_watch(ifd, path, mask); if (kn->kev.data < 0) { diff --git a/vendor/libkqueue/src/solaris/socket.c b/vendor/libkqueue/src/solaris/socket.c index 621f57c1a..09a0b0336 100644 --- a/vendor/libkqueue/src/solaris/socket.c +++ b/vendor/libkqueue/src/solaris/socket.c @@ -48,7 +48,7 @@ evfilt_socket_knote_create(struct filter *filt, struct knote *kn) return (-1); } - dbg_printf("port_associate kq fd %d with actual fd %ld", filter_epoll_fd(filt), kn->kev.ident); + dbg_printf("port_associate kq fd=%d with actual fd %ld", filter_epoll_fd(filt), kn->kev.ident); rv = port_associate(filter_epoll_fd(filt), PORT_SOURCE_FD, kn->kev.ident, events, kn); @@ -90,14 +90,13 @@ evfilt_socket_knote_delete(struct filter *filt, struct knote *kn) int evfilt_socket_knote_enable(struct filter *filt, struct knote *kn) { - dbg_printf("enabling knote %p", kn); + return evfilt_socket_knote_create(filt, kn); } int evfilt_socket_knote_disable(struct filter *filt, struct knote *kn) { - dbg_printf("disabling knote %p", kn); return evfilt_socket_knote_delete(filt, kn); } diff --git a/vendor/libkqueue/src/solaris/timer.c b/vendor/libkqueue/src/solaris/timer.c index a7e922905..fce24973c 100644 --- a/vendor/libkqueue/src/solaris/timer.c +++ b/vendor/libkqueue/src/solaris/timer.c @@ -138,7 +138,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) } kn->data.timerid = timerid; - dbg_printf("created timer with id #%lu", (unsigned long) timerid); + dbg_printf("th=%lu - created timer", (unsigned long) timerid); return (0); } @@ -159,7 +159,7 @@ evfilt_timer_knote_delete(struct filter *filt UNUSED, struct knote *kn) if (kn->kev.flags & EV_DISABLE) return (0); - dbg_printf("deleting timer # %d", kn->data.timerid); + dbg_printf("th=%d - deleting timer", kn->data.timerid); return timer_delete(kn->data.timerid); } diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index df93a82df..5b3d3f134 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -105,10 +105,10 @@ windows_kevent_wait(struct kqueue *kq, int no, const struct timespec *timeout) timeout_ms += timeout->tv_nsec / 1000000; } - dbg_printf("waiting for events (timeout=%u ms)", (unsigned int) timeout_ms); + dbg_printf("timeout=%u ms - waiting for events", (unsigned int) timeout_ms); #if 0 if(timeout_ms <= 0) - dbg_printf("Woop, not waiting !?"); + dbg_puts("Woop, not waiting !?"); #endif memset(&iocp_buf, 0, sizeof(iocp_buf)); success = GetQueuedCompletionStatus(kq->kq_iocp, @@ -212,7 +212,7 @@ windows_get_descriptor_type(struct knote *kn) default: { struct stat sb; if (fstat((int)kn->kev.ident, &sb) == 0) { - dbg_printf("HANDLE %d appears to be a regular file", kn->kev.ident); + dbg_printf("handle=%d - appears to be a regular file", kn->kev.ident); kn->kn_flags |= KNFL_FILE; } } diff --git a/vendor/libkqueue/src/windows/timer.c b/vendor/libkqueue/src/windows/timer.c index 167af703e..292bb2bdb 100644 --- a/vendor/libkqueue/src/windows/timer.c +++ b/vendor/libkqueue/src/windows/timer.c @@ -125,7 +125,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) dbg_lasterror("CreateWaitableTimer()"); return (-1); } - dbg_printf("created timer handle %p", th); + dbg_printf("th=%p - created timer handle", th); convert_msec_to_filetime(&liDueTime, kn->kev.data); From 3369a8809cec1e3d077fd469225fe93610d1fa59 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 18 Jun 2020 17:21:10 -0500 Subject: [PATCH 0769/1120] KQUEUE_DEBUG=0 should not enable debugging --- vendor/libkqueue/src/common/kqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 81afebd6c..3e9c7ffe7 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -66,7 +66,7 @@ libkqueue_init(void) DEBUG_KQUEUE = 0; #else char *s = getenv("KQUEUE_DEBUG"); - if (s != NULL && strlen(s) > 0) { + if ((s != NULL) && (strlen(s) > 0) && (*s != '0')) { DEBUG_KQUEUE = 1; #ifdef _WIN32 From 79c39a630f06408df8664447e7cad79a1fd3169c Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 18 Jun 2020 17:38:35 -0500 Subject: [PATCH 0770/1120] More debug info in cleanup test --- vendor/libkqueue/test/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 95e6e60f4..7eb76c61e 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -148,12 +148,12 @@ test_cleanup(void *unused) /* Create initial kqueue to avoid cleanup thread being destroyed on each close */ if ((kqfd1 = kqueue()) < 0) - die("kqueue()"); + die("kqueue() - max_fds=%u", max_fds); /* Create and close 2 * max fd number of kqueues */ for (i=0; i < 2 * max_fds + 1; i++) { if ((kqfd2 = kqueue()) < 0) - die("kqueue()"); + die("kqueue() - i=%i max_fds=%u", i, max_fds); kevent_add(kqfd2, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000,NULL); From 7eafe1a16371308209cbdd96658bf1d3cd47571b Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 18 Jun 2020 17:45:52 -0500 Subject: [PATCH 0771/1120] We're calling printf for die anyway, may as well allow additional arguments --- vendor/libkqueue/test/common.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 6f39011a5..a1298867c 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -25,8 +25,8 @@ # define errx(rc,msg,...) do { puts(msg); exit(rc); } while (0) #endif -#define die(str) do { \ - fprintf(stderr, "%s(): %s: %s\n", __func__,str, strerror(errno));\ +#define die(str, ...) do { \ + fprintf(stderr, "%s(): %s: %s\n", __func__,str, strerror(errno), ##__VA_ARGS__);\ abort();\ } while (0) From a0093236ae2206998a3ba23384c44e3f084884f3 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 18 Jun 2020 18:14:30 -0500 Subject: [PATCH 0772/1120] Print allowed/used FDs when we fail to create file descriptor --- vendor/libkqueue/src/common/debug.h | 8 ++++---- vendor/libkqueue/src/common/private.h | 3 +++ vendor/libkqueue/src/linux/signal.c | 6 +++++- vendor/libkqueue/src/linux/timer.c | 6 +++++- vendor/libkqueue/src/linux/user.c | 6 +++++- vendor/libkqueue/src/linux/vnode.c | 6 +++++- 6 files changed, 27 insertions(+), 8 deletions(-) diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index c5530a957..d95a0f10d 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -49,13 +49,13 @@ extern char *KQUEUE_DEBUG_IDENT; #define dbg_printf(fmt,...) do { \ if (DEBUG_KQUEUE) \ fprintf(stderr, "%s [%d]: %s(): "fmt"\n", \ - KQUEUE_DEBUG_IDENT, THREAD_ID, __func__, __VA_ARGS__); \ + KQUEUE_DEBUG_IDENT, THREAD_ID, __func__, ##__VA_ARGS__); \ } while (0) -#define dbg_perror(str) do { \ +#define dbg_perror(fmt,...) do { \ if (DEBUG_KQUEUE) \ - fprintf(stderr, "%s [%d]: %s(): %s: %s (errno=%d)\n", \ - KQUEUE_DEBUG_IDENT, THREAD_ID, __func__, str, \ + fprintf(stderr, "%s [%d]: %s(): "fmt": %s (errno=%d)\n", \ + KQUEUE_DEBUG_IDENT, THREAD_ID, __func__, ##__VA_ARGS__, \ strerror(errno), errno); \ } while (0) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index b30e60e8f..799fd3a28 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -239,6 +239,7 @@ int knote_delete(struct filter *, struct knote *); int knote_init(void); int knote_disable(struct filter *, struct knote *); int knote_enable(struct filter *, struct knote *); +int knote_modify(struct filter *, struct knote *); #define knote_get_filter(knt) &((knt)->kn_kq->kq_filt[(knt)->kev.filter]) @@ -248,6 +249,8 @@ void filter_unregister_all(struct kqueue *); const char *filter_name(short); unsigned int get_fd_limit(void); +unsigned int get_fd_used(void); + int kevent_wait(struct kqueue *, const struct timespec *); int kevent_copyout(struct kqueue *, int, struct kevent *, int); void kevent_free(struct kqueue *); diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index bf8182041..b44393f5c 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -94,7 +94,11 @@ signalfd_create(int epoll_fd, struct knote *kn, int signum) sigfd = signalfd(-1, &sigmask, flags); } if (sigfd < 0) { - dbg_perror("signalfd(2)"); + if ((errno == EMFILE) || (errno == ENFILE)) { + dbg_perror("signalfd(2) fd_used=%u fd_max=%u", get_fd_used(), get_fd_limit()); + } else { + dbg_perror("signalfd(2)"); + } goto errout; } diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index abbb9d8fb..28087cb87 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -161,7 +161,11 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) tfd = timerfd_create(CLOCK_MONOTONIC, 0); if (tfd < 0) { - dbg_printf("timerfd_create(2): %s", strerror(errno)); + if ((errno == EMFILE) || (errno == ENFILE)) { + dbg_perror("timerfd_create(2) fd_used=%u fd_max=%u", get_fd_used(), get_fd_limit()); + } else { + dbg_perror("timerfd_create(2)"); + } return (-1); } dbg_printf("timer_fd=%i - created", tfd); diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index 2dfbb72c1..f4bcd9309 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -121,7 +121,11 @@ linux_evfilt_user_knote_create(struct filter *filt, struct knote *kn) /* Create an eventfd */ evfd = eventfd(0, 0); if (evfd < 0) { - dbg_perror("eventfd"); + if ((errno == EMFILE) || (errno == ENFILE)) { + dbg_perror("eventfd(2) fd_used=%u fd_max=%u", get_fd_used(), get_fd_limit()); + } else { + dbg_perror("eventfd(2)"); + } error: if (evfd >= 0) close(evfd); kn->kdata.kn_eventfd = -1; diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 233482d06..69d700dfa 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -130,7 +130,11 @@ add_watch(struct filter *filt, struct knote *kn) /* Create an inotify descriptor */ ifd = inotify_init(); if (ifd < 0) { - dbg_perror("inotify_init(2)"); + if ((errno == EMFILE) || (errno == ENFILE)) { + dbg_perror("inotify_init(2) fd_used=%u fd_max=%u", get_fd_used(), get_fd_limit()); + } else { + dbg_perror("inotify_init(2)"); + } return (-1); } From 23aea6e581b7f540b8d2cc2d0ff1b21d7786ab9d Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 18 Jun 2020 18:18:25 -0500 Subject: [PATCH 0773/1120] Fix die macro --- vendor/libkqueue/test/common.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index a1298867c..a7415eca5 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -25,8 +25,8 @@ # define errx(rc,msg,...) do { puts(msg); exit(rc); } while (0) #endif -#define die(str, ...) do { \ - fprintf(stderr, "%s(): %s: %s\n", __func__,str, strerror(errno), ##__VA_ARGS__);\ +#define die(fmt, ...) do { \ + fprintf(stderr, "%s(): "fmt": %s (%i)\n", __func__, ##__VA_ARGS__, strerror(errno), errno);\ abort();\ } while (0) From 1612199b250cb76f9855798f7b8e99c3b5ea6633 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 18 Jun 2020 18:20:23 -0500 Subject: [PATCH 0774/1120] Actually commit get_fd_used --- vendor/libkqueue/src/common/kqueue.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 3e9c7ffe7..44dead3d0 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -57,6 +57,23 @@ get_fd_limit(void) #endif } +unsigned int +get_fd_used(void) +{ + unsigned int fd_max = get_fd_limit(); + unsigned int i; + unsigned int used = 0; + +#ifdef __linux__ + for (i = 0; i < fd_max; i++) { + if (fcntl(i, F_GETFD) == 0) + used++; + } +#endif + + return used; +} + static struct map *kqmap; void From 24a5c6f8a948af9f593b6cbc9010754c72f9c56e Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 18 Jun 2020 18:33:51 -0500 Subject: [PATCH 0775/1120] Print number of used FDs if we error out in the FD cleanup test --- vendor/libkqueue/test/common.h | 3 +++ vendor/libkqueue/test/main.c | 46 ++++++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index a7415eca5..9d355278a 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -128,6 +128,9 @@ kevent_add(int kqfd, struct kevent *kev, #define test_no_kevents(a) _test_no_kevents(a, __FILE__, __LINE__) void _test_no_kevents(int, const char *, int); +unsigned int print_fd_table(void); +unsigned int get_fd_limit(void); + /* From test.c */ void test_begin(struct test_context *, const char *); void test_end(struct test_context *); diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 7eb76c61e..fb3f9cc5b 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -18,8 +18,50 @@ #include #include #endif + #include "common.h" +unsigned int +get_fd_limit(void) +{ +#ifdef _WIN32 + /* actually windows should be able to hold + way more, as they use HANDLEs for everything. + Still this number should still be sufficient for + the provided number of kqueue fds. + */ + return 65536; +#else + struct rlimit rlim; + + if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { + perror("getrlimit(2)"); + return (65536); + } else { + return (rlim.rlim_max); + } +#endif +} + +unsigned int +print_fd_table(void) +{ + unsigned int fd_max = get_fd_limit(); + unsigned int i; + unsigned int used = 0; + +#ifdef __linux__ + for (i = 0; i < fd_max; i++) { + if (fcntl(i, F_GETFD) == 0) { + printf("fd=%i used\n", i); + used++; + } + } +#endif + + return used; +} + /* Maximum number of threads that can be created */ #define MAX_THREADS 100 @@ -148,12 +190,12 @@ test_cleanup(void *unused) /* Create initial kqueue to avoid cleanup thread being destroyed on each close */ if ((kqfd1 = kqueue()) < 0) - die("kqueue() - max_fds=%u", max_fds); + die("kqueue() - used_fds=%u max_fds=%u", print_fd_table(), max_fds); /* Create and close 2 * max fd number of kqueues */ for (i=0; i < 2 * max_fds + 1; i++) { if ((kqfd2 = kqueue()) < 0) - die("kqueue() - i=%i max_fds=%u", i, max_fds); + die("kqueue() - i=%i used_fds=%u max_fds=%u", i, print_fd_table(), max_fds); kevent_add(kqfd2, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000,NULL); From 7a1463870a3891835def9270bc3846f14d4dfd1e Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 18 Jun 2020 18:34:10 -0500 Subject: [PATCH 0776/1120] Delay creating kq for general tests --- vendor/libkqueue/test/main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index fb3f9cc5b..2a735bb2c 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -280,9 +280,6 @@ test_harness(struct unit_test tests[MAX_TESTS], int iterations) test(cleanup, ctx); #endif - if ((kqfd = kqueue()) < 0) - die("kqueue()"); - test(ev_receipt, ctx); /* TODO: this fails now, but would be good later test(kqueue_descriptor_is_pollable); @@ -290,6 +287,8 @@ test_harness(struct unit_test tests[MAX_TESTS], int iterations) free(ctx); + if ((kqfd = kqueue()) < 0) + die("kqueue()"); n = 0; for (i = 0; i < iterations; i++) { ctx = calloc(1, sizeof(*ctx)); From 45b80d477f0bd3427ac454467de5ec0b49cffb4a Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Thu, 18 Jun 2020 19:41:04 -0300 Subject: [PATCH 0777/1120] Fix leak in kevent_to_str() --- vendor/libkqueue/test/kevent.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index 602f2adc0..f8c233b1e 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -140,7 +140,7 @@ kevent_flags_dump(struct kevent *kev) const char * kevent_to_str(struct kevent *kev) { - char buf[512]; + static __thread char buf[512]; snprintf(buf, sizeof(buf), "[ident=%d, filter=%d, %s, %s, data=%d, udata=%p]", @@ -151,7 +151,7 @@ kevent_to_str(struct kevent *kev) (int) kev->data, kev->udata); - return (strdup(buf)); + return buf; } void From b8372f2786fa15e3f70cdbc184965f8767d69168 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 18 Jun 2020 18:50:29 -0500 Subject: [PATCH 0778/1120] Preserve error number in get_fd_used as it's used primarily for debuggin --- vendor/libkqueue/src/common/kqueue.c | 3 +++ vendor/libkqueue/test/main.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 44dead3d0..d315a6d83 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -63,6 +63,7 @@ get_fd_used(void) unsigned int fd_max = get_fd_limit(); unsigned int i; unsigned int used = 0; + int our_errno = errno; /* Preserve errno */ #ifdef __linux__ for (i = 0; i < fd_max; i++) { @@ -71,6 +72,8 @@ get_fd_used(void) } #endif + errno = our_errno; + return used; } diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 2a735bb2c..d764cf520 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -49,6 +49,7 @@ print_fd_table(void) unsigned int fd_max = get_fd_limit(); unsigned int i; unsigned int used = 0; + int our_errno = errno; /* Preserve errno */ #ifdef __linux__ for (i = 0; i < fd_max; i++) { @@ -59,6 +60,8 @@ print_fd_table(void) } #endif + errno = our_errno; + return used; } From c88d8c766f8c3082ab71b55c40f661316e79597f Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 18 Jun 2020 18:55:13 -0500 Subject: [PATCH 0779/1120] Remove useless 'do {} while (0)' used as noop code for debugging macros Add variadic arguments to debug version of dbg_perror --- vendor/libkqueue/src/common/debug.h | 14 +++++++------- vendor/libkqueue/src/linux/platform.c | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index d95a0f10d..430830290 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -128,18 +128,18 @@ typedef struct { } while (0) #else /* NDEBUG */ -# define dbg_puts(str) do {} while (0) -# define dbg_printf(fmt,...) do {} while (0) -# define dbg_perror(str) do {} while (0) -# define dbg_lasterror(str) do {} while (0) -# define dbg_wsalasterror(str) do {} while (0) -# define reset_errno() do {} while (0) +# define dbg_puts(str) +# define dbg_printf(fmt, ...) +# define dbg_perror(str, ...) +# define dbg_lasterror(str) +# define dbg_wsalasterror(str) +# define reset_errno() # define MTX_UNLOCKED # define MTX_LOCKED # define tracing_mutex_t pthread_mutex_t # define tracing_mutex_init pthread_mutex_init # define tracing_mutex_destroy pthread_mutex_destroy -# define tracing_mutex_assert(x,y) do {} while (0) +# define tracing_mutex_assert(x,y) # define tracing_mutex_lock pthread_mutex_lock # define tracing_mutex_unlock pthread_mutex_unlock #endif diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 37d922eb1..ed826add5 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -149,7 +149,7 @@ monitoring_thread_kq_cleanup(int signal_fd, bool ignore_use_count) static void monitoring_thread_cleanup(void *arg) { - int i; + int i; /* Reset so that thread can be restarted */ monitoring_thread_initialized = PTHREAD_ONCE_INIT; From af10e65c09113fefe4aa9dcfe1ae159305263903 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 18 Jun 2020 19:01:22 -0500 Subject: [PATCH 0780/1120] sleep 25ms between each cleanup iteration --- vendor/libkqueue/test/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index d764cf520..3578f2c66 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -222,6 +222,8 @@ test_cleanup(void *unused) if (close(kqfd2) < 0) die("close()"); + + nanosleep(&(struct timespec) { .tv_nsec = 25000000 }, NULL); /* deschedule thread */ } /* Restore FD limit */ From f2515fd512b628ccb9caa7037e8e1b6a88f7c2aa Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 18 Jun 2020 19:16:23 -0500 Subject: [PATCH 0781/1120] print when we're closing the other end of the KQ pipe simplify linux_kqueue_cleanup --- vendor/libkqueue/src/linux/platform.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index ed826add5..8aee445c7 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -78,7 +78,7 @@ const struct kqueue_vtable kqops = { .eventfd_descriptor = linux_eventfd_descriptor, }; -static bool +static void linux_kqueue_cleanup(struct kqueue *kq); static bool end_monitoring_thread = false; @@ -381,7 +381,7 @@ linux_kqueue_init(struct kqueue *kq) * - true if epoll fd and pipes were closed * - false if epoll fd was already closed */ -static bool +static void linux_kqueue_cleanup(struct kqueue *kq) { char buffer; @@ -391,14 +391,13 @@ linux_kqueue_cleanup(struct kqueue *kq) if (kq->epollfd > 0) { close(kq->epollfd); kq->epollfd = -1; - } else { - dbg_puts("epollfd already closed, not performing cleanup"); - // Don't do cleanup if epollfd has already been closed - return false; } /* * read will return 0 on pipe EOF (i.e. if the write end of the pipe has been closed) + * + * kq->pipefd[1] should have already been called outside of libkqueue + * as a signal the kqueue should be closed. */ ret = read(kq->pipefd[0], &buffer, 1); if (ret == -1 && errno == EWOULDBLOCK) { @@ -410,10 +409,12 @@ linux_kqueue_cleanup(struct kqueue *kq) // Shouldn't happen unless data is written to kqueue FD // Ignore write and continue with close dbg_puts("unexpected data available on kqueue FD"); + assert(0); } pipefd = kq->pipefd[0]; if (pipefd > 0) { + dbg_printf("kq_fd=%i - closed", pipefd); close(pipefd); kq->pipefd[0] = -1; } @@ -421,8 +422,6 @@ linux_kqueue_cleanup(struct kqueue *kq) /* Decrement kqueue counter */ kqueue_cnt--; dbg_printf("kq=%p - cleaned up kqueue, active_kqueues=%u", kq, kqueue_cnt); - - return true; } /** Explicitly free the kqueue @@ -435,12 +434,9 @@ linux_kqueue_cleanup(struct kqueue *kq) void linux_kqueue_free(struct kqueue *kq) { - /* Increment use counter as cleanup is being performed outside signal handler */ - if (linux_kqueue_cleanup(kq)) { - fd_use_cnt[kq->kq_id]++; - dbg_printf("kq=%p - increased fd=%i use_count=%u", kq, kq->kq_id, fd_use_cnt[kq->kq_id]); - } else /* Reset counter as FD had already been cleaned */ - fd_use_cnt[kq->kq_id] = 0; + linux_kqueue_cleanup(kq); + fd_use_cnt[kq->kq_id]++; + dbg_printf("kq=%p - increased fd=%i use_count=%u", kq, kq->kq_id, fd_use_cnt[kq->kq_id]); } static int From 28e4382020f119ec484037e0ade7f84451c3a38c Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 18 Jun 2020 19:23:24 -0500 Subject: [PATCH 0782/1120] Print when we close the epoll_fd --- vendor/libkqueue/src/linux/platform.c | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 8aee445c7..62952c124 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -389,6 +389,7 @@ linux_kqueue_cleanup(struct kqueue *kq) int pipefd; if (kq->epollfd > 0) { + dbg_printf("epoll_fd=%i - closed", kq->epollfd); close(kq->epollfd); kq->epollfd = -1; } From d73f6d8ba722cb3762611fa414e231d730e5c0c6 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 18 Jun 2020 19:36:54 -0500 Subject: [PATCH 0783/1120] Print error if we fail to close something --- vendor/libkqueue/src/linux/platform.c | 35 ++++++++++++++++++++------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 62952c124..3f4999ea3 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -292,18 +292,27 @@ linux_kqueue_init(struct kqueue *kq) * will be caught by the monitoring thread. */ if (pipe(kq->pipefd)) { - close(kq->epollfd); + if (close(kq->epollfd) < 0) + dbg_perror("close(2)"); kq->epollfd = -1; + return (-1); } if (filter_register_all(kq) < 0) { error: - close(kq->epollfd); - close(kq->pipefd[0]); + if (close(kq->epollfd) < 0) + dbg_perror("close(2)"); + kq->epollfd = -1; + + if (close(kq->pipefd[0]) < 0) + dbg_perror("close(2)"); kq->pipefd[0] = -1; - close(kq->pipefd[1]); + + if (close(kq->pipefd[1]) < 0) + dbg_perror("close(2)"); kq->pipefd[1] = -1; + return (-1); } @@ -390,7 +399,9 @@ linux_kqueue_cleanup(struct kqueue *kq) if (kq->epollfd > 0) { dbg_printf("epoll_fd=%i - closed", kq->epollfd); - close(kq->epollfd); + + if (close(kq->epollfd) < 0) + dbg_perror("close(2)"); kq->epollfd = -1; } @@ -404,7 +415,9 @@ linux_kqueue_cleanup(struct kqueue *kq) if (ret == -1 && errno == EWOULDBLOCK) { // Shoudn't happen unless kqops.kqueue_free is called on an open FD dbg_puts("kqueue wasn't closed"); - close(kq->pipefd[1]); + + if (close(kq->pipefd[1]) < 0) + dbg_perror("close(2)"); kq->pipefd[1] = -1; } else if (ret > 0) { // Shouldn't happen unless data is written to kqueue FD @@ -416,7 +429,9 @@ linux_kqueue_cleanup(struct kqueue *kq) pipefd = kq->pipefd[0]; if (pipefd > 0) { dbg_printf("kq_fd=%i - closed", pipefd); - close(pipefd); + + if (close(pipefd) < 0) + dbg_perror("close(2)"); kq->pipefd[0] = -1; } @@ -651,7 +666,8 @@ linux_eventfd_init(struct eventfd *e) } if (fcntl(evfd, F_SETFL, O_NONBLOCK) < 0) { dbg_perror("fcntl"); - close(evfd); + if (close(evfd) < 0) + dbg_perror("close(2)"); return (-1); } e->ef_id = evfd; @@ -662,7 +678,8 @@ linux_eventfd_init(struct eventfd *e) void linux_eventfd_close(struct eventfd *e) { - close(e->ef_id); + if (close(e->ef_id) < 0) + dbg_perror("close(2)"); e->ef_id = -1; } From 5c966cd11ace648b78ec3c07ff92dd4d6a47ab3a Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 18 Jun 2020 19:44:06 -0500 Subject: [PATCH 0784/1120] broadcast not signal to avoid deadlock --- vendor/libkqueue/src/linux/platform.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 3f4999ea3..b6984b532 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -225,8 +225,11 @@ monitoring_thread_loop(void *arg) /* * Now that thread is initialized, let kqueue init resume + * + * For some obscure reason this needs to be a broadcast + * not a signal, else we occasionally get hangs. */ - pthread_cond_signal(&monitoring_thread_cond); + pthread_cond_broadcast(&monitoring_thread_cond); pthread_detach(pthread_self()); pthread_cleanup_push(monitoring_thread_cleanup, NULL) From bbc82f334894cc44b68be6b547cfb9d6e16f6a61 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 18 Jun 2020 19:47:21 -0500 Subject: [PATCH 0785/1120] Don't need to print failures twice? --- vendor/libkqueue/.travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/vendor/libkqueue/.travis.yml b/vendor/libkqueue/.travis.yml index 265d6e82c..0f7923ab2 100644 --- a/vendor/libkqueue/.travis.yml +++ b/vendor/libkqueue/.travis.yml @@ -9,7 +9,6 @@ env: global: - KQUEUE_DEBUG="yes" - M_PERTURB=0x42 - - CTEST_OUTPUT_ON_FAILURE=1 - ASAN_OPTIONS="symbolize=1 detect_leaks=1 detect_stack_use_after_return=1" - LSAN_OPTIONS="fast_unwind_on_malloc=0:malloc_context_size=50" matrix: From 1663919c6f11fc1002ca27bad9035fc556715ea1 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 18 Jun 2020 19:53:14 -0500 Subject: [PATCH 0786/1120] Only set LSAN/ASAN envvars when we're building with ASAN and LSAN --- vendor/libkqueue/.travis.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/vendor/libkqueue/.travis.yml b/vendor/libkqueue/.travis.yml index 0f7923ab2..247afa327 100644 --- a/vendor/libkqueue/.travis.yml +++ b/vendor/libkqueue/.travis.yml @@ -9,12 +9,10 @@ env: global: - KQUEUE_DEBUG="yes" - M_PERTURB=0x42 - - ASAN_OPTIONS="symbolize=1 detect_leaks=1 detect_stack_use_after_return=1" - - LSAN_OPTIONS="fast_unwind_on_malloc=0:malloc_context_size=50" matrix: - BUILD_TYPE=Release - BUILD_TYPE=Debug - - BUILD_TYPE=Debug ENABLE_ASAN=YES ENABLE_LSAN=YES ENABLE_UBSAN=YES + - BUILD_TYPE=Debug ENABLE_ASAN=YES ENABLE_LSAN=YES ENABLE_UBSAN=YES ASAN_OPTIONS="symbolize=1 detect_leaks=1 detect_stack_use_after_return=1" LSAN_OPTIONS="fast_unwind_on_malloc=0:malloc_context_size=50" addons: apt: config: From ea800c943098b6d76cc206e28e85a873f04ea9aa Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sat, 6 Apr 2019 17:43:35 -0400 Subject: [PATCH 0787/1120] Fix cross-building on Ubuntu --- vendor/libkqueue/test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/test/CMakeLists.txt b/vendor/libkqueue/test/CMakeLists.txt index 2c8161978..d57c0e060 100644 --- a/vendor/libkqueue/test/CMakeLists.txt +++ b/vendor/libkqueue/test/CMakeLists.txt @@ -52,7 +52,7 @@ target_link_libraries(libkqueue-test if(WIN32) target_link_libraries(libkqueue-test PRIVATE - Ws2_32) + ws2_32) endif() add_test(NAME libkqueue-test From ab58c0daf86601c9a332711364ccc439f361ce1c Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 18 Jun 2020 23:01:49 -0500 Subject: [PATCH 0788/1120] Same fix for kqueue --- vendor/libkqueue/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index ae913c689..5ca2f9752 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -227,7 +227,7 @@ if(MINGW AND CMAKE_C_COMPILER_ID MATCHES GNU) endif() if(WIN32) - target_link_libraries(kqueue PRIVATE Ws2_32) + target_link_libraries(kqueue PRIVATE ws2_32) endif() target_link_libraries(kqueue PRIVATE Threads::Threads) From 50d2d8fffb899a541e60c0412a1551b41ffd1923 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Tue, 2 Apr 2019 20:40:35 -0400 Subject: [PATCH 0789/1120] Fix some more Windows things --- vendor/libkqueue/src/windows/read.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/windows/read.c b/vendor/libkqueue/src/windows/read.c index 6e4c7b98c..9087dc414 100644 --- a/vendor/libkqueue/src/windows/read.c +++ b/vendor/libkqueue/src/windows/read.c @@ -97,7 +97,7 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) if (src->flags & KNFL_FILE) { ... } */ memcpy(dst, &src->kev, sizeof(*dst)); - if (src->kn_flags & KNFL_PASSIVE_SOCKET) { + if (src->kn_flags & KNFL_SOCKET_PASSIVE) { /* TODO: should contains the length of the socket backlog */ dst->data = 1; } else { From 12561a0b39b14bd6af318fc975556384c13e9673 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Tue, 2 Apr 2019 20:34:01 -0400 Subject: [PATCH 0790/1120] Define kq_mtx on Windows --- vendor/libkqueue/src/common/kqueue.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index d315a6d83..abc7c3c0c 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -30,6 +30,7 @@ char *KQUEUE_DEBUG_IDENT = "KQ"; #ifdef _WIN32 static LONG kq_init_begin = 0; static int kq_init_complete = 0; +pthread_mutex_t kq_mtx; #else pthread_mutex_t kq_mtx = PTHREAD_MUTEX_INITIALIZER; pthread_once_t kq_is_initialized = PTHREAD_ONCE_INIT; @@ -90,6 +91,7 @@ libkqueue_init(void) DEBUG_KQUEUE = 1; #ifdef _WIN32 + pthread_mutex_init(&kq_mtx); /* Initialize the Winsock library */ WSADATA wsaData; if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) From 519be2ebfb6e886cd3437487657754424248c91d Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Tue, 2 Apr 2019 20:25:31 -0400 Subject: [PATCH 0791/1120] Fix some build issues on MinGW # Conflicts: # include/sys/event.h --- vendor/libkqueue/README.md | 10 ++++++++++ vendor/libkqueue/Toolchain-mingw32.cmake | 18 ++++++++++++++++++ vendor/libkqueue/src/windows/platform.h | 8 +++++--- 3 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 vendor/libkqueue/Toolchain-mingw32.cmake diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index 3d40ded9a..b6564c459 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -55,6 +55,16 @@ Windows (clang/C2) (Visual Studio Project) cmake -G "Visual Studio 14 2015" -T "LLVM-vs2014" cmake --build . +Windows (cross-compiling on Ubuntu using MinGW) +----------------------------------------------- + + sudo apt-get install mingw-w64 + rm -rf CMakeCache.txt CMakeFiles + mkdir build + cd build + cmake -DCMAKE_TOOLCHAIN_FILE=Toolchain-mingw32.cmake .. + make + Xcode (project) --------------- diff --git a/vendor/libkqueue/Toolchain-mingw32.cmake b/vendor/libkqueue/Toolchain-mingw32.cmake new file mode 100644 index 000000000..e32959e02 --- /dev/null +++ b/vendor/libkqueue/Toolchain-mingw32.cmake @@ -0,0 +1,18 @@ +# the name of the target operating system +SET(CMAKE_SYSTEM_NAME Windows) + +# which compilers to use for C and C++ +SET(CMAKE_C_COMPILER /usr/bin/i686-w64-mingw32-gcc) +SET(CMAKE_CXX_COMPILER /usr/bin/i686-w64-mingw32-g++) +SET(CMAKE_RC_COMPILER i686-w64-mingw32-windres) + +# here is the target environment located +#SET(CMAKE_FIND_ROOT_PATH /usr/i586-mingw32msvc /home/alex/mingw-install ) + +# adjust the default behaviour of the FIND_XXX() commands: +# search headers and libraries in the target environment, search +# programs in the host environment +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 934e7fac8..6ab44c995 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -17,9 +17,11 @@ #ifndef _KQUEUE_WINDOWS_PLATFORM_H #define _KQUEUE_WINDOWS_PLATFORM_H -/* Require Windows XP or later */ -#define WINVER 0x0501 -#define _WIN32_WINNT 0x0501 +/* Require Windows Server 2003 or later */ +#define WINVER 0x0502 +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0502 +#endif /* Reduces build time by omitting extra system headers */ #define WIN32_LEAN_AND_MEAN From 641fa085b29db68feac8c6403fb918d2ad0a0a35 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 19 Jun 2020 00:38:02 -0500 Subject: [PATCH 0792/1120] Make linux platform pipe ends non-blocking --- vendor/libkqueue/src/linux/platform.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index b6984b532..19de13871 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -319,6 +319,16 @@ linux_kqueue_init(struct kqueue *kq) return (-1); } + /* + * Ensure pipe ends are non-blocking so that there's + * no chance of them delaying close(). + */ + if ((fcntl(kq->pipefd[0], F_SETFL, O_NONBLOCK) < 0) || + (fcntl(kq->pipefd[1], F_SETFL, O_NONBLOCK) < 0)) { + dbg_perror("fcntl(2)"); + goto error; + } + kq->kq_id = kq->pipefd[1]; /* From bfac2da3e48f5c3b05f1da56cc9af121c880291c Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 19 Jun 2020 01:52:46 -0500 Subject: [PATCH 0793/1120] Proper fix for stalled monitor thread --- vendor/libkqueue/src/linux/platform.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 19de13871..81d28cadf 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -225,11 +225,10 @@ monitoring_thread_loop(void *arg) /* * Now that thread is initialized, let kqueue init resume - * - * For some obscure reason this needs to be a broadcast - * not a signal, else we occasionally get hangs. */ - pthread_cond_broadcast(&monitoring_thread_cond); + pthread_mutex_lock(arg); /* Must try to lock to ensure parent is waiting on signal */ + pthread_cond_signal(&monitoring_thread_cond); + pthread_mutex_unlock(arg); pthread_detach(pthread_self()); pthread_cleanup_push(monitoring_thread_cleanup, NULL) @@ -265,12 +264,12 @@ linux_kqueue_start_thread(void) pthread_mutex_lock(&mt_mtx); - if (pthread_create(&monitoring_thread, NULL, &monitoring_thread_loop, NULL)) { + if (pthread_create(&monitoring_thread, NULL, &monitoring_thread_loop, &mt_mtx)) { dbg_perror("linux_kqueue_start_thread failure"); } /* Wait for thread creating to be done as we need monitoring_tid to be available */ - pthread_cond_wait(&monitoring_thread_cond, &mt_mtx); + pthread_cond_wait(&monitoring_thread_cond, &mt_mtx); /* unlocks mt_mtx allowing child to lock it */ pthread_mutex_unlock(&mt_mtx); } From 542ae055e6360d832ac1e1f8351da8d08c1ed1ba Mon Sep 17 00:00:00 2001 From: Matthew Newton Date: Fri, 26 Jun 2020 00:47:43 +0100 Subject: [PATCH 0794/1120] Be more specific where files come from Needed when building out-of-tree, which for example is what the Debian packaging does. --- vendor/libkqueue/CMakeLists.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 5ca2f9752..d38aa6047 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -119,7 +119,8 @@ check_symbol_exists(ppoll poll.h HAVE_DECL_PPOLL) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) -include_directories(${CMAKE_CURRENT_BINARY_DIR}) +include_directories(${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/include) set(LIBKQUEUE_HEADERS include/sys/event.h) @@ -248,7 +249,8 @@ set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION ${CMAKE_INSTALL_FULL_MANDIR} ${CMAKE_INSTALL_FULL_LIBDIR}${LIB_SUFFIX}/pkgconfig) install(FILES - "include/sys/event.h" "include/sys/libkqueue_version.h" + "${CMAKE_SOURCE_DIR}/include/sys/event.h" + "${CMAKE_CURRENT_BINARY_DIR}/include/sys/libkqueue_version.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/kqueue/sys" COMPONENT headers) @@ -258,7 +260,7 @@ install(TARGETS "${CMAKE_INSTALL_FULL_LIBDIR}${LIB_SUFFIX}" COMPONENT libraries) install(FILES - kqueue.2 + "${CMAKE_SOURCE_DIR}/kqueue.2" DESTINATION "${CMAKE_INSTALL_FULL_MANDIR}/man2" COMPONENT man) From bda9e1716f1dc5acbc299e3a26faa8e475844148 Mon Sep 17 00:00:00 2001 From: Matthew Newton Date: Fri, 26 Jun 2020 01:06:00 +0100 Subject: [PATCH 0795/1120] Fix file globs for Debian packaging --- vendor/libkqueue/pkg/debian/libkqueue0.install | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/pkg/debian/libkqueue0.install b/vendor/libkqueue/pkg/debian/libkqueue0.install index d55f15e28..0879cd03b 100644 --- a/vendor/libkqueue/pkg/debian/libkqueue0.install +++ b/vendor/libkqueue/pkg/debian/libkqueue0.install @@ -1 +1,2 @@ -usr/lib/*/lib*.so.0 +usr/lib/*/lib*.so +usr/lib/*/lib*.so.* From cc76e33a954ba2810bd10b01302cec3407e8eab0 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Fri, 26 Jun 2020 16:59:33 -0300 Subject: [PATCH 0796/1120] Add *.swp items to .gitignore --- vendor/libkqueue/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/.gitignore b/vendor/libkqueue/.gitignore index 202092736..354e55ec4 100644 --- a/vendor/libkqueue/.gitignore +++ b/vendor/libkqueue/.gitignore @@ -3,6 +3,7 @@ config.h *.pc *.log *.deb +*.swp CMakeCache.txt CMakeFiles/ CPackConfig.cmake From 28df8eea29e03543705e32a566addcc48282ec05 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Fri, 26 Jun 2020 18:23:30 -0300 Subject: [PATCH 0797/1120] Clean up some DEADWOOD --- vendor/libkqueue/src/common/private.h | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 799fd3a28..36f08e8f0 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -142,14 +142,11 @@ struct filter { short kf_id; //!< EVFILT_* facility this filter provides. /* filter operations */ - int (*kf_init)(struct filter *); void (*kf_destroy)(struct filter *); int (*kf_copyout)(struct kevent *, struct knote *, void *); /* knote operations */ - - int (*kn_create)(struct filter *, struct knote *); int (*kn_modify)(struct filter *, struct knote *, const struct kevent *); int (*kn_delete)(struct filter *, struct knote *); @@ -268,17 +265,4 @@ void *map_lookup(struct map *, int); void *map_delete(struct map *, int); void map_free(struct map *); -/* DEADWOOD: No longer needed due to the un-smerging of POSIX and Linux - -int posix_evfilt_user_init(struct filter *); -void posix_evfilt_user_destroy(struct filter *); -int posix_evfilt_user_copyout(struct kevent *, struct knote *, void *ptr UNUSED); -int posix_evfilt_user_knote_create(struct filter *, struct knote *); -int posix_evfilt_user_knote_modify(struct filter *, struct knote *, const struct kevent *); -int posix_evfilt_user_knote_delete(struct filter *, struct knote *); -int posix_evfilt_user_knote_enable(struct filter *, struct knote *); -int posix_evfilt_user_knote_disable(struct filter *, struct knote *); - -*/ - #endif /* ! _KQUEUE_PRIVATE_H */ From a5a2c847f7daaa6f015ae0dc95aa5b17234dacbd Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Wed, 8 Jul 2020 23:35:27 -0300 Subject: [PATCH 0798/1120] test: Only link with -lkqueue where is exist We don't need to use -lkqueue on *BSD/OSX systems. Only where is supposed to have such library. --- vendor/libkqueue/test/CMakeLists.txt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/test/CMakeLists.txt b/vendor/libkqueue/test/CMakeLists.txt index d57c0e060..5d0a883f5 100644 --- a/vendor/libkqueue/test/CMakeLists.txt +++ b/vendor/libkqueue/test/CMakeLists.txt @@ -45,10 +45,17 @@ if(WIN32) elseif(UNIX) target_link_libraries(libkqueue-test PRIVATE -rdynamic) endif() -target_link_libraries(libkqueue-test - PRIVATE + +# +# Don't link against -lkqueue on OSX and FreeBSD +# +if(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "(Darwin|FreeBSD)") + target_link_libraries(libkqueue-test + PRIVATE kqueue Threads::Threads) +endif() + if(WIN32) target_link_libraries(libkqueue-test PRIVATE From 97753d90898a139c08efba0a4171bc271e300713 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Wed, 8 Jul 2020 23:46:10 -0300 Subject: [PATCH 0799/1120] test: Don't build test_kqueue_descriptor_is_pollable() on OSX --- vendor/libkqueue/test/main.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 3578f2c66..845c06c2e 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -68,6 +68,12 @@ print_fd_table(void) /* Maximum number of threads that can be created */ #define MAX_THREADS 100 +/** + * Don't build the below function on OSX due to a known-issue + * breakking the build with FD_SET()/FD_ISSET() + OSX. + * e.g: https://www.google.com/search?q=___darwin_check_fd_set_overflow + */ +#ifndef __APPLE__ void test_kqueue_descriptor_is_pollable(void) { @@ -98,6 +104,7 @@ test_kqueue_descriptor_is_pollable(void) close(kq); } +#endif /* * Test the method for detecting when one end of a socketpair From 9e91443820710295101d1937c4ed0ac706fe5dae Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Wed, 8 Jul 2020 23:50:47 -0300 Subject: [PATCH 0800/1120] test: Don't expect 'config.h' on OSX/BSD --- vendor/libkqueue/test/common.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 9d355278a..56fa85cc6 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -39,7 +39,10 @@ #include #include -#include "config.h" +#if !defined(__APPLE__) && !defined(__FreeBSD__) +# include "config.h" +#endif + #ifndef _WIN32 #include #include From c9e42e512fd78a27479b70fb183dff7e97ed800d Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Thu, 9 Jul 2020 16:25:44 -0300 Subject: [PATCH 0801/1120] test: Fix missing project() --- vendor/libkqueue/test/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/test/CMakeLists.txt b/vendor/libkqueue/test/CMakeLists.txt index 5d0a883f5..968f361e4 100644 --- a/vendor/libkqueue/test/CMakeLists.txt +++ b/vendor/libkqueue/test/CMakeLists.txt @@ -13,6 +13,7 @@ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # +project(libkqueue-test LANGUAGES C) set(LIBKQUEUE_TEST_SOURCES kevent.c From b98b9047d79a725d1183609cf8d206aeda66f692 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Thu, 9 Jul 2020 15:47:30 -0300 Subject: [PATCH 0802/1120] test: Update README.md --- vendor/libkqueue/README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index b6564c459..4d17f4b7c 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -76,7 +76,15 @@ Running Unit Tests cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib -DENABLE_TESTING=YES -DCMAKE_BUILD_TYPE=Debug make make test - + +Build & Running only the test suite +----------------------------------- +Helpful to see the behavior of the tests on systems with native `kqueue`, e.g: OSX, FreeBSD + + cmake . --config test/CMakeLists.txt + make -C test/ + ./test/libkqueue-test + Debugging --------- From 164061d76f6bd804c871e340415364a15a703b3e Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Thu, 9 Jul 2020 17:21:22 -0300 Subject: [PATCH 0803/1120] Fix kevent_cmp() We should call kevent_to_str() separately due to the function using a single static buffer. It will fix false-positive reports showing the same content among two 'struct kevent' report. --- vendor/libkqueue/test/kevent.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index f8c233b1e..488392e2e 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -192,8 +192,9 @@ _kevent_cmp(struct kevent *k1, struct kevent *k2, const char *file, int line) k2->flags |= EV_ADD; #endif if (memcmp(k1, k2, sizeof(*k1)) != 0) { - printf("[%s:%d]: kevent_cmp() failed:\n expected %s\n but got %s\n", - file, line, kevent_to_str(k1), kevent_to_str(k2)); + printf("[%s:%d]: kevent_cmp() failed:\n", file, line); + printf("expected %s\n", kevent_to_str(k1)); + printf("but got %s\n", kevent_to_str(k2)); abort(); } } From fa5ba2c6a5c9b0d49dc0d5fc9215be0dfc10b622 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Thu, 9 Jul 2020 17:25:16 -0300 Subject: [PATCH 0804/1120] Fix memory leak in kevent_flags_dump() --- vendor/libkqueue/test/kevent.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index 488392e2e..32d3bfa76 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -107,16 +107,13 @@ kevent_fflags_dump(struct kevent *kev) char * kevent_flags_dump(struct kevent *kev) { - char *buf; + static __thread char buf[512]; #define KEVFL_DUMP(attrib) \ if (kev->flags & attrib) \ strncat(buf, #attrib" ", 64); - if ((buf = calloc(1, 1024)) == NULL) - abort(); - - snprintf(buf, 1024, "flags = %d (", kev->flags); + snprintf(buf, sizeof(buf), "flags = %d (", kev->flags); KEVFL_DUMP(EV_ADD); KEVFL_DUMP(EV_ENABLE); KEVFL_DUMP(EV_DISABLE); From 0bfd2a6207c263517703691191af5b23c124b498 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Thu, 9 Jul 2020 17:26:04 -0300 Subject: [PATCH 0805/1120] Fix memory leak in kevent_fflags_dump() --- vendor/libkqueue/test/kevent.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index 32d3bfa76..710687c13 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -71,22 +71,19 @@ kevent_get_hires(struct kevent *kev, int kqfd) char * kevent_fflags_dump(struct kevent *kev) { - char *buf; + static __thread char buf[512]; #define KEVFFL_DUMP(attrib) \ if (kev->fflags & attrib) \ strncat(buf, #attrib" ", 64); - if ((buf = calloc(1, 1024)) == NULL) - abort(); - /* Not every filter has meaningful fflags */ if (kev->filter != EVFILT_VNODE) { - snprintf(buf, 1024, "fflags = %d", kev->fflags); + snprintf(buf, sizeof(buf), "fflags = %d", kev->fflags); return (buf); } - snprintf(buf, 1024, "fflags = %d (", kev->fflags); + snprintf(buf, sizeof(buf), "fflags = %d (", kev->fflags); KEVFFL_DUMP(NOTE_DELETE); KEVFFL_DUMP(NOTE_WRITE); KEVFFL_DUMP(NOTE_EXTEND); From 009269a2e91c57e2648ba9d61fd10b4224a40db8 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Thu, 9 Jul 2020 18:48:04 -0300 Subject: [PATCH 0806/1120] test: Fix err()/errx() macros It expects to support variadic vars. --- vendor/libkqueue/test/common.h | 13 +++++++++++-- vendor/libkqueue/test/kevent.c | 2 +- vendor/libkqueue/test/vnode.c | 8 ++++---- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 56fa85cc6..56cb817b7 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -21,8 +21,17 @@ #if HAVE_ERR_H # include #else -# define err(rc,msg,...) do { perror(msg); exit(rc); } while (0) -# define errx(rc,msg,...) do { puts(msg); exit(rc); } while (0) +# define err(rc, fmt, ...) do { \ + char buf[128]; \ + snprintf(buf, sizeof(buf), fmt, ##__VA_ARGS__);\ + perror(buf); \ + exit(rc); \ +} while (0) + +# define errx(rc, msg, ...) do { \ + fprintf(stderr, msg"\n", ##__VA_ARGS__);\ + exit(rc); \ +} while (0) #endif #define die(fmt, ...) do { \ diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index 710687c13..4ff348546 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -32,7 +32,7 @@ _test_no_kevents(int kqfd, const char *file, int line) err(1, "kevent(2)"); if (nfds > 0) { printf("\n[%s:%d]: Unexpected event:", file, line); - err(1, kevent_to_str(&kev)); + err(1, "%s", kevent_to_str(&kev)); } } diff --git a/vendor/libkqueue/test/vnode.c b/vendor/libkqueue/test/vnode.c index 365cd9a46..7fb6006b5 100644 --- a/vendor/libkqueue/test/vnode.c +++ b/vendor/libkqueue/test/vnode.c @@ -130,7 +130,7 @@ test_kevent_vnode_note_attrib(struct test_context *ctx) kev.filter != EVFILT_VNODE || kev.fflags != NOTE_ATTRIB) err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + ctx->cur_test_id, (unsigned int)kev.ident, kev.filter, kev.flags); } void @@ -150,7 +150,7 @@ test_kevent_vnode_note_rename(struct test_context *ctx) kev.filter != EVFILT_VNODE || kev.fflags != NOTE_RENAME) err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + ctx->cur_test_id, (unsigned int)kev.ident, kev.filter, kev.flags); testfile_rename(ctx->testfile, 1); @@ -193,7 +193,7 @@ test_kevent_vnode_disable_and_enable(struct test_context *ctx) kev.filter != EVFILT_VNODE || kev.fflags != NOTE_ATTRIB) err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + ctx->cur_test_id, (unsigned int)kev.ident, kev.filter, kev.flags); } #ifdef EV_DISPATCH @@ -216,7 +216,7 @@ test_kevent_vnode_dispatch(struct test_context *ctx) kev.filter != EVFILT_VNODE || kev.fflags != NOTE_ATTRIB) err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); + ctx->cur_test_id, (unsigned int)kev.ident, kev.filter, kev.flags); /* Confirm that the watch is disabled automatically */ testfile_touch(ctx->testfile); From b64cb8d379dbfe6d5c9485d9f9c7687666bb3210 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Thu, 9 Jul 2020 19:26:31 -0300 Subject: [PATCH 0807/1120] test: Fix build on FreeBSD --- vendor/libkqueue/test/common.h | 4 ++++ vendor/libkqueue/test/main.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 56cb817b7..5eff4ff97 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -52,6 +52,10 @@ # include "config.h" #endif +#if defined(__FreeBSD__) +# include +#endif + #ifndef _WIN32 #include #include diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 845c06c2e..0479ddff3 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#if defined(__linux__) +#if defined(__linux__) || defined(__FreeBSD__) #include #include #endif From 059b5f0563442edf85e77e44fa03ce283822d866 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Thu, 9 Jul 2020 18:32:56 -0300 Subject: [PATCH 0808/1120] test: Update kevent_get_hires() to receive the timeout as parameter --- vendor/libkqueue/test/common.h | 2 +- vendor/libkqueue/test/kevent.c | 7 ++----- vendor/libkqueue/test/user.c | 6 +++++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 5eff4ff97..d1b8d2f28 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -115,7 +115,7 @@ void test_evfilt_user(struct test_context *); extern const char * kevent_to_str(struct kevent *); void kevent_get(struct kevent *, int); -void kevent_get_hires(struct kevent *, int); +void kevent_get_hires(struct kevent *, int, struct timespec *); void kevent_update(int kqfd, struct kevent *kev); #define kevent_cmp(a,b) _kevent_cmp(a,b, __FILE__, __LINE__) diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index 4ff348546..85d793a20 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -56,14 +56,11 @@ kevent_get(struct kevent *kev, int kqfd) This test exercises that codepath. */ void -kevent_get_hires(struct kevent *kev, int kqfd) +kevent_get_hires(struct kevent *kev, int kqfd, struct timespec *ts) { int nfds; - struct timespec timeo; - timeo.tv_sec = 0; - timeo.tv_nsec = 500000; - nfds = kevent(kqfd, NULL, 0, kev, 1, &timeo); + nfds = kevent(kqfd, NULL, 0, kev, 1, ts); if (nfds < 1) die("kevent(2)"); } diff --git a/vendor/libkqueue/test/user.c b/vendor/libkqueue/test/user.c index f9c76c35e..29e1bcd49 100644 --- a/vendor/libkqueue/test/user.c +++ b/vendor/libkqueue/test/user.c @@ -52,6 +52,10 @@ static void test_kevent_user_get_hires(struct test_context *ctx) { struct kevent kev, ret; + struct timespec timeo = { + .tv_sec = 0, + .tv_nsec = 500000 + }; test_no_kevents(ctx->kqfd); @@ -62,7 +66,7 @@ test_kevent_user_get_hires(struct test_context *ctx) kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; kev.flags = EV_CLEAR; - kevent_get_hires(&ret, ctx->kqfd); + kevent_get_hires(&ret, ctx->kqfd, &timeo); kevent_cmp(&kev, &ret); test_no_kevents(ctx->kqfd); From a76f12cd592260aa5193c41855acba8f36e5d600 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Thu, 9 Jul 2020 21:20:52 -0300 Subject: [PATCH 0809/1120] test: Update kevent_fflags_dump() --- vendor/libkqueue/test/kevent.c | 66 ++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index 85d793a20..a671c102a 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -69,31 +69,59 @@ char * kevent_fflags_dump(struct kevent *kev) { static __thread char buf[512]; + size_t len; #define KEVFFL_DUMP(attrib) \ if (kev->fflags & attrib) \ - strncat(buf, #attrib" ", 64); - - /* Not every filter has meaningful fflags */ - if (kev->filter != EVFILT_VNODE) { - snprintf(buf, sizeof(buf), "fflags = %d", kev->fflags); - return (buf); - } + strncat((char *) buf, #attrib" ", 64); + + snprintf(buf, sizeof(buf), "fflags=0x%04x (", kev->fflags); + switch (kev->filter) { + case EVFILT_VNODE: + KEVFFL_DUMP(NOTE_DELETE); + KEVFFL_DUMP(NOTE_WRITE); + KEVFFL_DUMP(NOTE_EXTEND); + KEVFFL_DUMP(NOTE_ATTRIB); + KEVFFL_DUMP(NOTE_LINK); + KEVFFL_DUMP(NOTE_RENAME); + break; + + case EVFILT_USER: + KEVFFL_DUMP(NOTE_FFNOP); + KEVFFL_DUMP(NOTE_FFAND); + KEVFFL_DUMP(NOTE_FFOR); + KEVFFL_DUMP(NOTE_FFCOPY); + KEVFFL_DUMP(NOTE_TRIGGER); + break; + + case EVFILT_READ: + case EVFILT_WRITE: +#ifdef NOTE_LOWAT + KEVFFL_DUMP(NOTE_LOWAT); +#endif + break; - snprintf(buf, sizeof(buf), "fflags = %d (", kev->fflags); - KEVFFL_DUMP(NOTE_DELETE); - KEVFFL_DUMP(NOTE_WRITE); - KEVFFL_DUMP(NOTE_EXTEND); -#if HAVE_NOTE_TRUNCATE - KEVFFL_DUMP(NOTE_TRUNCATE); + case EVFILT_PROC: + KEVFFL_DUMP(NOTE_CHILD); + KEVFFL_DUMP(NOTE_EXIT); +#ifdef NOTE_EXITSTATUS + KEVFFL_DUMP(NOTE_EXITSTATUS); #endif - KEVFFL_DUMP(NOTE_ATTRIB); - KEVFFL_DUMP(NOTE_LINK); - KEVFFL_DUMP(NOTE_RENAME); -#if HAVE_NOTE_REVOKE - KEVFFL_DUMP(NOTE_REVOKE); + KEVFFL_DUMP(NOTE_FORK); + KEVFFL_DUMP(NOTE_EXEC); +#ifdef NOTE_SIGNAL + KEVFFL_DUMP(NOTE_SIGNAL); #endif - buf[strlen(buf) - 1] = ')'; + break; + + default: + break; + } + len = strlen(buf); + if (buf[len - 1] == ' ') buf[len - 1] = '\0'; /* Trim trailing space */ + strcat(buf, ")"); + +#undef KEVFFL_DUMP return (buf); } From 02b46cf7c3c121fc920ac9da1ea08de413f74a5c Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Thu, 9 Jul 2020 20:46:24 -0300 Subject: [PATCH 0810/1120] Backport kevent_get_timeout() from FreeBSD kqueue() test suite --- vendor/libkqueue/test/common.h | 1 + vendor/libkqueue/test/kevent.c | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index d1b8d2f28..dc61612e8 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -116,6 +116,7 @@ void test_evfilt_user(struct test_context *); extern const char * kevent_to_str(struct kevent *); void kevent_get(struct kevent *, int); void kevent_get_hires(struct kevent *, int, struct timespec *); +int kevent_get_timeout(struct kevent *, int, struct timespec *); void kevent_update(int kqfd, struct kevent *kev); #define kevent_cmp(a,b) _kevent_cmp(a,b, __FILE__, __LINE__) diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index a671c102a..879edc967 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -51,6 +51,27 @@ kevent_get(struct kevent *kev, int kqfd) err(1, "kevent(2)"); } +/** + * Retrieve a single kevent, specifying a maximum time to wait for it. + * Result: + * 0 = Timeout + * 1 = Success + */ +int +kevent_get_timeout(struct kevent *kev, int fd, struct timespec *ts) +{ + int nfds; + + nfds = kevent(fd, NULL, 0, kev, 1, ts); + if (nfds < 0) { + err(1, "kevent(2)"); + } else if (nfds == 0) { + return 0; + } + + return 1; +} + /* In Linux, a kevent() call with less than 1ms resolution will perform a pselect() call to obtain the higer resolution. This test exercises that codepath. From bc3f3038a6e108f5c291b393240f0ee93e769c51 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 16 Jul 2020 12:10:19 -0700 Subject: [PATCH 0811/1120] Drop the debug only .travis.yml matrix entry --- vendor/libkqueue/.travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/vendor/libkqueue/.travis.yml b/vendor/libkqueue/.travis.yml index 247afa327..4dd5d25d8 100644 --- a/vendor/libkqueue/.travis.yml +++ b/vendor/libkqueue/.travis.yml @@ -11,7 +11,6 @@ env: - M_PERTURB=0x42 matrix: - BUILD_TYPE=Release - - BUILD_TYPE=Debug - BUILD_TYPE=Debug ENABLE_ASAN=YES ENABLE_LSAN=YES ENABLE_UBSAN=YES ASAN_OPTIONS="symbolize=1 detect_leaks=1 detect_stack_use_after_return=1" LSAN_OPTIONS="fast_unwind_on_malloc=0:malloc_context_size=50" addons: apt: From 20bdf7edfc2d1cb01a5e218fa7457b166321945b Mon Sep 17 00:00:00 2001 From: Matthew Newton Date: Mon, 20 Jul 2020 13:27:12 +0100 Subject: [PATCH 0812/1120] fix debian -dev package - shouldn't include library symlink - add missing header file --- vendor/libkqueue/pkg/debian/libkqueue-dev.install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/pkg/debian/libkqueue-dev.install b/vendor/libkqueue/pkg/debian/libkqueue-dev.install index 4efbacfe3..763a6b2c9 100644 --- a/vendor/libkqueue/pkg/debian/libkqueue-dev.install +++ b/vendor/libkqueue/pkg/debian/libkqueue-dev.install @@ -1,4 +1,4 @@ -usr/lib/*/libkqueue.so usr/lib/*/pkgconfig/libkqueue.pc usr/include/kqueue/sys/event.h +usr/include/kqueue/sys/libkqueue_version.h usr/share/man/man2/* From 384f96a1fa21e64c34d37c95425a3dbffba58a98 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 12 Oct 2020 18:54:52 -0500 Subject: [PATCH 0813/1120] Print out masked st_mode when we can't determine the file descriptor type --- vendor/libkqueue/src/linux/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 81d28cadf..5a4837777 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -802,7 +802,7 @@ linux_get_descriptor_type(struct knote *kn) switch (sb.st_mode & S_IFMT) { default: errno = EBADF; - dbg_perror("unknown fd type"); + dbg_perror("fd=%i unknown fd type, st_mode=0x%x", fd, sb.st_mode & S_IFMT); return (-1); case S_IFREG: From 1de006c86585e7182ec28837495d24d1d2191543 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 13 Oct 2020 00:42:25 -0500 Subject: [PATCH 0814/1120] Default to marking file descriptors as passive sockets if fstat() doesn't hint at the type Closes #97 --- vendor/libkqueue/src/linux/platform.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 5a4837777..9eb8e054b 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -828,6 +828,12 @@ linux_get_descriptor_type(struct knote *kn) case S_IFSOCK: dbg_printf("fd=%i is a socket", fd); break; /* deferred type determination */ + + case 0: /* seen with eventfd */ + dbg_printf("fd=%i fstat() provided no S_IFMT flags, treating fd as passive socket", fd); + kn->kn_flags |= KNFL_SOCKET; + kn->kn_flags |= KNFL_SOCKET_PASSIVE; + return (0); } /* From cdd405dbb7f14f4ae1b8f8e2ec2f4ece1ae586dd Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 13 Jul 2021 12:09:32 -0500 Subject: [PATCH 0815/1120] Revert "Automatically append '64' to the library dir if we're building 64 bit libraries on linux". Closes #101 This reverts commit a1bd5e9c49af06fb319a58399470a47387c89edf. --- vendor/libkqueue/CMakeLists.txt | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index d38aa6047..d7cb70a72 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -162,16 +162,6 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL Linux) if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set (CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "default install path" FORCE ) endif() - - # - # Set library directory correctly if we're building 64bit libraries - # - get_property(LIB64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS) - if ("${LIB64}" STREQUAL "TRUE") - set(LIB_SUFFIX 64) - else() - set(LIB_SUFFIX "") - endif() list(APPEND LIBKQUEUE_SOURCES src/posix/platform.c src/posix/platform.h @@ -245,8 +235,7 @@ configure_file("${CMAKE_SOURCE_DIR}/libkqueue.pc.in" # set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION ${CMAKE_INSTALL_FULL_MANDIR} ${CMAKE_INSTALL_FULL_MANDIR}/man2 - ${CMAKE_INSTALL_FULL_INCLUDEDIR}/sys - ${CMAKE_INSTALL_FULL_LIBDIR}${LIB_SUFFIX}/pkgconfig) + ${CMAKE_INSTALL_FULL_INCLUDEDIR}/sys) install(FILES "${CMAKE_SOURCE_DIR}/include/sys/event.h" @@ -257,7 +246,7 @@ install(FILES install(TARGETS kqueue DESTINATION - "${CMAKE_INSTALL_FULL_LIBDIR}${LIB_SUFFIX}" + "${CMAKE_INSTALL_FULL_LIBDIR}" COMPONENT libraries) install(FILES "${CMAKE_SOURCE_DIR}/kqueue.2" @@ -267,7 +256,7 @@ install(FILES install(FILES "${CMAKE_BINARY_DIR}/libkqueue.pc" DESTINATION - "${CMAKE_INSTALL_FULL_LIBDIR}${LIB_SUFFIX}/pkgconfig" + "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig" COMPONENT pkgconfig) set(CPACK_PACKAGE_NAME ${PROJECT_NAME}) From c1debe879efa28efa12f4632dc031ab6ebb1a965 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 9 Aug 2021 18:45:56 +0000 Subject: [PATCH 0816/1120] Use prctl() to set names on threads for Linux and POSIX --- vendor/libkqueue/src/linux/platform.c | 6 ++++++ vendor/libkqueue/src/linux/proc.c | 5 +++++ vendor/libkqueue/src/posix/proc.c | 5 +++++ vendor/libkqueue/src/posix/timer.c | 5 +++++ 4 files changed, 21 insertions(+) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 9eb8e054b..e92735510 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -17,6 +17,7 @@ #define _GNU_SOURCE #include #include +#include #include #include #include "../common/private.h" @@ -268,6 +269,11 @@ linux_kqueue_start_thread(void) dbg_perror("linux_kqueue_start_thread failure"); } + /* Set the thread's name to something descriptive so it shows up in gdb, + * etc. glibc >= 2.1.2 supports pthread_setname_np, but this is a safer way + * to do it for backwards compatibility. Max name length is 16 bytes. */ + prctl(PR_SET_NAME, "libkqueue_mon", 0, 0, 0); + /* Wait for thread creating to be done as we need monitoring_tid to be available */ pthread_cond_wait(&monitoring_thread_cond, &mt_mtx); /* unlocks mt_mtx allowing child to lock it */ pthread_mutex_unlock(&mt_mtx); diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index 60ea5d1b6..891df0802 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -135,6 +136,10 @@ evfilt_proc_init(struct filter *filt) if (pthread_create(&ed->wthr_id, NULL, wait_thread, filt) != 0) goto errout; + /* Set the thread's name to something descriptive so it shows up in gdb, + * etc. glibc >= 2.1.2 supports pthread_setname_np, but this is a safer way + * to do it for backwards compatibility. Max name length is 16 bytes. */ + prctl(PR_SET_NAME, "libkqueue_wait", 0, 0, 0); return (0); diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 54966e229..1f5578d20 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -115,6 +116,10 @@ evfilt_proc_init(struct filter *filt) if (pthread_create(&ed->wthr_id, NULL, wait_thread, filt) != 0) goto errout; + /* Set the thread's name to something descriptive so it shows up in gdb, + * etc. Max name length is 16 bytes. */ + prctl(PR_SET_NAME, "libkqueue_wait", 0, 0, 0); + return (0); errout: diff --git a/vendor/libkqueue/src/posix/timer.c b/vendor/libkqueue/src/posix/timer.c index d52d23dc2..794b16256 100644 --- a/vendor/libkqueue/src/posix/timer.c +++ b/vendor/libkqueue/src/posix/timer.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -166,6 +167,10 @@ _timer_create(struct filter *filt, struct knote *kn) free(req); return (-1); } + /* Set the thread's name to something descriptive so it shows up in gdb, + * etc. Max name length is 16 bytes. */ + prctl(PR_SET_NAME, "libkqueue_sleep", 0, 0, 0); + pthread_attr_destroy(&attr); return (0); From 1a5c1cb252bdccef912aa42ba611b7417341dea4 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 9 Aug 2021 20:35:59 +0000 Subject: [PATCH 0817/1120] Added support for TSan to CMake, added CI run --- vendor/libkqueue/.travis.yml | 2 +- vendor/libkqueue/CMakeLists.txt | 10 ++++++++++ vendor/libkqueue/scripts/travis/build.sh | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/.travis.yml b/vendor/libkqueue/.travis.yml index 4dd5d25d8..f42311ab9 100644 --- a/vendor/libkqueue/.travis.yml +++ b/vendor/libkqueue/.travis.yml @@ -12,6 +12,7 @@ env: matrix: - BUILD_TYPE=Release - BUILD_TYPE=Debug ENABLE_ASAN=YES ENABLE_LSAN=YES ENABLE_UBSAN=YES ASAN_OPTIONS="symbolize=1 detect_leaks=1 detect_stack_use_after_return=1" LSAN_OPTIONS="fast_unwind_on_malloc=0:malloc_context_size=50" + - BUILD_TYPE=Debug ENABLE_TSAN=YES addons: apt: config: @@ -42,4 +43,3 @@ before_script: - ./scripts/travis/build.sh script: - make ARGS="-V" test - diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index d7cb70a72..04aa5df55 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -84,6 +84,16 @@ if(ENABLE_UBSAN) list(APPEND DEBUG_FSANITIZERFLAGS "undefined") endif() +# +# ThreadSanitizer +# +if(ENABLE_TSAN) + # + # -fsanitize=thread - Build with tsan support + # + list(APPEND DEBUG_FSANITIZERFLAGS "thread") +endif() + if(DEBUG_FSANITIZERFLAGS) string (REPLACE ";" "," DEBUG_FSANITIZERFLAGS "${DEBUG_FSANITIZERFLAGS}") set(CMAKE_C_FLAGS_DEBUG "-fsanitize=${DEBUG_FSANITIZERFLAGS} ${CMAKE_C_FLAGS_DEBUG}") diff --git a/vendor/libkqueue/scripts/travis/build.sh b/vendor/libkqueue/scripts/travis/build.sh index 612caa25d..4833469ed 100755 --- a/vendor/libkqueue/scripts/travis/build.sh +++ b/vendor/libkqueue/scripts/travis/build.sh @@ -19,6 +19,7 @@ if ! cmake . -G "Unix Makefiles" \ -DENABLE_ASAN="${ENABLE_ASAN:-NO}" \ -DENABLE_LSAN="${ENABLE_LSAN:-NO}" \ -DENABLE_UBSAN="${ENABLE_UBSAN:-NO}" \ + -DENABLE_TSAN="${ENABLE_TSAN:-NO}" \ -DCMAKE_BUILD_TYPE="${BUILD_TYPE}"; then fatal "Failed during cmake build configuration" fi From 75b089aa9dc444d94cd2faa5c9bdde8635759bf2 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sat, 14 Aug 2021 13:55:22 -0400 Subject: [PATCH 0818/1120] Update Travis CI build image --- vendor/libkqueue/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index 4d17f4b7c..d9fa94cb6 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -1,7 +1,7 @@ libkqueue ========= -[![Travis CI build status][BuildStatus]][BuildStatusLink] +[![Build Status](https://travis-ci.com/mheily/fs123.svg?branch=master)](https://travis-ci.com/mheily/fs123) A user space implementation of the kqueue(2) kernel event notification mechanism libkqueue acts as a translator between the kevent structure and the native From 264260e14fca213a400135a0582f7ead83d4494d Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sat, 14 Aug 2021 13:57:57 -0400 Subject: [PATCH 0819/1120] Fix the Travis CI build status image It was pointing at the wrong repository --- vendor/libkqueue/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index d9fa94cb6..9aece4cbd 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -1,7 +1,7 @@ libkqueue ========= -[![Build Status](https://travis-ci.com/mheily/fs123.svg?branch=master)](https://travis-ci.com/mheily/fs123) +[![Build Status](https://travis-ci.com/mheily/libkqueue.svg?branch=master)](https://travis-ci.com/mheily/libkqueue) A user space implementation of the kqueue(2) kernel event notification mechanism libkqueue acts as a translator between the kevent structure and the native From 5085ab6fd88b2da59e5184fce8bf29cac4984c63 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sat, 14 Aug 2021 17:31:55 -0400 Subject: [PATCH 0820/1120] Update the ChangeLog for v2.4.0 --- vendor/libkqueue/ChangeLog | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 796291393..50be3b92e 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,10 +1,45 @@ Unreleased ------------------------------------------------------------------------ +Nothing here yet. + +2021-08-14 v2.4.0 +------------------------------------------------------------------------ + + * Fix: avoid segfaults when kqueue descriptors are cleaned up. + + * Fix: Prevent potential dead-lock in linux_kqueue_init() + + * Fix: slight deadlock in thread_start() + + * Fix: missing inotify_rm_watch() + + * Fix: call close() in an error handling path + + * Fix: take the write lock when freeing knotes + + * Keep a separate state tree for file descriptors inserted into epoll to avoid conflicts between + EVFILT_READ and EVFILT_WRITE (Closes #29 Closes #59) + + * Fix: deadlock and memory leak in kqueue() + + * Fix: use after free issue in decrementing kq reference counts + + * Default to marking file descriptors as passive sockets if fstat() doesn't hint at the type + (Closes #97) + + * Fix various leaks and issues found by LSAN + * Install event.h in $INCLUDEDIR/kqueue/sys, rather than $INCLUDEDIR/sys * Add support for building native Debian packages using Docker + * Detect raw sockets. + + * Use high-resolution wait on Linux for timeouts finer than a millisecond. + + * Various CMake improvements. + 2019-02-06 v2.3.1 ------------------------------------------------------------------------ From 6618cf19bcdecb89d794aabb7de579ee2d201af2 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 19 Aug 2021 15:37:45 -0500 Subject: [PATCH 0821/1120] Add note on enabling TSAN --- vendor/libkqueue/README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index 9aece4cbd..d3b7a54be 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -91,16 +91,17 @@ Debugging For best results add `-DCMAKE_BUILD_TYPE=Debug` to your cmake invocation, this will disable optimisation and add debugging symbols to ensure your debugger produces usable output, it also enables asserts. +The environmental variable `KQUEUE_DEBUG` can then be set to enable debug output from libkqueue and the test utility. + + KQUEUE_DEBUG=1 + When building under clang and some later versions of GCC, you can add the following flags: - `-DENABLE_ASAN=YES`, enables address sansitizer (detects use after free issues, and out of bounds accesses). - `-DENABLE_LSAN=YES`, enables leak sanitizer (detects memory leaks). +- `-DENABLE_TSAN=YES`, enables thread sanitizer (detects races). - `-DENABLE_UBSAN=YES`, enables undefined behaviour sanitizer (detects misaligned accesses, interger wrap, divide by zero etc...). -The environmental variable `KQUEUE_DEBUG` can then be set to enable debug output from libkqueue and the test utility. - - KQUEUE_DEBUG=1 - Building Applications --------------------- From a031f1fa2e47477f94263ab23bc48f7676337854 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 19 Aug 2021 10:37:25 -0500 Subject: [PATCH 0822/1120] Add more docs for kqueue_vtable and other structures/callbacks --- vendor/libkqueue/include/sys/event.h | 10 ++- vendor/libkqueue/src/common/private.h | 103 ++++++++++++++++++++------ vendor/libkqueue/src/linux/platform.c | 10 ++- vendor/libkqueue/src/linux/platform.h | 7 +- 4 files changed, 101 insertions(+), 29 deletions(-) diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index ceebcb3ba..c9d7ef972 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -72,11 +72,15 @@ struct timespec; * to set which notifications the application wishes to received. * * A list of kevent structures are passed back to the application as the eventlist - * to inform the application of events which occurred or filter states. + * to inform the application of events which occurred or of filter states. */ struct kevent { - uintptr_t ident; //!< The unique identifier for this event. - short filter; //!< The unique identifier for this event. + uintptr_t ident; //!< The unique identifier (within a given filter) + ///< for this event, usually a PID, FD, signal or + ///< other unique identifier. + ///< The type of identifier passed depends on the + ///< filter. + short filter; //!< Filter for this event. unsigned short flags; //!< One or more of the EV_* macros or'd together. unsigned int fflags; //!< Filter specific flags. intptr_t data; //!< Additional data for the filter. diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 36f08e8f0..7f4e4e7e6 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -89,8 +89,14 @@ struct eventfd { KNFL_SOCKET_RAW) struct knote { - struct kevent kev; - unsigned int kn_flags; + struct kevent kev; //!< kevent used to create this knote. + ///< Contains flags/fflags/data/udata etc. + + unsigned int kn_flags; //!< Internal flags used to record additional + ///< information about the knote. i.e. whether + ///< it is enabled and what type of + ///< socket/file/device it refers to. + ///< See the KNFL_* macros for more details. union { /* OLD */ int pfd; //!< Used by timerfd. @@ -104,7 +110,7 @@ struct knote { void *handle; //!< Used by win32 filters. } data; - struct kqueue *kn_kq; + struct kqueue *kn_kq; //!< kqueue this knote is associated with. volatile uint32_t kn_ref; #if defined(KNOTE_PLATFORM_SPECIFIC) KNOTE_PLATFORM_SPECIFIC; @@ -112,14 +118,21 @@ struct knote { RB_ENTRY(knote) kn_entries; }; -#define KNOTE_ENABLE(ent) do { \ - (ent)->kev.flags &= ~EV_DISABLE; \ +/** Mark a knote as enabled + */ +#define KNOTE_ENABLE(_kn) do { \ + (_kn)->kev.flags &= ~EV_DISABLE; \ } while (0/*CONSTCOND*/) -#define KNOTE_DISABLE(ent) do { \ - (ent)->kev.flags |= EV_DISABLE; \ +/** Mark a knote as disabled + */ +#define KNOTE_DISABLE(_kn) do { \ + (_kn)->kev.flags |= EV_DISABLE; \ } while (0/*CONSTCOND*/) +#define KNOTE_ENABLED(_kn) (!((_kn)->kev.flags & EV_DISABLE)) +#define KNOTE_DISABLED(_kn) ((_kn)->kev.flags & EV_DISABLE) + /** A filter within a kqueue notification channel * * Filters are discreet event notification facilities within a kqueue. @@ -144,7 +157,18 @@ struct filter { /* filter operations */ int (*kf_init)(struct filter *); void (*kf_destroy)(struct filter *); - int (*kf_copyout)(struct kevent *, struct knote *, void *); + + /** Copy an event from the eventing system to a kevent structure + * + * @param[in] dst kevent to populate. + * @param[in] kn the event was triggered on. + * @param[in] ev event system specific structure representing the event, + * i.e. for Linux this would be a `struct epoll_event *`. + * @return + * - 0 on success. + * - -1 on failure. + */ + int (*kf_copyout)(struct kevent *dst, struct knote *kn, void *ev); /* knote operations */ int (*kn_create)(struct filter *, struct knote *); @@ -192,21 +216,56 @@ struct kqueue { RB_ENTRY(kqueue) entries; }; +/** Platform specific support functions + * + */ struct kqueue_vtable { - int (*kqueue_init)(struct kqueue *); - void (*kqueue_free)(struct kqueue *); - // @param timespec can be given as timeout - // @param int the number of events to wait for - // @param kqueue the queue to wait on - int (*kevent_wait)(struct kqueue *, int, const struct timespec *); - // @param kqueue the queue to look at - // @param int The number of events that should be ready - // @param kevent the structure to copy the events into - // @param int The number of events to copy - // @return the actual number of events copied - int (*kevent_copyout)(struct kqueue *, int, struct kevent *, int); - int (*filter_init)(struct kqueue *, struct filter *); - void (*filter_free)(struct kqueue *, struct filter *); + /** Called once for every kqueue created + * + */ + int (*kqueue_init)(struct kqueue *kq); + + /** Called when a kqueue is destroyed + * + */ + void (*kqueue_free)(struct kqueue *kq); + + /** Wait on this platform's eventing system to produce events + * + * ...or return if there are no events within the timeout period. + * + * @param[in] kq The queue to wait on. + * @param[in] numevents The number of events to wait for. + * @param[in] ts How long to wait before returning. + * May be NULL if no timeout is required. + * @return The number of events that ocurred. + */ + int (*kevent_wait)(struct kqueue *kq, int numevents, const struct timespec *ts); + + /** Translate events produced by the eventing system to kevents + * + * @param[in] kq to retrieve events from. + * @param[in] nready The number of events kevent_wait indicated were ready. + * @param[out] el The structure to copy the events into. + * @param[in] nevents The maximum number of events we're allowed to produce. + * This indicates how much free space is available in the + * kevent structure. + * @return The number of events we copied. + */ + int (*kevent_copyout)(struct kqueue *kq, int nready, struct kevent *el, int); + + /** Perform platform specific initialisation for filters + * + * Called once per kqueue per filter. + */ + int (*filter_init)(struct kqueue *kq, struct filter *filt); + + /** Perform platform specific de-initialisation for filters + * + * Called once per kqueue per filter. + */ + void (*filter_free)(struct kqueue *kq, struct filter *filt); + int (*eventfd_init)(struct eventfd *); void (*eventfd_close)(struct eventfd *); int (*eventfd_raise)(struct eventfd *); diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index e92735510..33c322aef 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -591,15 +591,19 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven int rv; if (!epoll_udata) { - dbg_puts("event has no filter, skipping..."); + dbg_puts("event has no knote, skipping..."); /* Forgot to call KN_UDATA()? */ continue; } - switch (epoll_udata->ud_type) { /* * epoll event is associated with a single filter - * so we just have the one knote. + * so we just have one knote per event. + * + * As different filters store pointers to different + * structures, we need to examine ud_type to figure + * out what epoll_data contains. */ + switch (epoll_udata->ud_type) { case EPOLL_UDATA_KNOTE: { struct knote *kn = epoll_udata->ud_kn; diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 2aaf30ce9..19586ae15 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -56,7 +56,12 @@ extern long int syscall (long int __sysno, ...); #define kqueue_epoll_fd(kq) ((kq)->epollfd) #define filter_epoll_fd(filt) ((filt)->kf_kqueue->epollfd) -/** Macro for populating the kn udata structure +/** Macro for populating the kn_udata structure + * + * We set the udata for the epoll event so we can retrieve the knote associated + * with the event when the event occurs. + * + * This should be called before adding a new epoll event associated with a knote. * * @param[in] _kn to populate. */ From 5c8efceaf920cea72765cd23e2bc6818c7310c37 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 19 Aug 2021 16:36:54 -0500 Subject: [PATCH 0823/1120] Add UNUSED_NDEBUG macro Marks arguments as unused if not debugging --- vendor/libkqueue/src/posix/platform.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 2ad8f92f3..37e129d56 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -42,6 +42,11 @@ #define VISIBLE __attribute__((visibility("default"))) #define HIDDEN __attribute__((visibility("hidden"))) #define UNUSED __attribute__((unused)) +#ifndef NDEBUG +#define UNUSED_NDEBUG __attribute__((unused)) +#else +#define UNUSED_NDEBUG +#endif #include #include From e0f657d0a8069110af5d40dd7e9edefbc8b14548 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 19 Aug 2021 17:15:07 -0500 Subject: [PATCH 0824/1120] Use the kn_timerfd for the linux timer fd --- vendor/libkqueue/src/linux/timer.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 28087cb87..f9c489395 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -139,7 +139,7 @@ evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr) /* On return, data contains the number of times the timer has been trigered. */ - n = read(src->data.pfd, &expired, sizeof(expired)); + n = read(src->kdata.kn_timerfd, &expired, sizeof(expired)); if (n != sizeof(expired)) { dbg_puts("invalid read from timerfd"); expired = 1; /* Fail gracefully */ @@ -190,7 +190,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) return (-1); } - kn->data.pfd = tfd; + kn->kdata.kn_timerfd = tfd; return (0); } @@ -209,21 +209,21 @@ evfilt_timer_knote_delete(struct filter *filt, struct knote *kn) { int rv = 0; - if (kn->data.pfd == -1) + if (kn->kdata.kn_timerfd == -1) return (0); - if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, kn->data.pfd, NULL) < 0) { + if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, kn->kdata.kn_timerfd, NULL) < 0) { dbg_printf("epoll_ctl(2): %s", strerror(errno)); rv = -1; } - dbg_printf("timer_fd=%i - closed", kn->data.pfd); - if (close(kn->data.pfd) < 0) { + dbg_printf("timer_fd=%i - closed", kn->kdata.kn_timerfd); + if (close(kn->kdata.kn_timerfd) < 0) { dbg_printf("close(2): %s", strerror(errno)); rv = -1; } - kn->data.pfd = -1; + kn->kdata.kn_timerfd = -1; return (rv); } From fa9aaeeda6ad4acd77f17d0c15d8f6f42f4d0209 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 19 Aug 2021 17:26:57 -0500 Subject: [PATCH 0825/1120] Split out the kqueue tests into their own suite so we avoid running them when they're not explicitly specified --- vendor/libkqueue/test/main.c | 42 +++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 0479ddff3..7444541b1 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -143,7 +143,7 @@ test_peer_close_detection(void *unused) } void -test_kqueue(void *unused) +test_kqueue_alloc(void *unused) { int kqfd; @@ -259,6 +259,24 @@ test_ev_receipt(void *unused) close(kq); } +void +test_kqueue(struct test_context *ctx) +{ + test(peer_close_detection, ctx); + + test(kqueue_alloc, ctx); + test(kevent, ctx); + +#if defined(__linux__) + test(cleanup, ctx); +#endif + + test(ev_receipt, ctx); + /* TODO: this fails now, but would be good later + test(kqueue_descriptor_is_pollable); + */ +} + void run_iteration(struct test_context *ctx) { @@ -281,24 +299,6 @@ test_harness(struct unit_test tests[MAX_TESTS], int iterations) testing_begin(); - ctx = calloc(1, sizeof(*ctx)); - - test(peer_close_detection, ctx); - - test(kqueue, ctx); - test(kevent, ctx); - -#if defined(__linux__) - test(cleanup, ctx); -#endif - - test(ev_receipt, ctx); - /* TODO: this fails now, but would be good later - test(kqueue_descriptor_is_pollable); - */ - - free(ctx); - if ((kqfd = kqueue()) < 0) die("kqueue()"); n = 0; @@ -324,7 +324,7 @@ usage(void) printf("usage: [-hn] [testclass ...]\n" " -h This message\n" " -n Number of iterations (default: 1)\n" - " testclass Tests suites to run: [socket signal timer vnode user]\n" + " testclass Tests suites to run: [kqueue socket signal timer vnode user]\n" " All tests are run by default\n" "\n" ); @@ -335,6 +335,8 @@ int main(int argc, char **argv) { struct unit_test tests[MAX_TESTS] = { + { "kqueue", 1, test_kqueue }, + { "socket", 1, test_evfilt_read }, #if !defined(_WIN32) && !defined(__ANDROID__) // XXX-FIXME -- BROKEN ON LINUX WHEN RUN IN A SEPARATE THREAD From 159df9ca02152813892655e46e7cd0f4fe8b7aa1 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 19 Aug 2021 17:15:10 -0500 Subject: [PATCH 0826/1120] Add EVFILT_PROC support back to Linux using the new pidfd syscall --- vendor/libkqueue/CMakeLists.txt | 1 + vendor/libkqueue/src/linux/platform.c | 4 - vendor/libkqueue/src/linux/platform.h | 1 + vendor/libkqueue/src/linux/proc.c | 258 +++++++++----------------- vendor/libkqueue/test/CMakeLists.txt | 1 + vendor/libkqueue/test/main.c | 26 ++- vendor/libkqueue/test/proc.c | 55 ++++-- 7 files changed, 151 insertions(+), 195 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 04aa5df55..2d907e141 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -177,6 +177,7 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL Linux) src/posix/platform.h src/linux/platform.c src/linux/platform.h + src/linux/proc.c src/linux/read.c src/linux/signal.c src/linux/timer.c diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 33c322aef..e9223c864 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -24,10 +24,6 @@ #define MONITORING_THREAD_SIGNAL (SIGRTMIN + 1) - -//XXX-FIXME TEMP -const struct filter evfilt_proc = EVFILT_NOTIMPL; - /* * Per-thread epoll event buffer used to ferry data between * kevent_wait() and kevent_copyout(). diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 19586ae15..5d3f41d68 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -162,6 +162,7 @@ struct fd_state { int kn_timerfd; \ int kn_signalfd; \ int kn_inotifyfd; \ + int kn_procfd; \ int kn_eventfd; \ } kdata; \ struct epoll_udata kn_udata /* Common struct passed to epoll */ diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index 891df0802..62e0666b5 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -14,229 +14,148 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include + +/* We depend on the SYS_pidfd_open call to determine when a process has exited + * + * The SYS_pidfd_open call is only available in Kernels >= 5.3. If this call + * isn't available there's currently no good fallback. We could implement + * some code around netlink in future, but for now just mark the proc filter + * as not implemented. + */ +#ifndef SYS_pidfd_open +#include "private.h" +const struct filter evfilt_proc = EVFILT_NOTIMPL; +#else #include #include #include -#include -#include #include #include -#include -#include #include #include #include #include #include -#include #include #include "sys/event.h" #include "private.h" +int +evfilt_proc_copyout(struct kevent *dst, struct knote *src, UNUSED_NDEBUG void *ptr) +{ + siginfo_t info; + struct epoll_event * const ev = (struct epoll_event *) ptr; -/* XXX-FIXME Should only have one wait_thread per process. - Now, there is one thread per kqueue - */ -struct evfilt_data { - pthread_t wthr_id; - pthread_cond_t wait_cond; - pthread_mutex_t wait_mtx; -}; + dbg_printf("epoll_ev=%s", epoll_event_dump(ev)); + memcpy(dst, &src->kev, sizeof(*dst)); /* Populate flags from the src kevent */ -//FIXME: WANT: static void * -void * -wait_thread(void *arg) -{ - struct filter *filt = (struct filter *) arg; - uint64_t counter = 1; - const int options = WEXITED | WNOWAIT; - struct knote *kn; - siginfo_t si; - sigset_t sigmask; - - /* Block all signals */ - sigfillset (&sigmask); - pthread_sigmask(SIG_BLOCK, &sigmask, NULL); - - for (;;) { - - /* Wait for a child process to exit(2) */ - if (waitid(P_ALL, 0, &si, options) != 0) { - if (errno == ECHILD) { - dbg_puts("got ECHILD, waiting for wakeup condition"); - pthread_mutex_lock(&filt->kf_data->wait_mtx); - pthread_cond_wait(&filt->kf_data->wait_cond, &filt->kf_data->wait_mtx); - pthread_mutex_unlock(&filt->kf_data->wait_mtx); - dbg_puts("awoken from ECHILD-induced sleep"); - continue; - } - - dbg_puts("waitid(2) returned"); - if (errno == EINTR) - continue; - dbg_perror("waitid(2)"); - break; - } - - /* Scan the wait queue to see if anyone is interested */ - kn = knote_lookup(filt, si.si_pid); - if (kn == NULL) - continue; - - /* Create a proc_event */ - if (si.si_code == CLD_EXITED) { - kn->kev.data = si.si_status; - } else if (si.si_code == CLD_KILLED) { - /* FIXME: probably not true on BSD */ - /* FIXME: arbitrary non-zero number */ - kn->kev.data = 254; - } else { - /* Should never happen. */ - /* FIXME: arbitrary non-zero number */ - kn->kev.data = 1; - } - - knote_enqueue(filt, kn); - - /* Indicate read(2) readiness */ - if (write(filt->kf_pfd, &counter, sizeof(counter)) < 0) { - if (errno != EAGAIN) { - dbg_printf("write(2): %s", strerror(errno)); - /* TODO: set filter error flag */ - break; - } - } + /* Get the exit status _without_ reaping the process, waitpid() should still work in the caller */ + if (waitid(P_PID, (id_t)src->kev.ident, &info, WEXITED | WNOHANG | WNOWAIT) < 0) { + dbg_printf("waitid(2): %s", strerror(errno)); + return (-1); } - /* TODO: error handling */ + if (info.si_code == CLD_EXITED) { + dst->data = WIFEXITED(info.si_status); + dbg_printf("pid=%u exited, status %u", (unsigned int)src->kev.ident, (unsigned int)dst->data); + } else if (info.si_code == CLD_KILLED || info.si_code == CLD_DUMPED) { + dst->data = WTERMSIG(info.si_status); + dbg_printf("pid=%u killed, status %u", (unsigned int)src->kev.ident, (unsigned int)dst->data); + } else { + dst->data = 0; + } + dst->flags |= EV_EOF; /* Set in macOS and FreeBSD kqueue implementations */ - return (NULL); + return (1); } int -evfilt_proc_init(struct filter *filt) +evfilt_proc_knote_enable(struct filter *filt, struct knote *kn) { -#if FIXME - struct evfilt_data *ed; - int efd = -1; - - if ((ed = calloc(1, sizeof(*ed))) == NULL) - return (-1); - filt->kf_data = ed; - - pthread_mutex_init(&ed->wait_mtx, NULL); - pthread_cond_init(&ed->wait_cond, NULL); - if ((efd = eventfd(0, 0)) < 0) - goto errout; - if (fcntl(filt->kf_pfd, F_SETFL, O_NONBLOCK) < 0) - goto errout; - filt->kf_pfd = efd; - if (pthread_create(&ed->wthr_id, NULL, wait_thread, filt) != 0) - goto errout; - - /* Set the thread's name to something descriptive so it shows up in gdb, - * etc. glibc >= 2.1.2 supports pthread_setname_np, but this is a safer way - * to do it for backwards compatibility. Max name length is 16 bytes. */ - prctl(PR_SET_NAME, "libkqueue_wait", 0, 0, 0); - + if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_ADD, kn->kdata.kn_procfd, EPOLL_EV_KN(EPOLLIN, kn)) < 0) { + dbg_printf("epoll_ctl(2): %s", strerror(errno)); + return -1; + } return (0); - -errout: - if (efd >= 0) - close(efd); - free(ed); - close(filt->kf_pfd); - return (-1); -#endif - return (-1); /*STUB*/ } -void -evfilt_proc_destroy(struct filter *filt) +int +evfilt_proc_knote_disable(struct filter *filt, struct knote *kn) { -//TODO: pthread_cancel(filt->kf_data->wthr_id); - close(filt->kf_pfd); + if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, kn->kdata.kn_procfd, NULL) < 0) { + dbg_printf("epoll_ctl(2): %s", strerror(errno)); + return (-1); + } + return (0); } int -evfilt_proc_copyout(struct filter *filt, - struct kevent *dst, - int maxevents) +evfilt_proc_knote_create(struct filter *filt, struct knote *kn) { - struct knote *kn; - int nevents = 0; - uint64_t cur; + int pfd; - /* Reset the counter */ - if (read(filt->kf_pfd, &cur, sizeof(cur)) < sizeof(cur)) { - dbg_printf("read(2): %s", strerror(errno)); - return (-1); + /* This mirrors the behaviour of kqueue if fflags doesn't specify any events */ + if (!(kn->kev.fflags & NOTE_EXIT)) { + dbg_printf("not monitoring pid=%u as no NOTE_* fflags set", (unsigned int)kn->kev.ident); + kn->kdata.kn_procfd = -1; + return 0; } - dbg_printf(" counter=%llu", (unsigned long long) cur); - - for (kn = knote_dequeue(filt); kn != NULL; kn = knote_dequeue(filt)) { - kevent_dump(&kn->kev); - memcpy(dst, &kn->kev, sizeof(*dst)); - if (kn->kev.flags & EV_DISPATCH) { - KNOTE_DISABLE(kn); - } - if (kn->kev.flags & EV_ONESHOT) { - knote_delete(filt, kn); - } else { - kn->kev.data = 0; //why?? - } + /* Returns an FD, which, when readable, indicates the process has exited */ + pfd = syscall(SYS_pidfd_open, (pid_t)kn->kev.ident, 0); + if (pfd < 0) { + dbg_printf("pidfd_open(2): %s", strerror(errno)); + return (-1); + } + dbg_printf("created pidfd=%i monitoring pid=%u", pfd, (unsigned int)kn->kev.ident); + kn->kdata.kn_procfd = pfd; - if (++nevents > maxevents) - break; - dst++; - } + /* + * These get added by default on macOS (and likely FreeBSD) + * which make sense considering a process exiting is an + * edge triggered event, not a level triggered one. + */ + kn->kev.flags |= EV_ONESHOT; + kn->kev.flags |= EV_CLEAR; - if (knote_events_pending(filt)) { - /* XXX-FIXME: If there are leftover events on the waitq, - re-arm the eventfd. list */ - abort(); - } + KN_UDATA(kn); /* populate this knote's kn_udata field */ - return (nevents); + return evfilt_proc_knote_enable(filt, kn); } int -evfilt_proc_knote_create(struct filter *filt, struct knote *kn) +evfilt_proc_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { - return (0); /* STUB */ -} + /* We don't need to make any changes to the pidfd, just record the new flags */ + kn->kev.flags = kev->flags; + kn->kev.fflags = kev->fflags; -int -evfilt_proc_knote_modify(struct filter *filt, struct knote *kn, - const struct kevent *kev) -{ - return (0); /* STUB */ + if (kn->kdata.kn_procfd < 0) return evfilt_proc_knote_create(filt, kn); + + return (0); } int evfilt_proc_knote_delete(struct filter *filt, struct knote *kn) { - return (0); /* STUB */ -} + int rv = 0; -int -evfilt_proc_knote_enable(struct filter *filt, struct knote *kn) -{ - return (0); /* STUB */ -} + /* If it's enabled, we need to remove the pidfd from epoll */ + if (KNOTE_ENABLED(kn) && (evfilt_proc_knote_disable(filt, kn) < 0)) rv = -1; -int -evfilt_proc_knote_disable(struct filter *filt, struct knote *kn) -{ - return (0); /* STUB */ + dbg_printf("closed pidfd=%i", kn->kdata.kn_procfd); + if (close(kn->kdata.kn_procfd) < 0) rv = -1; + kn->kdata.kn_procfd = -1; + + return (rv); } -const struct filter evfilt_proc_DEADWOOD = { - .kf_id = 0, //XXX-FIXME broken: EVFILT_PROC, +const struct filter evfilt_proc = { + .kf_id = EVFILT_PROC, .kf_copyout = evfilt_proc_copyout, .kn_create = evfilt_proc_knote_create, .kn_modify = evfilt_proc_knote_modify, @@ -244,3 +163,4 @@ const struct filter evfilt_proc_DEADWOOD = { .kn_enable = evfilt_proc_knote_enable, .kn_disable = evfilt_proc_knote_disable, }; +#endif diff --git a/vendor/libkqueue/test/CMakeLists.txt b/vendor/libkqueue/test/CMakeLists.txt index 968f361e4..601115b99 100644 --- a/vendor/libkqueue/test/CMakeLists.txt +++ b/vendor/libkqueue/test/CMakeLists.txt @@ -19,6 +19,7 @@ set(LIBKQUEUE_TEST_SOURCES kevent.c main.c read.c + proc.c test.c timer.c user.c diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 7444541b1..5345c248c 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -19,6 +19,19 @@ #include #endif +#if defined(__linux__) +#include +#endif + +/* + * We need a fairly late kernel (>= 5.3) to have + * pidfd available on Linux which is required for + * EVFILT_PROC to function. + */ +#if !defined(__linux__) || defined(SYS_pidfd_open) +#define DO_PROC_TEST 1 +#endif + #include "common.h" unsigned int @@ -324,7 +337,16 @@ usage(void) printf("usage: [-hn] [testclass ...]\n" " -h This message\n" " -n Number of iterations (default: 1)\n" - " testclass Tests suites to run: [kqueue socket signal timer vnode user]\n" + " testclass Tests suites to run: [" + "kqueue " + "socket " + "signal " +#ifdef DO_PROC_TEST + "proc " +#endif + "timer " + "vnode " + "user]\n" " All tests are run by default\n" "\n" ); @@ -342,7 +364,7 @@ main(int argc, char **argv) // XXX-FIXME -- BROKEN ON LINUX WHEN RUN IN A SEPARATE THREAD { "signal", 1, test_evfilt_signal }, #endif -#if FIXME +#ifdef DO_PROC_TEST { "proc", 1, test_evfilt_proc }, #endif { "timer", 1, test_evfilt_timer }, diff --git a/vendor/libkqueue/test/proc.c b/vendor/libkqueue/test/proc.c index 8c0a23f34..b91bd2671 100644 --- a/vendor/libkqueue/test/proc.c +++ b/vendor/libkqueue/test/proc.c @@ -18,7 +18,6 @@ static int sigusr1_caught = 0; static pid_t pid; -static int kqfd; static void sig_handler(int signum) @@ -31,9 +30,9 @@ test_kevent_proc_add(struct test_context *ctx) { struct kevent kev; - test_no_kevents(kqfd); - kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD, 0, 0, NULL); - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); + kevent_add(ctx->kqfd, &kev, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL); + test_no_kevents(ctx->kqfd); } static void @@ -41,18 +40,30 @@ test_kevent_proc_delete(struct test_context *ctx) { struct kevent kev; - test_no_kevents(kqfd); - kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_DELETE, 0, 0, NULL); + test_no_kevents(ctx->kqfd); + kevent_add(ctx->kqfd, &kev, pid, EVFILT_PROC, EV_DELETE, NOTE_EXIT, 0, NULL); if (kill(pid, SIGKILL) < 0) die("kill"); sleep(1); - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); } static void test_kevent_proc_get(struct test_context *ctx) { struct kevent kev, buf; + int fflags; + + /* + * macOS requires NOTE_EXITSTATUS to get the + * exit code of the process, FreeBSD always + * provides it. + */ +#ifdef __APPLE__ + fflags = NOTE_EXIT | NOTE_EXITSTATUS; +#else + fflags = NOTE_EXIT; +#endif /* Create a child that waits to be killed and then exits */ pid = fork(); @@ -63,16 +74,20 @@ test_kevent_proc_get(struct test_context *ctx) } printf(" -- child created (pid %d)\n", (int) pid); - test_no_kevents(kqfd); - kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD, 0, 0, NULL); + test_no_kevents(ctx->kqfd); + kevent_add(ctx->kqfd, &kev, pid, EVFILT_PROC, EV_ADD, fflags, 0, NULL); /* Cause the child to exit, then retrieve the event */ printf(" -- killing process %d\n", (int) pid); - if (kill(pid, SIGUSR1) < 0) + if (kill(pid, SIGKILL) < 0) die("kill"); - kevent_get(&buf, kqfd); + kevent_get(&buf, ctx->kqfd); + + kev.data = SIGKILL; /* What we expected the process exit code to be */ + kev.flags = EV_ADD | EV_ONESHOT | EV_CLEAR | EV_EOF; + kevent_cmp(&kev, &buf); - test_no_kevents(kqfd); + test_no_kevents(ctx->kqfd); } #ifdef TODO @@ -85,13 +100,13 @@ test_kevent_signal_disable(struct test_context *ctx) test_begin(test_id); EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("%s", test_id); /* Block SIGUSR1, then send it to ourselves */ sigset_t mask; sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); + sigaddset(&mask, SIGKILL); if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) die("sigprocmask"); if (kill(getpid(), SIGKILL) < 0) @@ -111,7 +126,7 @@ test_kevent_signal_enable(struct test_context *ctx) test_begin(test_id); EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("%s", test_id); /* Block SIGUSR1, then send it to ourselves */ @@ -129,11 +144,11 @@ test_kevent_signal_enable(struct test_context *ctx) #else kev.data = 2; // one extra time from test_kevent_signal_disable() #endif - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_cmp(&kev, kevent_get(ctx->kqfd)); /* Delete the watch */ kev.flags = EV_DELETE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("%s", test_id); success(); @@ -149,7 +164,7 @@ test_kevent_signal_del(struct test_context *ctx) /* Delete the kevent */ EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("%s", test_id); /* Block SIGUSR1, then send it to ourselves */ @@ -174,7 +189,7 @@ test_kevent_signal_oneshot(struct test_context *ctx) test_begin(test_id); EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) + if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("%s", test_id); /* Block SIGUSR1, then send it to ourselves */ @@ -188,7 +203,7 @@ test_kevent_signal_oneshot(struct test_context *ctx) kev.flags |= EV_CLEAR; kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); + kevent_cmp(&kev, kevent_get(ctx->kqfd)); /* Send another one and make sure we get no events */ if (kill(getpid(), SIGUSR1) < 0) From 8b7abec39b4265fd41bc338e5db24d05cf85fe08 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 19 Aug 2021 21:51:06 -0500 Subject: [PATCH 0827/1120] Bump version to 2.4.1 --- vendor/libkqueue/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 2d907e141..21f25f4a4 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -14,7 +14,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -set(PROJECT_VERSION 2.4.0) +set(PROJECT_VERSION 2.4.1) if(EXISTS "/etc/debian_version") cmake_minimum_required(VERSION 3.7.2) From 3c93a85e09e3c6166f8131c440668e602b8e8dd6 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 20 Aug 2021 12:40:39 -0500 Subject: [PATCH 0828/1120] Use C11 atomic operations instead of GCC intrinsics Use atomic loads where appropriate, and fix map_delete to use an atomic swap instead of a loop. Simplify kqueue_free by having it call map_remove instead of performing a lookup and then a delete. --- vendor/libkqueue/src/common/kevent.c | 2 +- vendor/libkqueue/src/common/kqueue.c | 20 ++++--------- vendor/libkqueue/src/common/map.c | 40 ++++++++----------------- vendor/libkqueue/src/common/private.h | 2 +- vendor/libkqueue/src/posix/platform.h | 19 ++++++++---- vendor/libkqueue/src/solaris/platform.h | 17 ++++++++--- vendor/libkqueue/src/windows/platform.h | 13 +++++--- 7 files changed, 56 insertions(+), 57 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index b6632848e..d79b00077 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -256,7 +256,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, struct kqueue *kq; int rv = 0; #ifndef NDEBUG - static unsigned int _kevent_counter = 0; + static atomic_uint _kevent_counter = 0; unsigned int myid = 0; (void) myid; diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index abc7c3c0c..11e836d68 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -120,27 +120,19 @@ libkqueue_init(void) #endif } -#if DEADWOOD -static int -kqueue_cmp(struct kqueue *a, struct kqueue *b) -{ - return memcmp(&a->kq_id, &b->kq_id, sizeof(int)); -} -#endif - -/* Must hold the kqtree_mtx when calling this */ void kqueue_free(struct kqueue *kq) { dbg_printf("kq=%p - freeing", kq); /* - * Ensure the current map entry points to - * this kqueue. We don't want to remove - * the entry for another kqueue. + * map_remove ensures the current map entry + * points to this kqueue. + * + * If it doesn't we leave it alone and just + * free the kq. */ - if (map_lookup(kqmap, kq->kq_id) == kq) - map_delete(kqmap, kq->kq_id); + map_remove(kqmap, kq->kq_id, kq); filter_unregister_all(kq); kqops.kqueue_free(kq); diff --git a/vendor/libkqueue/src/common/map.c b/vendor/libkqueue/src/common/map.c index ca8ebd961..4ac654989 100644 --- a/vendor/libkqueue/src/common/map.c +++ b/vendor/libkqueue/src/common/map.c @@ -18,7 +18,7 @@ struct map { size_t len; - void **data; + atomic_uintptr_t *data; }; struct map * @@ -30,7 +30,7 @@ map_new(size_t len) if (dst == NULL) return (NULL); #ifdef _WIN32 - dst->data = calloc(len, sizeof(void*)); + dst->data = calloc(len, len * sizeof(dst->data[0])); if(dst->data == NULL) { dbg_perror("calloc()"); free(dst); @@ -38,7 +38,7 @@ map_new(size_t len) } dst->len = len; #else - dst->data = mmap(NULL, len * sizeof(void *), PROT_READ | PROT_WRITE, + dst->data = mmap(NULL, len * sizeof(dst->data[0]), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_NORESERVE | MAP_ANON, -1, 0); if (dst->data == MAP_FAILED) { dbg_perror("mmap(2)"); @@ -57,12 +57,12 @@ map_insert(struct map *m, int idx, void *ptr) if (unlikely(idx < 0 || idx > (int)m->len)) return (-1); - if (atomic_ptr_cas(&(m->data[idx]), 0, ptr) == NULL) { + if (atomic_ptr_cas(&(m->data[idx]), NULL, ptr)) { dbg_printf("idx=%i - inserted ptr=%p into map", idx, ptr); return (0); } else { dbg_printf("idx=%i - tried to insert ptr=%p into a non-empty location (cur_ptr=%p)", - idx, ptr, m->data[idx]); + idx, ptr, (void *)m->data[idx]); return (-1); } } @@ -73,11 +73,11 @@ map_remove(struct map *m, int idx, void *ptr) if (unlikely(idx < 0 || idx > (int)m->len)) return (-1); - if (atomic_ptr_cas(&(m->data[idx]), ptr, 0) == NULL) { - dbg_printf("idx=%i - removed ptr=%p from map", idx, ptr); + if (atomic_ptr_cas(&(m->data[idx]), ptr, NULL)) { + dbg_printf("idx=%i - removed ptr=%p from map", idx, (void *)ptr); return (0); } else { - dbg_printf("idx=%i - removal failed, ptr=%p != cur_ptr=%p", idx, ptr, m->data[idx]); + dbg_printf("idx=%i - removal failed, ptr=%p != cur_ptr=%p", idx, ptr, (void *)m->data[idx]); return (-1); } } @@ -85,18 +85,15 @@ map_remove(struct map *m, int idx, void *ptr) int map_replace(struct map *m, int idx, void *oldp, void *newp) { - void *tmp; - if (unlikely(idx < 0 || idx > (int)m->len)) return (-1); - tmp = atomic_ptr_cas(&(m->data[idx]), oldp, newp); - if (tmp == oldp) { - dbg_printf("idx=%i - replaced item in map with ptr=%p", idx, newp); + if (atomic_ptr_cas(&(m->data[idx]), oldp, newp)) { + dbg_printf("idx=%i - replaced item in map with ptr=%p", idx, (void *)newp); return (0); } else { - dbg_printf("idx=%i - replace failed, ptr=%p != cur_ptr=%p", idx, newp, m->data[idx]); + dbg_printf("idx=%i - replace failed, ptr=%p != cur_ptr=%p", idx, newp, (void *)m->data[idx]); return (-1); } } @@ -107,25 +104,14 @@ map_lookup(struct map *m, int idx) if (unlikely(idx < 0 || idx > (int)m->len)) return (NULL); - return m->data[idx]; + return (void *)atomic_ptr_load(&m->data[idx]); } void * map_delete(struct map *m, int idx) { - void *oval; - void *nval; - if (unlikely(idx < 0 || idx > (int)m->len)) return ((void *)-1); - /* Hopefully we aren't racing with another thread, but you never know.. */ - do { - oval = m->data[idx]; - nval = atomic_ptr_cas(&(m->data[idx]), oval, NULL); - } while (nval != oval); - - m->data[idx] = NULL; - - return ((void *) oval); + return (void *)atomic_ptr_swap(&(m->data[idx]), NULL); } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 7f4e4e7e6..93876d492 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -111,7 +111,7 @@ struct knote { } data; struct kqueue *kn_kq; //!< kqueue this knote is associated with. - volatile uint32_t kn_ref; + atomic_uint kn_ref; #if defined(KNOTE_PLATFORM_SPECIFIC) KNOTE_PLATFORM_SPECIFIC; #endif diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 37e129d56..890675e8e 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -17,23 +17,30 @@ #ifndef _KQUEUE_POSIX_PLATFORM_H #define _KQUEUE_POSIX_PLATFORM_H +#include + /* Required by glibc for MAP_ANON */ #define __USE_MISC 1 #include "../../include/sys/event.h" /* - * GCC-compatible atomic operations + * C11 atomic operations */ -#define atomic_inc(p) __sync_add_and_fetch((p), 1) -#define atomic_dec(p) __sync_sub_and_fetch((p), 1) -#define atomic_cas(p, oval, nval) __sync_val_compare_and_swap(p, oval, nval) -#define atomic_ptr_cas(p, oval, nval) __sync_val_compare_and_swap(p, oval, nval) +#define atomic_inc(p) (atomic_fetch_add((p), 1) + 1) +#define atomic_dec(p) (atomic_fetch_sub((p), 1) - 1) + +/* We use compound literals here to stop the 'expected' values from being overwritten */ +#define atomic_cas(p, oval, nval) atomic_compare_exchange_strong(p, &(__typeof__(oval)){ oval }, nval) +#define atomic_ptr_cas(p, oval, nval) atomic_compare_exchange_strong(p, (&(uintptr_t){ (uintptr_t)oval }), (uintptr_t)nval) +#define atomic_ptr_swap(p, nval) atomic_exchange(p, (uintptr_t)nval) +#define atomic_ptr_load(p) atomic_load(p) + /* * GCC-compatible branch prediction macros */ -#define likely(x) __builtin_expect((x), 1) +#define likely(x) __builtin_expect((x), 1) #define unlikely(x) __builtin_expect((x), 0) /* diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index 4afa85008..a00392bc9 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -23,14 +23,23 @@ * Atomic operations that override the ones in posix/platform.h */ #include + +#undef atomic_uintptr_t +#define atomic_uintptr_t uintptr_t +#undef atomic_unit +#define atomic_uint unsigned int #undef atomic_inc -#define atomic_inc atomic_inc_32_nv +#define atomic_inc atomic_inc_32_nv #undef atomic_dec -#define atomic_dec atomic_dec_32_nv +#define atomic_dec atomic_dec_32_nv #undef atomic_cas -#define atomic_cas atomic_cas_ptr +#define atomic_cas(p, oval, nval) (atomic_cas(p, oval, nval) == oval) #undef atomic_ptr_cas -#define atomic_ptr_cas atomic_cas_ptr +#define atomic_ptr_cas(p, oval, nval) (atomic_cas_ptr(p, oval, nval) == oval) +#undef atomic_ptr_swap +#define atomic_ptr_swap(p, nval) (atomic_swap_ptr(p, nval) +#undef atomic_ptr_load +#define atomic_ptr_load(p) (*p) /* * Event ports diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 6ab44c995..dfa9a8263 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -48,10 +48,15 @@ /* * Atomic integer operations */ -#define atomic_inc(value) InterlockedIncrement((LONG volatile *)value) -#define atomic_dec(value) InterlockedDecrement((LONG volatile *)value) -#define atomic_cas(p, oval, nval) InterlockedCompareExchange(p, nval, oval) -#define atomic_ptr_cas(p, oval, nval) InterlockedCompareExchangePointer(p, nval, oval) +#define atomic_uintptr_t uintptr_t +#define atomic_uint unsigned int +#define atomic_inc(value) InterlockedIncrement((LONG volatile *)value) +#define atomic_dec(value) InterlockedDecrement((LONG volatile *)value) +#define atomic_cas(p, oval, nval) (InterlockedCompareExchange(p, nval, oval) == oval) +#define atomic_ptr_cas(p, oval, nval) (InterlockedCompareExchangePointer(p, nval, oval) == oval) +#define atomic_ptr_swap(p, oval) InterlockedExchangePointer(p, nval) +#define atomic_ptr_load(p) (*p) + /* * Additional members of struct kqueue From 17c564c61b9ac8311582819a0ee056355e3c2169 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 20 Aug 2021 14:29:09 -0500 Subject: [PATCH 0829/1120] Move atomic macros outside of posix.h solaris undefines the existing macros anyway --- vendor/libkqueue/src/linux/platform.h | 14 ++++++++++++++ vendor/libkqueue/src/posix/platform.h | 15 --------------- vendor/libkqueue/src/solaris/platform.h | 8 -------- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 5d3f41d68..d92b60ccc 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -42,6 +42,20 @@ struct filter; # include #endif +#include + +/* + * C11 atomic operations + */ +#define atomic_inc(p) (atomic_fetch_add((p), 1) + 1) +#define atomic_dec(p) (atomic_fetch_sub((p), 1) - 1) + +/* We use compound literals here to stop the 'expected' values from being overwritten */ +#define atomic_cas(p, oval, nval) atomic_compare_exchange_strong(p, &(__typeof__(oval)){ oval }, nval) +#define atomic_ptr_cas(p, oval, nval) atomic_compare_exchange_strong(p, (&(uintptr_t){ (uintptr_t)oval }), (uintptr_t)nval) +#define atomic_ptr_swap(p, nval) atomic_exchange(p, (uintptr_t)nval) +#define atomic_ptr_load(p) atomic_load(p) + /* * Get the current thread ID */ diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 890675e8e..2b8acbf50 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -17,26 +17,11 @@ #ifndef _KQUEUE_POSIX_PLATFORM_H #define _KQUEUE_POSIX_PLATFORM_H -#include - /* Required by glibc for MAP_ANON */ #define __USE_MISC 1 #include "../../include/sys/event.h" -/* - * C11 atomic operations - */ -#define atomic_inc(p) (atomic_fetch_add((p), 1) + 1) -#define atomic_dec(p) (atomic_fetch_sub((p), 1) - 1) - -/* We use compound literals here to stop the 'expected' values from being overwritten */ -#define atomic_cas(p, oval, nval) atomic_compare_exchange_strong(p, &(__typeof__(oval)){ oval }, nval) -#define atomic_ptr_cas(p, oval, nval) atomic_compare_exchange_strong(p, (&(uintptr_t){ (uintptr_t)oval }), (uintptr_t)nval) -#define atomic_ptr_swap(p, nval) atomic_exchange(p, (uintptr_t)nval) -#define atomic_ptr_load(p) atomic_load(p) - - /* * GCC-compatible branch prediction macros */ diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index a00392bc9..ab056ac5b 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -24,21 +24,13 @@ */ #include -#undef atomic_uintptr_t #define atomic_uintptr_t uintptr_t -#undef atomic_unit #define atomic_uint unsigned int -#undef atomic_inc #define atomic_inc atomic_inc_32_nv -#undef atomic_dec #define atomic_dec atomic_dec_32_nv -#undef atomic_cas #define atomic_cas(p, oval, nval) (atomic_cas(p, oval, nval) == oval) -#undef atomic_ptr_cas #define atomic_ptr_cas(p, oval, nval) (atomic_cas_ptr(p, oval, nval) == oval) -#undef atomic_ptr_swap #define atomic_ptr_swap(p, nval) (atomic_swap_ptr(p, nval) -#undef atomic_ptr_load #define atomic_ptr_load(p) (*p) /* From 627a8abb2c56cfa7d8bad58b24f007b5a3b4b905 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 20 Aug 2021 14:33:24 -0500 Subject: [PATCH 0830/1120] Remove unneeded comment --- vendor/libkqueue/src/solaris/platform.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index ab056ac5b..ef64a7fe0 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -19,9 +19,6 @@ #include -/* - * Atomic operations that override the ones in posix/platform.h - */ #include #define atomic_uintptr_t uintptr_t From a2a5417ee08512d319f586e8c324e49a642b3710 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 20 Aug 2021 14:40:03 -0500 Subject: [PATCH 0831/1120] Move compiler macros to private.h (they're not platform specific) --- vendor/libkqueue/src/common/private.h | 26 ++++++++++++++++++++++++++ vendor/libkqueue/src/posix/platform.h | 18 ------------------ 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 93876d492..6f211fdb6 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -54,6 +54,32 @@ struct evfilt_data; */ #define NUM_ELEMENTS(_t) (sizeof((_t)) / sizeof(*(_t))) +#if defined(__clang__) || defined(__GNUC__) +/* + * Branch prediction macros + */ +#define likely(x) __builtin_expect((x), 1) +#define unlikely(x) __builtin_expect((x), 0) + +/* + * Compiler attributes + */ +#define VISIBLE __attribute__((visibility("default"))) +#define HIDDEN __attribute__((visibility("hidden"))) +#define UNUSED __attribute__((unused)) +#ifndef NDEBUG +#define UNUSED_NDEBUG __attribute__((unused)) +#else +#define UNUSED_NDEBUG +#endif +#else +#define likely(x) (x) +#define unlikely(x) (x) +#define VISIBLE +#define HIDDEN +#define UNUSED_NDEBUG +#endif + #include "debug.h" /* Workaround for Android */ diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 2b8acbf50..9b4b34d31 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -22,24 +22,6 @@ #include "../../include/sys/event.h" -/* - * GCC-compatible branch prediction macros - */ -#define likely(x) __builtin_expect((x), 1) -#define unlikely(x) __builtin_expect((x), 0) - -/* - * GCC-compatible attributes - */ -#define VISIBLE __attribute__((visibility("default"))) -#define HIDDEN __attribute__((visibility("hidden"))) -#define UNUSED __attribute__((unused)) -#ifndef NDEBUG -#define UNUSED_NDEBUG __attribute__((unused)) -#else -#define UNUSED_NDEBUG -#endif - #include #include #include From 536f1f844c27bd987a08199c33b3150f24f4dc1a Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 22 Aug 2021 15:57:29 -0500 Subject: [PATCH 0832/1120] Move kqueue tests out of main --- vendor/libkqueue/test/CMakeLists.txt | 1 + vendor/libkqueue/test/common.h | 2 +- vendor/libkqueue/test/kqueue.c | 235 +++++++++++++++++++++++++++ vendor/libkqueue/test/main.c | 212 ------------------------ 4 files changed, 237 insertions(+), 213 deletions(-) create mode 100644 vendor/libkqueue/test/kqueue.c diff --git a/vendor/libkqueue/test/CMakeLists.txt b/vendor/libkqueue/test/CMakeLists.txt index 601115b99..260caf310 100644 --- a/vendor/libkqueue/test/CMakeLists.txt +++ b/vendor/libkqueue/test/CMakeLists.txt @@ -17,6 +17,7 @@ project(libkqueue-test LANGUAGES C) set(LIBKQUEUE_TEST_SOURCES kevent.c + kqueue.c main.c read.c proc.c diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index dc61612e8..ce9079d2f 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -17,7 +17,6 @@ #ifndef _COMMON_H #define _COMMON_H - #if HAVE_ERR_H # include #else @@ -97,6 +96,7 @@ struct test_context { char testfile[1024]; }; +void test_kqueue(struct test_context *); void test_evfilt_read(struct test_context *); void test_evfilt_signal(struct test_context *); void test_evfilt_vnode(struct test_context *); diff --git a/vendor/libkqueue/test/kqueue.c b/vendor/libkqueue/test/kqueue.c new file mode 100644 index 000000000..f07e3bd07 --- /dev/null +++ b/vendor/libkqueue/test/kqueue.c @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2009 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "common.h" + +#if defined(__linux__) || defined(__FreeBSD__) +#include +#endif + +/* + * Test the method for detecting when one end of a socketpair + * has been closed. This technique is used in kqueue_validate() + */ +static void +test_peer_close_detection(void *unused) +{ +#ifdef _WIN32 + return; + //FIXME +#else + int sockfd[2]; + char buf[1]; + struct pollfd pfd; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) + die("socketpair"); + + pfd.fd = sockfd[0]; + pfd.events = POLLIN | POLLHUP; + pfd.revents = 0; + + if (poll(&pfd, 1, 0) > 0) + die("unexpected data"); + + if (close(sockfd[1]) < 0) + die("close"); + + if (poll(&pfd, 1, 0) > 0) { + if (recv(sockfd[0], buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT) != 0) + die("failed to detect peer shutdown"); + } + close(sockfd[0]); +#endif +} + +void +test_kqueue_alloc(void *unused) +{ + int kqfd; + + if ((kqfd = kqueue()) < 0) + die("kqueue()"); + test_no_kevents(kqfd); + if (close(kqfd) < 0) + die("close()"); +} + +void +test_kevent(void *unused) +{ + struct kevent kev; + + memset(&kev, 0, sizeof(kev)); + + /* Provide an invalid kqueue descriptor */ + if (kevent(-1, &kev, 1, NULL, 0, NULL) == 0) + die("invalid kq parameter"); +} + +#if defined(__linux__) +/* Maximum number of FD for current process */ +#define MAX_FDS 32 +/* + * Test the cleanup process for Linux + */ +void +test_cleanup(void *unused) +{ + int i; + int max_fds = MAX_FDS; + struct rlimit curr_rlim, rlim; + int kqfd1, kqfd2; + struct kevent kev; + + /* Remeber current FD limit */ + if (getrlimit(RLIMIT_NOFILE, &curr_rlim) < 0) { + die("getrlimit failed"); + } + + /* lower FD limit to 32 */ + if (max_fds < rlim.rlim_cur) { + /* Set FD limit to MAX_FDS */ + rlim = curr_rlim; + rlim.rlim_cur = 32; + if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) { + die("setrlimit failed"); + } + } else { + max_fds = rlim.rlim_cur; + } + + /* Create initial kqueue to avoid cleanup thread being destroyed on each close */ + if ((kqfd1 = kqueue()) < 0) + die("kqueue() - used_fds=%u max_fds=%u", print_fd_table(), max_fds); + + /* Create and close 2 * max fd number of kqueues */ + for (i=0; i < 2 * max_fds + 1; i++) { + if ((kqfd2 = kqueue()) < 0) + die("kqueue() - i=%i used_fds=%u max_fds=%u", i, print_fd_table(), max_fds); + + kevent_add(kqfd2, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000,NULL); + + if (close(kqfd2) < 0) + die("close()"); + } + + if (close(kqfd1) < 0) + die("close()"); + + /* + * Run same test again but without extra kqueue + * Cleanup thread will be destroyed + * Create and close 2 * max fd number of kqueues + */ + for (i=0; i < 2 * max_fds + 1; i++) { + if ((kqfd2 = kqueue()) < 0) + die("kqueue()"); + + kevent_add(kqfd2, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000,NULL); + + if (close(kqfd2) < 0) + die("close()"); + + nanosleep(&(struct timespec) { .tv_nsec = 25000000 }, NULL); /* deschedule thread */ + } + + /* Restore FD limit */ + if (setrlimit(RLIMIT_NOFILE, &curr_rlim) < 0) { + die("setrlimit failed"); + } +} +#endif + +void +test_ev_receipt(void *unused) +{ + int kq; + struct kevent kev; + + if ((kq = kqueue()) < 0) + die("kqueue()"); +#if !defined(_WIN32) + EV_SET(&kev, SIGUSR2, EVFILT_SIGNAL, EV_ADD | EV_RECEIPT, 0, 0, NULL); + if (kevent(kq, &kev, 1, &kev, 1, NULL) < 0) + die("kevent"); +#else + memset(&kev, 0, sizeof(kev)); + puts("Skipped -- EV_RECEIPT is not available or running on Win32"); +#endif + close(kq); +} + +/* Maximum number of threads that can be created */ +#define MAX_THREADS 100 + +/** + * Don't build the below function on OSX due to a known-issue + * breaking the build with FD_SET()/FD_ISSET() + OSX. + * e.g: https://www.google.com/search?q=___darwin_check_fd_set_overflow + */ +#ifndef __APPLE__ +void +test_kqueue_descriptor_is_pollable(void) +{ + int kq, rv; + struct kevent kev; + fd_set fds; + struct timeval tv; + + if ((kq = kqueue()) < 0) + die("kqueue()"); + + test_no_kevents(kq); + kevent_add(kq, &kev, 2, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 1000, NULL); + test_no_kevents(kq); + + FD_ZERO(&fds); + FD_SET(kq, &fds); + tv.tv_sec = 5; + tv.tv_usec = 0; + rv = select(1, &fds, NULL, NULL, &tv); + if (rv < 0) + die("select() error"); + if (rv == 0) + die("select() no events"); + if (!FD_ISSET(kq, &fds)) { + die("descriptor is not ready for reading"); + } + + close(kq); +} +#endif + +void +test_kqueue(struct test_context *ctx) +{ + test(peer_close_detection, ctx); + + test(kqueue_alloc, ctx); + test(kevent, ctx); + +#if defined(__linux__) + test(cleanup, ctx); +#endif + + test(ev_receipt, ctx); + /* TODO: this fails now, but would be good later + test(kqueue_descriptor_is_pollable); + */ +} + + diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 5345c248c..fd37c7494 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -78,218 +78,6 @@ print_fd_table(void) return used; } -/* Maximum number of threads that can be created */ -#define MAX_THREADS 100 - -/** - * Don't build the below function on OSX due to a known-issue - * breakking the build with FD_SET()/FD_ISSET() + OSX. - * e.g: https://www.google.com/search?q=___darwin_check_fd_set_overflow - */ -#ifndef __APPLE__ -void -test_kqueue_descriptor_is_pollable(void) -{ - int kq, rv; - struct kevent kev; - fd_set fds; - struct timeval tv; - - if ((kq = kqueue()) < 0) - die("kqueue()"); - - test_no_kevents(kq); - kevent_add(kq, &kev, 2, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 1000, NULL); - test_no_kevents(kq); - - FD_ZERO(&fds); - FD_SET(kq, &fds); - tv.tv_sec = 5; - tv.tv_usec = 0; - rv = select(1, &fds, NULL, NULL, &tv); - if (rv < 0) - die("select() error"); - if (rv == 0) - die("select() no events"); - if (!FD_ISSET(kq, &fds)) { - die("descriptor is not ready for reading"); - } - - close(kq); -} -#endif - -/* - * Test the method for detecting when one end of a socketpair - * has been closed. This technique is used in kqueue_validate() - */ -static void -test_peer_close_detection(void *unused) -{ -#ifdef _WIN32 - return; - //FIXME -#else - int sockfd[2]; - char buf[1]; - struct pollfd pfd; - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) - die("socketpair"); - - pfd.fd = sockfd[0]; - pfd.events = POLLIN | POLLHUP; - pfd.revents = 0; - - if (poll(&pfd, 1, 0) > 0) - die("unexpected data"); - - if (close(sockfd[1]) < 0) - die("close"); - - if (poll(&pfd, 1, 0) > 0) { - if (recv(sockfd[0], buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT) != 0) - die("failed to detect peer shutdown"); - } - close(sockfd[0]); -#endif -} - -void -test_kqueue_alloc(void *unused) -{ - int kqfd; - - if ((kqfd = kqueue()) < 0) - die("kqueue()"); - test_no_kevents(kqfd); - if (close(kqfd) < 0) - die("close()"); -} - -void -test_kevent(void *unused) -{ - struct kevent kev; - - memset(&kev, 0, sizeof(kev)); - - /* Provide an invalid kqueue descriptor */ - if (kevent(-1, &kev, 1, NULL, 0, NULL) == 0) - die("invalid kq parameter"); -} - -#if defined(__linux__) -/* Maximum number of FD for current process */ -#define MAX_FDS 32 -/* - * Test the cleanup process for Linux - */ -void -test_cleanup(void *unused) -{ - int i; - int max_fds = MAX_FDS; - struct rlimit curr_rlim, rlim; - int kqfd1, kqfd2; - struct kevent kev; - - /* Remeber current FD limit */ - if (getrlimit(RLIMIT_NOFILE, &curr_rlim) < 0) { - die("getrlimit failed"); - } - - /* lower FD limit to 32 */ - if (max_fds < rlim.rlim_cur) { - /* Set FD limit to MAX_FDS */ - rlim = curr_rlim; - rlim.rlim_cur = 32; - if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) { - die("setrlimit failed"); - } - } else { - max_fds = rlim.rlim_cur; - } - - /* Create initial kqueue to avoid cleanup thread being destroyed on each close */ - if ((kqfd1 = kqueue()) < 0) - die("kqueue() - used_fds=%u max_fds=%u", print_fd_table(), max_fds); - - /* Create and close 2 * max fd number of kqueues */ - for (i=0; i < 2 * max_fds + 1; i++) { - if ((kqfd2 = kqueue()) < 0) - die("kqueue() - i=%i used_fds=%u max_fds=%u", i, print_fd_table(), max_fds); - - kevent_add(kqfd2, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000,NULL); - - if (close(kqfd2) < 0) - die("close()"); - } - - if (close(kqfd1) < 0) - die("close()"); - - /* - * Run same test again but without extra kqueue - * Cleanup thread will be destroyed - * Create and close 2 * max fd number of kqueues - */ - for (i=0; i < 2 * max_fds + 1; i++) { - if ((kqfd2 = kqueue()) < 0) - die("kqueue()"); - - kevent_add(kqfd2, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000,NULL); - - if (close(kqfd2) < 0) - die("close()"); - - nanosleep(&(struct timespec) { .tv_nsec = 25000000 }, NULL); /* deschedule thread */ - } - - /* Restore FD limit */ - if (setrlimit(RLIMIT_NOFILE, &curr_rlim) < 0) { - die("setrlimit failed"); - } -} -#endif - -void -test_ev_receipt(void *unused) -{ - int kq; - struct kevent kev; - - if ((kq = kqueue()) < 0) - die("kqueue()"); -#if !defined(_WIN32) - EV_SET(&kev, SIGUSR2, EVFILT_SIGNAL, EV_ADD | EV_RECEIPT, 0, 0, NULL); - if (kevent(kq, &kev, 1, &kev, 1, NULL) < 0) - die("kevent"); -#else - memset(&kev, 0, sizeof(kev)); - puts("Skipped -- EV_RECEIPT is not available or running on Win32"); -#endif - close(kq); -} - -void -test_kqueue(struct test_context *ctx) -{ - test(peer_close_detection, ctx); - - test(kqueue_alloc, ctx); - test(kevent, ctx); - -#if defined(__linux__) - test(cleanup, ctx); -#endif - - test(ev_receipt, ctx); - /* TODO: this fails now, but would be good later - test(kqueue_descriptor_is_pollable); - */ -} - void run_iteration(struct test_context *ctx) { From 06b8daa47e2d545a14f40c2279685f28d9c18c1d Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 22 Aug 2021 15:58:04 -0500 Subject: [PATCH 0833/1120] Fix intermitent failure of test_kevent_socket_clear on macOS --- vendor/libkqueue/test/read.c | 48 ++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 62a81a948..a241bdd17 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -76,10 +76,17 @@ kevent_socket_drain(struct test_context *ctx) } static void -kevent_socket_fill(struct test_context *ctx) +kevent_socket_fill(struct test_context *ctx, size_t len) { - if (send(ctx->server_fd, ".", 1, 0) < 1) + uint8_t *data; + + data = malloc(len); + memset(data, '.', len); + + if (send(ctx->server_fd, data, len, 0) < 1) die("send(2)"); + + free(data); } @@ -101,7 +108,7 @@ test_kevent_socket_add_without_ev_add(struct test_context *ctx) if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) == 0) die("kevent should have failed"); - kevent_socket_fill(ctx); + kevent_socket_fill(ctx, 1); test_no_kevents(ctx->kqfd); kevent_socket_drain(ctx); @@ -120,7 +127,7 @@ test_kevent_socket_get(struct test_context *ctx) if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent:1"); - kevent_socket_fill(ctx); + kevent_socket_fill(ctx, 1); kev.data = 1; kevent_get(&ret, ctx->kqfd); @@ -146,8 +153,16 @@ test_kevent_socket_clear(struct test_context *ctx) if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent1"); - kevent_socket_fill(ctx); - kevent_socket_fill(ctx); + /* + * write two bytes in one call. + * This used to be two calls writing one byte, but macOS didn't + * always reliably report the amount of pending data correctly + * (1 byte instead of 2). + * + * Adding usleep(1000) on macOS also solved the issue, but this + * seemed like a cleaner fix. + */ + kevent_socket_fill(ctx, 2); /* Solaris does not offer a way to get the amount of data pending */ #if defined(__sun__) @@ -155,14 +170,15 @@ test_kevent_socket_clear(struct test_context *ctx) #else kev.data = 2; #endif - kevent_get(&ret, ctx->kqfd); + + kevent_get(&ret, ctx->kqfd); /* data is pending, so we should get an event */ kevent_cmp(&kev, &ret); /* We filled twice, but drain once. Edge-triggered would not generate additional events. */ - kevent_socket_drain(ctx); - test_no_kevents(ctx->kqfd); + kevent_socket_drain(ctx); /* drain one byte, data is still pending... */ + test_no_kevents(ctx->kqfd); /* ...but because this is edge triggered we should get no events */ kevent_socket_drain(ctx); EV_SET(&kev, ctx->client_fd, EVFILT_READ, EV_DELETE, 0, 0, &ctx->client_fd); @@ -183,7 +199,7 @@ test_kevent_socket_disable_and_enable(struct test_context *ctx) if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent"); - kevent_socket_fill(ctx); + kevent_socket_fill(ctx, 1); test_no_kevents(ctx->kqfd); /* Re-enable the knote, then see if an event is generated */ @@ -211,7 +227,7 @@ test_kevent_socket_del(struct test_context *ctx) if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) die("kevent"); - kevent_socket_fill(ctx); + kevent_socket_fill(ctx, 1); test_no_kevents(ctx->kqfd); kevent_socket_drain(ctx); } @@ -225,7 +241,7 @@ test_kevent_socket_oneshot(struct test_context *ctx) kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &ctx->client_fd); test_no_kevents(ctx->kqfd); - kevent_socket_fill(ctx); + kevent_socket_fill(ctx, 1); kev.data = 1; kevent_get(&ret, ctx->kqfd); kevent_cmp(&kev, &ret); @@ -233,7 +249,7 @@ test_kevent_socket_oneshot(struct test_context *ctx) test_no_kevents(ctx->kqfd); /* Verify that the kernel watch has been deleted */ - kevent_socket_fill(ctx); + kevent_socket_fill(ctx, 1); test_no_kevents(ctx->kqfd); kevent_socket_drain(ctx); @@ -310,7 +326,7 @@ test_kevent_socket_dispatch(struct test_context *ctx) /* The event will occur only once, even though EV_CLEAR is not specified. */ - kevent_socket_fill(ctx); + kevent_socket_fill(ctx, 1); kev.data = 1; kevent_get(&ret, ctx->kqfd); kevent_cmp(&kev, &ret); @@ -348,11 +364,11 @@ test_kevent_socket_lowat(struct test_context *ctx) test_no_kevents(); puts("-- checking that one byte does not trigger an event.."); - kevent_socket_fill(ctx); + kevent_socket_fill(ctx, 1); test_no_kevents(); puts("-- checking that two bytes triggers an event.."); - kevent_socket_fill(ctx); + kevent_socket_fill(ctx, 1); if (kevent(ctx->kqfd, NULL, 0, &kev, 1, NULL) != 1) die("%s", test_id); KEV_CMP(kev, ctx->client_fd, EVFILT_READ, 0); From 309a530b2483c5bfae8b3de08a2c9eb8b458957f Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 22 Aug 2021 16:04:30 -0500 Subject: [PATCH 0834/1120] Print the filter name for failing tests --- vendor/libkqueue/test/common.h | 5 +++++ vendor/libkqueue/test/kevent.c | 39 ++++++++++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index ce9079d2f..a0f205497 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -70,6 +70,11 @@ # include "src/windows/platform.h" #endif +/** Convenience macros + * + */ +#define NUM_ELEMENTS(_t) (sizeof((_t)) / sizeof(*(_t))) + struct test_context; struct unit_test { diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index 879edc967..a50ef5e66 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -86,6 +86,41 @@ kevent_get_hires(struct kevent *kev, int kqfd, struct timespec *ts) die("kevent(2)"); } +static const char * +filter_name(short filt) +{ + int id; + const char *fname[EVFILT_SYSCOUNT] = { + "EVFILT_READ", + "EVFILT_WRITE", + "EVFILT_AIO", + "EVFILT_VNODE", + "EVFILT_PROC", + "EVFILT_SIGNAL", + "EVFILT_TIMER", + "EVFILT_NETDEV", + "EVFILT_FS", + "EVFILT_LIO", + "EVFILT_USER" + }; + + id = ~filt; + if (id < 0 || id >= NUM_ELEMENTS(fname)) + return "EVFILT_INVALID"; + else + return fname[id]; +} + +static const char * +kevent_filter_dump(const struct kevent *kev) +{ + static __thread char buf[64]; + + snprintf(buf, sizeof(buf), "%d (%s)", + kev->filter, filter_name(kev->filter)); + return ((const char *) buf); +} + char * kevent_fflags_dump(struct kevent *kev) { @@ -183,9 +218,9 @@ kevent_to_str(struct kevent *kev) static __thread char buf[512]; snprintf(buf, sizeof(buf), - "[ident=%d, filter=%d, %s, %s, data=%d, udata=%p]", + "[ident=%d, filter=%s, %s, %s, data=%d, udata=%p]", (u_int) kev->ident, - kev->filter, + kevent_filter_dump(kev), kevent_flags_dump(kev), kevent_fflags_dump(kev), (int) kev->data, From 85efd5b5357444a2e06bc0fdf1f5f488b98f456d Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 22 Aug 2021 16:29:09 -0500 Subject: [PATCH 0835/1120] Clear errno before every test --- vendor/libkqueue/test/common.h | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index a0f205497..ddb2f9e58 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -114,6 +114,7 @@ void test_evfilt_user(struct test_context *); #define test(f,ctx,...) do { \ assert(ctx != NULL); \ test_begin(ctx, "test_"#f"()\t"__VA_ARGS__); \ + errno = 0; \ test_##f(ctx); \ test_end(ctx); \ } while (/*CONSTCOND*/0) From e0697c1453ad76999cb619fe18ffeeabca1f89d4 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 22 Aug 2021 16:29:59 -0500 Subject: [PATCH 0836/1120] Work around issue with test_kevent_signal_dispatch on macOS --- vendor/libkqueue/test/signal.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/test/signal.c b/vendor/libkqueue/test/signal.c index f27e95194..ccab5fdc1 100644 --- a/vendor/libkqueue/test/signal.c +++ b/vendor/libkqueue/test/signal.c @@ -142,19 +142,30 @@ test_kevent_signal_dispatch(struct test_context *ctx) test_no_kevents(ctx->kqfd); - kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_CLEAR | EV_DISPATCH, 0, 0, NULL); + /* EV_CLEAR should be set internally */ + kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_DISPATCH, 0, 0, NULL); /* Get one event */ if (kill(getpid(), SIGUSR1) < 0) die("kill"); + kev.flags |= EV_CLEAR; kev.data = 1; kevent_get(&ret, ctx->kqfd); kevent_cmp(&kev, &ret); + /* + * On macOS 11.5.2 the signal generated below is still + * delivered when the filter is next re-enabled. + * + * It's not clear if this is expected behaviour or not. + * EV_DISPATCH isn't even mentioned in man kqueue... + */ +#ifndef __APPLE__ /* Confirm that the knote is disabled */ if (kill(getpid(), SIGUSR1) < 0) die("kill"); test_no_kevents(ctx->kqfd); +#endif /* Enable the knote and make sure no events are pending */ kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE | EV_DISPATCH, 0, 0, NULL); From d3b56e6804366ed209c233cdf428c6ab49c20daf Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 22 Aug 2021 16:32:50 -0500 Subject: [PATCH 0837/1120] Account for behaviour differences between platforms in test_kevent_vnode_note_write --- vendor/libkqueue/test/vnode.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/test/vnode.c b/vendor/libkqueue/test/vnode.c index 7fb6006b5..28420dd06 100644 --- a/vendor/libkqueue/test/vnode.c +++ b/vendor/libkqueue/test/vnode.c @@ -108,7 +108,14 @@ test_kevent_vnode_note_write(struct test_context *ctx) /* BSD kqueue adds NOTE_EXTEND even though it was not requested */ /* BSD kqueue removes EV_ENABLE */ kev.flags &= ~EV_ENABLE; // XXX-FIXME compatibility issue - kev.fflags |= NOTE_EXTEND; // XXX-FIXME compatibility issue + + /* + * macOS 11.5.2 does not add NOTE_EXTEND, BSD kqueue + * does, as does libkqueue. + */ +#ifndef __APPLE__ + kev.fflags |= NOTE_EXTEND; +#endif kevent_get(&ret, ctx->kqfd); kevent_cmp(&kev, &ret); } From a450d4fa3dfd87efeb3cc584d59ca6d85ee901df Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 22 Aug 2021 16:38:56 -0500 Subject: [PATCH 0838/1120] More macOS fixes for test_kevent_vnode_note_delete and test_kevent_vnode_note_write --- vendor/libkqueue/test/vnode.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/test/vnode.c b/vendor/libkqueue/test/vnode.c index 28420dd06..7f223be7d 100644 --- a/vendor/libkqueue/test/vnode.c +++ b/vendor/libkqueue/test/vnode.c @@ -93,6 +93,17 @@ test_kevent_vnode_note_delete(struct test_context *ctx) die("unlink"); kevent_get(&ret, ctx->kqfd); + + /* + * FIXME - macOS 11.5.2 also sets NOTE_LINK. + * This seems redundant, but behaviour should be + * checked on FreeBSD/OpenBSD to determine the + * correct behaviour for libkqueue. + */ +#ifdef __APPLE__ + kev.fflags |= NOTE_LINK; +#endif + kevent_cmp(&kev, &ret); } @@ -105,13 +116,9 @@ test_kevent_vnode_note_write(struct test_context *ctx) testfile_write(ctx->testfile); - /* BSD kqueue adds NOTE_EXTEND even though it was not requested */ - /* BSD kqueue removes EV_ENABLE */ - kev.flags &= ~EV_ENABLE; // XXX-FIXME compatibility issue - /* - * macOS 11.5.2 does not add NOTE_EXTEND, BSD kqueue - * does, as does libkqueue. + * macOS 11.5.2 does not add NOTE_EXTEND, + * BSD kqueue does, as does libkqueue. */ #ifndef __APPLE__ kev.fflags |= NOTE_EXTEND; From 2d305e9e8662b4a42783625e01484b939b7f98d5 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 22 Aug 2021 16:44:35 -0500 Subject: [PATCH 0839/1120] Fix filter name strings --- vendor/libkqueue/src/common/filter.c | 26 +++++++++++++++----------- vendor/libkqueue/test/kevent.c | 26 +++++++++++++++----------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index bc738e0cf..682ca4bb8 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -159,17 +159,21 @@ filter_name(short filt) { int id; const char *fname[EVFILT_SYSCOUNT] = { - "EVFILT_READ", - "EVFILT_WRITE", - "EVFILT_AIO", - "EVFILT_VNODE", - "EVFILT_PROC", - "EVFILT_SIGNAL", - "EVFILT_TIMER", - "EVFILT_NETDEV", - "EVFILT_FS", - "EVFILT_LIO", - "EVFILT_USER" + [~EVFILT_READ] = "EVFILT_READ", + [~EVFILT_WRITE] = "EVFILT_WRITE", + [~EVFILT_AIO] = "EVFILT_AIO", + [~EVFILT_VNODE] = "EVFILT_VNODE", + [~EVFILT_PROC] = "EVFILT_PROC", + [~EVFILT_SIGNAL] = "EVFILT_SIGNAL", + [~EVFILT_TIMER] = "EVFILT_TIMER", +#ifdef EVFILT_NETDEV + [~EVFILT_NETDEV] = "EVFILT_NETDEV", +#endif + [~EVFILT_FS] = "EVFILT_FS", +#ifdef EVFILT_LIO + [~EVFILT_LIO] = "EVFILT_LIO", +#endif + [~EVFILT_USER] = "EVFILT_USER" }; id = ~filt; diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index a50ef5e66..6cb81d0c8 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -91,17 +91,21 @@ filter_name(short filt) { int id; const char *fname[EVFILT_SYSCOUNT] = { - "EVFILT_READ", - "EVFILT_WRITE", - "EVFILT_AIO", - "EVFILT_VNODE", - "EVFILT_PROC", - "EVFILT_SIGNAL", - "EVFILT_TIMER", - "EVFILT_NETDEV", - "EVFILT_FS", - "EVFILT_LIO", - "EVFILT_USER" + [~EVFILT_READ] = "EVFILT_READ", + [~EVFILT_WRITE] = "EVFILT_WRITE", + [~EVFILT_AIO] = "EVFILT_AIO", + [~EVFILT_VNODE] = "EVFILT_VNODE", + [~EVFILT_PROC] = "EVFILT_PROC", + [~EVFILT_SIGNAL] = "EVFILT_SIGNAL", + [~EVFILT_TIMER] = "EVFILT_TIMER", +#ifdef EVFILT_NETDEV + [~EVFILT_NETDEV] = "EVFILT_NETDEV", +#endif + [~EVFILT_FS] = "EVFILT_FS", +#ifdef EVFILT_LIO + [~EVFILT_LIO] = "EVFILT_LIO", +#endif + [~EVFILT_USER] = "EVFILT_USER" }; id = ~filt; From fbdd0f4c45bc882d1793a63b03a693b54f8229a1 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 22 Aug 2021 21:31:33 -0500 Subject: [PATCH 0840/1120] Fix definition/call for commented out test --- vendor/libkqueue/test/kqueue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/test/kqueue.c b/vendor/libkqueue/test/kqueue.c index f07e3bd07..ec08fbbb4 100644 --- a/vendor/libkqueue/test/kqueue.c +++ b/vendor/libkqueue/test/kqueue.c @@ -183,7 +183,7 @@ test_ev_receipt(void *unused) */ #ifndef __APPLE__ void -test_kqueue_descriptor_is_pollable(void) +test_kqueue_descriptor_is_pollable(void *unused) { int kq, rv; struct kevent kev; @@ -228,7 +228,7 @@ test_kqueue(struct test_context *ctx) test(ev_receipt, ctx); /* TODO: this fails now, but would be good later - test(kqueue_descriptor_is_pollable); + test(kqueue_descriptor_is_pollable, ctx); */ } From 5aa43c656b0e25bba6ec1833e8653c6b5ed8f9b4 Mon Sep 17 00:00:00 2001 From: Fabio Scotoni <34964387+fscoto@users.noreply.github.com> Date: Thu, 2 May 2019 15:46:33 +0200 Subject: [PATCH 0841/1120] kqueue.2: NOTE_LOWAT is #undef'd --- vendor/libkqueue/kqueue.2 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/kqueue.2 b/vendor/libkqueue/kqueue.2 index 7be32b792..5dd957af5 100644 --- a/vendor/libkqueue/kqueue.2 +++ b/vendor/libkqueue/kqueue.2 @@ -266,11 +266,14 @@ subject to the value of the socket buffer. This may be overridden with a per-filter low water mark at the time the filter is added by setting the -NOTE_LOWAT +.Dv NOTE_LOWAT flag in .Va fflags , and specifying the new low water mark in .Va data . +.Sy This is not supported by libkqueue . +.Dv SO_RCVLOWAT +may be ignored on Linux. On return, .Va data contains the number of bytes of protocol data available to read. From 78bb89e75ac038474cb7af0bebf29451be3992d9 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 23 Aug 2021 14:07:16 -0500 Subject: [PATCH 0842/1120] A cleaner way of not runing the EV_RECEIPT test --- vendor/libkqueue/test/kqueue.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/test/kqueue.c b/vendor/libkqueue/test/kqueue.c index ec08fbbb4..bacce8cc9 100644 --- a/vendor/libkqueue/test/kqueue.c +++ b/vendor/libkqueue/test/kqueue.c @@ -154,6 +154,8 @@ test_cleanup(void *unused) } #endif +/* EV_RECEIPT is not available or running on Win32 */ +#if !defined(_WIN32) void test_ev_receipt(void *unused) { @@ -162,16 +164,12 @@ test_ev_receipt(void *unused) if ((kq = kqueue()) < 0) die("kqueue()"); -#if !defined(_WIN32) EV_SET(&kev, SIGUSR2, EVFILT_SIGNAL, EV_ADD | EV_RECEIPT, 0, 0, NULL); if (kevent(kq, &kev, 1, &kev, 1, NULL) < 0) die("kevent"); -#else - memset(&kev, 0, sizeof(kev)); - puts("Skipped -- EV_RECEIPT is not available or running on Win32"); -#endif close(kq); } +#endif /* Maximum number of threads that can be created */ #define MAX_THREADS 100 @@ -226,7 +224,9 @@ test_kqueue(struct test_context *ctx) test(cleanup, ctx); #endif +#if !defined(_WIN32) test(ev_receipt, ctx); +#endif /* TODO: this fails now, but would be good later test(kqueue_descriptor_is_pollable, ctx); */ From 03be3199914ff9c4c975c41534f641a64cdee288 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 23 Aug 2021 14:08:43 -0500 Subject: [PATCH 0843/1120] Add comparison function for testing return values from kqueue --- vendor/libkqueue/test/common.h | 5 ++++- vendor/libkqueue/test/kevent.c | 23 +++++++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index ddb2f9e58..50208e87c 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -126,7 +126,10 @@ int kevent_get_timeout(struct kevent *, int, struct timespec *); void kevent_update(int kqfd, struct kevent *kev); #define kevent_cmp(a,b) _kevent_cmp(a,b, __FILE__, __LINE__) -void _kevent_cmp(struct kevent *, struct kevent *, const char *, int); +void _kevent_cmp(struct kevent *expected, struct kevent *got, const char *file, int line); + +#define kevent_rv_cmp(a,b) _kevent_rv_cmp(a,b, __FILE__, __LINE__) +void _kevent_rv_cmp(int expected, int got, const char *file, int line); void kevent_add(int kqfd, struct kevent *kev, diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index 6cb81d0c8..281edd00b 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -261,19 +261,30 @@ kevent_add(int kqfd, struct kevent *kev, } void -_kevent_cmp(struct kevent *k1, struct kevent *k2, const char *file, int line) +_kevent_cmp(struct kevent *expected, struct kevent *got, const char *file, int line) { /* XXX- Workaround for inconsistent implementation of kevent(2) */ #if defined (__FreeBSD_kernel__) || defined (__FreeBSD__) - if (k1->flags & EV_ADD) - k2->flags |= EV_ADD; + if (expected->flags & EV_ADD) + got->flags |= EV_ADD; #endif - if (memcmp(k1, k2, sizeof(*k1)) != 0) { + if (memcmp(expected, got, sizeof(*expected)) != 0) { printf("[%s:%d]: kevent_cmp() failed:\n", file, line); - printf("expected %s\n", kevent_to_str(k1)); - printf("but got %s\n", kevent_to_str(k2)); + printf("expected %s\n", kevent_to_str(expected)); + printf("but got %s\n", kevent_to_str(got)); + abort(); + } +} + +void +_kevent_rv_cmp(int expected, int got, const char *file, int line) +{ + if (expected != got) { + printf("[%s:%d]: kevent_rv_cmp() failed:\n", file, line); + printf("expected %u\n", expected); + printf("but got %u\n", got); abort(); } } From 923f8d90dfd1a827682209ea74f0af07ff6f2625 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 23 Aug 2021 14:08:18 -0500 Subject: [PATCH 0844/1120] Return failed changelist entries (and EV_RECEIPT entries) in the event list closes mheily#108 closes mheily#109 Fix return code to indicate that there are changelist entries in the kevent list. Use pointers to represent current position in kevent list (reduces possibility of errors). Calculate nevents earlier so the correct number is passed into kevent_copyin. Have kevent_copyin set the EV_ERROR flags in the kevent it produces, and set errno to 0 if it added a kevent successfully. --- vendor/libkqueue/src/common/kevent.c | 92 +++++++++++++++++++--------- vendor/libkqueue/test/kqueue.c | 16 ++--- 2 files changed, 70 insertions(+), 38 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index d79b00077..422a66aa6 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -28,6 +28,8 @@ #include "private.h" +static struct kevent null_kev; /* null kevent for when we get passed a NULL eventlist */ + static const char * kevent_filter_dump(const struct kevent *kev) { @@ -216,36 +218,46 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) /** @return number of events added to the eventlist */ static int -kevent_copyin(struct kqueue *kq, const struct kevent *src, int nchanges, +kevent_copyin(struct kqueue *kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents) { - int status, nret; + int status; + struct kevent *el_p = eventlist, *el_end = el_p + nevents; dbg_printf("nchanges=%d nevents=%d", nchanges, nevents); - for (nret = 0; nchanges > 0; src++, nchanges--) { - - if (kevent_copyin_one(kq, src) < 0) { - dbg_printf("errno=%s",strerror(errno)); + for (struct kevent const *cl_p = changelist, *cl_end = cl_p + nchanges; + cl_p < cl_end; + cl_p++) { + if (kevent_copyin_one(kq, cl_p) < 0) { + dbg_printf("errno=%s", strerror(errno)); status = errno; - } else if (src->flags & EV_RECEIPT) { + } else if (cl_p->flags & EV_RECEIPT) { status = 0; } else { continue; } - if (nevents > 0) { - memcpy(eventlist, src, sizeof(*src)); - eventlist->data = status; - nevents--; - eventlist++; - nret++; - } else { + /* + * We're out of kevent entries, just return -1 and leave + * the errno set. This is... odd, because it means the + * caller won't have any idea which entries in the + * changelist were processed. But I guess the + * requirement here is for the caller to always provide + * a kevent array with >= entries as the changelist. + */ + if (el_p == el_end) return (-1); - } + + memcpy(el_p, cl_p, sizeof(*cl_p)); + el_p->flags |= EV_ERROR; /* This is set both on error and for EV_RECEIPT */ + el_p->data = status; + el_p++; + + errno = 0; /* Reset back to 0 if we recorded the error as a kevent */ } - return (nret); + return (el_p - eventlist); } int VISIBLE @@ -254,6 +266,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, const struct timespec *timeout) { struct kqueue *kq; + struct kevent *el_p, *el_end; int rv = 0; #ifndef NDEBUG static atomic_uint _kevent_counter = 0; @@ -262,6 +275,17 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, (void) myid; #endif + /* deal with ubsan "runtime error: applying zero offset to null pointer" */ + if (eventlist) { + if (nevents > MAX_KEVENT) + nevents = MAX_KEVENT; + + el_p = eventlist; + el_end = el_p + nevents; + } else { + eventlist = el_p = el_end = &null_kev; + } + /* Convert the descriptor into an object pointer */ kq = kqueue_lookup(kqfd); if (kq == NULL) { @@ -281,46 +305,54 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, */ if (nchanges > 0) { kqueue_lock(kq); - rv = kevent_copyin(kq, changelist, nchanges, eventlist, nevents); kqueue_unlock(kq); + rv = kevent_copyin(kq, changelist, nchanges, el_p, el_end - el_p); dbg_printf("(%u) kevent_copyin rv=%d", myid, rv); if (rv < 0) goto out; if (rv > 0) { - eventlist += rv; - nevents -= rv; + el_p += rv; /* EV_RECEIPT and EV_ERROR entries */ } } - rv = 0; - /* - * Wait for events and copy them to the eventlist + * If we have space remaining after processing + * the changelist, copy events out. */ - if (nevents > MAX_KEVENT) - nevents = MAX_KEVENT; - if (nevents > 0) { + if ((el_end - el_p) > 0) { rv = kqops.kevent_wait(kq, nevents, timeout); dbg_printf("kqops.kevent_wait rv=%i", rv); if (likely(rv > 0)) { kqueue_lock(kq); - rv = kqops.kevent_copyout(kq, rv, eventlist, nevents); + rv = kqops.kevent_copyout(kq, rv, el_p, el_end - el_p); kqueue_unlock(kq); + dbg_printf("(%u) kevent_copyout rv=%i", myid, rv); + if (rv >= 0) { + el_p += rv; /* Add events from copyin */ + rv += el_p - eventlist; /* recalculate rv to be the total events in the eventlist */ + } } else if (rv == 0) { /* Timeout reached */ + dbg_printf("(%u) kevent_wait timedout", myid); } else { dbg_printf("(%u) kevent_wait failed", myid); goto out; } + /* + * If we have no space, return how many kevents + * were added by copyin. + */ + } else { + rv = el_p - eventlist; } #ifndef NDEBUG - if (DEBUG_KQUEUE) { + if (DEBUG_KQUEUE && (rv > 0)) { int n; - dbg_printf("(%u) returning %d events", myid, rv); - for (n = 0; n < rv; n++) { - dbg_printf("(%u) eventlist[%d] = %s", myid, n, kevent_dump(&eventlist[n])); + dbg_printf("(%u) returning %zu events", myid, el_p - eventlist); + for (n = 0; n < el_p - eventlist; n++) { + dbg_printf("(%u) eventlist[%d] = %s", myid, n, kevent_dump(&eventlist[n])); } } #endif diff --git a/vendor/libkqueue/test/kqueue.c b/vendor/libkqueue/test/kqueue.c index bacce8cc9..8d7e5a55b 100644 --- a/vendor/libkqueue/test/kqueue.c +++ b/vendor/libkqueue/test/kqueue.c @@ -157,17 +157,17 @@ test_cleanup(void *unused) /* EV_RECEIPT is not available or running on Win32 */ #if !defined(_WIN32) void -test_ev_receipt(void *unused) +test_ev_receipt(struct test_context *ctx) { - int kq; struct kevent kev; + struct kevent buf; - if ((kq = kqueue()) < 0) - die("kqueue()"); - EV_SET(&kev, SIGUSR2, EVFILT_SIGNAL, EV_ADD | EV_RECEIPT, 0, 0, NULL); - if (kevent(kq, &kev, 1, &kev, 1, NULL) < 0) - die("kevent"); - close(kq); + EV_SET(&kev, SIGUSR2, EVFILT_SIGNAL, EV_ADD | EV_ERROR | EV_RECEIPT, 0, 0, NULL); + buf = kev; + + kevent_rv_cmp(1, kevent(ctx->kqfd, &kev, 1, &buf, 1, NULL)); + + kevent_cmp(&kev, &buf); } #endif From 7408d83beba751bd3bc6499692f9d232ed1791ba Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 23 Aug 2021 14:46:37 -0500 Subject: [PATCH 0845/1120] Fix potential ubsan complaints for changelist too --- vendor/libkqueue/src/common/kevent.c | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 422a66aa6..2222df186 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -285,6 +285,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, } else { eventlist = el_p = el_end = &null_kev; } + if (!changelist) changelist = &null_kev; /* Convert the descriptor into an object pointer */ kq = kqueue_lookup(kqfd); From e624ef0344722adba7cb39aac913c62ea6df88b2 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 23 Aug 2021 14:48:12 -0500 Subject: [PATCH 0846/1120] Mutex should probably wrap kevent_copyin call... --- vendor/libkqueue/src/common/kevent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 2222df186..cf0f274ee 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -306,8 +306,8 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, */ if (nchanges > 0) { kqueue_lock(kq); - kqueue_unlock(kq); rv = kevent_copyin(kq, changelist, nchanges, el_p, el_end - el_p); + kqueue_unlock(kq); dbg_printf("(%u) kevent_copyin rv=%d", myid, rv); if (rv < 0) goto out; From 19011540a2d8349defde42a7bc7b12230f97c129 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 23 Aug 2021 14:53:15 -0500 Subject: [PATCH 0847/1120] Update changelog --- vendor/libkqueue/ChangeLog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 50be3b92e..a4178de72 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -3,6 +3,11 @@ Unreleased Nothing here yet. + * Add support for monitoring process exit with EVFILT_PROC via pidfd for Linux >= 5.3 + + * Fix: Include errors (EV_ERROR), and changelist entries with EV_RECEIPT in eventlist. + (Reported by: orbitz) + 2021-08-14 v2.4.0 ------------------------------------------------------------------------ From 77e8d19da207d17d088c6df1fd0b24bea2960087 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 23 Aug 2021 18:33:33 -0500 Subject: [PATCH 0848/1120] Set the name of the correct thread... --- vendor/libkqueue/src/linux/platform.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index e9223c864..d21cd63a3 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -190,6 +190,11 @@ monitoring_thread_loop(void *arg) sigset_t monitoring_sig_set; + /* Set the thread's name to something descriptive so it shows up in gdb, + * etc. glibc >= 2.1.2 supports pthread_setname_np, but this is a safer way + * to do it for backwards compatibility. Max name length is 16 bytes. */ + prctl(PR_SET_NAME, "libkqueue_mon", 0, 0, 0); + nb_max_fd = get_fd_limit(); sigemptyset(&monitoring_sig_set); @@ -265,11 +270,6 @@ linux_kqueue_start_thread(void) dbg_perror("linux_kqueue_start_thread failure"); } - /* Set the thread's name to something descriptive so it shows up in gdb, - * etc. glibc >= 2.1.2 supports pthread_setname_np, but this is a safer way - * to do it for backwards compatibility. Max name length is 16 bytes. */ - prctl(PR_SET_NAME, "libkqueue_mon", 0, 0, 0); - /* Wait for thread creating to be done as we need monitoring_tid to be available */ pthread_cond_wait(&monitoring_thread_cond, &mt_mtx); /* unlocks mt_mtx allowing child to lock it */ pthread_mutex_unlock(&mt_mtx); From 96c71094a495bd8fc0c019acbfb304e4189e3496 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 23 Aug 2021 18:36:18 -0500 Subject: [PATCH 0849/1120] Combine fcntl calls in linux_kqueue_init --- vendor/libkqueue/src/linux/platform.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index d21cd63a3..d65be4426 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -279,7 +279,6 @@ int linux_kqueue_init(struct kqueue *kq) { struct f_owner_ex sig_owner; - int flags; kq->epollfd = epoll_create(1); if (kq->epollfd < 0) { @@ -321,10 +320,13 @@ linux_kqueue_init(struct kqueue *kq) } /* - * Ensure pipe ends are non-blocking so that there's - * no chance of them delaying close(). + * O_NONBLOCK - Ensure pipe ends are non-blocking so that + * there's no chance of them delaying close(). + * + * O_ASYNC - Raise a SIGIO signal if the file descriptor + * becomes readable or is closed. */ - if ((fcntl(kq->pipefd[0], F_SETFL, O_NONBLOCK) < 0) || + if ((fcntl(kq->pipefd[0], F_SETFL, O_NONBLOCK | O_ASYNC ) < 0) || (fcntl(kq->pipefd[1], F_SETFL, O_NONBLOCK) < 0)) { dbg_perror("fcntl(2)"); goto error; @@ -332,17 +334,6 @@ linux_kqueue_init(struct kqueue *kq) kq->kq_id = kq->pipefd[1]; - /* - * Setting O_ASYNC means a signal (SIGIO) will be sent - * whenever I/O is possible OR when the other end of the - * pipe has been closed. - */ - flags = fcntl(kq->pipefd[0], F_GETFL, 0); - if (fcntl(kq->pipefd[0], F_SETFL, flags | O_ASYNC) < 0) { - dbg_printf("fd=%i - failed setting FSETFL O_ASYNC (%i): %s", kq->pipefd[0], flags, strerror(errno)); - goto error; - } - /* * SIGIO may be used by the application, so we use F_SETSIG * to change the signal sent to one in the realtime range From d0e1d0cd9075cdb1593da0cb185a819e69c819b0 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 24 Aug 2021 08:33:14 -0500 Subject: [PATCH 0850/1120] Document known and unfixable issues with libkqueue (userland) Closes #99 --- vendor/libkqueue/BUGS | 56 --------------------------- vendor/libkqueue/BUGS.md | 83 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 56 deletions(-) delete mode 100644 vendor/libkqueue/BUGS create mode 100644 vendor/libkqueue/BUGS.md diff --git a/vendor/libkqueue/BUGS b/vendor/libkqueue/BUGS deleted file mode 100644 index 8ce69d193..000000000 --- a/vendor/libkqueue/BUGS +++ /dev/null @@ -1,56 +0,0 @@ - * On Windows, you need to supply -DMAKE_STATIC in CFLAGS when building the - static library. This does not apply when using cmake. - - * When passing a knote pointer to the kernel, the reference count of - the knote structure should be incremented. Conversely, when the pointer - has been returned from the kernel and the event unregistered from the - kernel, the reference count should be decremented. - - * Some functions should crash instead of silently printing a debug - message.. for example, knote_release(). - - * knote_get_by_ident uses 'short' for the ident, but the actual datatype - is 'uintptr_t'. - - * need to uninitialize library after fork() using pthread_atfork() - - * Solaris unit test failure. - - LD_LIBRARY_PATH="..:/usr/sfw/lib/64" ./kqtest - 1: test_peer_close_detection() - 2: test_kqueue() - 3: test_kevent_socket_add() - 4: test_kevent_socket_del() - 5: test_kevent_socket_add_without_ev_add() - 6: test_kevent_socket_get() - - [read.c:84]: Unexpected event:_test_no_kevents(): [ident=7, filter=-1, flags = 1 (EV_ADD), fflags = 0, data=0, udata=fffffd7fff08c6b4]: Error 0 - - - * There are a number of stub functions that silently fail or succeed. - These need to be cleaned up; at a minimum, they should emit very loud - debugging output saying "FIXME -- UNIMPLEMENTED". - - $ grep STUB src/*/*.c - src/linux/proc.c: return (-1); /*STUB*/ - src/linux/proc.c: return (0); /* STUB */ - src/linux/proc.c: return (0); /* STUB */ - src/linux/proc.c: return (0); /* STUB */ - src/linux/proc.c: return (0); /* STUB */ - src/linux/proc.c: return (0); /* STUB */ - src/linux/read.c: return (-1); /* STUB */ - src/linux/timer.c: return (0); /* STUB */ - src/linux/vnode.c: return (-1); /* FIXME - STUB */ - src/linux/write.c: return (-1); /* STUB */ - src/posix/timer.c: return (-1); /* STUB */ - src/solaris/socket.c: return (-1); /* STUB */ - src/solaris/timer.c: return (-1); /* STUB */ - src/windows/read.c: return (-1); /* STUB */ - src/windows/timer.c: return (0); /* STUB */ - - * kqueue() should defer thread cancellation until the end. - - * kevent() should defer thread cancellation and call pthread_testcancel() - before and after the call to kevent_wait(). This may require changing the - way that EINTR is handled, to make sure that the EINTR is propagated up - the call stack to kevent(). diff --git a/vendor/libkqueue/BUGS.md b/vendor/libkqueue/BUGS.md new file mode 100644 index 000000000..e39ba3f9c --- /dev/null +++ b/vendor/libkqueue/BUGS.md @@ -0,0 +1,83 @@ + # libkqueue (userland) + + This documents the current behavioural differences or defficiencies of + libkqueue vs the native BSD kqueue implementations. + + ## Common + + * We need to uninitialize library after `fork()` `using pthread_atfork()`. + BSD kqueue file descriptors are not inherited by the fork copy and + will be closed automatically in the fork. With libkqueue, because + we don't unitialize the library, kqueue file descriptors will persist + in the fork. + + * Some functions should crash instead of silently printing a debug + message.. for example, knote_release(). + + * There are a number of stub functions that silently fail or succeed. + These need to be cleaned up; at a minimum, they should emit very loud + debugging output saying "FIXME -- UNIMPLEMENTED". + ``` + $ grep STUB src/*/*.c + src/linux/read.c: return (-1); /* STUB */ + src/linux/timer.c: return (0); /* STUB */ + src/linux/vnode.c: return (-1); /* FIXME - STUB */ + src/linux/write.c: return (-1); /* STUB */ + src/posix/timer.c: return (-1); /* STUB */ + src/solaris/socket.c: return (-1); /* STUB */ + src/solaris/timer.c: return (-1); /* STUB */ + src/windows/read.c: return (-1); /* STUB */ + src/windows/timer.c: return (0); /* STUB */ + ``` + + * kqueue() should defer thread cancellation until the end. + + * kevent() should defer thread cancellation and call pthread_testcancel() + before and after the call to kevent_wait(). This may require changing the + way that EINTR is handled, to make sure that the EINTR is propagated up + the call stack to kevent(). + + ## Linux + + * If a file descriptor outside of kqueue is closed, the internal kqueue + state is not cleaned up. On Linux this is pretty much impossible to + fix as there's no mechanism to retrieve file descriptor reference + counts, and no way to be notified of when a file descriptor is closed. + Applications should ensure that file descriptors are removed from + the kqueue before they are closed. + + ## Solaris + + * Solaris unit test failure. + ``` + LD_LIBRARY_PATH="..:/usr/sfw/lib/64" ./kqtest + 1: test_peer_close_detection() + 2: test_kqueue() + 3: test_kevent_socket_add() + 4: test_kevent_socket_del() + 5: test_kevent_socket_add_without_ev_add() + 6: test_kevent_socket_get() + + [read.c:84]: Unexpected event:_test_no_kevents(): [ident=7, filter=-1, flags = 1 (EV_ADD), fflags = 0, data=0, udata=fffffd7fff08c6b4]: Error 0 + ``` + * If a file descriptor outside of kqueue is closed, the internal kqueue + state is not cleaned up. + Applications should ensure that file descriptors are removed from + the kqueue before they are closed. + + ## Windows + + * On Windows, you need to supply -DMAKE_STATIC in CFLAGS when building the + static library. This does not apply when using cmake. + + * If a file descriptor outside of kqueue is closed, the internal kqueue + state is not cleaned up. + Applications should ensure that file descriptors are removed from + the kqueue before they are closed. + +# libkqueue (kernel) + + * When passing a knote pointer to the kernel, the reference count of + the knote structure should be incremented. Conversely, when the pointer + has been returned from the kernel and the event unregistered from the + kernel, the reference count should be decremented. From 56ed47776476f7e9d5f28cd441bfc0785b1556e4 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 24 Aug 2021 08:35:35 -0500 Subject: [PATCH 0851/1120] Add a link to bugs --- vendor/libkqueue/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index d3b7a54be..19f461017 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -7,6 +7,10 @@ A user space implementation of the kqueue(2) kernel event notification mechanism libkqueue acts as a translator between the kevent structure and the native kernel facilities on Linux, Android, Solaris, and Windows. +libkqueue is not perfect, and you may need to change the behaviour of your application +to work around limitations on a given platform. Please see [BUGS](bugs.md) for known +behavioural differences between libkqueue and BSD kqueues. + Supported Event Types --------------------- From 1d73cb44a81802134bc133ffcbcc786111fd5bcb Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 24 Aug 2021 08:36:05 -0500 Subject: [PATCH 0852/1120] Linking is case sensitive... --- vendor/libkqueue/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index 19f461017..0ac51363a 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -8,7 +8,7 @@ libkqueue acts as a translator between the kevent structure and the native kernel facilities on Linux, Android, Solaris, and Windows. libkqueue is not perfect, and you may need to change the behaviour of your application -to work around limitations on a given platform. Please see [BUGS](bugs.md) for known +to work around limitations on a given platform. Please see [BUGS](BUGS.md) for known behavioural differences between libkqueue and BSD kqueues. Supported Event Types From 9c54b5f18495adb4e056160a03681c883096cc64 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 24 Aug 2021 08:37:15 -0500 Subject: [PATCH 0853/1120] Minor formatting --- vendor/libkqueue/BUGS.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/BUGS.md b/vendor/libkqueue/BUGS.md index e39ba3f9c..9f33f9e86 100644 --- a/vendor/libkqueue/BUGS.md +++ b/vendor/libkqueue/BUGS.md @@ -12,7 +12,7 @@ in the fork. * Some functions should crash instead of silently printing a debug - message.. for example, knote_release(). + message.. for example, `note_release()`. * There are a number of stub functions that silently fail or succeed. These need to be cleaned up; at a minimum, they should emit very loud @@ -30,12 +30,12 @@ src/windows/timer.c: return (0); /* STUB */ ``` - * kqueue() should defer thread cancellation until the end. + * `kqueue()` should defer thread cancellation until the end. - * kevent() should defer thread cancellation and call pthread_testcancel() - before and after the call to kevent_wait(). This may require changing the - way that EINTR is handled, to make sure that the EINTR is propagated up - the call stack to kevent(). + * `kevent()` should defer thread cancellation and call `pthread_testcancel()` + before and after the call to `kevent_wait()`. This may require changing the + way that `EINTR` is handled, to make sure that the `EINTR` is propagated up + the call stack to `kevent()`. ## Linux @@ -67,7 +67,7 @@ ## Windows - * On Windows, you need to supply -DMAKE_STATIC in CFLAGS when building the + * On Windows, you need to supply `-DMAKE_STATIC` in `CFLAGS` when building the static library. This does not apply when using cmake. * If a file descriptor outside of kqueue is closed, the internal kqueue From 6a5c7026cbf6c16658ceea607bc8f90ff8471125 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 26 Aug 2021 12:45:45 -0500 Subject: [PATCH 0854/1120] Unset variables which are used as arguments DT_NEEDED entries in libkqueue.so caused linking order issues as apparently ASAN wasn't linked early enough in our application... but we never told the linker to link to libasan... Figuring out _why_ libkqueue.so was linked against ASAN when again we hadn't requested it pointed the finger at cmake's caching. Why cmake doesn't have a way of defining arguments, or special cache behaviour for externally defined variables I don't know. At first I thought I was missing some unique build paradigm cmake alone was a member of. Now I just think it's oversite or incompetence. --- vendor/libkqueue/CMakeLists.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 21f25f4a4..c62c2976c 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -59,6 +59,7 @@ if(ENABLE_ASAN) # set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer -fno-optimize-sibling-calls") list(APPEND DEBUG_FSANITIZERFLAGS "address") + MESSAGE("ENABLING ASAN") endif() # @@ -69,6 +70,7 @@ if(ENABLE_LSAN) # -fsanitize=leak - Build with lsan support # list(APPEND DEBUG_FSANITIZERFLAGS "leak") + MESSAGE("ENABLING LSAN") endif() # @@ -82,6 +84,7 @@ if(ENABLE_UBSAN) set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-sanitize-recover=undefined -fno-omit-frame-pointer") set(CMAKE_LD_FLAGS_DEBUG "${CMAKE_LD_FLAGS_DEBUG} -fno-sanitize-recover=undefined") list(APPEND DEBUG_FSANITIZERFLAGS "undefined") + MESSAGE("ENABLING UBSAN") endif() # @@ -92,6 +95,7 @@ if(ENABLE_TSAN) # -fsanitize=thread - Build with tsan support # list(APPEND DEBUG_FSANITIZERFLAGS "thread") + MESSAGE("ENABLING TSAN") endif() if(DEBUG_FSANITIZERFLAGS) @@ -339,3 +343,17 @@ set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON) include(CPack) add_custom_target(tarball git archive -o "libkqueue-${PROJECT_VERSION}.tar.gz" --prefix "libkqueue-${PROJECT_VERSION}/" HEAD) + +# +# Ensure variables which represent arguments are not +# cached. This provides more of a sane interface where +# cmake will build with the arguments you last specified +# not all the arguments provided since the beginning of +# the lifetime of CMakeCache.txt. +# +unset(ENABLE_ASAN CACHE) +unset(ENABLE_LSAN CACHE) +unset(ENABLE_UBSAN CACHE) +unset(ENABLE_TSAN CACHE) +unset(ENABLE_TESTING CACHE) +unset(CMAKE_BUILD_TYPE CACHE) From a1872c7c93d52c5b7c61e45fdd065e59e099e881 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 26 Aug 2021 17:51:06 -0500 Subject: [PATCH 0855/1120] Not used if not building debug packages --- vendor/libkqueue/src/linux/proc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index 62e0666b5..47a7b9bfd 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -47,7 +47,9 @@ int evfilt_proc_copyout(struct kevent *dst, struct knote *src, UNUSED_NDEBUG void *ptr) { siginfo_t info; +#ifndef NDEBUG struct epoll_event * const ev = (struct epoll_event *) ptr; +#endif dbg_printf("epoll_ev=%s", epoll_event_dump(ev)); memcpy(dst, &src->kev, sizeof(*dst)); /* Populate flags from the src kevent */ From bd1bf481be651afd39ae8ef8bf8706f4bcd60238 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 26 Aug 2021 18:13:53 -0500 Subject: [PATCH 0856/1120] Correct return value --- vendor/libkqueue/src/common/kevent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index cf0f274ee..c0b8df555 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -330,7 +330,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, dbg_printf("(%u) kevent_copyout rv=%i", myid, rv); if (rv >= 0) { el_p += rv; /* Add events from copyin */ - rv += el_p - eventlist; /* recalculate rv to be the total events in the eventlist */ + rv = el_p - eventlist; /* recalculate rv to be the total events in the eventlist */ } } else if (rv == 0) { /* Timeout reached */ From f732c884dd49f57e91feb26227a9aee99e70988d Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 26 Aug 2021 18:52:31 -0500 Subject: [PATCH 0857/1120] Deschedule thread during first test_cleanup iteration to try and encourage cleanup --- vendor/libkqueue/src/common/kevent.c | 2 +- vendor/libkqueue/test/kqueue.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index c0b8df555..2bce0a528 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -329,7 +329,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, kqueue_unlock(kq); dbg_printf("(%u) kevent_copyout rv=%i", myid, rv); if (rv >= 0) { - el_p += rv; /* Add events from copyin */ + el_p += rv; /* Add events from copyin */ rv = el_p - eventlist; /* recalculate rv to be the total events in the eventlist */ } } else if (rv == 0) { diff --git a/vendor/libkqueue/test/kqueue.c b/vendor/libkqueue/test/kqueue.c index 8d7e5a55b..3657763bd 100644 --- a/vendor/libkqueue/test/kqueue.c +++ b/vendor/libkqueue/test/kqueue.c @@ -121,10 +121,12 @@ test_cleanup(void *unused) if ((kqfd2 = kqueue()) < 0) die("kqueue() - i=%i used_fds=%u max_fds=%u", i, print_fd_table(), max_fds); - kevent_add(kqfd2, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000,NULL); + kevent_add(kqfd2, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL); if (close(kqfd2) < 0) die("close()"); + + nanosleep(&(struct timespec) { .tv_nsec = 25000000 }, NULL); /* deschedule thread */ } if (close(kqfd1) < 0) @@ -139,7 +141,7 @@ test_cleanup(void *unused) if ((kqfd2 = kqueue()) < 0) die("kqueue()"); - kevent_add(kqfd2, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000,NULL); + kevent_add(kqfd2, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL); if (close(kqfd2) < 0) die("close()"); From a057ed67e4aa41482b292784616943ca38266fae Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 26 Aug 2021 19:24:12 -0500 Subject: [PATCH 0858/1120] Tighter checks on return codes in all tests --- vendor/libkqueue/test/common.h | 12 +---- vendor/libkqueue/test/kevent.c | 6 +-- vendor/libkqueue/test/proc.c | 27 +++++------ vendor/libkqueue/test/read.c | 82 +++++++++++++--------------------- vendor/libkqueue/test/signal.c | 15 +++---- vendor/libkqueue/test/timer.c | 14 +++--- vendor/libkqueue/test/user.c | 12 ++--- vendor/libkqueue/test/vnode.c | 26 +++-------- 8 files changed, 74 insertions(+), 120 deletions(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 50208e87c..44d1924b1 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -120,7 +120,7 @@ void test_evfilt_user(struct test_context *); } while (/*CONSTCOND*/0) extern const char * kevent_to_str(struct kevent *); -void kevent_get(struct kevent *, int); +void kevent_get(struct kevent *, int, int); void kevent_get_hires(struct kevent *, int, struct timespec *); int kevent_get_timeout(struct kevent *, int, struct timespec *); void kevent_update(int kqfd, struct kevent *kev); @@ -140,16 +140,6 @@ kevent_add(int kqfd, struct kevent *kev, intptr_t data, void *udata); -/* DEPRECATED: */ -#define KEV_CMP(kev,_ident,_filter,_flags) do { \ - if (kev.ident != (_ident) || \ - kev.filter != (_filter) || \ - kev.flags != (_flags)) \ - err(1, "kevent mismatch: got [%d,%d,%d] but expecting [%d,%d,%d]", \ - (int)_ident, (int)_filter, (int)_flags,\ - (int)kev.ident, kev.filter, kev.flags);\ -} while (0); - /* Checks if any events are pending, which is an error. */ #define test_no_kevents(a) _test_no_kevents(a, __FILE__, __LINE__) void _test_no_kevents(int, const char *, int); diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index 281edd00b..ba83f545c 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -38,7 +38,7 @@ _test_no_kevents(int kqfd, const char *file, int line) /* Retrieve a single kevent */ void -kevent_get(struct kevent *kev, int kqfd) +kevent_get(struct kevent *kev, int kqfd, int expect) { struct kevent buf; int nfds; @@ -46,9 +46,7 @@ kevent_get(struct kevent *kev, int kqfd) if (kev == NULL) kev = &buf; - nfds = kevent(kqfd, NULL, 0, kev, 1, NULL); - if (nfds < 1) - err(1, "kevent(2)"); + kevent_rv_cmp(expect, kevent(kqfd, NULL, 0, kev, 1, NULL)); } /** diff --git a/vendor/libkqueue/test/proc.c b/vendor/libkqueue/test/proc.c index b91bd2671..6965dc095 100644 --- a/vendor/libkqueue/test/proc.c +++ b/vendor/libkqueue/test/proc.c @@ -81,7 +81,7 @@ test_kevent_proc_get(struct test_context *ctx) printf(" -- killing process %d\n", (int) pid); if (kill(pid, SIGKILL) < 0) die("kill"); - kevent_get(&buf, ctx->kqfd); + kevent_get(&buf, ctx->kqfd, 1); kev.data = SIGKILL; /* What we expected the process exit code to be */ kev.flags = EV_ADD | EV_ONESHOT | EV_CLEAR | EV_EOF; @@ -100,8 +100,7 @@ test_kevent_signal_disable(struct test_context *ctx) test_begin(test_id); EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, NULL); - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("%s", test_id); + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); /* Block SIGUSR1, then send it to ourselves */ sigset_t mask; @@ -121,13 +120,12 @@ void test_kevent_signal_enable(struct test_context *ctx) { const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)"; - struct kevent kev; + struct kevent kev, buf; test_begin(test_id); EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL); - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("%s", test_id); + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); /* Block SIGUSR1, then send it to ourselves */ sigset_t mask; @@ -144,12 +142,12 @@ test_kevent_signal_enable(struct test_context *ctx) #else kev.data = 2; // one extra time from test_kevent_signal_disable() #endif - kevent_cmp(&kev, kevent_get(ctx->kqfd)); + kevent_get(&buf, ctx->kqfd, 1) + kevent_cmp(&kev, &buf); /* Delete the watch */ kev.flags = EV_DELETE; - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("%s", test_id); + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); success(); } @@ -164,8 +162,7 @@ test_kevent_signal_del(struct test_context *ctx) /* Delete the kevent */ EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL); - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("%s", test_id); + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); /* Block SIGUSR1, then send it to ourselves */ sigset_t mask; @@ -184,13 +181,12 @@ void test_kevent_signal_oneshot(struct test_context *ctx) { const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)"; - struct kevent kev; + struct kevent kev, buf; test_begin(test_id); EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL); - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("%s", test_id); + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); /* Block SIGUSR1, then send it to ourselves */ sigset_t mask; @@ -203,7 +199,8 @@ test_kevent_signal_oneshot(struct test_context *ctx) kev.flags |= EV_CLEAR; kev.data = 1; - kevent_cmp(&kev, kevent_get(ctx->kqfd)); + kevent_get(&buf, ctx->kqfd, 1) + kevent_cmp(&kev, &buf); /* Send another one and make sure we get no events */ if (kill(getpid(), SIGUSR1) < 0) diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index a241bdd17..0fa204444 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -105,8 +105,7 @@ test_kevent_socket_add_without_ev_add(struct test_context *ctx) /* Try to add a kevent without specifying EV_ADD */ EV_SET(&kev, ctx->client_fd, EVFILT_READ, 0, 0, 0, &ctx->client_fd); - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) == 0) - die("kevent should have failed"); + kevent_rv_cmp(-1, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); kevent_socket_fill(ctx, 1); test_no_kevents(ctx->kqfd); @@ -114,8 +113,7 @@ test_kevent_socket_add_without_ev_add(struct test_context *ctx) /* Try to delete a kevent which does not exist */ kev.flags = EV_DELETE; - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) == 0) - die("kevent should have failed"); + kevent_rv_cmp(-1, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); } void @@ -124,21 +122,19 @@ test_kevent_socket_get(struct test_context *ctx) struct kevent kev, ret; EV_SET(&kev, ctx->client_fd, EVFILT_READ, EV_ADD, 0, 0, &ctx->client_fd); - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("kevent:1"); + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); kevent_socket_fill(ctx, 1); kev.data = 1; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); kevent_socket_drain(ctx); test_no_kevents(ctx->kqfd); kev.flags = EV_DELETE; - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("kevent:2"); + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); } void @@ -150,8 +146,7 @@ test_kevent_socket_clear(struct test_context *ctx) kevent_socket_drain(ctx); EV_SET(&kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &ctx->client_fd); - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("kevent1"); + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); /* * write two bytes in one call. @@ -171,7 +166,7 @@ test_kevent_socket_clear(struct test_context *ctx) kev.data = 2; #endif - kevent_get(&ret, ctx->kqfd); /* data is pending, so we should get an event */ + kevent_get(&ret, ctx->kqfd, 1); /* data is pending, so we should get an event */ kevent_cmp(&kev, &ret); /* We filled twice, but drain once. Edge-triggered would not generate @@ -182,8 +177,7 @@ test_kevent_socket_clear(struct test_context *ctx) kevent_socket_drain(ctx); EV_SET(&kev, ctx->client_fd, EVFILT_READ, EV_DELETE, 0, 0, &ctx->client_fd); - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("kevent2"); + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); } void @@ -193,29 +187,26 @@ test_kevent_socket_disable_and_enable(struct test_context *ctx) /* Add an event, then disable it. */ EV_SET(&kev, ctx->client_fd, EVFILT_READ, EV_ADD, 0, 0, &ctx->client_fd); - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("kevent"); + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); + EV_SET(&kev, ctx->client_fd, EVFILT_READ, EV_DISABLE, 0, 0, &ctx->client_fd); - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("kevent"); + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); kevent_socket_fill(ctx, 1); test_no_kevents(ctx->kqfd); /* Re-enable the knote, then see if an event is generated */ kev.flags = EV_ENABLE; - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("kevent"); + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); kev.flags = EV_ADD; kev.data = 1; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); kevent_socket_drain(ctx); kev.flags = EV_DELETE; - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("kevent"); + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); } void @@ -224,9 +215,7 @@ test_kevent_socket_del(struct test_context *ctx) struct kevent kev; EV_SET(&kev, ctx->client_fd, EVFILT_READ, EV_DELETE, 0, 0, &ctx->client_fd); - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("kevent"); - + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); kevent_socket_fill(ctx, 1); test_no_kevents(ctx->kqfd); kevent_socket_drain(ctx); @@ -243,7 +232,7 @@ test_kevent_socket_oneshot(struct test_context *ctx) kevent_socket_fill(ctx, 1); kev.data = 1; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); test_no_kevents(ctx->kqfd); @@ -255,8 +244,7 @@ test_kevent_socket_oneshot(struct test_context *ctx) /* Verify that the kevent structure does not exist. */ kev.flags = EV_DELETE; - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) == 0) - die("kevent() should have failed"); + kevent_rv_cmp(-1, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); } /* @@ -306,7 +294,7 @@ test_kevent_socket_listen_backlog(struct test_context *ctx) /* Verify that data=1 */ kev.data = 1; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); test_no_kevents(ctx->kqfd); @@ -328,7 +316,7 @@ test_kevent_socket_dispatch(struct test_context *ctx) specified. */ kevent_socket_fill(ctx, 1); kev.data = 1; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); test_no_kevents(ctx->kqfd); @@ -337,7 +325,7 @@ test_kevent_socket_dispatch(struct test_context *ctx) kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ENABLE | EV_DISPATCH, 0, 0, &ctx->client_fd); kev.data = 1; kev.flags = EV_ADD | EV_DISPATCH; /* FIXME: may not be portable */ - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); test_no_kevents(ctx->kqfd); @@ -352,15 +340,14 @@ test_kevent_socket_dispatch(struct test_context *ctx) void test_kevent_socket_lowat(struct test_context *ctx) { - struct kevent kev; + struct kevent kev, buf; test_begin(test_id); /* Re-add the watch and make sure no events are pending */ puts("-- re-adding knote, setting low watermark to 2 bytes"); EV_SET(&kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &ctx->client_fd); - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("%s", test_id); + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); test_no_kevents(); puts("-- checking that one byte does not trigger an event.."); @@ -369,9 +356,8 @@ test_kevent_socket_lowat(struct test_context *ctx) puts("-- checking that two bytes triggers an event.."); kevent_socket_fill(ctx, 1); - if (kevent(ctx->kqfd, NULL, 0, &kev, 1, NULL) != 1) - die("%s", test_id); - KEV_CMP(kev, ctx->client_fd, EVFILT_READ, 0); + kevent_rv_cmp(1, kevent(ctx->kqfd, NULL, 0, &buf, 1, NULL)); + kevent_cmp(&kev, &buf); test_no_kevents(); kevent_socket_drain(ctx); @@ -394,7 +380,7 @@ test_kevent_socket_eof(struct test_context *ctx) die("close(2)"); kev.flags |= EV_EOF; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); /* Delete the watch */ @@ -414,10 +400,8 @@ test_kevent_regular_file(struct test_context *ctx) abort(); EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, &fd); - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("kevent"); - - kevent_get(&ret, ctx->kqfd); + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); + kevent_get(&ret, ctx->kqfd, 1); /* Set file position to EOF-1 */ ret.data--; @@ -428,7 +412,7 @@ test_kevent_regular_file(struct test_context *ctx) } /* Set file position to EOF */ - kevent_get(NULL, ctx->kqfd); + kevent_get(NULL, ctx->kqfd, 1); ret.data = curpos + 1; if ((curpos = lseek(fd, ret.data, SEEK_SET)) != ret.data) { printf("seek to %u failed with rv=%lu\n", @@ -439,8 +423,8 @@ test_kevent_regular_file(struct test_context *ctx) test_no_kevents(ctx->kqfd); kev.flags = EV_DELETE; - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("kevent"); + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); + close(fd); } @@ -460,12 +444,10 @@ test_transition_from_write_to_read(struct test_context *ctx) err(1, "socketpair"); EV_SET(&kev, sd[0], EVFILT_WRITE, EV_ADD, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1,"kevent"); + kevent_rv_cmp(0, kevent(kqfd, &kev, 1, NULL, 0, NULL)); EV_SET(&kev, sd[0], EVFILT_READ, EV_ADD, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1,"kevent"); + kevent_rv_cmp(0, kevent(kqfd, &kev, 1, NULL, 0, NULL)); close(sd[0]); close(sd[1]); diff --git a/vendor/libkqueue/test/signal.c b/vendor/libkqueue/test/signal.c index ccab5fdc1..dfde4fc07 100644 --- a/vendor/libkqueue/test/signal.c +++ b/vendor/libkqueue/test/signal.c @@ -36,7 +36,7 @@ test_kevent_signal_get(struct test_context *ctx) kev.flags |= EV_CLEAR; kev.data = 1; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); } @@ -69,13 +69,12 @@ test_kevent_signal_enable(struct test_context *ctx) #else kev.data = 2; // one extra time from test_kevent_signal_disable() #endif - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); /* Delete the watch */ kev.flags = EV_DELETE; - if (kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL) < 0) - die("kevent"); + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); } void @@ -105,7 +104,7 @@ test_kevent_signal_oneshot(struct test_context *ctx) kev.flags |= EV_CLEAR; kev.data = 1; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); /* Send another one and make sure we get no events */ @@ -128,7 +127,7 @@ test_kevent_signal_modify(struct test_context *ctx) kev.flags |= EV_CLEAR; kev.data = 1; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); test_kevent_signal_del(ctx); @@ -150,7 +149,7 @@ test_kevent_signal_dispatch(struct test_context *ctx) die("kill"); kev.flags |= EV_CLEAR; kev.data = 1; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); /* @@ -176,7 +175,7 @@ test_kevent_signal_dispatch(struct test_context *ctx) die("kill"); kev.flags = EV_ADD | EV_CLEAR | EV_DISPATCH; kev.data = 1; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); /* Remove the knote and ensure the event no longer fires */ diff --git a/vendor/libkqueue/test/timer.c b/vendor/libkqueue/test/timer.c index 24db7c0a2..eedf7df29 100644 --- a/vendor/libkqueue/test/timer.c +++ b/vendor/libkqueue/test/timer.c @@ -43,7 +43,7 @@ test_kevent_timer_get(struct test_context *ctx) kev.flags |= EV_CLEAR; kev.data = 1; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); kevent_add(ctx->kqfd, &kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); @@ -61,7 +61,7 @@ test_kevent_timer_oneshot(struct test_context *ctx) /* Retrieve the event */ kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT; kev.data = 1; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); /* Check if the event occurs again */ @@ -81,12 +81,12 @@ test_kevent_timer_periodic(struct test_context *ctx) /* Retrieve the event */ kev.flags = EV_ADD | EV_CLEAR; kev.data = 1; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); /* Check if the event occurs again */ sleep(1); - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); /* Delete the event */ @@ -113,7 +113,7 @@ test_kevent_timer_disable_and_enable(struct test_context *ctx) kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT; kev.data = 1; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); } @@ -130,7 +130,7 @@ test_kevent_timer_dispatch(struct test_context *ctx) /* Get one event */ kev.flags = EV_ADD | EV_CLEAR | EV_DISPATCH; kev.data = 1; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); /* Confirm that the knote is disabled */ @@ -145,7 +145,7 @@ test_kevent_timer_dispatch(struct test_context *ctx) sleep(1); kev.flags = EV_ADD | EV_CLEAR | EV_DISPATCH; kev.data = 1; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); /* Remove the knote and ensure the event no longer fires */ diff --git a/vendor/libkqueue/test/user.c b/vendor/libkqueue/test/user.c index 29e1bcd49..0e5eb83a0 100644 --- a/vendor/libkqueue/test/user.c +++ b/vendor/libkqueue/test/user.c @@ -42,7 +42,7 @@ test_kevent_user_get(struct test_context *ctx) kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; kev.flags = EV_CLEAR; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); test_no_kevents(ctx->kqfd); @@ -92,7 +92,7 @@ test_kevent_user_disable_and_enable(struct test_context *ctx) kev.flags = EV_CLEAR; kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); } @@ -109,7 +109,7 @@ test_kevent_user_oneshot(struct test_context *ctx) kev.flags = EV_ONESHOT; kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); test_no_kevents(ctx->kqfd); @@ -131,7 +131,7 @@ test_kevent_user_multi_trigger_merged(struct test_context *ctx) kev.flags = EV_CLEAR; kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); test_no_kevents(ctx->kqfd); @@ -153,7 +153,7 @@ test_kevent_user_dispatch(struct test_context *ctx) kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; kev.flags = EV_CLEAR; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); /* Confirm that the knote is disabled automatically */ @@ -169,7 +169,7 @@ test_kevent_user_dispatch(struct test_context *ctx) kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; kev.flags = EV_CLEAR; - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); test_no_kevents(ctx->kqfd); diff --git a/vendor/libkqueue/test/vnode.c b/vendor/libkqueue/test/vnode.c index 7f223be7d..4e7f7d43f 100644 --- a/vendor/libkqueue/test/vnode.c +++ b/vendor/libkqueue/test/vnode.c @@ -92,7 +92,7 @@ test_kevent_vnode_note_delete(struct test_context *ctx) if (unlink(ctx->testfile) < 0) die("unlink"); - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); /* * FIXME - macOS 11.5.2 also sets NOTE_LINK. @@ -123,7 +123,7 @@ test_kevent_vnode_note_write(struct test_context *ctx) #ifndef __APPLE__ kev.fflags |= NOTE_EXTEND; #endif - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); } @@ -131,15 +131,12 @@ void test_kevent_vnode_note_attrib(struct test_context *ctx) { struct kevent kev; - int nfds; kevent_add(ctx->kqfd, &kev, ctx->vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL); testfile_touch(ctx->testfile); - nfds = kevent(ctx->kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - die("kevent"); + kevent_rv_cmp(1, kevent(ctx->kqfd, NULL, 0, &kev, 1, NULL)); if (kev.ident != ctx->vnode_fd || kev.filter != EVFILT_VNODE || kev.fflags != NOTE_ATTRIB) @@ -151,15 +148,12 @@ void test_kevent_vnode_note_rename(struct test_context *ctx) { struct kevent kev; - int nfds; kevent_add(ctx->kqfd, &kev, ctx->vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_RENAME, 0, NULL); testfile_rename(ctx->testfile, 0); - nfds = kevent(ctx->kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - die("kevent"); + kevent_rv_cmp(1, kevent(ctx->kqfd, NULL, 0, &kev, 1, NULL)); if (kev.ident != ctx->vnode_fd || kev.filter != EVFILT_VNODE || kev.fflags != NOTE_RENAME) @@ -183,7 +177,6 @@ void test_kevent_vnode_disable_and_enable(struct test_context *ctx) { struct kevent kev; - int nfds; test_no_kevents(ctx->kqfd); @@ -200,9 +193,7 @@ test_kevent_vnode_disable_and_enable(struct test_context *ctx) kev.flags = EV_ENABLE; kevent_update(ctx->kqfd, &kev); testfile_touch(ctx->testfile); - nfds = kevent(ctx->kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - die("kevent"); + kevent_rv_cmp(1, kevent(ctx->kqfd, NULL, 0, &kev, 1, NULL)); if (kev.ident != ctx->vnode_fd || kev.filter != EVFILT_VNODE || kev.fflags != NOTE_ATTRIB) @@ -215,7 +206,6 @@ void test_kevent_vnode_dispatch(struct test_context *ctx) { struct kevent kev, ret; - int nfds; test_no_kevents(ctx->kqfd); @@ -223,9 +213,7 @@ test_kevent_vnode_dispatch(struct test_context *ctx) testfile_touch(ctx->testfile); - nfds = kevent(ctx->kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - die("kevent"); + kevent_rv_cmp(1, kevent(ctx->kqfd, NULL, 0, &kev, 1, NULL)); if (kev.ident != ctx->vnode_fd || kev.filter != EVFILT_VNODE || kev.fflags != NOTE_ATTRIB) @@ -242,7 +230,7 @@ test_kevent_vnode_dispatch(struct test_context *ctx) kev.flags = EV_ADD | EV_DISPATCH; /* FIXME: may not be portable */ kev.fflags = NOTE_ATTRIB; testfile_touch(ctx->testfile); - kevent_get(&ret, ctx->kqfd); + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); test_no_kevents(ctx->kqfd); From 39d9125a0682ebf4a2ff876e9b6f334ecf80e5af Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 27 Aug 2021 18:30:01 -0500 Subject: [PATCH 0859/1120] Use the correct macro to get the process exit status --- vendor/libkqueue/src/linux/proc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index 47a7b9bfd..53bb340df 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -47,7 +47,7 @@ int evfilt_proc_copyout(struct kevent *dst, struct knote *src, UNUSED_NDEBUG void *ptr) { siginfo_t info; -#ifndef NDEBUG +#ifndef NDEBUG struct epoll_event * const ev = (struct epoll_event *) ptr; #endif @@ -61,7 +61,7 @@ evfilt_proc_copyout(struct kevent *dst, struct knote *src, UNUSED_NDEBUG void *p } if (info.si_code == CLD_EXITED) { - dst->data = WIFEXITED(info.si_status); + dst->data = WEXITSTATUS(info.si_status); dbg_printf("pid=%u exited, status %u", (unsigned int)src->kev.ident, (unsigned int)dst->data); } else if (info.si_code == CLD_KILLED || info.si_code == CLD_DUMPED) { dst->data = WTERMSIG(info.si_status); From 8cd3b0559c0f974e10e7f7874ceb6bbfb94bb653 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 27 Aug 2021 18:56:00 -0500 Subject: [PATCH 0860/1120] We don't need to use WEXITSTATUS or WTERMSIG on si_status Add tests to catch the error this produced --- vendor/libkqueue/src/linux/proc.c | 5 +- vendor/libkqueue/test/common.h | 1 + vendor/libkqueue/test/proc.c | 84 ++++++++++++++++++++++++++++++- vendor/libkqueue/test/test.c | 10 +++- 4 files changed, 95 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index 53bb340df..93b4c8126 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -60,11 +60,12 @@ evfilt_proc_copyout(struct kevent *dst, struct knote *src, UNUSED_NDEBUG void *p return (-1); } + /* It appears we don't need to use the W* macros here */ if (info.si_code == CLD_EXITED) { - dst->data = WEXITSTATUS(info.si_status); + dst->data = info.si_status; dbg_printf("pid=%u exited, status %u", (unsigned int)src->kev.ident, (unsigned int)dst->data); } else if (info.si_code == CLD_KILLED || info.si_code == CLD_DUMPED) { - dst->data = WTERMSIG(info.si_status); + dst->data = info.si_status; dbg_printf("pid=%u killed, status %u", (unsigned int)src->kev.ident, (unsigned int)dst->data); } else { dst->data = 0; diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 44d1924b1..cde544417 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -153,6 +153,7 @@ void test_end(struct test_context *); void test_atexit(void); void testing_begin(void); void testing_end(void); +void testing_end_quiet(void); int testing_make_uid(void); #endif /* _COMMON_H */ diff --git a/vendor/libkqueue/test/proc.c b/vendor/libkqueue/test/proc.c index 6965dc095..5f7df31d5 100644 --- a/vendor/libkqueue/test/proc.c +++ b/vendor/libkqueue/test/proc.c @@ -70,7 +70,8 @@ test_kevent_proc_get(struct test_context *ctx) if (pid == 0) { pause(); printf(" -- child caught signal, exiting\n"); - exit(2); + testing_end_quiet(); + exit(0); } printf(" -- child created (pid %d)\n", (int) pid); @@ -90,6 +91,84 @@ test_kevent_proc_get(struct test_context *ctx) test_no_kevents(ctx->kqfd); } +static void +test_kevent_proc_exit_status_ok(struct test_context *ctx) +{ + struct kevent kev, buf; + int fflags; + + /* + * macOS requires NOTE_EXITSTATUS to get the + * exit code of the process, FreeBSD always + * provides it. + */ +#ifdef __APPLE__ + fflags = NOTE_EXIT | NOTE_EXITSTATUS; +#else + fflags = NOTE_EXIT; +#endif + + /* Create a child that waits to be killed and then exits */ + pid = fork(); + if (pid == 0) { + usleep(100000); + printf(" -- child done sleeping, exiting (0)\n"); + testing_end_quiet(); + exit(0); + } + printf(" -- child created (pid %d)\n", (int) pid); + + test_no_kevents(ctx->kqfd); + kevent_add(ctx->kqfd, &kev, pid, EVFILT_PROC, EV_ADD, fflags, 0, NULL); + + kevent_get(&buf, ctx->kqfd, 1); + + kev.data = 0; /* What we expected the process exit code to be */ + kev.flags = EV_ADD | EV_ONESHOT | EV_CLEAR | EV_EOF; + + kevent_cmp(&kev, &buf); + test_no_kevents(ctx->kqfd); +} + +static void +test_kevent_proc_exit_status_error(struct test_context *ctx) +{ + struct kevent kev, buf; + int fflags; + + /* + * macOS requires NOTE_EXITSTATUS to get the + * exit code of the process, FreeBSD always + * provides it. + */ +#ifdef __APPLE__ + fflags = NOTE_EXIT | NOTE_EXITSTATUS; +#else + fflags = NOTE_EXIT; +#endif + + /* Create a child that waits to be killed and then exits */ + pid = fork(); + if (pid == 0) { + usleep(100000); + printf(" -- child done sleeping, exiting (64)\n"); + testing_end_quiet(); + exit(64); + } + printf(" -- child created (pid %d)\n", (int) pid); + + test_no_kevents(ctx->kqfd); + kevent_add(ctx->kqfd, &kev, pid, EVFILT_PROC, EV_ADD, fflags, 0, NULL); + + kevent_get(&buf, ctx->kqfd, 1); + + kev.data = 64; /* What we expected the process exit code to be */ + kev.flags = EV_ADD | EV_ONESHOT | EV_CLEAR | EV_EOF; + + kevent_cmp(&kev, &buf); + test_no_kevents(ctx->kqfd); +} + #ifdef TODO void test_kevent_signal_disable(struct test_context *ctx) @@ -220,6 +299,7 @@ test_evfilt_proc(struct test_context *ctx) pid = fork(); if (pid == 0) { pause(); + testing_end_quiet(); exit(2); } printf(" -- child created (pid %d)\n", (int) pid); @@ -227,6 +307,8 @@ test_evfilt_proc(struct test_context *ctx) test(kevent_proc_add, ctx); test(kevent_proc_delete, ctx); test(kevent_proc_get, ctx); + test(kevent_proc_exit_status_ok, ctx); + test(kevent_proc_exit_status_error, ctx); signal(SIGUSR1, SIG_DFL); diff --git a/vendor/libkqueue/test/test.c b/vendor/libkqueue/test/test.c index 81d918c44..895e9de79 100644 --- a/vendor/libkqueue/test/test.c +++ b/vendor/libkqueue/test/test.c @@ -45,10 +45,10 @@ error_handler(int signum) static void testing_atexit(void) { - if (error_flag) { + if (error_flag == 1) { printf(" *** TEST FAILED ***\n"); //TODO: print detailed log - } else { + } else if (error_flag == 0) { printf("\n---\n" "+OK All %d tests completed.\n", testnum - 1); } @@ -91,6 +91,12 @@ testing_begin(void) } +void +testing_end_quiet(void) +{ + error_flag = 2; +} + void testing_end(void) { From 42cadc6ac6e6d94d23041d976026fce10e2716a7 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 30 Aug 2021 08:34:54 -0500 Subject: [PATCH 0861/1120] Return the equivalent of the status code of waitpid in the data field of EVFILT_PROC The OpenBSD man pages and observations on macOS confirm this is correct. Both the pre-existing Linux EVFILT_PROC code and the posix EVFILT_PROC code were/are incorrect. --- vendor/libkqueue/src/linux/proc.c | 37 +++++++++++++++++++++++-------- vendor/libkqueue/test/proc.c | 2 +- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index 93b4c8126..533ad7727 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -47,6 +47,7 @@ int evfilt_proc_copyout(struct kevent *dst, struct knote *src, UNUSED_NDEBUG void *ptr) { siginfo_t info; + unsigned int status = 0; #ifndef NDEBUG struct epoll_event * const ev = (struct epoll_event *) ptr; #endif @@ -60,16 +61,34 @@ evfilt_proc_copyout(struct kevent *dst, struct knote *src, UNUSED_NDEBUG void *p return (-1); } - /* It appears we don't need to use the W* macros here */ - if (info.si_code == CLD_EXITED) { - dst->data = info.si_status; - dbg_printf("pid=%u exited, status %u", (unsigned int)src->kev.ident, (unsigned int)dst->data); - } else if (info.si_code == CLD_KILLED || info.si_code == CLD_DUMPED) { - dst->data = info.si_status; - dbg_printf("pid=%u killed, status %u", (unsigned int)src->kev.ident, (unsigned int)dst->data); - } else { - dst->data = 0; + /* + * Try and reconstruct the status code that would have been + * returned by waitpid. The OpenBSD man pages + * and observations of the macOS kqueue confirm this is what + * we should be returning in the data field of the kevent. + */ + switch (info.si_code) { + case CLD_EXITED: /* WIFEXITED - High byte contains status, low byte zeroed */ + status = info.si_status << 8; + dbg_printf("pid=%u exited, status %u", (unsigned int)src->kev.ident, status); + break; + + case CLD_DUMPED: /* WIFSIGNALED/WCOREDUMP - Core flag set - Low 7 bits contains fatal signal */ + status |= 0x80; /* core flag */ + status = info.si_status & 0x7f; + dbg_printf("pid=%u dumped, status %u", (unsigned int)src->kev.ident, status); + break; + + case CLD_KILLED: /* WIFSIGNALED - Low 7 bits contains fatal signal */ + status = info.si_status & 0x7f; + dbg_printf("pid=%u signalled, status %u", (unsigned int)src->kev.ident, status); + break; + + default: /* The rest aren't valid exit states */ + return (0); } + + dst->data = status; dst->flags |= EV_EOF; /* Set in macOS and FreeBSD kqueue implementations */ return (1); diff --git a/vendor/libkqueue/test/proc.c b/vendor/libkqueue/test/proc.c index 5f7df31d5..16fb48a7e 100644 --- a/vendor/libkqueue/test/proc.c +++ b/vendor/libkqueue/test/proc.c @@ -162,7 +162,7 @@ test_kevent_proc_exit_status_error(struct test_context *ctx) kevent_get(&buf, ctx->kqfd, 1); - kev.data = 64; /* What we expected the process exit code to be */ + kev.data = 64 << 8; /* What we expected the process exit code to be */ kev.flags = EV_ADD | EV_ONESHOT | EV_CLEAR | EV_EOF; kevent_cmp(&kev, &buf); From 568100925af7967b3bdcc504fbeeeb17b3da59d2 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 30 Aug 2021 13:24:32 -0500 Subject: [PATCH 0862/1120] Ignore some additional files --- vendor/libkqueue/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/.gitignore b/vendor/libkqueue/.gitignore index 354e55ec4..c106de061 100644 --- a/vendor/libkqueue/.gitignore +++ b/vendor/libkqueue/.gitignore @@ -3,7 +3,9 @@ config.h *.pc *.log *.deb +*.ddeb *.swp +.fuse* CMakeCache.txt CMakeFiles/ CPackConfig.cmake From 07efd761337833b90186bebbf207ed57411dd5be Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 30 Aug 2021 13:25:01 -0500 Subject: [PATCH 0863/1120] Fallback to using posix EVFILT_PROC if SYS_pidfd_open isn't available --- vendor/libkqueue/CMakeLists.txt | 8 +++++++- vendor/libkqueue/src/linux/proc.c | 12 ++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index c62c2976c..cc3946a54 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -130,6 +130,7 @@ endif() set(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE) check_symbol_exists(ppoll poll.h HAVE_DECL_PPOLL) +check_symbol_exists(SYS_pidfd_open sys/syscall.h HAVE_SYS_PIDFD_OPEN) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) @@ -181,13 +182,18 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL Linux) src/posix/platform.h src/linux/platform.c src/linux/platform.h - src/linux/proc.c src/linux/read.c src/linux/signal.c src/linux/timer.c src/linux/user.c src/linux/vnode.c src/linux/write.c) + + if (HAVE_SYS_PIDFD_OPEN) + list(APPEND LIBKQUEUE_SOURCES src/linux/proc.c) + else() + list(APPEND LIBKQUEUE_SOURCES src/posix/proc.c) + endif() else() message(FATAL_ERROR "unsupported host os") endif() diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index 533ad7727..c253313c9 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -19,14 +19,11 @@ /* We depend on the SYS_pidfd_open call to determine when a process has exited * * The SYS_pidfd_open call is only available in Kernels >= 5.3. If this call - * isn't available there's currently no good fallback. We could implement - * some code around netlink in future, but for now just mark the proc filter - * as not implemented. + * isn't available there's currently no good fallback. + * + * If the build system detects SYS_pidfd_open is not available it will fall back + * to using posix/proc.c and not build this source file. */ -#ifndef SYS_pidfd_open -#include "private.h" -const struct filter evfilt_proc = EVFILT_NOTIMPL; -#else #include #include #include @@ -185,4 +182,3 @@ const struct filter evfilt_proc = { .kn_enable = evfilt_proc_knote_enable, .kn_disable = evfilt_proc_knote_disable, }; -#endif From 9d451a22e46b85e182566bcd6aa5a56219ef7f5f Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 31 Aug 2021 20:15:33 -0500 Subject: [PATCH 0864/1120] Pass nevents into each filter's copyout function This allows a filter to return multiple events per copyout call. This may allow us to remove the FD state hacks in platform.c This allows us to use the existing posix proc code. --- vendor/libkqueue/src/common/private.h | 8 ++++--- vendor/libkqueue/src/linux/platform.c | 30 ++++++++++++++----------- vendor/libkqueue/src/linux/proc.c | 2 +- vendor/libkqueue/src/linux/read.c | 6 ++--- vendor/libkqueue/src/linux/signal.c | 4 ++-- vendor/libkqueue/src/linux/timer.c | 4 ++-- vendor/libkqueue/src/linux/user.c | 4 ++-- vendor/libkqueue/src/linux/vnode.c | 4 ++-- vendor/libkqueue/src/linux/write.c | 4 ++-- vendor/libkqueue/src/posix/kevent.c | 2 +- vendor/libkqueue/src/posix/signal.c | 2 +- vendor/libkqueue/src/posix/timer.c | 2 +- vendor/libkqueue/src/posix/user.c | 5 ++--- vendor/libkqueue/src/solaris/platform.c | 10 ++++----- vendor/libkqueue/src/solaris/signal.c | 2 +- vendor/libkqueue/src/solaris/socket.c | 4 ++-- vendor/libkqueue/src/solaris/timer.c | 2 +- vendor/libkqueue/src/solaris/user.c | 2 +- vendor/libkqueue/src/windows/platform.c | 2 +- vendor/libkqueue/src/windows/read.c | 4 ++-- vendor/libkqueue/src/windows/timer.c | 4 ++-- vendor/libkqueue/src/windows/user.c | 4 ++-- vendor/libkqueue/test/proc.c | 4 ++-- 23 files changed, 60 insertions(+), 55 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 6f211fdb6..521be9b8a 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -186,15 +186,17 @@ struct filter { /** Copy an event from the eventing system to a kevent structure * - * @param[in] dst kevent to populate. + * @param[in] el array of `struct kevent` to populate. Most filters + * will insert a single event, but some may insert multiple. + * @param[in] nevents The maximum number of events to copy to el. * @param[in] kn the event was triggered on. * @param[in] ev event system specific structure representing the event, * i.e. for Linux this would be a `struct epoll_event *`. * @return - * - 0 on success. + * - >=0 the number of events copied to el. * - -1 on failure. */ - int (*kf_copyout)(struct kevent *dst, struct knote *kn, void *ev); + int (*kf_copyout)(struct kevent *el, int nevents, struct knote *kn, void *ev); /* knote operations */ int (*kn_create)(struct filter *, struct knote *); diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index d65be4426..c8179d98a 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -531,13 +531,12 @@ linux_kevent_wait(struct kqueue *kq, int nevents, const struct timespec *ts) return (nret); } -static inline int linux_kevent_copyout_ev(struct kevent **el_p, struct epoll_event *ev, +static inline int linux_kevent_copyout_ev(struct kevent *el, int nevents, struct epoll_event *ev, struct filter *filt, struct knote *kn) { int rv; - struct kevent *el = *el_p; - rv = filt->kf_copyout(el, kn, ev); + rv = filt->kf_copyout(el, nevents, kn, ev); if (unlikely(rv < 0)) { dbg_puts("knote_copyout failed"); assert(0); @@ -545,12 +544,14 @@ static inline int linux_kevent_copyout_ev(struct kevent **el_p, struct epoll_eve } /* - * Advance to the next el entry + * Don't emit bad events... + * + * Fixme - We shouldn't be emitting bad events + * in the first place? */ - if (likely(el->filter != 0)) { - (*el_p)++; - } else { + if (unlikely(el->filter == 0)) { dbg_puts("spurious wakeup, discarding event"); + rv = 0; } /* @@ -601,8 +602,9 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven goto done; } - rv = linux_kevent_copyout_ev(&el_p, ev, &kq->kq_filt[~(kn->kev.filter)], kn); + rv = linux_kevent_copyout_ev(el_p, (el_end - el_p), ev, &kq->kq_filt[~(kn->kev.filter)], kn); if (rv < 0) goto done; + el_p += rv; } break; @@ -612,8 +614,8 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven */ case EPOLL_UDATA_FD_STATE: { - struct fd_state *fds = epoll_udata->ud_fds; - struct knote *kn; + struct fd_state *fds = epoll_udata->ud_fds; + struct knote *kn; /* * FD is readable @@ -631,8 +633,9 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven */ assert(kn); - rv = linux_kevent_copyout_ev(&el_p, ev, &kq->kq_filt[~(kn->kev.filter)], kn); + rv = linux_kevent_copyout_ev(el_p, (el_end - el_p), ev, &kq->kq_filt[~(kn->kev.filter)], kn); if (rv < 0) goto done; + el_p += rv; } /* @@ -645,8 +648,9 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven assert(kn); /* We shouldn't receive events we didn't request */ - rv = linux_kevent_copyout_ev(&el_p, ev, &kq->kq_filt[~(kn->kev.filter)], kn); + rv = linux_kevent_copyout_ev(el_p, (el_end - el_p), ev, &kq->kq_filt[~(kn->kev.filter)], kn); if (rv < 0) goto done; + el_p += rv; } } break; @@ -826,7 +830,7 @@ linux_get_descriptor_type(struct knote *kn) dbg_printf("fd=%i is a socket", fd); break; /* deferred type determination */ - case 0: /* seen with eventfd */ + case 0: /* seen with eventfd */ dbg_printf("fd=%i fstat() provided no S_IFMT flags, treating fd as passive socket", fd); kn->kn_flags |= KNFL_SOCKET; kn->kn_flags |= KNFL_SOCKET_PASSIVE; diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index c253313c9..0a9699459 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -41,7 +41,7 @@ #include "private.h" int -evfilt_proc_copyout(struct kevent *dst, struct knote *src, UNUSED_NDEBUG void *ptr) +evfilt_proc_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, UNUSED_NDEBUG void *ptr) { siginfo_t info; unsigned int status = 0; diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index a108e16a3..576bb585d 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -54,7 +54,7 @@ get_eof_offset(int fd) } int -evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) +evfilt_read_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr) { int ret; int serr; @@ -104,7 +104,7 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) #endif } - return (0); + return (1); } dbg_printf("epoll_ev=%s", epoll_event_dump(ev)); @@ -144,7 +144,7 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) } } - return (0); + return (1); } int diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index b44393f5c..483f900f0 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -123,7 +123,7 @@ signalfd_create(int epoll_fd, struct knote *kn, int signum) } int -evfilt_signal_copyout(struct kevent *dst, struct knote *src, void *x UNUSED) +evfilt_signal_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *x UNUSED) { int sigfd; @@ -137,7 +137,7 @@ evfilt_signal_copyout(struct kevent *dst, struct knote *src, void *x UNUSED) */ dst->data = 1; - return (0); + return (1); } int diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index f9c489395..5e4ae8830 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -126,7 +126,7 @@ convert_timedata_to_itimerspec(struct itimerspec *dst, long src, } int -evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr) +evfilt_timer_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr) { struct epoll_event * const ev = (struct epoll_event *) ptr; uint64_t expired; @@ -146,7 +146,7 @@ evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr) } dst->data = expired; - return (0); + return (1); } int diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index f4bcd9309..9f98a46f7 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -90,7 +90,7 @@ eventfd_lower(int evfd) } int -linux_evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) +linux_evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr UNUSED) { memcpy(dst, &src->kev, sizeof(*dst)); dst->fflags &= ~NOTE_FFCTRLMASK; //FIXME: Not sure if needed @@ -110,7 +110,7 @@ linux_evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSE if (src->kev.flags & EV_DISPATCH) src->kev.fflags &= ~NOTE_TRIGGER; - return (0); + return (1); } int diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 69d700dfa..1ca5289f8 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -183,7 +183,7 @@ delete_watch(struct filter *filt, struct knote *kn) } int -evfilt_vnode_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) +evfilt_vnode_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr UNUSED) { uint8_t buf[sizeof(struct inotify_event) + NAME_MAX + 1] __attribute__ ((aligned(__alignof__(struct inotify_event)))); struct inotify_event *evt; @@ -248,7 +248,7 @@ scriptors reference the same file. if (evt->mask & IN_DELETE_SELF && src->kev.fflags & NOTE_DELETE) dst->fflags |= NOTE_DELETE; - return (0); + return (1); } int diff --git a/vendor/libkqueue/src/linux/write.c b/vendor/libkqueue/src/linux/write.c index 44170e4f5..5a2c4f9f8 100644 --- a/vendor/libkqueue/src/linux/write.c +++ b/vendor/libkqueue/src/linux/write.c @@ -31,7 +31,7 @@ #include "private.h" int -evfilt_write_copyout(struct kevent *dst, struct knote *src, void *ptr) +evfilt_write_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr) { int ret; int serr; @@ -61,7 +61,7 @@ evfilt_write_copyout(struct kevent *dst, struct knote *src, void *ptr) dst->data = 0; } - return (0); + return (1); } int diff --git a/vendor/libkqueue/src/posix/kevent.c b/vendor/libkqueue/src/posix/kevent.c index 99e386609..4ed7f04af 100644 --- a/vendor/libkqueue/src/posix/kevent.c +++ b/vendor/libkqueue/src/posix/kevent.c @@ -62,7 +62,7 @@ posix_kevent_copyout(struct kqueue *kq, int nready, // dbg_printf("pfd[%d] = %d", i, filt->kf_pfd); if (FD_ISSET(filt->kf_pfd, &kq->kq_rfds)) { dbg_printf("pending events for filter %d (%s)", filt->kf_id, filter_name(filt->kf_id)); - rv = filt->kf_copyout(filt, eventlist, nevents); + rv = filt->kf_copyout(eventlist, nevents, kn, evt); if (rv < 0) { dbg_puts("kevent_copyout failed"); nret = -1; diff --git a/vendor/libkqueue/src/posix/signal.c b/vendor/libkqueue/src/posix/signal.c index b7aaa74c9..dedddff3d 100644 --- a/vendor/libkqueue/src/posix/signal.c +++ b/vendor/libkqueue/src/posix/signal.c @@ -170,7 +170,7 @@ evfilt_signal_knote_disable(struct filter *filt, struct knote *kn) } int -evfilt_signal_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) +evfilt_signal_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr UNUSED) { struct sentry *s; struct knote *kn; diff --git a/vendor/libkqueue/src/posix/timer.c b/vendor/libkqueue/src/posix/timer.c index 794b16256..34cdc49ae 100644 --- a/vendor/libkqueue/src/posix/timer.c +++ b/vendor/libkqueue/src/posix/timer.c @@ -222,7 +222,7 @@ evfilt_timer_destroy(struct filter *filt) } int -evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) +evfilt_timer_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr UNUSED) { struct filter *filt; struct sleepinfo si; diff --git a/vendor/libkqueue/src/posix/user.c b/vendor/libkqueue/src/posix/user.c index 6e13ea98f..3e326bae1 100644 --- a/vendor/libkqueue/src/posix/user.c +++ b/vendor/libkqueue/src/posix/user.c @@ -48,11 +48,10 @@ posix_evfilt_user_destroy(struct filter *filt) } int -posix_evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) +posix_evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr UNUSED) { memcpy(dst, &src->kev, sizeof(*dst)); struct knote *kn; - int nevents = 0; dst->fflags &= ~NOTE_FFCTRLMASK; //FIXME: Not sure if needed dst->fflags &= ~NOTE_TRIGGER; @@ -70,7 +69,7 @@ posix_evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSE if (src->kev.flags & EV_DISPATCH) src->kev.fflags &= ~NOTE_TRIGGER; - return (0); + return (1); } int diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index 3c302d388..085c2e183 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -145,7 +145,7 @@ solaris_kevent_wait( int solaris_kevent_copyout(struct kqueue *kq, int nready, - struct kevent *eventlist, int nevents UNUSED) + struct kevent *eventlist, int nevents) { port_event_t *evt; struct knote *kn; @@ -162,7 +162,7 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, case PORT_SOURCE_FD: //XXX-FIXME WHAT ABOUT WRITE??? filter_lookup(&filt, kq, EVFILT_READ); - rv = filt->kf_copyout(eventlist, kn, evt); + rv = filt->kf_copyout(eventlist, nevents, kn, evt); /* For sockets, the event port object must be reassociated after each event is retrieved. */ @@ -178,18 +178,18 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, case PORT_SOURCE_TIMER: filter_lookup(&filt, kq, EVFILT_TIMER); - rv = filt->kf_copyout(eventlist, kn, evt); + rv = filt->kf_copyout(eventlist, nevents, kn, evt); break; case PORT_SOURCE_USER: switch (evt->portev_events) { case X_PORT_SOURCE_SIGNAL: filter_lookup(&filt, kq, EVFILT_SIGNAL); - rv = filt->kf_copyout(eventlist, kn, evt); + rv = filt->kf_copyout(eventlist, nevents, kn, evt); break; case X_PORT_SOURCE_USER: filter_lookup(&filt, kq, EVFILT_USER); - rv = filt->kf_copyout(eventlist, kn, evt); + rv = filt->kf_copyout(eventlist, nevents, kn, evt); break; default: dbg_puts("unsupported portev_events"); diff --git a/vendor/libkqueue/src/solaris/signal.c b/vendor/libkqueue/src/solaris/signal.c index 9ef04682c..f1b07b91b 100644 --- a/vendor/libkqueue/src/solaris/signal.c +++ b/vendor/libkqueue/src/solaris/signal.c @@ -134,7 +134,7 @@ evfilt_signal_knote_disable(struct filter *filt UNUSED, struct knote *kn) } int -evfilt_signal_copyout(struct kevent *dst, struct knote *src, void *ptr) +evfilt_signal_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr) { port_event_t *pe = (port_event_t *) ptr; struct sentry *ent = (struct sentry *) pe->portev_user; diff --git a/vendor/libkqueue/src/solaris/socket.c b/vendor/libkqueue/src/solaris/socket.c index 09a0b0336..b3276f1c2 100644 --- a/vendor/libkqueue/src/solaris/socket.c +++ b/vendor/libkqueue/src/solaris/socket.c @@ -101,7 +101,7 @@ evfilt_socket_knote_disable(struct filter *filt, struct knote *kn) } int -evfilt_socket_copyout(struct kevent *dst, struct knote *src, void *ptr) +evfilt_socket_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr) { port_event_t *pe = (port_event_t *) ptr; unsigned int pending_data = 0; @@ -133,7 +133,7 @@ evfilt_socket_copyout(struct kevent *dst, struct knote *src, void *ptr) } */ - return (0); + return (1); } const struct filter evfilt_read = { diff --git a/vendor/libkqueue/src/solaris/timer.c b/vendor/libkqueue/src/solaris/timer.c index fce24973c..2f3a0bbe2 100644 --- a/vendor/libkqueue/src/solaris/timer.c +++ b/vendor/libkqueue/src/solaris/timer.c @@ -85,7 +85,7 @@ evfilt_timer_destroy(struct filter *filt UNUSED) } int -evfilt_timer_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) +evfilt_timer_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr UNUSED) { /* port_event_t *pe = (port_event_t *) ptr; */ diff --git a/vendor/libkqueue/src/solaris/user.c b/vendor/libkqueue/src/solaris/user.c index 3d3407960..63aa95a3d 100644 --- a/vendor/libkqueue/src/solaris/user.c +++ b/vendor/libkqueue/src/solaris/user.c @@ -17,7 +17,7 @@ #include "private.h" int -evfilt_user_copyout(struct kevent *dst, struct knote *src, void *ptr UNUSED) +evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr UNUSED) { //port_event_t *pe = (port_event_t *) ptr; diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 5b3d3f134..92d4be350 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -139,7 +139,7 @@ windows_kevent_copyout(struct kqueue *kq, int nready, //FIXME: not true for EVFILT_IOCP kn = (struct knote *) iocp_buf.overlap; filt = &kq->kq_filt[~(kn->kev.filter)]; - rv = filt->kf_copyout(eventlist, kn, &iocp_buf); + rv = filt->kf_copyout(eventlist, nevents, kn, &iocp_buf); if (unlikely(rv < 0)) { dbg_puts("knote_copyout failed"); /* XXX-FIXME: hard to handle this without losing events */ diff --git a/vendor/libkqueue/src/windows/read.c b/vendor/libkqueue/src/windows/read.c index 9087dc414..1ffe6d112 100644 --- a/vendor/libkqueue/src/windows/read.c +++ b/vendor/libkqueue/src/windows/read.c @@ -87,7 +87,7 @@ get_eof_offset(int fd) #endif int -evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) +evfilt_read_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr) { unsigned long bufsize; @@ -111,7 +111,7 @@ evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr) dst->data = bufsize; } - return (0); + return (1); } int diff --git a/vendor/libkqueue/src/windows/timer.c b/vendor/libkqueue/src/windows/timer.c index 292bb2bdb..69c0f231a 100644 --- a/vendor/libkqueue/src/windows/timer.c +++ b/vendor/libkqueue/src/windows/timer.c @@ -99,7 +99,7 @@ evfilt_timer_destroy(struct filter *filt) } int -evfilt_timer_copyout(struct kevent* dst, struct knote* src, void* ptr) +evfilt_timer_copyout(struct kevent *dst, UNUSED int nevents, struct knote* src, void* ptr) { memcpy(dst, &src->kev, sizeof(struct kevent)); // TODO: Timer error handling @@ -109,7 +109,7 @@ evfilt_timer_copyout(struct kevent* dst, struct knote* src, void* ptr) */ dst->data = 1; - return (0); + return (1); } int diff --git a/vendor/libkqueue/src/windows/user.c b/vendor/libkqueue/src/windows/user.c index b036d9729..d915430b3 100644 --- a/vendor/libkqueue/src/windows/user.c +++ b/vendor/libkqueue/src/windows/user.c @@ -28,7 +28,7 @@ evfilt_user_destroy(struct filter *filt) } int -evfilt_user_copyout(struct kevent* dst, struct knote* src, void* ptr) +evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct knote* src, void* ptr) { memcpy(dst, &src->kev, sizeof(struct kevent)); @@ -45,7 +45,7 @@ evfilt_user_copyout(struct kevent* dst, struct knote* src, void* ptr) if (src->kev.flags & EV_DISPATCH) src->kev.fflags &= ~NOTE_TRIGGER; - return (0); + return (1); } int diff --git a/vendor/libkqueue/test/proc.c b/vendor/libkqueue/test/proc.c index 16fb48a7e..9f4dee824 100644 --- a/vendor/libkqueue/test/proc.c +++ b/vendor/libkqueue/test/proc.c @@ -111,7 +111,7 @@ test_kevent_proc_exit_status_ok(struct test_context *ctx) /* Create a child that waits to be killed and then exits */ pid = fork(); if (pid == 0) { - usleep(100000); + usleep(100000); printf(" -- child done sleeping, exiting (0)\n"); testing_end_quiet(); exit(0); @@ -150,7 +150,7 @@ test_kevent_proc_exit_status_error(struct test_context *ctx) /* Create a child that waits to be killed and then exits */ pid = fork(); if (pid == 0) { - usleep(100000); + usleep(100000); printf(" -- child done sleeping, exiting (64)\n"); testing_end_quiet(); exit(64); From 272d950d3ace82ec9ce7a3ff6555fd074d2a86af Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 1 Sep 2021 10:31:14 -0500 Subject: [PATCH 0865/1120] Document the eventfd callbacks --- vendor/libkqueue/src/common/private.h | 47 ++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 521be9b8a..ffb041fea 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -294,11 +294,48 @@ struct kqueue_vtable { */ void (*filter_free)(struct kqueue *kq, struct filter *filt); - int (*eventfd_init)(struct eventfd *); - void (*eventfd_close)(struct eventfd *); - int (*eventfd_raise)(struct eventfd *); - int (*eventfd_lower)(struct eventfd *); - int (*eventfd_descriptor)(struct eventfd *); + /** Initialise a new eventfd + * + * @param[in] efd structure to initialise. + * @return + * - 0 on success. + * - -1 on failure. + */ + int (*eventfd_init)(struct eventfd *efd); + + /** Close an eventfd + * + * @param[in] efd to close. + * @return + * - 0 on success. + * - -1 on failure. + */ + void (*eventfd_close)(struct eventfd *efd); + + /** "raise" an eventfd, i.e. signal it as pending + * + * @param[in] efd to raise. + * @return + * - 0 on success. + * - -1 on failure. + */ + int (*eventfd_raise)(struct eventfd *efd); + + /** "lower" an eventfd, consume the pending signal + * + * @param[in] efd to lower. + * @return + * - 0 on success. + * - -1 on failure. + */ + int (*eventfd_lower)(struct eventfd *efd); + + /** Return the file descriptor associated with an eventfd + * + * @param[in] efd to return the file descriptor for. + * @return The file descriptor. + */ + int (*eventfd_descriptor)(struct eventfd *efd); }; extern const struct kqueue_vtable kqops; From 83a43c19fdd3d78fbbe95dc3e0b95a15f31e9d4b Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 1 Sep 2021 10:31:30 -0500 Subject: [PATCH 0866/1120] kqueue rbentry is unused --- vendor/libkqueue/src/common/private.h | 1 - 1 file changed, 1 deletion(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index ffb041fea..246485e1b 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -241,7 +241,6 @@ struct kqueue { #if defined(KQUEUE_PLATFORM_SPECIFIC) KQUEUE_PLATFORM_SPECIFIC; #endif - RB_ENTRY(kqueue) entries; }; /** Platform specific support functions From b8cf6148f55ca264a3137b5cfeb8387a222cea1e Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 1 Sep 2021 10:48:11 -0500 Subject: [PATCH 0867/1120] Move some comon headers into private.h or platform.h --- vendor/libkqueue/src/common/alloc.h | 3 - vendor/libkqueue/src/common/filter.c | 4 - vendor/libkqueue/src/common/kevent.c | 6 -- vendor/libkqueue/src/common/knote.c | 3 - vendor/libkqueue/src/common/kqueue.c | 7 -- vendor/libkqueue/src/common/map.c | 4 + vendor/libkqueue/src/common/private.h | 19 +++- vendor/libkqueue/src/linux/platform.c | 4 +- vendor/libkqueue/src/linux/platform.h | 14 ++- vendor/libkqueue/src/linux/proc.c | 14 +-- vendor/libkqueue/src/linux/read.c | 11 --- vendor/libkqueue/src/linux/signal.c | 2 + vendor/libkqueue/src/linux/timer.c | 3 +- vendor/libkqueue/src/linux/user.c | 11 --- vendor/libkqueue/src/linux/write.c | 10 --- vendor/libkqueue/src/posix/platform.h | 14 ++- vendor/libkqueue/src/posix/proc.c | 110 ++++++++++++------------ vendor/libkqueue/src/posix/signal.c | 9 -- vendor/libkqueue/src/posix/timer.c | 9 -- vendor/libkqueue/src/posix/user.c | 9 -- vendor/libkqueue/src/solaris/platform.h | 8 +- vendor/libkqueue/src/solaris/socket.c | 7 -- vendor/libkqueue/src/solaris/timer.c | 10 +-- vendor/libkqueue/src/windows/platform.h | 6 +- 24 files changed, 107 insertions(+), 190 deletions(-) diff --git a/vendor/libkqueue/src/common/alloc.h b/vendor/libkqueue/src/common/alloc.h index 65b341661..584a0f479 100644 --- a/vendor/libkqueue/src/common/alloc.h +++ b/vendor/libkqueue/src/common/alloc.h @@ -32,9 +32,6 @@ * is that mem_alloc() does not allow you to specify a specific size. * */ - -#include - #ifndef _WIN32 # include #endif diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index 682ca4bb8..f53e09cf5 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -15,11 +15,7 @@ */ #include -#include -#include -#include #include -#include #include "private.h" diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 2bce0a528..51a3beb66 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -18,13 +18,7 @@ #define _GNU_SOURCE #include -#include -#include #include -#include -#include -#include -#include #include "private.h" diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 09bb76704..ddfdb75da 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -15,9 +15,6 @@ */ #include -#include -#include -#include #include "private.h" diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 11e836d68..835853a39 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -13,14 +13,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - -#include -#include #include -#include -#include -#include -#include #include "private.h" diff --git a/vendor/libkqueue/src/common/map.c b/vendor/libkqueue/src/common/map.c index 4ac654989..882175d78 100644 --- a/vendor/libkqueue/src/common/map.c +++ b/vendor/libkqueue/src/common/map.c @@ -16,6 +16,10 @@ #include "private.h" +#ifndef _WIN32 +#include +#endif + struct map { size_t len; atomic_uintptr_t *data; diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 246485e1b..ab1c793c0 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -17,9 +17,17 @@ #ifndef _KQUEUE_PRIVATE_H #define _KQUEUE_PRIVATE_H -#include +/** Frequently used headers that should be standard on all platforms + * + */ +#include +#include #include -#include +#include +/* Required by glibc for MAP_ANON */ +#define __USE_MISC 1 +#include + #include "config.h" #include "tree.h" @@ -35,7 +43,7 @@ struct evfilt_data; #if defined(_WIN32) # include "../windows/platform.h" -# include "../common/queue.h" + # if !defined(NDEBUG) && !defined(__GNUC__) # include # endif @@ -49,6 +57,11 @@ struct evfilt_data; # error Unknown platform #endif +/** Additional macro to check if an item is in a doubly linked list + * + */ +#define LIST_INSERTED(elm, field) (((elm)->field.le_next) || ((elm)->field.le_prev)) + /** Convenience macros * */ diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index c8179d98a..941ccb507 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -16,10 +16,10 @@ #define _GNU_SOURCE #include -#include +#include #include -#include #include + #include "../common/private.h" #define MONITORING_THREAD_SIGNAL (SIGRTMIN + 1) diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index d92b60ccc..e0c1f425a 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -38,11 +38,17 @@ struct filter; return (0); } #endif -#if HAVE_SYS_TIMERFD_H -# include -#endif - +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include /* * C11 atomic operations diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index 0a9699459..3b1b81603 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -14,8 +14,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include - /* We depend on the SYS_pidfd_open call to determine when a process has exited * * The SYS_pidfd_open call is only available in Kernels >= 5.3. If this call @@ -24,18 +22,8 @@ * If the build system detects SYS_pidfd_open is not available it will fall back * to using posix/proc.c and not build this source file. */ -#include -#include -#include -#include -#include -#include +#include #include -#include -#include - -#include -#include #include "sys/event.h" #include "private.h" diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index 576bb585d..db4d6cd75 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -13,20 +13,9 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - -#include -#include #include -#include -#include -#include -#include #include -#include #include -#include -#include -#include #include "private.h" diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index 483f900f0..0df3c93c2 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -16,6 +16,8 @@ #include "private.h" +#include + #if HAVE_SYS_SIGNALFD_H # include #else diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 5e4ae8830..019fff89d 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -58,7 +58,8 @@ int timerfd_gettime(int ufc, struct itimerspec *otmr) { return syscall(SYS_timerfd_gettime, ufc, otmr); } - +#else +#include #endif #ifndef NDEBUG diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index 9f98a46f7..ed0f0470f 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -13,20 +13,9 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - -#include -#include -#include #include -#include -#include -#include #include -#include -#include -#include -#include "sys/event.h" #include "private.h" /* NOTE: copy+pasted from linux_eventfd_raise() */ diff --git a/vendor/libkqueue/src/linux/write.c b/vendor/libkqueue/src/linux/write.c index 5a2c4f9f8..e3b5c4b6a 100644 --- a/vendor/libkqueue/src/linux/write.c +++ b/vendor/libkqueue/src/linux/write.c @@ -14,19 +14,9 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include #include -#include -#include -#include -#include #include -#include #include -#include -#include -#include #include "private.h" diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 9b4b34d31..5dd31a409 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -20,23 +20,19 @@ /* Required by glibc for MAP_ANON */ #define __USE_MISC 1 -#include "../../include/sys/event.h" - +#include #include #include +#include +#include #include -#include -#include -#include #include -#include -#include +#include +#include #include #include #include #include -#include -#include #include /* diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 1f5578d20..e12504c20 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -13,19 +13,10 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - -#include #include -#include -#include #include -#include -#include #include -#include -#include #include -#include #include #include @@ -44,8 +35,9 @@ static void * wait_thread(void *arg) { struct filter *filt = (struct filter *) arg; - struct knote *kn; - int status, result; + struct knote *dst; + int status; + siginfo_t info; pid_t pid; sigset_t sigmask; @@ -55,9 +47,8 @@ wait_thread(void *arg) pthread_sigmask(SIG_BLOCK, &sigmask, NULL); for (;;) { - - /* Wait for a child process to exit(2) */ - if ((pid = waitpid(-1, &status, 0)) < 0) { + /* Get the exit status _without_ reaping the process, waitpid() should still work in the caller */ + if (waitid(P_ALL, 0, &info, WEXITED | WNOWAIT) < 0) { if (errno == ECHILD) { dbg_puts("got ECHILD, waiting for wakeup condition"); pthread_mutex_lock(&wait_mtx); @@ -68,33 +59,50 @@ wait_thread(void *arg) } if (errno == EINTR) continue; - dbg_printf("wait(2): %s", strerror(errno)); - break; - } - - /* Create a proc_event */ - if (WIFEXITED(status)) { - result = WEXITSTATUS(status); - } else if (WIFSIGNALED(status)) { - /* FIXME: probably not true on BSD */ - result = WTERMSIG(status); - } else { - dbg_puts("unexpected code path"); - result = 234; /* arbitrary error value */ + dbg_printf("waitid(2): %s", strerror(errno)); } /* Scan the wait queue to see if anyone is interested */ pthread_mutex_lock(&filt->kf_mtx); - kn = knote_lookup(filt, pid); - if (kn != NULL) { - kn->kev.data = result; - kn->kev.fflags = NOTE_EXIT; - LIST_REMOVE(kn, entries); - LIST_INSERT_HEAD(&filt->kf_eventlist, kn, entries); - /* Indicate read(2) readiness */ - /* TODO: error handling */ - filter_raise(filt); + dst = knote_lookup(filt, pid); + if (!dst) + goto next; + + /* + * Try and reconstruct the status code that would have been + * returned by waitpid. The OpenBSD man pages + * and observations of the macOS kqueue confirm this is what + * we should be returning in the data field of the kevent. + */ + switch (info.si_code) { + case CLD_EXITED: /* WIFEXITED - High byte contains status, low byte zeroed */ + status = info.si_status << 8; + dbg_printf("pid=%u exited, status %u", (unsigned int)info.si_pid, status); + break; + + case CLD_DUMPED: /* WIFSIGNALED/WCOREDUMP - Core flag set - Low 7 bits contains fatal signal */ + status |= 0x80; /* core flag */ + status = info.si_status & 0x7f; + dbg_printf("pid=%u dumped, status %u", (unsigned int)info.si_pid, status); + break; + + case CLD_KILLED: /* WIFSIGNALED - Low 7 bits contains fatal signal */ + status = info.si_status & 0x7f; + dbg_printf("pid=%u signalled, status %u", (unsigned int)info.si_pid, status); + break; + + default: /* The rest aren't valid exit states */ + goto next; } + + dst->kev.data = status; + dst->flags |= EV_EOF; /* Set in macOS and FreeBSD kqueue implementations */ + + LIST_REMOVE(dst, kn_list); + LIST_INSERT_HEAD(&filt->kf_eventlist, kn, kn_list); + filter_raise(filt); + + next: pthread_mutex_unlock(&filt->kf_mtx); } @@ -103,7 +111,7 @@ wait_thread(void *arg) return (NULL); } -int +static int evfilt_proc_init(struct filter *filt) { struct evfilt_data *ed; @@ -127,14 +135,14 @@ evfilt_proc_init(struct filter *filt) return (-1); } -void +static void evfilt_proc_destroy(struct filter *filt) { -//TODO: pthread_cancel(filt->kf_data->wthr_id); + pthread_cancel(filt->kf_data->wthr_id); close(filt->kf_pfd); } -int +static int evfilt_proc_create(struct filter *filt, struct knote *dst, const struct kevent *src) { @@ -151,32 +159,26 @@ evfilt_proc_create(struct filter *filt, return (0); } -int -evfilt_proc_copyout(struct filter *filt, - struct kevent *dst, - int maxevents) +static int +evfilt_proc_copyout(struct kevent *dst, int nevents, struct knote *kn, void *ev) { struct knote *kn; - int nevents = 0; + int events = 0; - filter_lower(filt); + LIST_FOREACH_SAFE(kn, &filt->kf_eventlist, kn_list) { + if (++events > nevents) + break; - LIST_FOREACH(kn, &filt->kf_eventlist, entries) { kevent_dump(&kn->kev); memcpy(dst, &kn->kev, sizeof(*dst)); dst->fflags = NOTE_EXIT; - if (kn->kev.flags & EV_DISPATCH) { + if (kn->kev.flags & EV_DISPATCH) KNOTE_DISABLE(kn); - } -#if FIXME - /* XXX - NEED TO use safe foreach instead */ + if (kn->kev.flags & EV_ONESHOT) knote_delete(filt, kn); -#endif - if (++nevents > maxevents) - break; dst++; } diff --git a/vendor/libkqueue/src/posix/signal.c b/vendor/libkqueue/src/posix/signal.c index dedddff3d..a955ce5d9 100644 --- a/vendor/libkqueue/src/posix/signal.c +++ b/vendor/libkqueue/src/posix/signal.c @@ -13,17 +13,8 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - -#include -#include -#include #include -#include -#include -#include #include -#include -#include #include #include "sys/event.h" diff --git a/vendor/libkqueue/src/posix/timer.c b/vendor/libkqueue/src/posix/timer.c index 34cdc49ae..967b67910 100644 --- a/vendor/libkqueue/src/posix/timer.c +++ b/vendor/libkqueue/src/posix/timer.c @@ -13,19 +13,10 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - -#include -#include -#include #include -#include -#include #include -#include #include #include -#include -#include #include #include diff --git a/vendor/libkqueue/src/posix/user.c b/vendor/libkqueue/src/posix/user.c index 3e326bae1..8c56c5f3f 100644 --- a/vendor/libkqueue/src/posix/user.c +++ b/vendor/libkqueue/src/posix/user.c @@ -13,17 +13,8 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - -#include -#include -#include #include -#include -#include -#include #include -#include -#include #include #include "sys/event.h" diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index ef64a7fe0..6b1dd9ff7 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -17,9 +17,13 @@ #ifndef _KQUEUE_SOLARIS_PLATFORM_H #define _KQUEUE_SOLARIS_PLATFORM_H -#include - #include +#include +#include +#include +#include +#include +#include #define atomic_uintptr_t uintptr_t #define atomic_uint unsigned int diff --git a/vendor/libkqueue/src/solaris/socket.c b/vendor/libkqueue/src/solaris/socket.c index b3276f1c2..7d7f75d03 100644 --- a/vendor/libkqueue/src/solaris/socket.c +++ b/vendor/libkqueue/src/solaris/socket.c @@ -14,15 +14,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include #include -#include -#include -#include #include -#include -#include #include #include diff --git a/vendor/libkqueue/src/solaris/timer.c b/vendor/libkqueue/src/solaris/timer.c index 2f3a0bbe2..1066a69d1 100644 --- a/vendor/libkqueue/src/solaris/timer.c +++ b/vendor/libkqueue/src/solaris/timer.c @@ -13,17 +13,9 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - -#include -#include -#include #include -#include -#include -#include + #include -#include -#include #include #include diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index dfa9a8263..f48137f2e 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -30,11 +30,9 @@ #include #include #include -#include -#include -#include #include -#include + +#include "../common/queue.h" #define _CRT_SECURE_NO_WARNINGS 1 /* The #define doesn't seem to work, but the #pragma does.. */ From ed7e10413ef451f6843a9d4698e2071ed54ec173 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 1 Sep 2021 10:48:24 -0500 Subject: [PATCH 0868/1120] Include sys/event.h centrally This isn't the test suite... it's needed by literally every platform and filter --- vendor/libkqueue/src/common/private.h | 1 + vendor/libkqueue/src/linux/proc.c | 1 - vendor/libkqueue/src/posix/kevent.c | 4 ---- vendor/libkqueue/src/posix/proc.c | 1 - vendor/libkqueue/src/posix/signal.c | 1 - vendor/libkqueue/src/posix/timer.c | 1 - vendor/libkqueue/src/posix/user.c | 1 - vendor/libkqueue/src/solaris/socket.c | 1 - vendor/libkqueue/src/solaris/timer.c | 1 - vendor/libkqueue/src/windows/platform.h | 3 --- 10 files changed, 1 insertion(+), 14 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index ab1c793c0..0f9054ab0 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -30,6 +30,7 @@ #include "config.h" #include "tree.h" +#include "sys/event.h" /* Maximum events returnable in a single kevent() call */ #define MAX_KEVENT 512 diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index 3b1b81603..82cfa433d 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -25,7 +25,6 @@ #include #include -#include "sys/event.h" #include "private.h" int diff --git a/vendor/libkqueue/src/posix/kevent.c b/vendor/libkqueue/src/posix/kevent.c index 4ed7f04af..3cba6c9bb 100644 --- a/vendor/libkqueue/src/posix/kevent.c +++ b/vendor/libkqueue/src/posix/kevent.c @@ -13,10 +13,6 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - -#include - -#include "sys/event.h" #include "private.h" const struct filter evfilt_proc = EVFILT_NOTIMPL; diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index e12504c20..dbc8aef74 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -21,7 +21,6 @@ #include -#include "sys/event.h" #include "private.h" pthread_cond_t wait_cond = PTHREAD_COND_INITIALIZER; diff --git a/vendor/libkqueue/src/posix/signal.c b/vendor/libkqueue/src/posix/signal.c index a955ce5d9..cc94a99a3 100644 --- a/vendor/libkqueue/src/posix/signal.c +++ b/vendor/libkqueue/src/posix/signal.c @@ -17,7 +17,6 @@ #include #include -#include "sys/event.h" #include "private.h" /* Highest signal number supported. POSIX standard signals are < 32 */ diff --git a/vendor/libkqueue/src/posix/timer.c b/vendor/libkqueue/src/posix/timer.c index 967b67910..ac23c9b26 100644 --- a/vendor/libkqueue/src/posix/timer.c +++ b/vendor/libkqueue/src/posix/timer.c @@ -20,7 +20,6 @@ #include #include -#include "sys/event.h" #include "private.h" /* A request to sleep for a certain time */ diff --git a/vendor/libkqueue/src/posix/user.c b/vendor/libkqueue/src/posix/user.c index 8c56c5f3f..6c4a48df7 100644 --- a/vendor/libkqueue/src/posix/user.c +++ b/vendor/libkqueue/src/posix/user.c @@ -17,7 +17,6 @@ #include #include -#include "sys/event.h" #include "private.h" int diff --git a/vendor/libkqueue/src/solaris/socket.c b/vendor/libkqueue/src/solaris/socket.c index 7d7f75d03..6f7485dd6 100644 --- a/vendor/libkqueue/src/solaris/socket.c +++ b/vendor/libkqueue/src/solaris/socket.c @@ -21,7 +21,6 @@ #include -#include "sys/event.h" #include "private.h" int diff --git a/vendor/libkqueue/src/solaris/timer.c b/vendor/libkqueue/src/solaris/timer.c index 1066a69d1..c607d2140 100644 --- a/vendor/libkqueue/src/solaris/timer.c +++ b/vendor/libkqueue/src/solaris/timer.c @@ -19,7 +19,6 @@ #include #include -#include "sys/event.h" #include "private.h" #ifndef NDEBUG diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index f48137f2e..4a66eda3a 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -40,9 +40,6 @@ # pragma warning( disable : 4996 ) #endif -#include "../../include/sys/event.h" - - /* * Atomic integer operations */ From fe5ab47407419fa27cd272674bc48603ed8ba803 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 1 Sep 2021 09:12:54 -0500 Subject: [PATCH 0869/1120] Use branchless comparator for knotes --- vendor/libkqueue/src/common/knote.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index ddfdb75da..9af70ba06 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -27,10 +27,22 @@ knote_init(void) // return (mem_init(sizeof(struct knote), 1024)); } +/** Comparator for the knote_index + * + * FIXME - Should respect EV_UDATA_SPECIFIC but that's a whole + * lot of additional work. + * + * @param[in] a First knote to compare. + * @param[in] b Second knote to compare. + * @return + * - +1 if a's ident is > than b's. + * - 0 if a and b's ident are equal. + * - -1 if a's ident is < than b's. + */ static int knote_cmp(struct knote *a, struct knote *b) { - return memcmp(&a->kev.ident, &b->kev.ident, sizeof(a->kev.ident)); + return (a->kev.ident > b->kev.ident) - (a->kev.ident < b->kev.ident); } RB_GENERATE(knt, knote, kn_entries, knote_cmp) From 27fc0a9879d93d96a4007ebf3494c4462d3dcd4f Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 1 Sep 2021 10:52:20 -0500 Subject: [PATCH 0870/1120] Don't build posix/platform.c for linux or solaris If we need to use common filters from posix, then their interaction with the rest of the code needs to be abstracted. Including posix/platform.h causes conflits. --- vendor/libkqueue/CMakeLists.txt | 4 ---- vendor/libkqueue/src/common/filter.c | 2 -- vendor/libkqueue/src/common/private.h | 5 +---- vendor/libkqueue/src/posix/platform.c | 5 ++++- vendor/libkqueue/src/posix/platform.h | 4 ++++ 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index cc3946a54..4a31c73ef 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -162,8 +162,6 @@ if(CMAKE_SYSTEM_NAME MATCHES Windows) src/windows/user.c) elseif(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") list(APPEND LIBKQUEUE_SOURCES - src/posix/platform.c - src/posix/platform.h src/solaris/platform.c src/solaris/platform.h src/solaris/signal.c @@ -178,8 +176,6 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL Linux) set (CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "default install path" FORCE ) endif() list(APPEND LIBKQUEUE_SOURCES - src/posix/platform.c - src/posix/platform.h src/linux/platform.c src/linux/platform.h src/linux/read.c diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index f53e09cf5..47ae473e6 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -82,7 +82,6 @@ filter_register_all(struct kqueue *kq) { int rv; - FD_ZERO(&kq->kq_fds); rv = 0; rv += filter_register(kq, &evfilt_read); rv += filter_register(kq, &evfilt_write); @@ -91,7 +90,6 @@ filter_register_all(struct kqueue *kq) rv += filter_register(kq, &evfilt_proc); rv += filter_register(kq, &evfilt_timer); rv += filter_register(kq, &evfilt_user); - kq->kq_nfds++; if (rv != 0) { filter_unregister_all(kq); return (-1); diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 0f9054ab0..d32c21ebd 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -49,10 +49,8 @@ struct evfilt_data; # include # endif #elif defined(__linux__) -# include "../posix/platform.h" # include "../linux/platform.h" #elif defined(__sun) -# include "../posix/platform.h" # include "../solaris/platform.h" #else # error Unknown platform @@ -248,10 +246,9 @@ struct kqueue { struct filter kq_filt[EVFILT_SYSCOUNT]; //!< Filters supported by the kqueue. Each ///< kqueue maintains one filter state structure ///< per filter type. - fd_set kq_fds, kq_rfds; - int kq_nfds; tracing_mutex_t kq_mtx; volatile uint32_t kq_ref; + #if defined(KQUEUE_PLATFORM_SPECIFIC) KQUEUE_PLATFORM_SPECIFIC; #endif diff --git a/vendor/libkqueue/src/posix/platform.c b/vendor/libkqueue/src/posix/platform.c index d00686855..5e8744ec5 100644 --- a/vendor/libkqueue/src/posix/platform.c +++ b/vendor/libkqueue/src/posix/platform.c @@ -15,10 +15,13 @@ */ #include "../common/private.h" +#include "platform.h" int -posix_kqueue_init(struct kqueue *kq UNUSED) +posix_kqueue_init(struct kqueue *kq) { + FD_ZERO(&kq->kq_fds); + kq->kq_nfds++; return (0); } diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 5dd31a409..e6c63edfb 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -41,6 +41,10 @@ #define EVENTFD_PLATFORM_SPECIFIC \ int ef_wfd +#define KQUEUE_PLATFORM_SPECIFIC \ + fd_set kq_fds, kq_rfds; \ + int kq_nfds + void posix_kqueue_free(struct kqueue *); int posix_kqueue_init(struct kqueue *); From 6eb245765373694a58b5ceea6bcc6259442515ca Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 1 Sep 2021 11:12:25 -0500 Subject: [PATCH 0871/1120] Move kqops to the bottom of linux/platform.c This lets us remove the public declarations --- vendor/libkqueue/src/linux/platform.c | 38 +++++++++++++-------------- vendor/libkqueue/src/linux/platform.h | 12 --------- 2 files changed, 19 insertions(+), 31 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 941ccb507..02424b7f0 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -63,18 +63,6 @@ static unsigned int *fd_use_cnt; static int nb_max_fd; -const struct kqueue_vtable kqops = { - .kqueue_init = linux_kqueue_init, - .kqueue_free = linux_kqueue_free, - .kevent_wait = linux_kevent_wait, - .kevent_copyout = linux_kevent_copyout, - .eventfd_init = linux_eventfd_init, - .eventfd_close = linux_eventfd_close, - .eventfd_raise = linux_eventfd_raise, - .eventfd_lower = linux_eventfd_lower, - .eventfd_descriptor = linux_eventfd_descriptor, -}; - static void linux_kqueue_cleanup(struct kqueue *kq); @@ -275,7 +263,7 @@ linux_kqueue_start_thread(void) pthread_mutex_unlock(&mt_mtx); } -int +static int linux_kqueue_init(struct kqueue *kq) { struct f_owner_ex sig_owner; @@ -452,7 +440,7 @@ linux_kqueue_cleanup(struct kqueue *kq) * KQ fd is in use, and we shouldn't attempt to free it if we * receive a signal in the monitoring thread. */ -void +static void linux_kqueue_free(struct kqueue *kq) { linux_kqueue_cleanup(kq); @@ -499,7 +487,7 @@ linux_kevent_wait_hires( return (n); } -int +static int linux_kevent_wait(struct kqueue *kq, int nevents, const struct timespec *ts) { int timeout, nret; @@ -688,7 +676,7 @@ linux_eventfd_init(struct eventfd *e) return (0); } -void +static void linux_eventfd_close(struct eventfd *e) { if (close(e->ef_id) < 0) @@ -696,7 +684,7 @@ linux_eventfd_close(struct eventfd *e) e->ef_id = -1; } -int +static int linux_eventfd_raise(struct eventfd *e) { uint64_t counter; @@ -722,7 +710,7 @@ linux_eventfd_raise(struct eventfd *e) return (rv); } -int +static int linux_eventfd_lower(struct eventfd *e) { uint64_t cur; @@ -754,7 +742,7 @@ linux_eventfd_lower(struct eventfd *e) return (rv); } -int +static int linux_eventfd_descriptor(struct eventfd *e) { return (e->ef_id); @@ -1350,3 +1338,15 @@ linux_fd_to_path(char *buf, size_t bufsz, int fd) memset(buf, 0, bufsz); return (readlink(path, buf, bufsz)); } + +const struct kqueue_vtable kqops = { + .kqueue_init = linux_kqueue_init, + .kqueue_free = linux_kqueue_free, + .kevent_wait = linux_kevent_wait, + .kevent_copyout = linux_kevent_copyout, + .eventfd_init = linux_eventfd_init, + .eventfd_close = linux_eventfd_close, + .eventfd_raise = linux_eventfd_raise, + .eventfd_lower = linux_eventfd_lower, + .eventfd_descriptor = linux_eventfd_descriptor, +}; diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index e0c1f425a..b71a3e501 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -197,20 +197,8 @@ struct fd_state { struct epoll_event kq_plist[MAX_KEVENT]; \ size_t kq_nplist -int linux_kqueue_init(struct kqueue *); -void linux_kqueue_free(struct kqueue *); - -int linux_kevent_wait(struct kqueue *, int, const struct timespec *); -int linux_kevent_copyout(struct kqueue *, int, struct kevent *, int); - int linux_knote_copyout(struct kevent *, struct knote *); -int linux_eventfd_init(struct eventfd *); -void linux_eventfd_close(struct eventfd *); -int linux_eventfd_raise(struct eventfd *); -int linux_eventfd_lower(struct eventfd *); -int linux_eventfd_descriptor(struct eventfd *); - /* utility functions */ int linux_get_descriptor_type(struct knote *); From c09f36351b2909dd9bbb2451fa222bfa8a0e27b5 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 1 Sep 2021 11:19:26 -0500 Subject: [PATCH 0872/1120] Rename knote rbtree to make it clearer what it's used for --- vendor/libkqueue/src/common/filter.c | 2 +- vendor/libkqueue/src/common/knote.c | 23 ++++++----------- vendor/libkqueue/src/common/private.h | 37 ++++++++++++++++++++------- 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index 47ae473e6..f6f026aab 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -46,7 +46,7 @@ filter_register(struct kqueue *kq, const struct filter *src) dst = &kq->kq_filt[filt]; memcpy(dst, src, sizeof(*src)); dst->kf_kqueue = kq; - RB_INIT(&dst->kf_knote); + RB_INIT(&dst->kf_index); pthread_rwlock_init(&dst->kf_knote_mtx, NULL); if (src->kf_id == 0) { dbg_puts("filter is not implemented"); diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 9af70ba06..f1f0f96c6 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -45,7 +45,7 @@ knote_cmp(struct knote *a, struct knote *b) return (a->kev.ident > b->kev.ident) - (a->kev.ident < b->kev.ident); } -RB_GENERATE(knt, knote, kn_entries, knote_cmp) +RB_GENERATE(knote_index, knote, kn_index, knote_cmp) struct knote * knote_new(void) @@ -82,7 +82,7 @@ void knote_insert(struct filter *filt, struct knote *kn) { pthread_rwlock_wrlock(&filt->kf_knote_mtx); - RB_INSERT(knt, &filt->kf_knote, kn); + RB_INSERT(knote_index, &filt->kf_index, kn); pthread_rwlock_unlock(&filt->kf_knote_mtx); } @@ -95,7 +95,7 @@ knote_lookup(struct filter *filt, uintptr_t ident) query.kev.ident = ident; pthread_rwlock_rdlock(&filt->kf_knote_mtx); - ent = RB_FIND(knt, &filt->kf_knote, &query); + ent = RB_FIND(knote_index, &filt->kf_index, &query); pthread_rwlock_unlock(&filt->kf_knote_mtx); return (ent); @@ -106,14 +106,8 @@ int knote_delete_all(struct filter *filt) struct knote *kn, *tmp; pthread_rwlock_wrlock(&filt->kf_knote_mtx); - RB_FOREACH_SAFE(kn, knt, &filt->kf_knote, tmp) { - /* Check return code */ - filt->kn_delete(filt, kn); - - kn->kn_flags |= KNFL_KNOTE_DELETED; - - knote_release(kn); - } + RB_FOREACH_SAFE(kn, knote_index, &filt->kf_index, tmp) + knote_delete(filt, kn); pthread_rwlock_unlock(&filt->kf_knote_mtx); return (0); } @@ -137,10 +131,9 @@ knote_delete(struct filter *filt, struct knote *kn) */ query.kev.ident = kn->kev.ident; pthread_rwlock_wrlock(&filt->kf_knote_mtx); - tmp = RB_FIND(knt, &filt->kf_knote, &query); - if (tmp == kn) { - RB_REMOVE(knt, &filt->kf_knote, kn); - } + tmp = RB_FIND(knote_index, &filt->kf_index, &query); + if (tmp == kn) + RB_REMOVE(knote_index, &filt->kf_index, kn); pthread_rwlock_unlock(&filt->kf_knote_mtx); rv = filt->kn_delete(filt, kn); diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index d32c21ebd..cae23ab17 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -149,11 +149,14 @@ struct knote { } data; struct kqueue *kn_kq; //!< kqueue this knote is associated with. - atomic_uint kn_ref; + atomic_uint kn_ref; //!< Reference counter for this knote. + + RB_ENTRY(knote) kn_index; //!< Entry in tree holding all knotes associated + ///< with a given filter. #if defined(KNOTE_PLATFORM_SPECIFIC) KNOTE_PLATFORM_SPECIFIC; #endif - RB_ENTRY(knote) kn_entries; + }; /** Mark a knote as enabled @@ -178,7 +181,7 @@ struct knote { * * Filters handle notifications from different event sources. * The EVFILT_READ filter, for example, provides notifications when an FD is - * readable, and EVFILT_SIGNAL filter provides notifications when a particular + * readable, and the EVFILT_SIGNAL filter provides notifications when a particular * signal is received by the process/thread. * * Many of the fields in this struct are callbacks for functions which operate @@ -217,17 +220,33 @@ struct filter { int (*kn_enable)(struct filter *, struct knote *); int (*kn_disable)(struct filter *, struct knote *); - struct eventfd kf_efd; //!< Used by user.c - //MOVE TO POSIX? int kf_pfd; //!< fd to poll(2) for readiness int kf_wfd; //!< fd to write when an event occurs //----? - struct evfilt_data *kf_data; //!< filter-specific data */ - RB_HEAD(knt, knote) kf_knote; - pthread_rwlock_t kf_knote_mtx; - struct kqueue *kf_kqueue; + struct evfilt_data *kf_data; //!< Filter-specific data. + + RB_HEAD(knote_index, knote) kf_index; //!< Tree of knotes. This is for easy lookup + ///< and removal of knotes. All knotes are + ///< directly owned by a filter. + + struct eventfd kf_efd; //!< An eventfd associated with the filter. + ///< This is used in conjunction with the + ///< kf_ready list. When the eventfd is + ///< "raised", and the platform's eventing + ///< is blocked (waiting for events), the + ///< current epoll/select/etc... call returns + ///< and we process the knotes in the kf_ready + ///< list. + ///< This is not used by all filters. + + + pthread_rwlock_t kf_knote_mtx; //!< Used to synchronise knote operations + ///< on this filter. + + struct kqueue *kf_kqueue; //!< kqueue this filter is associated with. + #if defined(FILTER_PLATFORM_SPECIFIC) FILTER_PLATFORM_SPECIFIC; #endif From 56126e8458ac9991b5e78775309199689c880dcb Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 1 Sep 2021 11:26:23 -0500 Subject: [PATCH 0873/1120] Add common ready list for filters This helps with posix/proc.c as it needs to store multiple ready knotes against a filter. This may also help with linux/socket.c as we can put events which we were notified of, but didn't have space for, in the ready list. --- vendor/libkqueue/src/common/knote.c | 12 +++++++++++- vendor/libkqueue/src/common/private.h | 11 +++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index f1f0f96c6..803c29ef0 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -134,6 +134,9 @@ knote_delete(struct filter *filt, struct knote *kn) tmp = RB_FIND(knote_index, &filt->kf_index, &query); if (tmp == kn) RB_REMOVE(knote_index, &filt->kf_index, kn); + + if (LIST_INSERTED(kn, kn_ready)) + LIST_REMOVE(kn, kn_ready); pthread_rwlock_unlock(&filt->kf_knote_mtx); rv = filt->kn_delete(filt, kn); @@ -155,7 +158,14 @@ knote_disable(struct filter *filt, struct knote *kn) dbg_printf("kn=%p - calling kn_disable", kn); rv = filt->kn_disable(filt, kn); dbg_printf("kn=%p - kn_disable rv=%i", kn, rv); - if (rv == 0) KNOTE_DISABLE(kn); + if (rv == 0) { + pthread_rwlock_wrlock(&filt->kf_knote_mtx); + if (LIST_INSERTED(kn, kn_ready)) /* No longer marked as ready if disabled */ + LIST_REMOVE(kn, kn_ready); + pthread_rwlock_unlock(&filt->kf_knote_mtx); + KNOTE_DISABLE(kn); /* set the disable flag */ + } + return (rv); } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index cae23ab17..704a6d58e 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -153,6 +153,11 @@ struct knote { RB_ENTRY(knote) kn_index; //!< Entry in tree holding all knotes associated ///< with a given filter. + + LIST_ENTRY(knote) kn_ready; //!< Entry in a linked list of knotes which are + ///< ready for copyout. This isn't used for all + ///< filters. + #if defined(KNOTE_PLATFORM_SPECIFIC) KNOTE_PLATFORM_SPECIFIC; #endif @@ -241,6 +246,12 @@ struct filter { ///< list. ///< This is not used by all filters. + LIST_HEAD(knote_ready, knote) kf_ready; //!< knotes which are ready for copyout. + ///< This is used for filters which don't + ///< raise events using the platform's + ///< eventing system, and instead signal + ///< with eventfds. + ///< This is not used by all filters. pthread_rwlock_t kf_knote_mtx; //!< Used to synchronise knote operations ///< on this filter. From 12f9772742e5b5a6a49bdfb615e12f99bc3e8141 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 1 Sep 2021 11:39:00 -0500 Subject: [PATCH 0874/1120] Expose the posix/eventfd code separately Not at all convinced posix/platform.c or posix/platform.h is useful. They should likely be removed in future as POSIX isn't a target, it's just a repository of common POSIX compatible code. --- vendor/libkqueue/CMakeLists.txt | 2 + vendor/libkqueue/src/posix/eventfd.c | 79 +++++++++++++++++++++++++ vendor/libkqueue/src/posix/eventfd.h | 22 +++++++ vendor/libkqueue/src/posix/platform.c | 62 ------------------- vendor/libkqueue/src/posix/platform.h | 6 -- vendor/libkqueue/src/solaris/platform.h | 2 + 6 files changed, 105 insertions(+), 68 deletions(-) create mode 100644 vendor/libkqueue/src/posix/eventfd.c create mode 100644 vendor/libkqueue/src/posix/eventfd.h diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 4a31c73ef..b97b4848a 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -162,6 +162,8 @@ if(CMAKE_SYSTEM_NAME MATCHES Windows) src/windows/user.c) elseif(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") list(APPEND LIBKQUEUE_SOURCES + src/posix/eventfd.c + src/posix/eventfd.h src/solaris/platform.c src/solaris/platform.h src/solaris/signal.c diff --git a/vendor/libkqueue/src/posix/eventfd.c b/vendor/libkqueue/src/posix/eventfd.c new file mode 100644 index 000000000..f6016485a --- /dev/null +++ b/vendor/libkqueue/src/posix/eventfd.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "../common/private.h" + +int +posix_eventfd_init(struct eventfd *e) +{ + int sd[2]; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sd) < 0) { + return (-1); + } + if ((fcntl(sd[0], F_SETFL, O_NONBLOCK) < 0) || + (fcntl(sd[1], F_SETFL, O_NONBLOCK) < 0)) { + close(sd[0]); + close(sd[1]); + return (-1); + } + e->ef_wfd = sd[0]; + e->ef_id = sd[1]; + + return (0); +} + +void +posix_eventfd_close(struct eventfd *e) +{ + close(e->ef_id); + close(e->ef_wfd); + e->ef_id = -1; +} + +int +posix_eventfd_raise(struct eventfd *e) +{ + dbg_puts("raising event level"); + if (write(e->ef_wfd, ".", 1) < 0) { + /* FIXME: handle EAGAIN and EINTR */ + dbg_printf("write(2) on fd %d: %s", e->ef_wfd, strerror(errno)); + return (-1); + } + return (0); +} + +int +posix_eventfd_lower(struct eventfd *e) +{ + char buf[1024]; + + /* Reset the counter */ + dbg_puts("lowering event level"); + if (read(e->ef_id, &buf, sizeof(buf)) < 0) { + /* FIXME: handle EAGAIN and EINTR */ + /* FIXME: loop so as to consume all data.. may need mutex */ + dbg_printf("read(2): %s", strerror(errno)); + return (-1); + } + return (0); +} + +int +posix_eventfd_descriptor(struct eventfd *e) +{ + return (e->ef_id); +} + diff --git a/vendor/libkqueue/src/posix/eventfd.h b/vendor/libkqueue/src/posix/eventfd.h new file mode 100644 index 000000000..dbcfb1ce0 --- /dev/null +++ b/vendor/libkqueue/src/posix/eventfd.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "../common/private.h" + +int posix_eventfd_init(struct eventfd *); +void posix_eventfd_close(struct eventfd *); +int posix_eventfd_raise(struct eventfd *); +int posix_eventfd_lower(struct eventfd *); +int posix_eventfd_descriptor(struct eventfd *); diff --git a/vendor/libkqueue/src/posix/platform.c b/vendor/libkqueue/src/posix/platform.c index 5e8744ec5..29c523075 100644 --- a/vendor/libkqueue/src/posix/platform.c +++ b/vendor/libkqueue/src/posix/platform.c @@ -29,65 +29,3 @@ void posix_kqueue_free(struct kqueue *kq UNUSED) { } - -int -posix_eventfd_init(struct eventfd *e) -{ - int sd[2]; - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, sd) < 0) { - return (-1); - } - if ((fcntl(sd[0], F_SETFL, O_NONBLOCK) < 0) || - (fcntl(sd[1], F_SETFL, O_NONBLOCK) < 0)) { - close(sd[0]); - close(sd[1]); - return (-1); - } - e->ef_wfd = sd[0]; - e->ef_id = sd[1]; - - return (0); -} - -void -posix_eventfd_close(struct eventfd *e) -{ - close(e->ef_id); - close(e->ef_wfd); - e->ef_id = -1; -} - -int -posix_eventfd_raise(struct eventfd *e) -{ - dbg_puts("raising event level"); - if (write(e->ef_wfd, ".", 1) < 0) { - /* FIXME: handle EAGAIN and EINTR */ - dbg_printf("write(2) on fd %d: %s", e->ef_wfd, strerror(errno)); - return (-1); - } - return (0); -} - -int -posix_eventfd_lower(struct eventfd *e) -{ - char buf[1024]; - - /* Reset the counter */ - dbg_puts("lowering event level"); - if (read(e->ef_id, &buf, sizeof(buf)) < 0) { - /* FIXME: handle EAGAIN and EINTR */ - /* FIXME: loop so as to consume all data.. may need mutex */ - dbg_printf("read(2): %s", strerror(errno)); - return (-1); - } - return (0); -} - -int -posix_eventfd_descriptor(struct eventfd *e) -{ - return (e->ef_id); -} diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index e6c63edfb..94e1a8b26 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -51,10 +51,4 @@ int posix_kqueue_init(struct kqueue *); int posix_kevent_wait(struct kqueue *, const struct timespec *); int posix_kevent_copyout(struct kqueue *, int, struct kevent *, int); -int posix_eventfd_init(struct eventfd *); -void posix_eventfd_close(struct eventfd *); -int posix_eventfd_raise(struct eventfd *); -int posix_eventfd_lower(struct eventfd *); -int posix_eventfd_descriptor(struct eventfd *); - #endif /* ! _KQUEUE_POSIX_PLATFORM_H */ diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index 6b1dd9ff7..89c217d7b 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -25,6 +25,8 @@ #include #include +#include "../posix/eventfd.h" + #define atomic_uintptr_t uintptr_t #define atomic_uint unsigned int #define atomic_inc atomic_inc_32_nv From 516c85264e1bd01f880d32fa44f08ea4e234cfa2 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 1 Sep 2021 12:41:01 -0500 Subject: [PATCH 0875/1120] kq_ref is unused --- vendor/libkqueue/src/common/private.h | 1 - 1 file changed, 1 deletion(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 704a6d58e..a0a38be3b 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -277,7 +277,6 @@ struct kqueue { ///< kqueue maintains one filter state structure ///< per filter type. tracing_mutex_t kq_mtx; - volatile uint32_t kq_ref; #if defined(KQUEUE_PLATFORM_SPECIFIC) KQUEUE_PLATFORM_SPECIFIC; From 0130f6269738209abfae099a553d992854355eb9 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 1 Sep 2021 12:45:44 -0500 Subject: [PATCH 0876/1120] Remove all platform specific fields from common structures Move POSIX specific fields out of private.h Switch to using an anonymous union in the Linux knote structure --- vendor/libkqueue/src/common/private.h | 17 ------------ vendor/libkqueue/src/linux/platform.h | 9 +++++-- vendor/libkqueue/src/linux/proc.c | 16 +++++------ vendor/libkqueue/src/linux/read.c | 36 ++++++++++++------------- vendor/libkqueue/src/linux/signal.c | 12 ++++----- vendor/libkqueue/src/linux/timer.c | 14 +++++----- vendor/libkqueue/src/linux/user.c | 18 ++++++------- vendor/libkqueue/src/linux/vnode.c | 22 +++++++-------- vendor/libkqueue/src/linux/write.c | 8 +++--- vendor/libkqueue/src/posix/platform.h | 9 ++++++- vendor/libkqueue/src/posix/timer.c | 16 +++++------ vendor/libkqueue/src/posix/user.c | 2 +- vendor/libkqueue/src/solaris/platform.h | 6 +++++ vendor/libkqueue/src/solaris/timer.c | 14 +++++----- vendor/libkqueue/src/windows/platform.h | 3 ++- vendor/libkqueue/src/windows/read.c | 14 +++++----- vendor/libkqueue/src/windows/timer.c | 10 +++---- 17 files changed, 114 insertions(+), 112 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index a0a38be3b..e7e71c846 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -135,18 +135,6 @@ struct knote { ///< it is enabled and what type of ///< socket/file/device it refers to. ///< See the KNFL_* macros for more details. - union { - /* OLD */ - int pfd; //!< Used by timerfd. - int events; //!< Used by socket. - struct { - nlink_t nlink; //!< Used by vnode. - off_t size; //!< Used by vnode. - } vnode; - timer_t timerid; - struct sleepreq *sleepreq; //!< Used by posix/timer.c. - void *handle; //!< Used by win32 filters. - } data; struct kqueue *kn_kq; //!< kqueue this knote is associated with. atomic_uint kn_ref; //!< Reference counter for this knote. @@ -225,11 +213,6 @@ struct filter { int (*kn_enable)(struct filter *, struct knote *); int (*kn_disable)(struct filter *, struct knote *); - //MOVE TO POSIX? - int kf_pfd; //!< fd to poll(2) for readiness - int kf_wfd; //!< fd to write when an event occurs - //----? - struct evfilt_data *kf_data; //!< Filter-specific data. RB_HEAD(knote_index, knote) kf_index; //!< Tree of knotes. This is for easy lookup diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index b71a3e501..6e623d6d0 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -178,13 +178,18 @@ struct fd_state { int kn_epollfd; /* A copy of filter->epoll_fd */ \ int kn_registered; /* Is FD registered with epoll */ \ struct fd_state *kn_fds; /* File descriptor's registration state */ \ + int epoll_events; /* Which events this file descriptor is registered for */ \ union { \ int kn_timerfd; \ int kn_signalfd; \ - int kn_inotifyfd; \ int kn_procfd; \ int kn_eventfd; \ - } kdata; \ + struct { \ + nlink_t nlink; \ + off_t size; \ + int inotifyfd; \ + } kn_vnode; \ + }; \ struct epoll_udata kn_udata /* Common struct passed to epoll */ /** Additional members of struct kqueue diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index 82cfa433d..5fe613db1 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -81,7 +81,7 @@ evfilt_proc_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, U int evfilt_proc_knote_enable(struct filter *filt, struct knote *kn) { - if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_ADD, kn->kdata.kn_procfd, EPOLL_EV_KN(EPOLLIN, kn)) < 0) { + if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_ADD, kn->kn_procfd, EPOLL_EV_KN(EPOLLIN, kn)) < 0) { dbg_printf("epoll_ctl(2): %s", strerror(errno)); return -1; } @@ -91,7 +91,7 @@ evfilt_proc_knote_enable(struct filter *filt, struct knote *kn) int evfilt_proc_knote_disable(struct filter *filt, struct knote *kn) { - if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, kn->kdata.kn_procfd, NULL) < 0) { + if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, kn->kn_procfd, NULL) < 0) { dbg_printf("epoll_ctl(2): %s", strerror(errno)); return (-1); } @@ -106,7 +106,7 @@ evfilt_proc_knote_create(struct filter *filt, struct knote *kn) /* This mirrors the behaviour of kqueue if fflags doesn't specify any events */ if (!(kn->kev.fflags & NOTE_EXIT)) { dbg_printf("not monitoring pid=%u as no NOTE_* fflags set", (unsigned int)kn->kev.ident); - kn->kdata.kn_procfd = -1; + kn->kn_procfd = -1; return 0; } @@ -118,7 +118,7 @@ evfilt_proc_knote_create(struct filter *filt, struct knote *kn) } dbg_printf("created pidfd=%i monitoring pid=%u", pfd, (unsigned int)kn->kev.ident); - kn->kdata.kn_procfd = pfd; + kn->kn_procfd = pfd; /* * These get added by default on macOS (and likely FreeBSD) @@ -140,7 +140,7 @@ evfilt_proc_knote_modify(struct filter *filt, struct knote *kn, const struct kev kn->kev.flags = kev->flags; kn->kev.fflags = kev->fflags; - if (kn->kdata.kn_procfd < 0) return evfilt_proc_knote_create(filt, kn); + if (kn->kn_procfd < 0) return evfilt_proc_knote_create(filt, kn); return (0); } @@ -153,9 +153,9 @@ evfilt_proc_knote_delete(struct filter *filt, struct knote *kn) /* If it's enabled, we need to remove the pidfd from epoll */ if (KNOTE_ENABLED(kn) && (evfilt_proc_knote_disable(filt, kn) < 0)) rv = -1; - dbg_printf("closed pidfd=%i", kn->kdata.kn_procfd); - if (close(kn->kdata.kn_procfd) < 0) rv = -1; - kn->kdata.kn_procfd = -1; + dbg_printf("closed pidfd=%i", kn->kn_procfd); + if (close(kn->kn_procfd) < 0) rv = -1; + kn->kn_procfd = -1; return (rv); } diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index db4d6cd75..347fe5f7a 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -57,14 +57,14 @@ evfilt_read_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, v if (dst->data == 0) { dst->filter = 0; /* Will cause the kevent to be discarded */ - if (epoll_ctl(src->kn_epollfd, EPOLL_CTL_DEL, src->kdata.kn_eventfd, NULL) < 0) { + if (epoll_ctl(src->kn_epollfd, EPOLL_CTL_DEL, src->kn_eventfd, NULL) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); } src->kn_registered = 0; #if FIXME - /* XXX-FIXME Switch to using kn_inotifyfd to monitor for IN_ATTRIB events + /* XXX-FIXME Switch to using kn_vnode.inotifyfd to monitor for IN_ATTRIB events that may signify the file size has changed. This code is not tested. @@ -78,14 +78,14 @@ evfilt_read_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, v (void) close(inofd); return (-1); } - src->kdata.kn_inotifyfd = inofd; + src->kn_vnode.inotifyfd = inofd; if (linux_fd_to_path(path, sizeof(path), src->kev.ident) < 0) return (-1); if (inotify_add_watch(inofd, path, IN_ATTRIB) < 0) { dbg_perror("inotify_add_watch"); return (-1); } - if (epoll_ctl(src->kn_epollfd, EPOLL_CTL_ADD, src->kdata.kn_inotifyfd, NULL) < 0) { + if (epoll_ctl(src->kn_epollfd, EPOLL_CTL_ADD, src->kn_vnode.inotifyfd, NULL) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); } @@ -144,12 +144,12 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) /* Convert the kevent into an epoll_event */ #if defined(HAVE_EPOLLRDHUP) - kn->data.events = EPOLLIN | EPOLLRDHUP; + kn->epoll_events = EPOLLIN | EPOLLRDHUP; #else - kn->data.events = EPOLLIN; + kn->epoll_events = EPOLLIN; #endif if (kn->kev.flags & EV_CLEAR) - kn->data.events |= EPOLLET; + kn->epoll_events |= EPOLLET; /* Special case: for regular files, add a surrogate eventfd that is always readable */ if (kn->kn_flags & KNFL_FILE) { @@ -166,7 +166,7 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) * https://stackoverflow.com/questions/59517961/how-should-i-use-epoll-to-read-and-write-from-the-same-fd */ if (kn->kev.flags & EV_ONESHOT || kn->kev.flags & EV_DISPATCH) - kn->data.events |= EPOLLONESHOT; + kn->epoll_events |= EPOLLONESHOT; kn->kn_epollfd = filter_epoll_fd(filt); evfd = eventfd(0, 0); @@ -180,10 +180,10 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) return (-1); } - kn->kdata.kn_eventfd = evfd; + kn->kn_eventfd = evfd; KN_UDATA(kn); /* populate this knote's kn_udata field */ - if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_eventfd, EPOLL_EV_KN(kn->data.events, kn)) < 0) { + if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kn_eventfd, EPOLL_EV_KN(kn->epoll_events, kn)) < 0) { dbg_printf("epoll_ctl(2): %s", strerror(errno)); (void) close(evfd); return (-1); @@ -194,7 +194,7 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) return (0); } - return epoll_update(EPOLL_CTL_ADD, filt, kn, kn->data.events, false); + return epoll_update(EPOLL_CTL_ADD, filt, kn, kn->epoll_events, false); } int @@ -210,14 +210,14 @@ evfilt_read_knote_modify(struct filter *filt, struct knote *kn, int evfilt_read_knote_delete(struct filter *filt, struct knote *kn) { - if ((kn->kn_flags & KNFL_FILE) && (kn->kdata.kn_eventfd != -1)) { - if (kn->kn_registered && epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kdata.kn_eventfd, NULL) < 0) { + if ((kn->kn_flags & KNFL_FILE) && (kn->kn_eventfd != -1)) { + if (kn->kn_registered && epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kn_eventfd, NULL) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); } kn->kn_registered = 0; - (void) close(kn->kdata.kn_eventfd); - kn->kdata.kn_eventfd = -1; + (void) close(kn->kn_eventfd); + kn->kn_eventfd = -1; return (0); } @@ -228,7 +228,7 @@ int evfilt_read_knote_enable(struct filter *filt, struct knote *kn) { if (kn->kn_flags & KNFL_FILE) { - if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_eventfd, EPOLL_EV_KN(kn->data.events, kn)) < 0) { + if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kn_eventfd, EPOLL_EV_KN(kn->epoll_events, kn)) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); } @@ -236,14 +236,14 @@ evfilt_read_knote_enable(struct filter *filt, struct knote *kn) return (0); } - return epoll_update(EPOLL_CTL_ADD, filt, kn, kn->data.events, false); + return epoll_update(EPOLL_CTL_ADD, filt, kn, kn->epoll_events, false); } int evfilt_read_knote_disable(struct filter *filt, struct knote *kn) { if (kn->kn_flags & KNFL_FILE) { - if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kdata.kn_eventfd, NULL) < 0) { + if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kn_eventfd, NULL) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); } diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index 0df3c93c2..2e845fa27 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -129,7 +129,7 @@ evfilt_signal_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, { int sigfd; - sigfd = src->kdata.kn_signalfd; + sigfd = src->kn_signalfd; signalfd_reset(sigfd); @@ -150,10 +150,10 @@ evfilt_signal_knote_create(struct filter *filt, struct knote *kn) fd = signalfd_create(filter_epoll_fd(filt), kn, kn->kev.ident); if (fd > 0) { kn->kev.flags |= EV_CLEAR; - kn->kdata.kn_signalfd = fd; + kn->kn_signalfd = fd; return (0); } else { - kn->kdata.kn_signalfd = -1; + kn->kn_signalfd = -1; return (-1); } } @@ -171,11 +171,11 @@ evfilt_signal_knote_modify(struct filter *filt UNUSED, int evfilt_signal_knote_delete(struct filter *filt, struct knote *kn) { - const int sigfd = kn->kdata.kn_signalfd; + const int sigfd = kn->kn_signalfd; int rv = 0; /* Needed so that delete() can be called after disable() */ - if (kn->kdata.kn_signalfd == -1) + if (kn->kn_signalfd == -1) return (0); rv = epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, sigfd, NULL); @@ -192,7 +192,7 @@ evfilt_signal_knote_delete(struct filter *filt, struct knote *kn) } /* NOTE: This does not call sigprocmask(3) to unblock the signal. */ - kn->kdata.kn_signalfd = -1; + kn->kn_signalfd = -1; return (rv); } diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 019fff89d..06febd351 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -140,7 +140,7 @@ evfilt_timer_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, /* On return, data contains the number of times the timer has been trigered. */ - n = read(src->kdata.kn_timerfd, &expired, sizeof(expired)); + n = read(src->kn_timerfd, &expired, sizeof(expired)); if (n != sizeof(expired)) { dbg_puts("invalid read from timerfd"); expired = 1; /* Fail gracefully */ @@ -191,7 +191,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) return (-1); } - kn->kdata.kn_timerfd = tfd; + kn->kn_timerfd = tfd; return (0); } @@ -210,21 +210,21 @@ evfilt_timer_knote_delete(struct filter *filt, struct knote *kn) { int rv = 0; - if (kn->kdata.kn_timerfd == -1) + if (kn->kn_timerfd == -1) return (0); - if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, kn->kdata.kn_timerfd, NULL) < 0) { + if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, kn->kn_timerfd, NULL) < 0) { dbg_printf("epoll_ctl(2): %s", strerror(errno)); rv = -1; } - dbg_printf("timer_fd=%i - closed", kn->kdata.kn_timerfd); - if (close(kn->kdata.kn_timerfd) < 0) { + dbg_printf("timer_fd=%i - closed", kn->kn_timerfd); + if (close(kn->kn_timerfd) < 0) { dbg_printf("close(2): %s", strerror(errno)); rv = -1; } - kn->kdata.kn_timerfd = -1; + kn->kn_timerfd = -1; return (rv); } diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index ed0f0470f..2d5d1eb1b 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -92,7 +92,7 @@ linux_evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct knote * if (src->kev.flags & EV_CLEAR) src->kev.fflags &= ~NOTE_TRIGGER; if (src->kev.flags & (EV_DISPATCH | EV_CLEAR | EV_ONESHOT)) { - if (eventfd_lower(src->kdata.kn_eventfd) < 0) + if (eventfd_lower(src->kn_eventfd) < 0) return (-1); } @@ -117,7 +117,7 @@ linux_evfilt_user_knote_create(struct filter *filt, struct knote *kn) } error: if (evfd >= 0) close(evfd); - kn->kdata.kn_eventfd = -1; + kn->kn_eventfd = -1; kn->kn_registered = 0; return (-1); } @@ -131,7 +131,7 @@ linux_evfilt_user_knote_create(struct filter *filt, struct knote *kn) goto error; } - kn->kdata.kn_eventfd = evfd; + kn->kn_eventfd = evfd; kn->kn_registered = 1; return (0); @@ -169,7 +169,7 @@ linux_evfilt_user_knote_modify(struct filter *filt UNUSED, struct knote *kn, con if ((!(kn->kev.flags & EV_DISABLE)) && kev->fflags & NOTE_TRIGGER) { kn->kev.fflags |= NOTE_TRIGGER; - if (eventfd_raise(kn->kdata.kn_eventfd) < 0) + if (eventfd_raise(kn->kn_eventfd) < 0) return (-1); } @@ -182,23 +182,23 @@ linux_evfilt_user_knote_delete(struct filter *filt, struct knote *kn) int rv = 0; if (kn->kn_registered) { - rv = epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, kn->kdata.kn_eventfd, NULL); + rv = epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, kn->kn_eventfd, NULL); if (rv < 0) { dbg_perror("epoll_ctl(2)"); } else { dbg_printf("event_fd=%i - removed from epoll_fd=%i", - kn->kdata.kn_eventfd, filter_epoll_fd(filt)); + kn->kn_eventfd, filter_epoll_fd(filt)); } } kn->kn_registered = 0; - dbg_printf("event_fd=%i - closed", kn->kdata.kn_eventfd); - if (close(kn->kdata.kn_eventfd) < 0) { + dbg_printf("event_fd=%i - closed", kn->kn_eventfd); + if (close(kn->kn_eventfd) < 0) { dbg_perror("close(2)"); return (-1); } - kn->kdata.kn_eventfd = -1; + kn->kn_eventfd = -1; return rv; } diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 1ca5289f8..e5d43bceb 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -154,13 +154,13 @@ add_watch(struct filter *filt, struct knote *kn) goto errout; } - kn->kdata.kn_inotifyfd = ifd; + kn->kn_vnode.inotifyfd = ifd; return (0); errout: inotify_rm_watch(ifd, kn->kev.data); - kn->kdata.kn_inotifyfd = -1; + kn->kn_vnode.inotifyfd = -1; (void) close(ifd); return (-1); } @@ -168,7 +168,7 @@ add_watch(struct filter *filt, struct knote *kn) static int delete_watch(struct filter *filt, struct knote *kn) { - int ifd = kn->kdata.kn_inotifyfd; + int ifd = kn->kn_vnode.inotifyfd; if (ifd < 0) return (0); @@ -177,7 +177,7 @@ delete_watch(struct filter *filt, struct knote *kn) return (-1); } (void) close(ifd); - kn->kdata.kn_inotifyfd = -1; + kn->kn_vnode.inotifyfd = -1; return (0); } @@ -190,7 +190,7 @@ evfilt_vnode_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, struct stat sb; evt = (struct inotify_event *)buf; - if (get_one_event(evt, sizeof(buf), src->kdata.kn_inotifyfd) < 0) + if (get_one_event(evt, sizeof(buf), src->kn_vnode.inotifyfd) < 0) return (-1); dbg_printf("inotify event: %s", inotify_event_dump(evt)); @@ -223,18 +223,18 @@ scriptors reference the same file. if ((evt->mask & IN_ATTRIB || evt->mask & IN_MODIFY)) { if (sb.st_nlink == 0 && src->kev.fflags & NOTE_DELETE) dst->fflags |= NOTE_DELETE; - if (sb.st_nlink != src->data.vnode.nlink && + if (sb.st_nlink != src->kn_vnode.nlink && src->kev.fflags & NOTE_LINK) dst->fflags |= NOTE_LINK; #if HAVE_NOTE_TRUNCATE if (sb.st_nsize == 0 && src->kev.fflags & NOTE_TRUNCATE) dst->fflags |= NOTE_TRUNCATE; #endif - if (sb.st_size > src->data.vnode.size && + if (sb.st_size > src->kn_vnode.size && src->kev.fflags & NOTE_WRITE) dst->fflags |= NOTE_EXTEND; - src->data.vnode.nlink = sb.st_nlink; - src->data.vnode.size = sb.st_size; + src->kn_vnode.nlink = sb.st_nlink; + src->kn_vnode.size = sb.st_size; } } @@ -260,8 +260,8 @@ evfilt_vnode_knote_create(struct filter *filt, struct knote *kn) dbg_puts("fstat failed"); return (-1); } - kn->data.vnode.nlink = sb.st_nlink; - kn->data.vnode.size = sb.st_size; + kn->kn_vnode.nlink = sb.st_nlink; + kn->kn_vnode.size = sb.st_size; kn->kev.data = -1; return (add_watch(filt, kn)); diff --git a/vendor/libkqueue/src/linux/write.c b/vendor/libkqueue/src/linux/write.c index e3b5c4b6a..7087e6746 100644 --- a/vendor/libkqueue/src/linux/write.c +++ b/vendor/libkqueue/src/linux/write.c @@ -68,7 +68,7 @@ evfilt_write_knote_create(struct filter *filt, struct knote *kn) /* * Convert the kevent into an epoll_event */ - kn->data.events = EPOLLOUT; + kn->epoll_events = EPOLLOUT; /* * For EV_ONESHOT, EV_DISPATCH we rely on common code @@ -78,9 +78,9 @@ evfilt_write_knote_create(struct filter *filt, struct knote *kn) * https://stackoverflow.com/questions/59517961/how-should-i-use-epoll-to-read-and-write-from-the-same-fd */ if (kn->kev.flags & EV_CLEAR) - kn->data.events |= EPOLLET; + kn->epoll_events |= EPOLLET; - return epoll_update(EPOLL_CTL_ADD, filt, kn, kn->data.events, false); + return epoll_update(EPOLL_CTL_ADD, filt, kn, kn->epoll_events, false); } int @@ -102,7 +102,7 @@ evfilt_write_knote_delete(struct filter *filt, struct knote *kn) int evfilt_write_knote_enable(struct filter *filt, struct knote *kn) { - return epoll_update(EPOLL_CTL_ADD, filt, kn, kn->data.events, false); + return epoll_update(EPOLL_CTL_ADD, filt, kn, kn->epoll_events, false); } int diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 94e1a8b26..42ba4ac21 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -39,12 +39,19 @@ * Additional members of 'struct eventfd' */ #define EVENTFD_PLATFORM_SPECIFIC \ - int ef_wfd + int ef_wfd + +#define FILTER_PLATFORM_SPECIFIC \ + int kf_pfd; /* fd to poll(2) for readiness */ \ + int kf_wfd #define KQUEUE_PLATFORM_SPECIFIC \ fd_set kq_fds, kq_rfds; \ int kq_nfds +#define KNOTE_PLATFORM_SPECIFIC \ + struct sleepreq *kn_sleepreq + void posix_kqueue_free(struct kqueue *); int posix_kqueue_init(struct kqueue *); diff --git a/vendor/libkqueue/src/posix/timer.c b/vendor/libkqueue/src/posix/timer.c index ac23c9b26..d280eaaee 100644 --- a/vendor/libkqueue/src/posix/timer.c +++ b/vendor/libkqueue/src/posix/timer.c @@ -145,7 +145,7 @@ _timer_create(struct filter *filt, struct knote *kn) req->wfd = filt->kf_wfd; req->ident = kn->kev.ident; req->interval = kn->kev.data; - kn->data.sleepreq = req; + kn->kn_sleepreq = req; pthread_cond_init(&req->cond, NULL); pthread_mutex_init(&req->mtx, NULL); @@ -169,14 +169,14 @@ _timer_create(struct filter *filt, struct knote *kn) static int _timer_delete(struct knote *kn) { - if (kn->data.sleepreq != NULL) { + if (kn->kn_sleepreq != NULL) { dbg_puts("deleting timer"); - pthread_mutex_lock(&kn->data.sleepreq->mtx); //FIXME - error check - pthread_cond_signal(&kn->data.sleepreq->cond); //FIXME - error check - pthread_mutex_unlock(&kn->data.sleepreq->mtx); //FIXME - error check - pthread_cond_destroy(&kn->data.sleepreq->cond); //FIXME - error check - free(kn->data.sleepreq); - kn->data.sleepreq = NULL; + pthread_mutex_lock(&kn->kn_sleepreq->mtx); //FIXME - error check + pthread_cond_signal(&kn->kn_sleepreq->cond); //FIXME - error check + pthread_mutex_unlock(&kn->kn_sleepreq->mtx); //FIXME - error check + pthread_cond_destroy(&kn->kn_sleepreq->cond); //FIXME - error check + free(kn->kn_sleepreq); + kn->kn_sleepreq = NULL; } return (0); } diff --git a/vendor/libkqueue/src/posix/user.c b/vendor/libkqueue/src/posix/user.c index 6c4a48df7..b00f0e23d 100644 --- a/vendor/libkqueue/src/posix/user.c +++ b/vendor/libkqueue/src/posix/user.c @@ -53,7 +53,7 @@ posix_evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct knote * if (src->kev.flags & EV_CLEAR) src->kev.fflags &= ~NOTE_TRIGGER; if (src->kev.flags & (EV_DISPATCH | EV_CLEAR | EV_ONESHOT)) { - kqops.eventfd_raise(&src->kdata.kn_eventfd); + kqops.eventfd_raise(&src->kn_eventfd); } if (src->kev.flags & EV_DISPATCH) diff --git a/vendor/libkqueue/src/solaris/platform.h b/vendor/libkqueue/src/solaris/platform.h index 89c217d7b..3edcd6000 100644 --- a/vendor/libkqueue/src/solaris/platform.h +++ b/vendor/libkqueue/src/solaris/platform.h @@ -59,4 +59,10 @@ struct event_buf { TAILQ_ENTRY(event_buf) entries; }; +#define KNOTE_PLATFORM_SPECIFIC \ + timer_t kn_timerid + +#define FILTER_PLATFORM_SPECIFIC \ + int kf_pfd + #endif /* ! _KQUEUE_SOLARIS_PLATFORM_H */ diff --git a/vendor/libkqueue/src/solaris/timer.c b/vendor/libkqueue/src/solaris/timer.c index c607d2140..33cc58995 100644 --- a/vendor/libkqueue/src/solaris/timer.c +++ b/vendor/libkqueue/src/solaris/timer.c @@ -85,15 +85,15 @@ evfilt_timer_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, //if (ev->events & EPOLLERR) // dst->fflags = 1; /* FIXME: Return the actual timer error */ - dst->data = timer_getoverrun(src->data.timerid) + 1; + dst->data = timer_getoverrun(src->kn_timerid) + 1; #if FIXME - timerid = src->data.timerid; + timerid = src->kn_timerid; //should be done in kqops.copyout() if (src->kev.flags & EV_DISPATCH) { - timer_delete(src->data.timerid); + timer_delete(src->kn_timerid); } else if (src->kev.flags & EV_ONESHOT) { - timer_delete(src->data.timerid); + timer_delete(src->kn_timerid); } #endif @@ -128,7 +128,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) return (-1); } - kn->data.timerid = timerid; + kn->kn_timerid = timerid; dbg_printf("th=%lu - created timer", (unsigned long) timerid); return (0); @@ -150,8 +150,8 @@ evfilt_timer_knote_delete(struct filter *filt UNUSED, struct knote *kn) if (kn->kev.flags & EV_DISABLE) return (0); - dbg_printf("th=%d - deleting timer", kn->data.timerid); - return timer_delete(kn->data.timerid); + dbg_printf("th=%d - deleting timer", kn->kn_timerid); + return timer_delete(kn->kn_timerid); } int diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 4a66eda3a..0b641bd7a 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -74,7 +74,8 @@ * Additional members for struct knote */ #define KNOTE_PLATFORM_SPECIFIC \ - HANDLE kn_event_whandle + HANDLE kn_event_whandle; \ + void *kn_handle /* * Some datatype forward declarations diff --git a/vendor/libkqueue/src/windows/read.c b/vendor/libkqueue/src/windows/read.c index 1ffe6d112..44c6fe562 100644 --- a/vendor/libkqueue/src/windows/read.c +++ b/vendor/libkqueue/src/windows/read.c @@ -40,7 +40,7 @@ evfilt_read_callback(void *param, BOOLEAN fired) /* Retrieve the socket events and update the knote */ rv = WSAEnumNetworkEvents( (SOCKET) kn->kev.ident, - kn->data.handle, + kn->kn_handle, &events); if (rv != 0) { dbg_wsalasterror("WSAEnumNetworkEvents"); @@ -144,12 +144,12 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) /* TODO: handle in copyout if (kn->kev.flags & EV_ONESHOT || kn->kev.flags & EV_DISPATCH) - kn->data.events |= EPOLLONESHOT; + kn->epoll_events |= EPOLLONESHOT; if (kn->kev.flags & EV_CLEAR) - kn->data.events |= EPOLLET; + kn->epoll_events |= EPOLLET; */ - kn->data.handle = evt; + kn->kn_handle = evt; if (RegisterWaitForSingleObject(&kn->kn_event_whandle, evt, evfilt_read_callback, kn, INFINITE, 0) == 0) { @@ -171,19 +171,19 @@ evfilt_read_knote_modify(struct filter *filt, struct knote *kn, int evfilt_read_knote_delete(struct filter *filt, struct knote *kn) { - if (kn->data.handle == NULL || kn->kn_event_whandle == NULL) + if (kn->kn_handle == NULL || kn->kn_event_whandle == NULL) return (0); if(!UnregisterWaitEx(kn->kn_event_whandle, INVALID_HANDLE_VALUE)) { dbg_lasterror("UnregisterWait()"); return (-1); } - if (!WSACloseEvent(kn->data.handle)) { + if (!WSACloseEvent(kn->kn_handle)) { dbg_wsalasterror("WSACloseEvent()"); return (-1); } - kn->data.handle = NULL; + kn->kn_handle = NULL; return (0); } diff --git a/vendor/libkqueue/src/windows/timer.c b/vendor/libkqueue/src/windows/timer.c index 69c0f231a..f96e0264e 100644 --- a/vendor/libkqueue/src/windows/timer.c +++ b/vendor/libkqueue/src/windows/timer.c @@ -27,7 +27,7 @@ static int ktimer_delete(struct filter *filt, struct knote *kn) { - if (kn->data.handle == NULL || kn->kn_event_whandle == NULL) + if (kn->kn_handle == NULL || kn->kn_event_whandle == NULL) return (0); if(!UnregisterWaitEx(kn->kn_event_whandle, INVALID_HANDLE_VALUE)) { @@ -35,11 +35,11 @@ ktimer_delete(struct filter *filt, struct knote *kn) return (-1); } - if (!CancelWaitableTimer(kn->data.handle)) { + if (!CancelWaitableTimer(kn->kn_handle)) { dbg_lasterror("CancelWaitableTimer()"); return (-1); } - if (!CloseHandle(kn->data.handle)) { + if (!CloseHandle(kn->kn_handle)) { dbg_lasterror("CloseHandle()"); return (-1); } @@ -47,7 +47,7 @@ ktimer_delete(struct filter *filt, struct knote *kn) if( !(kn->kev.flags & EV_ONESHOT) ) knote_release(kn); - kn->data.handle = NULL; + kn->kn_handle = NULL; return (0); } @@ -136,7 +136,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) return (-1); } - kn->data.handle = th; + kn->kn_handle = th; RegisterWaitForSingleObject(&kn->kn_event_whandle, th, evfilt_timer_callback, kn, INFINITE, 0); knote_retain(kn); From c50fd21b899f047ccb792cbbaac8456c6fac5a8d Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 1 Sep 2021 14:19:22 -0500 Subject: [PATCH 0877/1120] Add more documentation for the structures and types in private.h --- vendor/libkqueue/src/common/private.h | 310 +++++++++++++++++++------- 1 file changed, 230 insertions(+), 80 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index e7e71c846..a2e71d01d 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -126,25 +126,36 @@ struct eventfd { KNFL_SOCKET_SEQPACKET |\ KNFL_SOCKET_RAW) +/** A knote representing an event we need to notify a caller of `kevent() ` about + * + * Knotes are usually associated with a single filter, and hold information about + * an event that the caller (of `kevent()`) is interested in receiving. + * + * Knotes often hold a lot of platform specific data such as file descriptors and + * handles for different eventing/notification systems. + * + * Knotes are reference counted, meaning multiple filters (may in theory) hold a + * reference to them. Deleting a knote from one filter may not free it entirely. + */ struct knote { - struct kevent kev; //!< kevent used to create this knote. - ///< Contains flags/fflags/data/udata etc. + struct kevent kev; //!< kevent used to create this knote. + ///< Contains flags/fflags/data/udata etc. - unsigned int kn_flags; //!< Internal flags used to record additional - ///< information about the knote. i.e. whether - ///< it is enabled and what type of - ///< socket/file/device it refers to. - ///< See the KNFL_* macros for more details. + unsigned int kn_flags; //!< Internal flags used to record additional + ///< information about the knote. i.e. whether + ///< it is enabled and what type of + ///< socket/file/device it refers to. + ///< See the KNFL_* macros for more details. - struct kqueue *kn_kq; //!< kqueue this knote is associated with. - atomic_uint kn_ref; //!< Reference counter for this knote. + struct kqueue *kn_kq; //!< kqueue this knote is associated with. + atomic_uint kn_ref; //!< Reference counter for this knote. - RB_ENTRY(knote) kn_index; //!< Entry in tree holding all knotes associated - ///< with a given filter. + RB_ENTRY(knote) kn_index; //!< Entry in tree holding all knotes associated + ///< with a given filter. - LIST_ENTRY(knote) kn_ready; //!< Entry in a linked list of knotes which are - ///< ready for copyout. This isn't used for all - ///< filters. + LIST_ENTRY(knote) kn_ready; //!< Entry in a linked list of knotes which are + ///< ready for copyout. This isn't used for all + ///< filters. #if defined(KNOTE_PLATFORM_SPECIFIC) KNOTE_PLATFORM_SPECIFIC; @@ -154,20 +165,25 @@ struct knote { /** Mark a knote as enabled */ -#define KNOTE_ENABLE(_kn) do { \ - (_kn)->kev.flags &= ~EV_DISABLE; \ +#define KNOTE_ENABLE(_kn) do { \ + (_kn)->kev.flags &= ~EV_DISABLE;\ } while (0/*CONSTCOND*/) /** Mark a knote as disabled */ -#define KNOTE_DISABLE(_kn) do { \ - (_kn)->kev.flags |= EV_DISABLE; \ +#define KNOTE_DISABLE(_kn) do { \ + (_kn)->kev.flags |= EV_DISABLE; \ } while (0/*CONSTCOND*/) +/** Check if a knote is enabled + */ #define KNOTE_ENABLED(_kn) (!((_kn)->kev.flags & EV_DISABLE)) + +/** Check if a knote is disabled + */ #define KNOTE_DISABLED(_kn) ((_kn)->kev.flags & EV_DISABLE) -/** A filter within a kqueue notification channel +/** A filter (discreet notification channel) within a kqueue * * Filters are discreet event notification facilities within a kqueue. * Filters do not usually interact with each other, and maintain separate states. @@ -178,19 +194,36 @@ struct knote { * signal is received by the process/thread. * * Many of the fields in this struct are callbacks for functions which operate - * on the filer. + * on the filer or its knotes. * - * Callbacks either change the state of the filter itself, or create new - * knotes associated with the filter. The knotes describe a filter-specific - * event the application is interested in receiving. + * Callbacks either change the state of the filter itself, or + * create/modify/delete knotes associated with the filter. + * The knotes describe a filter-specific event the application is interested in + * receiving. * */ struct filter { - short kf_id; //!< EVFILT_* facility this filter provides. + short kf_id; //!< EVFILT_* facility this filter provides. + + /** Perform initialisation for this filter + * + * This is called once per filer per kqueue as the kqueue is initialised. + * + * @param[in] filt to initialise. + * @return + * - 0 on success. + * - -1 on failure. + */ + int (*kf_init)(struct filter *filt); - /* filter operations */ - int (*kf_init)(struct filter *); - void (*kf_destroy)(struct filter *); + /** Perform de-initialisation for this filter + * + * This is called once per filter per kqueue as the kqueue is freed. + * + * This function should free/release any handles or other resources + * held by the filter. + */ + void (*kf_destroy)(struct filter *filt); /** Copy an event from the eventing system to a kevent structure * @@ -202,44 +235,161 @@ struct filter { * i.e. for Linux this would be a `struct epoll_event *`. * @return * - >=0 the number of events copied to el. - * - -1 on failure. + * - -1 on failure setting errno. + */ + int (*kf_copyout)(struct kevent *el, int nevents, struct knote *kn, void *ev); + + /** Complete filter-specific initialisation of a knote + * + * @note This function should not allocate a `struct knote`, zero out the + * `struct knote`, or insert the knote into the kf_index. + * This is done in common code. + * + * This function should allocate any handles or other resources required for + * the knote, and fill in any filter specific data in the knote's structure. + * + * @note Currently all knotes are created "enabled" by the various filters. + * This is arguably a bug, and should be fixed in a future release. + * + * @param[in] filt the knote is associated with. + * @param[in] kn to initialise. + * @return + * - 0 on success. + * - -1 on failure setting errno. + */ + int (*kn_create)(struct filter *filt, struct knote *kn); + + /** Modify a knote + * + * This is called when an entry in a changelist is found which has the same + * identifier as a knote associated with this filter. + * + * This function should examine kev and kn->kev for differences and make + * appropriate changes to the knote's event registrations and internal + * state. + * + * This function should also copy the contents of kev to kn->kev if all + * changes were successful. + * + * Changes must be atomic, that is, if this function experiences an error + * making the requested modifications to the knote, the knote should revert + * to the state it was in (and with the same registations) as when this + * function was called. + * + * @param[in] filt the knote is associated with. + * @param[in] kn to modify. + * @param[in] kev the entry in the changelist which triggered the + * modification. + * + * @return + * - 0 on success. + * - -1 on failure setting errno. + */ + int (*kn_modify)(struct filter *filt, struct knote *kn, const struct kevent *kev); + + /** Delete a knote + * + * This is called either when a kqueue is being freed or when a relevant + * EV_DELETE flag is found in the changelist. + * + * @note This function should not free the `struct knote` of remove the + * knote from the kf_index. This is done in common code. + * + * This function should deregister any file descriptors associated with + * this knote from the platform's eventing system. + * + * This function should close all file descriptors and free any other + * resources used by this knote. + * + * Changes must be atomic, that is, if this function experiences an error + * deleting the knote, the knote should revert to the state it was in + * (and with the same registations) as when this function was called. + * + * @param[in] filt the knote is associated with. + * @param[in] kn to delete. + * @return + * - 0 on success. + * - -1 on failure setting errno. + */ + int (*kn_delete)(struct filter *filt, struct knote *kn); + + /** Enable a knote + * + * This is called when a knote is enabled (after first being disabled). + * + * The idea behind having the enable/disable flags for knotes is that it + * allows the caller of `kevent()` to temporarily pause (and later re-enable) + * delivery of notifications without allocating, freeing or releasing any + * resources. + * + * Enabling a knote should re-add any previously removed file descriptors + * from the platform's eventing system. + * + * Changes must be atomic, that is, if this function experiences an + * error deleting the knote, the knote should revert to the state it + * was in (and with the same registations) as when this function was + * called. + * + * @param[in] filt the knote is associated with. + * @param[in] kn to enable. + * @return + * - 0 on success. + * - -1 on failure setting errno. + */ + int (*kn_enable)(struct filter *filt, struct knote *kn); + + /** Disable a knote + * + * This is called when a knote is disabled (after first being created or + * enabled). + * + * Disabling a knote should remove any previously added file descriptors + * from the platform's eventing system. + * + * @note This function should not remove the knote from the filter's + * ready list (if used), as this is done in common code. + * + * Changes must be atomic, that is, if this function experiences an + * error disabling the knote, the knote should revert to the state it + * was in (and with the same registations) as when this function was + * called. + * + * @param[in] filt the knote is associated with. + * @param[in] kn to disable. + * @return + * - 0 on success. + * - -1 on failure setting errno. */ - int (*kf_copyout)(struct kevent *el, int nevents, struct knote *kn, void *ev); - - /* knote operations */ - int (*kn_create)(struct filter *, struct knote *); - int (*kn_modify)(struct filter *, struct knote *, const struct kevent *); - int (*kn_delete)(struct filter *, struct knote *); - int (*kn_enable)(struct filter *, struct knote *); - int (*kn_disable)(struct filter *, struct knote *); - - struct evfilt_data *kf_data; //!< Filter-specific data. - - RB_HEAD(knote_index, knote) kf_index; //!< Tree of knotes. This is for easy lookup - ///< and removal of knotes. All knotes are - ///< directly owned by a filter. - - struct eventfd kf_efd; //!< An eventfd associated with the filter. - ///< This is used in conjunction with the - ///< kf_ready list. When the eventfd is - ///< "raised", and the platform's eventing - ///< is blocked (waiting for events), the - ///< current epoll/select/etc... call returns - ///< and we process the knotes in the kf_ready - ///< list. - ///< This is not used by all filters. - - LIST_HEAD(knote_ready, knote) kf_ready; //!< knotes which are ready for copyout. - ///< This is used for filters which don't - ///< raise events using the platform's - ///< eventing system, and instead signal - ///< with eventfds. - ///< This is not used by all filters. - - pthread_rwlock_t kf_knote_mtx; //!< Used to synchronise knote operations - ///< on this filter. - - struct kqueue *kf_kqueue; //!< kqueue this filter is associated with. + int (*kn_disable)(struct filter *filt, struct knote *kn); + + struct evfilt_data *kf_data; //!< Filter-specific data. + + RB_HEAD(knote_index, knote) kf_index; //!< Tree of knotes. This is for easy lookup + ///< and removal of knotes. All knotes are + ///< directly owned by a filter. + + struct eventfd kf_efd; //!< An eventfd associated with the filter. + ///< This is used in conjunction with the + ///< kf_ready list. When the eventfd is + ///< "raised", and the platform's eventing + ///< is blocked (waiting for events), the + ///< current epoll/select/etc... call returns + ///< and we process the knotes in the kf_ready + ///< list. + ///< This is not used by all filters. + + LIST_HEAD(knote_ready, knote) kf_ready; //!< knotes which are ready for copyout. + ///< This is used for filters which don't + ///< raise events using the platform's + ///< eventing system, and instead signal + ///< with eventfds. + ///< This is not used by all filters. + + pthread_rwlock_t kf_knote_mtx; //!< Used to synchronise knote operations + ///< (addition, removal, modification etc...) + ///< on this filter. + + struct kqueue *kf_kqueue; //!< kqueue this filter is associated with. #if defined(FILTER_PLATFORM_SPECIFIC) FILTER_PLATFORM_SPECIFIC; @@ -255,11 +405,11 @@ struct filter { * in receiving notifications for. */ struct kqueue { - int kq_id; //!< File descriptor used to identify this kqueue. - struct filter kq_filt[EVFILT_SYSCOUNT]; //!< Filters supported by the kqueue. Each - ///< kqueue maintains one filter state structure - ///< per filter type. - tracing_mutex_t kq_mtx; + int kq_id; //!< File descriptor used to identify this kqueue. + struct filter kq_filt[EVFILT_SYSCOUNT]; //!< Filters supported by the kqueue. Each + ///< kqueue maintains one filter state structure + ///< per filter type. + tracing_mutex_t kq_mtx; #if defined(KQUEUE_PLATFORM_SPECIFIC) KQUEUE_PLATFORM_SPECIFIC; @@ -273,12 +423,12 @@ struct kqueue_vtable { /** Called once for every kqueue created * */ - int (*kqueue_init)(struct kqueue *kq); + int (*kqueue_init)(struct kqueue *kq); /** Called when a kqueue is destroyed * */ - void (*kqueue_free)(struct kqueue *kq); + void (*kqueue_free)(struct kqueue *kq); /** Wait on this platform's eventing system to produce events * @@ -290,7 +440,7 @@ struct kqueue_vtable { * May be NULL if no timeout is required. * @return The number of events that ocurred. */ - int (*kevent_wait)(struct kqueue *kq, int numevents, const struct timespec *ts); + int (*kevent_wait)(struct kqueue *kq, int numevents, const struct timespec *ts); /** Translate events produced by the eventing system to kevents * @@ -302,19 +452,19 @@ struct kqueue_vtable { * kevent structure. * @return The number of events we copied. */ - int (*kevent_copyout)(struct kqueue *kq, int nready, struct kevent *el, int); + int (*kevent_copyout)(struct kqueue *kq, int nready, struct kevent *el, int); /** Perform platform specific initialisation for filters * * Called once per kqueue per filter. */ - int (*filter_init)(struct kqueue *kq, struct filter *filt); + int (*filter_init)(struct kqueue *kq, struct filter *filt); /** Perform platform specific de-initialisation for filters * * Called once per kqueue per filter. */ - void (*filter_free)(struct kqueue *kq, struct filter *filt); + void (*filter_free)(struct kqueue *kq, struct filter *filt); /** Initialise a new eventfd * @@ -323,7 +473,7 @@ struct kqueue_vtable { * - 0 on success. * - -1 on failure. */ - int (*eventfd_init)(struct eventfd *efd); + int (*eventfd_init)(struct eventfd *efd); /** Close an eventfd * @@ -332,7 +482,7 @@ struct kqueue_vtable { * - 0 on success. * - -1 on failure. */ - void (*eventfd_close)(struct eventfd *efd); + void (*eventfd_close)(struct eventfd *efd); /** "raise" an eventfd, i.e. signal it as pending * @@ -341,7 +491,7 @@ struct kqueue_vtable { * - 0 on success. * - -1 on failure. */ - int (*eventfd_raise)(struct eventfd *efd); + int (*eventfd_raise)(struct eventfd *efd); /** "lower" an eventfd, consume the pending signal * @@ -350,14 +500,14 @@ struct kqueue_vtable { * - 0 on success. * - -1 on failure. */ - int (*eventfd_lower)(struct eventfd *efd); + int (*eventfd_lower)(struct eventfd *efd); /** Return the file descriptor associated with an eventfd * * @param[in] efd to return the file descriptor for. * @return The file descriptor. */ - int (*eventfd_descriptor)(struct eventfd *efd); + int (*eventfd_descriptor)(struct eventfd *efd); }; extern const struct kqueue_vtable kqops; From f455c3ea6eda7a67236970f7afbfdb5164816aed Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 2 Sep 2021 10:32:03 -0500 Subject: [PATCH 0878/1120] Move processing EV_DISPATCH and EV_ONESHOT to the copyout functions of filters themselves The issue here is there's no way to do this in common code unless we take a performance hit by allocating a temporary array which associate knotes with kevents. We could do this at the platform level, but then we still have an issue with filters that produce multiple kevents per copyout call. --- vendor/libkqueue/src/common/private.h | 32 ++++++++++++++++++++++++- vendor/libkqueue/src/linux/platform.c | 12 +--------- vendor/libkqueue/src/linux/proc.c | 5 +++- vendor/libkqueue/src/linux/read.c | 5 +++- vendor/libkqueue/src/linux/signal.c | 5 +++- vendor/libkqueue/src/linux/timer.c | 5 +++- vendor/libkqueue/src/linux/user.c | 5 +++- vendor/libkqueue/src/linux/vnode.c | 6 +++-- vendor/libkqueue/src/linux/write.c | 5 +++- vendor/libkqueue/src/posix/kevent.c | 2 +- vendor/libkqueue/src/posix/proc.c | 8 +++---- vendor/libkqueue/src/posix/signal.c | 5 +++- vendor/libkqueue/src/posix/timer.c | 5 +++- vendor/libkqueue/src/posix/user.c | 5 +++- vendor/libkqueue/src/solaris/platform.c | 8 +++---- vendor/libkqueue/src/solaris/signal.c | 5 +++- vendor/libkqueue/src/solaris/socket.c | 9 +++---- vendor/libkqueue/src/solaris/timer.c | 5 +++- vendor/libkqueue/src/solaris/user.c | 5 +++- vendor/libkqueue/src/windows/platform.c | 2 +- vendor/libkqueue/src/windows/read.c | 5 +++- vendor/libkqueue/src/windows/timer.c | 5 +++- vendor/libkqueue/src/windows/user.c | 8 +++---- 23 files changed, 108 insertions(+), 49 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index a2e71d01d..ba5245d7d 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -230,6 +230,7 @@ struct filter { * @param[in] el array of `struct kevent` to populate. Most filters * will insert a single event, but some may insert multiple. * @param[in] nevents The maximum number of events to copy to el. + * @param[in] filt we're copying out events from. * @param[in] kn the event was triggered on. * @param[in] ev event system specific structure representing the event, * i.e. for Linux this would be a `struct epoll_event *`. @@ -237,7 +238,7 @@ struct filter { * - >=0 the number of events copied to el. * - -1 on failure setting errno. */ - int (*kf_copyout)(struct kevent *el, int nevents, struct knote *kn, void *ev); + int (*kf_copyout)(struct kevent *el, int nevents, struct filter *filt, struct knote *kn, void *ev); /** Complete filter-specific initialisation of a knote * @@ -534,6 +535,35 @@ int knote_disable(struct filter *, struct knote *); int knote_enable(struct filter *, struct knote *); int knote_modify(struct filter *, struct knote *); +/** Common code for respecting EV_DISPATCH and EV_ONESHOT + * + * This should be called by every filter for every knote + * processed. + * + * Unfortunately we can't do this internally as `struct kevent` + * does not contain references to the knotes which created + * the kevents. + * + * - EV_DISPATCH disable the knote after an event occurs. + * - EV_ONESHOT delete the knote after an event occurs. + */ +static inline int knote_copyout_flag_actions(struct filter *filt, struct knote *kn) +{ + int rv = 0; + + /* + * Certain flags cause the associated knote to be deleted + * or disabled. + */ + if (kn->kev.flags & EV_DISPATCH) + rv = knote_disable(filt, kn); + if (kn->kev.flags & EV_ONESHOT) { + rv = knote_delete(filt, kn); + } + + return rv; +} + #define knote_get_filter(knt) &((knt)->kn_kq->kq_filt[(knt)->kev.filter]) int filter_lookup(struct filter **, struct kqueue *, short); diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 02424b7f0..95d4ce7de 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -524,7 +524,7 @@ static inline int linux_kevent_copyout_ev(struct kevent *el, int nevents, struct { int rv; - rv = filt->kf_copyout(el, nevents, kn, ev); + rv = filt->kf_copyout(el, nevents, filt, kn, ev); if (unlikely(rv < 0)) { dbg_puts("knote_copyout failed"); assert(0); @@ -542,16 +542,6 @@ static inline int linux_kevent_copyout_ev(struct kevent *el, int nevents, struct rv = 0; } - /* - * Certain flags cause the associated knote to be deleted - * or disabled. - */ - if (el->flags & EV_DISPATCH) - knote_disable(filt, kn); //FIXME: Error checking - if (el->flags & EV_ONESHOT) { - knote_delete(filt, kn); //FIXME: Error checking - } - return rv; } diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index 5fe613db1..30b572c30 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -28,7 +28,8 @@ #include "private.h" int -evfilt_proc_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, UNUSED_NDEBUG void *ptr) +evfilt_proc_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, + struct knote *src, UNUSED_NDEBUG void *ptr) { siginfo_t info; unsigned int status = 0; @@ -75,6 +76,8 @@ evfilt_proc_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, U dst->data = status; dst->flags |= EV_EOF; /* Set in macOS and FreeBSD kqueue implementations */ + if (knote_copyout_flag_actions(filt, src) < 0) return -1; + return (1); } diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index 347fe5f7a..442e1d901 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -43,7 +43,8 @@ get_eof_offset(int fd) } int -evfilt_read_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr) +evfilt_read_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, + struct knote *src, void *ptr) { int ret; int serr; @@ -133,6 +134,8 @@ evfilt_read_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, v } } + if (knote_copyout_flag_actions(filt, src) < 0) return -1; + return (1); } diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index 2e845fa27..e785f96c0 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -125,7 +125,8 @@ signalfd_create(int epoll_fd, struct knote *kn, int signum) } int -evfilt_signal_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *x UNUSED) +evfilt_signal_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, + struct knote *src, void *x UNUSED) { int sigfd; @@ -139,6 +140,8 @@ evfilt_signal_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, */ dst->data = 1; + if (knote_copyout_flag_actions(filt, src) < 0) return -1; + return (1); } diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 06febd351..6ae380cf9 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -127,7 +127,8 @@ convert_timedata_to_itimerspec(struct itimerspec *dst, long src, } int -evfilt_timer_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr) +evfilt_timer_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, + struct knote *src, void *ptr) { struct epoll_event * const ev = (struct epoll_event *) ptr; uint64_t expired; @@ -147,6 +148,8 @@ evfilt_timer_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, } dst->data = expired; + if (knote_copyout_flag_actions(filt, src) < 0) return -1; + return (1); } diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index 2d5d1eb1b..82faffdbc 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -79,7 +79,8 @@ eventfd_lower(int evfd) } int -linux_evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr UNUSED) +linux_evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, + struct knote *src, void *ptr UNUSED) { memcpy(dst, &src->kev, sizeof(*dst)); dst->fflags &= ~NOTE_FFCTRLMASK; //FIXME: Not sure if needed @@ -99,6 +100,8 @@ linux_evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct knote * if (src->kev.flags & EV_DISPATCH) src->kev.fflags &= ~NOTE_TRIGGER; + if (knote_copyout_flag_actions(filt, src) < 0) return -1; + return (1); } diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index e5d43bceb..2f7dd51d8 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -183,7 +183,8 @@ delete_watch(struct filter *filt, struct knote *kn) } int -evfilt_vnode_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr UNUSED) +evfilt_vnode_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, + struct knote *src, void *ptr UNUSED) { uint8_t buf[sizeof(struct inotify_event) + NAME_MAX + 1] __attribute__ ((aligned(__alignof__(struct inotify_event)))); struct inotify_event *evt; @@ -238,7 +239,6 @@ scriptors reference the same file. } } - if (evt->mask & IN_MODIFY && src->kev.fflags & NOTE_WRITE) dst->fflags |= NOTE_WRITE; if (evt->mask & IN_ATTRIB && src->kev.fflags & NOTE_ATTRIB) @@ -248,6 +248,8 @@ scriptors reference the same file. if (evt->mask & IN_DELETE_SELF && src->kev.fflags & NOTE_DELETE) dst->fflags |= NOTE_DELETE; + if (knote_copyout_flag_actions(filt, src) < 0) return -1; + return (1); } diff --git a/vendor/libkqueue/src/linux/write.c b/vendor/libkqueue/src/linux/write.c index 7087e6746..cdc312c25 100644 --- a/vendor/libkqueue/src/linux/write.c +++ b/vendor/libkqueue/src/linux/write.c @@ -21,7 +21,8 @@ #include "private.h" int -evfilt_write_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr) +evfilt_write_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, + struct knote *src, void *ptr) { int ret; int serr; @@ -51,6 +52,8 @@ evfilt_write_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, dst->data = 0; } + if (knote_copyout_flag_actions(filt, src) < 0) return -1; + return (1); } diff --git a/vendor/libkqueue/src/posix/kevent.c b/vendor/libkqueue/src/posix/kevent.c index 3cba6c9bb..cc815ff68 100644 --- a/vendor/libkqueue/src/posix/kevent.c +++ b/vendor/libkqueue/src/posix/kevent.c @@ -58,7 +58,7 @@ posix_kevent_copyout(struct kqueue *kq, int nready, // dbg_printf("pfd[%d] = %d", i, filt->kf_pfd); if (FD_ISSET(filt->kf_pfd, &kq->kq_rfds)) { dbg_printf("pending events for filter %d (%s)", filt->kf_id, filter_name(filt->kf_id)); - rv = filt->kf_copyout(eventlist, nevents, kn, evt); + rv = filt->kf_copyout(eventlist, nevents, filt, kn, evt); if (rv < 0) { dbg_puts("kevent_copyout failed"); nret = -1; diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index dbc8aef74..990f46152 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -159,7 +159,8 @@ evfilt_proc_create(struct filter *filt, } static int -evfilt_proc_copyout(struct kevent *dst, int nevents, struct knote *kn, void *ev) +evfilt_proc_copyout(struct kevent *dst, int nevents, struct filter *filt, + struct knote *kn, void *ev) { struct knote *kn; int events = 0; @@ -172,11 +173,8 @@ evfilt_proc_copyout(struct kevent *dst, int nevents, struct knote *kn, void *ev) memcpy(dst, &kn->kev, sizeof(*dst)); dst->fflags = NOTE_EXIT; - if (kn->kev.flags & EV_DISPATCH) - KNOTE_DISABLE(kn); - if (kn->kev.flags & EV_ONESHOT) - knote_delete(filt, kn); + if (knote_copyout_flag_actions(filt, kn) < 0) return -1; dst++; } diff --git a/vendor/libkqueue/src/posix/signal.c b/vendor/libkqueue/src/posix/signal.c index cc94a99a3..cabdfdac3 100644 --- a/vendor/libkqueue/src/posix/signal.c +++ b/vendor/libkqueue/src/posix/signal.c @@ -160,7 +160,8 @@ evfilt_signal_knote_disable(struct filter *filt, struct knote *kn) } int -evfilt_signal_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr UNUSED) +evfilt_signal_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, + struct knote *src, void *ptr UNUSED) { struct sentry *s; struct knote *kn; @@ -200,6 +201,8 @@ evfilt_signal_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, } #endif + if (knote_copyout_flag_actions(filt, src) < 0) return -1; + return (1); } diff --git a/vendor/libkqueue/src/posix/timer.c b/vendor/libkqueue/src/posix/timer.c index d280eaaee..0f755f01e 100644 --- a/vendor/libkqueue/src/posix/timer.c +++ b/vendor/libkqueue/src/posix/timer.c @@ -212,7 +212,8 @@ evfilt_timer_destroy(struct filter *filt) } int -evfilt_timer_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr UNUSED) +evfilt_timer_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, + struct knote *src, void *ptr UNUSED) { struct filter *filt; struct sleepinfo si; @@ -267,6 +268,8 @@ evfilt_timer_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, } #endif + if (knote_copyout_flag_actions(filt, src) < 0) return -1; + return (1); } diff --git a/vendor/libkqueue/src/posix/user.c b/vendor/libkqueue/src/posix/user.c index b00f0e23d..4568b1019 100644 --- a/vendor/libkqueue/src/posix/user.c +++ b/vendor/libkqueue/src/posix/user.c @@ -38,7 +38,8 @@ posix_evfilt_user_destroy(struct filter *filt) } int -posix_evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr UNUSED) +posix_evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, + struct knote *src, void *ptr UNUSED) { memcpy(dst, &src->kev, sizeof(*dst)); struct knote *kn; @@ -59,6 +60,8 @@ posix_evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct knote * if (src->kev.flags & EV_DISPATCH) src->kev.fflags &= ~NOTE_TRIGGER; + if (knote_copyout_flag_actions(filt, src) < 0) return -1; + return (1); } diff --git a/vendor/libkqueue/src/solaris/platform.c b/vendor/libkqueue/src/solaris/platform.c index 085c2e183..9e22c6b18 100644 --- a/vendor/libkqueue/src/solaris/platform.c +++ b/vendor/libkqueue/src/solaris/platform.c @@ -162,7 +162,7 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, case PORT_SOURCE_FD: //XXX-FIXME WHAT ABOUT WRITE??? filter_lookup(&filt, kq, EVFILT_READ); - rv = filt->kf_copyout(eventlist, nevents, kn, evt); + rv = filt->kf_copyout(eventlist, nevents, filt, kn, evt); /* For sockets, the event port object must be reassociated after each event is retrieved. */ @@ -178,18 +178,18 @@ solaris_kevent_copyout(struct kqueue *kq, int nready, case PORT_SOURCE_TIMER: filter_lookup(&filt, kq, EVFILT_TIMER); - rv = filt->kf_copyout(eventlist, nevents, kn, evt); + rv = filt->kf_copyout(eventlist, nevents, filt, kn, evt); break; case PORT_SOURCE_USER: switch (evt->portev_events) { case X_PORT_SOURCE_SIGNAL: filter_lookup(&filt, kq, EVFILT_SIGNAL); - rv = filt->kf_copyout(eventlist, nevents, kn, evt); + rv = filt->kf_copyout(eventlist, nevents, filt, kn, evt); break; case X_PORT_SOURCE_USER: filter_lookup(&filt, kq, EVFILT_USER); - rv = filt->kf_copyout(eventlist, nevents, kn, evt); + rv = filt->kf_copyout(eventlist, nevents, filt, kn, evt); break; default: dbg_puts("unsupported portev_events"); diff --git a/vendor/libkqueue/src/solaris/signal.c b/vendor/libkqueue/src/solaris/signal.c index f1b07b91b..e614bb108 100644 --- a/vendor/libkqueue/src/solaris/signal.c +++ b/vendor/libkqueue/src/solaris/signal.c @@ -134,7 +134,8 @@ evfilt_signal_knote_disable(struct filter *filt UNUSED, struct knote *kn) } int -evfilt_signal_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr) +evfilt_signal_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, + struct knote *src, void *ptr) { port_event_t *pe = (port_event_t *) ptr; struct sentry *ent = (struct sentry *) pe->portev_user; @@ -152,6 +153,8 @@ evfilt_signal_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, if (src->kev.flags & EV_DISPATCH || src->kev.flags & EV_ONESHOT) ignore_signal(src->kev.ident); + if (knote_copyout_flag_actions(filt, src) < 0) return -1; + return (1); } diff --git a/vendor/libkqueue/src/solaris/socket.c b/vendor/libkqueue/src/solaris/socket.c index 6f7485dd6..4d8115a4e 100644 --- a/vendor/libkqueue/src/solaris/socket.c +++ b/vendor/libkqueue/src/solaris/socket.c @@ -93,7 +93,8 @@ evfilt_socket_knote_disable(struct filter *filt, struct knote *kn) } int -evfilt_socket_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr) +evfilt_socket_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, + struct knote *src, void *ptr) { port_event_t *pe = (port_event_t *) ptr; unsigned int pending_data = 0; @@ -119,11 +120,7 @@ evfilt_socket_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, dst->data = pending_data; } - /* FIXME: make sure this is in kqops.copyout() - if (src->kev.flags & EV_DISPATCH || src->kev.flags & EV_ONESHOT) { - socket_knote_delete(filt->kf_kqueue->kq_port, kn->kev.ident); - } - */ + if (knote_copyout_flag_actions(filt, src) < 0) return -1; return (1); } diff --git a/vendor/libkqueue/src/solaris/timer.c b/vendor/libkqueue/src/solaris/timer.c index 33cc58995..2571bff15 100644 --- a/vendor/libkqueue/src/solaris/timer.c +++ b/vendor/libkqueue/src/solaris/timer.c @@ -76,7 +76,8 @@ evfilt_timer_destroy(struct filter *filt UNUSED) } int -evfilt_timer_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr UNUSED) +evfilt_timer_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, + struct knote *src, void *ptr UNUSED) { /* port_event_t *pe = (port_event_t *) ptr; */ @@ -97,6 +98,8 @@ evfilt_timer_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, } #endif + if (knote_copyout_flag_actions(filt, src) < 0) return -1; + return (1); } diff --git a/vendor/libkqueue/src/solaris/user.c b/vendor/libkqueue/src/solaris/user.c index 63aa95a3d..fc1fbd760 100644 --- a/vendor/libkqueue/src/solaris/user.c +++ b/vendor/libkqueue/src/solaris/user.c @@ -17,7 +17,8 @@ #include "private.h" int -evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr UNUSED) +evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, + struct knote *src, void *ptr UNUSED) { //port_event_t *pe = (port_event_t *) ptr; @@ -44,6 +45,8 @@ evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, v } */ + if (knote_copyout_flag_actions(filt, src) < 0) return -1; + return (1); } diff --git a/vendor/libkqueue/src/windows/platform.c b/vendor/libkqueue/src/windows/platform.c index 92d4be350..52afa11d3 100644 --- a/vendor/libkqueue/src/windows/platform.c +++ b/vendor/libkqueue/src/windows/platform.c @@ -139,7 +139,7 @@ windows_kevent_copyout(struct kqueue *kq, int nready, //FIXME: not true for EVFILT_IOCP kn = (struct knote *) iocp_buf.overlap; filt = &kq->kq_filt[~(kn->kev.filter)]; - rv = filt->kf_copyout(eventlist, nevents, kn, &iocp_buf); + rv = filt->kf_copyout(eventlist, nevents, filt, kn, &iocp_buf); if (unlikely(rv < 0)) { dbg_puts("knote_copyout failed"); /* XXX-FIXME: hard to handle this without losing events */ diff --git a/vendor/libkqueue/src/windows/read.c b/vendor/libkqueue/src/windows/read.c index 44c6fe562..b65f0022b 100644 --- a/vendor/libkqueue/src/windows/read.c +++ b/vendor/libkqueue/src/windows/read.c @@ -87,7 +87,8 @@ get_eof_offset(int fd) #endif int -evfilt_read_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, void *ptr) +evfilt_read_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, + struct knote *src, void *ptr) { unsigned long bufsize; @@ -111,6 +112,8 @@ evfilt_read_copyout(struct kevent *dst, UNUSED int nevents, struct knote *src, v dst->data = bufsize; } + if (knote_copyout_flag_actions(filt, src) < 0) return -1; + return (1); } diff --git a/vendor/libkqueue/src/windows/timer.c b/vendor/libkqueue/src/windows/timer.c index f96e0264e..595135930 100644 --- a/vendor/libkqueue/src/windows/timer.c +++ b/vendor/libkqueue/src/windows/timer.c @@ -99,7 +99,8 @@ evfilt_timer_destroy(struct filter *filt) } int -evfilt_timer_copyout(struct kevent *dst, UNUSED int nevents, struct knote* src, void* ptr) +evfilt_timer_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, + struct knote* src, void* ptr) { memcpy(dst, &src->kev, sizeof(struct kevent)); // TODO: Timer error handling @@ -109,6 +110,8 @@ evfilt_timer_copyout(struct kevent *dst, UNUSED int nevents, struct knote* src, */ dst->data = 1; + if (knote_copyout_flag_actions(filt, src) < 0) return -1; + return (1); } diff --git a/vendor/libkqueue/src/windows/user.c b/vendor/libkqueue/src/windows/user.c index d915430b3..7de4571d2 100644 --- a/vendor/libkqueue/src/windows/user.c +++ b/vendor/libkqueue/src/windows/user.c @@ -28,7 +28,8 @@ evfilt_user_destroy(struct filter *filt) } int -evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct knote* src, void* ptr) +evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, + struct knote *src, void* ptr) { memcpy(dst, &src->kev, sizeof(struct kevent)); @@ -39,11 +40,10 @@ evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct knote* src, v other filters. */ dst->flags &= ~EV_ADD; } - if (src->kev.flags & EV_CLEAR) + if ((src->kev.flags & EV_CLEAR) || (src->kev.flags & EV_DISPATCH)) src->kev.fflags &= ~NOTE_TRIGGER; - if (src->kev.flags & EV_DISPATCH) - src->kev.fflags &= ~NOTE_TRIGGER; + if (knote_copyout_flag_actions(filt, src) < 0) return -1; return (1); } From ba31a735fe88d3d1766f973d6b102dcc39cb1c28 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 2 Sep 2021 10:36:12 -0500 Subject: [PATCH 0879/1120] Set the correct thread's name --- vendor/libkqueue/src/posix/proc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 990f46152..96feb7659 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -45,6 +45,10 @@ wait_thread(void *arg) sigdelset(&sigmask, SIGCHLD); pthread_sigmask(SIG_BLOCK, &sigmask, NULL); + /* Set the thread's name to something descriptive so it shows up in gdb, + * etc. Max name length is 16 bytes. */ + prctl(PR_SET_NAME, "libkqueue_wait", 0, 0, 0); + for (;;) { /* Get the exit status _without_ reaping the process, waitpid() should still work in the caller */ if (waitid(P_ALL, 0, &info, WEXITED | WNOWAIT) < 0) { @@ -123,10 +127,6 @@ evfilt_proc_init(struct filter *filt) if (pthread_create(&ed->wthr_id, NULL, wait_thread, filt) != 0) goto errout; - /* Set the thread's name to something descriptive so it shows up in gdb, - * etc. Max name length is 16 bytes. */ - prctl(PR_SET_NAME, "libkqueue_wait", 0, 0, 0); - return (0); errout: From 6e6b144970ec2a0296f45057c4267276cf3d8002 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 2 Sep 2021 11:57:21 -0500 Subject: [PATCH 0880/1120] Cleanup posix/platform.h to make it easier to include per-filter fields --- vendor/libkqueue/src/posix/platform.h | 41 ++++++++++++++++++++------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 42ba4ac21..b437bffb8 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -17,9 +17,6 @@ #ifndef _KQUEUE_POSIX_PLATFORM_H #define _KQUEUE_POSIX_PLATFORM_H -/* Required by glibc for MAP_ANON */ -#define __USE_MISC 1 - #include #include #include @@ -35,21 +32,45 @@ #include #include -/* - * Additional members of 'struct eventfd' +/** Additional members of 'struct eventfd' + * + * These should be included in the platform's EVENTFD_PLATFORM_SPECIFIC + * macro definition if using the POSIX eventfd functions. */ -#define EVENTFD_PLATFORM_SPECIFIC \ +#define POSIX_EVENTFD_PLATFORM_SPECIFIC \ int ef_wfd -#define FILTER_PLATFORM_SPECIFIC \ +/** Additional members of 'struct eventfd' + * + * These should be included in the platform's FILTER_PLATFORM_SPECIFIC + * macro definition if using the POSIX proc filter. + */ +#define POSIX_FILTER_PROC_PLATFORM_SPECIFIC \ + struct eventfd kf_proc_eventfd + +/** Additional members of 'struct filter' + * + * These should be included in the platform's FILTER_PLATFORM_SPECIFIC + * macro definition if using all the POSIX filters. + */ +#define POSIX_FILTER_PLATFORM_SPECIFIC \ int kf_pfd; /* fd to poll(2) for readiness */ \ - int kf_wfd + int kf_wfd; \ + POSIX_FILTER_PROC_PLATFORM_SPECIFIC -#define KQUEUE_PLATFORM_SPECIFIC \ +/** Additional members of 'struct kqueue' + * + * These should be included in the platform's KQUEUE_PLATFORM_SPECIFIC + * macro definition. + */ +#define POSIX_KQUEUE_PLATFORM_SPECIFIC \ fd_set kq_fds, kq_rfds; \ int kq_nfds -#define KNOTE_PLATFORM_SPECIFIC \ +/** Additional members of 'struct knote' + * + */ +#define POSIX_KNOTE_PLATFORM_SPECIFIC \ struct sleepreq *kn_sleepreq void posix_kqueue_free(struct kqueue *); From 39f26853e4f9b77a88f8c0305f1c8361044c0522 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 2 Sep 2021 12:24:26 -0500 Subject: [PATCH 0881/1120] Make knote mutexes recursive This is so that disable and delete can be called from within copyout functions, as the copyout functions should really be locking this mutex as well. There's also not a whole lot of point in a read/write lock here as it's very unlikely there'll be multiple simultaneous readers on the same knote. You could even argue it's wrong, as it could theoretically allow the same event to be raised multiple times for filters like posix/proc if 2+ threads called kevent simultaneously on the same kqueue. --- vendor/libkqueue/src/common/filter.c | 30 +++++++++++++++++++++------ vendor/libkqueue/src/common/knote.c | 20 +++++++++--------- vendor/libkqueue/src/common/private.h | 3 ++- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index f6f026aab..e23e33c1f 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -47,7 +47,17 @@ filter_register(struct kqueue *kq, const struct filter *src) memcpy(dst, src, sizeof(*src)); dst->kf_kqueue = kq; RB_INIT(&dst->kf_index); - pthread_rwlock_init(&dst->kf_knote_mtx, NULL); + + /* + * This allows disable and/or delete to be called from any + * of the other knote processing functions. + * + * It's probably not a great idea, but it makes the code + * simpler. + */ + pthread_mutexattr_init(&dst->kf_knote_mtx_attr); + pthread_mutexattr_settype(&dst->kf_knote_mtx_attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&dst->kf_knote_mtx, &dst->kf_knote_mtx_attr); if (src->kf_id == 0) { dbg_puts("filter is not implemented"); return (0); @@ -105,16 +115,24 @@ filter_unregister_all(struct kqueue *kq) int i; for (i = 0; i < NUM_ELEMENTS(kq->kq_filt); i++) { - if (kq->kq_filt[i].kf_id == 0) + struct filter *filt = &kq->kq_filt[i]; + + if (filt->kf_id == 0) continue; - if (kq->kq_filt[i].kf_destroy != NULL) - kq->kq_filt[i].kf_destroy(&kq->kq_filt[i]); + if (filt->kf_destroy != NULL) + filt->kf_destroy(&kq->kq_filt[i]); - knote_delete_all(&kq->kq_filt[i]); + knote_delete_all(filt); if (kqops.filter_free != NULL) - kqops.filter_free(kq, &kq->kq_filt[i]); + kqops.filter_free(kq, filt); + + /* + * ...and destroy the mutexes. + */ + pthread_mutex_destroy(&filt->kf_knote_mtx); + pthread_mutexattr_destroy(&filt->kf_knote_mtx_attr); } memset(&kq->kq_filt[0], 0, sizeof(kq->kq_filt)); } diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 803c29ef0..9bd6cffe1 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -81,9 +81,9 @@ knote_release(struct knote *kn) void knote_insert(struct filter *filt, struct knote *kn) { - pthread_rwlock_wrlock(&filt->kf_knote_mtx); + pthread_mutex_lock(&filt->kf_knote_mtx); RB_INSERT(knote_index, &filt->kf_index, kn); - pthread_rwlock_unlock(&filt->kf_knote_mtx); + pthread_mutex_unlock(&filt->kf_knote_mtx); } struct knote * @@ -94,9 +94,9 @@ knote_lookup(struct filter *filt, uintptr_t ident) query.kev.ident = ident; - pthread_rwlock_rdlock(&filt->kf_knote_mtx); + pthread_mutex_lock(&filt->kf_knote_mtx); ent = RB_FIND(knote_index, &filt->kf_index, &query); - pthread_rwlock_unlock(&filt->kf_knote_mtx); + pthread_mutex_unlock(&filt->kf_knote_mtx); return (ent); } @@ -105,10 +105,10 @@ int knote_delete_all(struct filter *filt) { struct knote *kn, *tmp; - pthread_rwlock_wrlock(&filt->kf_knote_mtx); + pthread_mutex_lock(&filt->kf_knote_mtx); RB_FOREACH_SAFE(kn, knote_index, &filt->kf_index, tmp) knote_delete(filt, kn); - pthread_rwlock_unlock(&filt->kf_knote_mtx); + pthread_mutex_unlock(&filt->kf_knote_mtx); return (0); } @@ -130,14 +130,14 @@ knote_delete(struct filter *filt, struct knote *kn) * thread before we acquired the knotelist lock. */ query.kev.ident = kn->kev.ident; - pthread_rwlock_wrlock(&filt->kf_knote_mtx); + pthread_mutex_lock(&filt->kf_knote_mtx); tmp = RB_FIND(knote_index, &filt->kf_index, &query); if (tmp == kn) RB_REMOVE(knote_index, &filt->kf_index, kn); if (LIST_INSERTED(kn, kn_ready)) LIST_REMOVE(kn, kn_ready); - pthread_rwlock_unlock(&filt->kf_knote_mtx); + pthread_mutex_unlock(&filt->kf_knote_mtx); rv = filt->kn_delete(filt, kn); dbg_printf("kn=%p - kn_delete rv=%i", kn, rv); @@ -159,10 +159,10 @@ knote_disable(struct filter *filt, struct knote *kn) rv = filt->kn_disable(filt, kn); dbg_printf("kn=%p - kn_disable rv=%i", kn, rv); if (rv == 0) { - pthread_rwlock_wrlock(&filt->kf_knote_mtx); + pthread_mutex_lock(&filt->kf_knote_mtx); if (LIST_INSERTED(kn, kn_ready)) /* No longer marked as ready if disabled */ LIST_REMOVE(kn, kn_ready); - pthread_rwlock_unlock(&filt->kf_knote_mtx); + pthread_mutex_unlock(&filt->kf_knote_mtx); KNOTE_DISABLE(kn); /* set the disable flag */ } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index ba5245d7d..43091d0b5 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -386,9 +386,10 @@ struct filter { ///< with eventfds. ///< This is not used by all filters. - pthread_rwlock_t kf_knote_mtx; //!< Used to synchronise knote operations + pthread_mutex_t kf_knote_mtx; //!< Used to synchronise knote operations ///< (addition, removal, modification etc...) ///< on this filter. + pthread_mutexattr_t kf_knote_mtx_attr; struct kqueue *kf_kqueue; //!< kqueue this filter is associated with. From 57186e4cfd205d88b3cface3aa745a4783f40eca Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 2 Sep 2021 12:24:51 -0500 Subject: [PATCH 0882/1120] Unused --- vendor/libkqueue/src/linux/platform.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 6e623d6d0..990a015b8 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -166,11 +166,6 @@ struct fd_state { struct epoll_udata fds_udata; //!< Common struct passed to epoll }; -/** Additional members of struct filter - * - */ -#define FILTER_PLATFORM_SPECIFIC - /** Additional members of struct knote * */ From f8f2a631471c003cccb2f3b8e588f26a5423b51d Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 2 Sep 2021 12:25:38 -0500 Subject: [PATCH 0883/1120] Include POSIX specific filter fields for posix/proc if we're lacking SYS_pidfd_open --- vendor/libkqueue/src/linux/platform.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 990a015b8..10d387beb 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -43,13 +43,26 @@ struct filter; #include #include #include +#include #include #include #include +#include #include -#include #include + +/* + * Check to see if we have SYS_pidfd_open support if we don't, + * fall back to the POSIX EVFILT_PROC code. + */ +#ifdef SYS_pidfd_open +#define FILTER_PROC_PLATFORM_SPECIFIC int kn_procfd +#else +#include "../posix/platform.h" +#define FILTER_PROC_PLATFORM_SPECIFIC POSIX_FILTER_PROC_PLATFORM_SPECIFIC +#endif + /* * C11 atomic operations */ @@ -177,13 +190,13 @@ struct fd_state { union { \ int kn_timerfd; \ int kn_signalfd; \ - int kn_procfd; \ int kn_eventfd; \ struct { \ nlink_t nlink; \ off_t size; \ int inotifyfd; \ } kn_vnode; \ + FILTER_PROC_PLATFORM_SPECIFIC; \ }; \ struct epoll_udata kn_udata /* Common struct passed to epoll */ From 2b01f5c1ddbca1dae001acf7e7162fab378fbcd7 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 2 Sep 2021 13:30:07 -0500 Subject: [PATCH 0884/1120] Remove fcntl call in linux_eventfd_init --- vendor/libkqueue/src/linux/platform.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 95d4ce7de..5bf0657d9 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -650,17 +650,11 @@ linux_eventfd_init(struct eventfd *e) { int evfd; - evfd = eventfd(0, 0); + evfd = eventfd(0, EFD_NONBLOCK); if (evfd < 0) { dbg_perror("eventfd"); return (-1); } - if (fcntl(evfd, F_SETFL, O_NONBLOCK) < 0) { - dbg_perror("fcntl"); - if (close(evfd) < 0) - dbg_perror("close(2)"); - return (-1); - } e->ef_id = evfd; return (0); @@ -707,7 +701,16 @@ linux_eventfd_lower(struct eventfd *e) ssize_t n; int rv = 0; - /* Reset the counter */ + /* + * Reset the counter + * Because we're not using EFD_SEMPAHOR the level + * state of the eventfd is cleared. + * + * Thus if there were multiple calls to + * linux_eventfd_raise, and a single call to + * linux_eventfd_lower, the eventfd state would + * still be lowered. + */ dbg_puts("lowering event level"); n = read(e->ef_id, &cur, sizeof(cur)); if (n < 0) { From b2e96f7789a5ce7fa4c16be52d3a72bfc4e0d904 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 2 Sep 2021 13:31:38 -0500 Subject: [PATCH 0885/1120] LIST_FOREACH_SAFE isn't available on Linux --- vendor/libkqueue/src/common/private.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 43091d0b5..8119b12a5 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -61,6 +61,16 @@ struct evfilt_data; */ #define LIST_INSERTED(elm, field) (((elm)->field.le_next) || ((elm)->field.le_prev)) +/** On Linux LIST_FOREACH_SAFE isn't provided + * + */ +#ifndef LIST_FOREACH_SAFE +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) +#endif + /** Convenience macros * */ From ff256b11139e8b2b781fc722adc2b55ad350157c Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 2 Sep 2021 21:16:27 -0500 Subject: [PATCH 0886/1120] Fix knote_get_filter (filter id should be inverted) --- vendor/libkqueue/src/common/private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 8119b12a5..da4c49c65 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -575,7 +575,7 @@ static inline int knote_copyout_flag_actions(struct filter *filt, struct knote * return rv; } -#define knote_get_filter(knt) &((knt)->kn_kq->kq_filt[(knt)->kev.filter]) +#define knote_get_filter(knt) &((knt)->kn_kq->kq_filt[~(knt)->kev.filter]) int filter_lookup(struct filter **, struct kqueue *, short); int filter_register_all(struct kqueue *); From 806f56681f68fd4491465a6e1cf95afed45d49d7 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 2 Sep 2021 21:20:14 -0500 Subject: [PATCH 0887/1120] Add support for registering eventfds with the platform event loop --- vendor/libkqueue/src/common/private.h | 30 +++++++++++++++++++-- vendor/libkqueue/src/linux/platform.c | 39 ++++++++++++++++++++++++++- vendor/libkqueue/src/linux/platform.h | 39 ++++++++++++++++++++------- vendor/libkqueue/src/posix/signal.c | 2 +- vendor/libkqueue/src/posix/user.c | 2 +- 5 files changed, 98 insertions(+), 14 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index da4c49c65..32689b2b3 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -109,8 +109,16 @@ struct evfilt_data; # define EPOLLONESHOT (1 << 30) #endif +/** An eventfd provides a mechanism to signal the eventing system that an event has occurred + * + * This is usually that a filter has pending events that it wants handled during the + * next call to copyout. + */ struct eventfd { - int ef_id; + int ef_id; //!< The file descriptor associated + ///< with this eventfd. + struct filter *ef_filt; //!< The filter associated with this eventfd. + #if defined(EVENTFD_PLATFORM_SPECIFIC) EVENTFD_PLATFORM_SPECIFIC; #endif @@ -478,14 +486,32 @@ struct kqueue_vtable { */ void (*filter_free)(struct kqueue *kq, struct filter *filt); + /** Register an eventfd with the eventing system associated with this kqueue + * + * @param[in] kq To register the event fd for. + * @param[in] efd to register. + * @return + * - 0 on success. + * - -1 on failure. + */ + int (*eventfd_register)(struct kqueue *kq, struct eventfd *efd); + + /** Remove an eventfd from the eventing system associated with this kqueue + * + * @param[in] kq To remove the event fd from. + * @param[in] efd Eventfd to remove. + */ + void (*eventfd_unregister)(struct kqueue *kq, struct eventfd *efd); + /** Initialise a new eventfd * * @param[in] efd structure to initialise. + * @param[in] filt Filter to associate this eventfd with. * @return * - 0 on success. * - -1 on failure. */ - int (*eventfd_init)(struct eventfd *efd); + int (*eventfd_init)(struct eventfd *efd, struct filter *filt); /** Close an eventfd * diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 5bf0657d9..23c181d5c 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -633,6 +633,20 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven } break; + case EPOLL_UDATA_EVENT_FD: + { + struct eventfd *efd = epoll_udata->ud_efd; + + assert(efd); + + dbg_printf("eventfd=%u - received event", (unsigned int)efd->ef_id); + + rv = linux_kevent_copyout_ev(el_p, (el_end - el_p), ev, efd->ef_filt, NULL); + if (rv < 0) goto done; + el_p += rv; + break; + } + /* * Bad udata value. Maybe use after free? */ @@ -645,8 +659,29 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven done: return el_p - el; } + int -linux_eventfd_init(struct eventfd *e) +linux_eventfd_register(struct kqueue *kq, struct eventfd *efd) +{ + EVENTFD_UDATA(efd); /* setup udata for the efd */ + + if (epoll_ctl(kq->epollfd, EPOLL_CTL_ADD, kqops.eventfd_descriptor(efd), EPOLL_EV_EVENTFD(EPOLLIN, efd)) < 0) { + dbg_perror("epoll_ctl(2)"); + return -1; + } + + return 0; +} + +void +linux_eventfd_unregister(struct kqueue *kq, struct eventfd *efd) +{ + if (epoll_ctl(kq->epollfd, EPOLL_CTL_DEL, kqops.eventfd_descriptor(efd), NULL) < 0) + dbg_perror("epoll_ctl(2)"); +} + +static int +linux_eventfd_init(struct eventfd *efd, struct filter *filt) { int evfd; @@ -1337,6 +1372,8 @@ const struct kqueue_vtable kqops = { .kqueue_free = linux_kqueue_free, .kevent_wait = linux_kevent_wait, .kevent_copyout = linux_kevent_copyout, + .eventfd_register = linux_eventfd_register, + .eventfd_unregister = linux_eventfd_unregister, .eventfd_init = linux_eventfd_init, .eventfd_close = linux_eventfd_close, .eventfd_raise = linux_eventfd_raise, diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 10d387beb..b6e005450 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -89,6 +89,15 @@ extern long int syscall (long int __sysno, ...); #define kqueue_epoll_fd(kq) ((kq)->epollfd) #define filter_epoll_fd(filt) ((filt)->kf_kqueue->epollfd) +/** What type of udata was passed to epoll + * + */ +enum epoll_udata_type { + EPOLL_UDATA_KNOTE = 1, //!< Udata is a pointer to a knote. + EPOLL_UDATA_FD_STATE, //!< Udata is a pointer to a fd state structure. + EPOLL_UDATA_EVENT_FD //!< Udata is a pointer to an eventfd. +}; + /** Macro for populating the kn_udata structure * * We set the udata for the epoll event so we can retrieve the knote associated @@ -106,6 +115,12 @@ extern long int syscall (long int __sysno, ...); */ #define FDS_UDATA(_fds) ((_fds)->fds_udata = (struct epoll_udata){ .ud_type = EPOLL_UDATA_FD_STATE, .ud_fds = _fds }) +/* Macro for populating an eventfd udata structure + * + * @param[in] _efd to populate. + */ +#define EVENTFD_UDATA(_efd) ((_efd)->efd_udata = (struct epoll_udata){ .ud_type = EPOLL_UDATA_EVENT_FD, .ud_efd = _efd }) + /** Macro for building a temporary kn epoll_event * * @param[in] _events One or more event flags EPOLLIN, EPOLLOUT etc... @@ -113,7 +128,7 @@ extern long int syscall (long int __sysno, ...); * determine the correct filter to notify * if the event fires. */ -#define EPOLL_EV_KN(_events, _kn) &(struct epoll_event){ .events = _events, .data = { .ptr = &(_kn)->kn_udata } } +#define EPOLL_EV_KN(_events, _kn) &(struct epoll_event){ .events = _events, .data = { .ptr = &(_kn)->kn_udata }} /** Macro for building a temporary fds epoll_event * @@ -122,21 +137,20 @@ extern long int syscall (long int __sysno, ...); * event. Is used during event demuxing to inform * multiple filters of read/write events on the fd. */ -#define EPOLL_EV_FDS(_events, _fds) &(struct epoll_event){ .events = _events, .data = { .ptr = &(_fds)->fds_udata } } +#define EPOLL_EV_FDS(_events, _fds) &(struct epoll_event){ .events = _events, .data = { .ptr = &(_fds)->fds_udata }} -/** Macro for building a temporary epoll_event +/** Macro for building a temporary eventfd epoll_event * * @param[in] _events One or more event flags EPOLLIN, EPOLLOUT etc... + * @param[in] _efd eventfd to build event for. */ -#define EPOLL_EV(_events) &(struct epoll_event){ .events = _events } +#define EPOLL_EV_EVENTFD(_events, _efd) &(struct epoll_event){ .events = _events, .data = { .ptr = &(_efd)->efd_udata }} -/** What type of udata is in the event loop +/** Macro for building a temporary epoll_event * + * @param[in] _events One or more event flags EPOLLIN, EPOLLOUT etc... */ -enum epoll_udata_type { - EPOLL_UDATA_KNOTE = 0x01, //!< Udata is a pointer to a knote. - EPOLL_UDATA_FD_STATE = 0x02 //!< Udata is a pointer to a fd state structure. -}; +#define EPOLL_EV(_events) &(struct epoll_event){ .events = _events } /** Common structure that's provided as the epoll data.ptr * @@ -151,6 +165,7 @@ struct epoll_udata { union { struct knote *ud_kn; //!< Pointer back to the containing knote. struct fd_state *ud_fds; //!< Pointer back to the containing fd_state. + struct eventfd *ud_efd; //!< Pointer back to the containing eventfd. }; enum epoll_udata_type ud_type; //!< Which union member to use. }; @@ -179,6 +194,12 @@ struct fd_state { struct epoll_udata fds_udata; //!< Common struct passed to epoll }; +/** Additional members of struct eventfd + * + */ +#define EVENTFD_PLATFORM_SPECIFIC \ + struct epoll_udata efd_udata + /** Additional members of struct knote * */ diff --git a/vendor/libkqueue/src/posix/signal.c b/vendor/libkqueue/src/posix/signal.c index cabdfdac3..ff8a4b1e9 100644 --- a/vendor/libkqueue/src/posix/signal.c +++ b/vendor/libkqueue/src/posix/signal.c @@ -104,7 +104,7 @@ ignore_signal(int sig) int evfilt_signal_init(struct filter *filt) { - if (kqops.eventfd_init(&filt->kf_efd) < 0) + if (kqops.eventfd_init(&filt->kf_efd, filt) < 0) return (-1); sig_eventfd = &filt->kf_efd; // XXX - does not work w/ multiple kqueues return (0); diff --git a/vendor/libkqueue/src/posix/user.c b/vendor/libkqueue/src/posix/user.c index 4568b1019..9d2153ed8 100644 --- a/vendor/libkqueue/src/posix/user.c +++ b/vendor/libkqueue/src/posix/user.c @@ -22,7 +22,7 @@ int posix_evfilt_user_init(struct filter *filt) { - if (kqops.eventfd_init(&filt->kf_efd) < 0) + if (kqops.eventfd_init(&filt->kf_efd, filt) < 0) return (-1); filt->kf_pfd = kqops.eventfd_descriptor(&filt->kf_efd); From 118942f5c9730c21302d2cdbdc9a468525225ed8 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 2 Sep 2021 21:23:30 -0500 Subject: [PATCH 0888/1120] Add more debug messages for eventfds --- vendor/libkqueue/src/linux/platform.c | 27 ++++++++++--------- vendor/libkqueue/src/posix/eventfd.c | 37 +++++++++++++++------------ 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 23c181d5c..793a548c6 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -690,28 +690,31 @@ linux_eventfd_init(struct eventfd *efd, struct filter *filt) dbg_perror("eventfd"); return (-1); } - e->ef_id = evfd; + dbg_printf("eventfd=%i - created", evfd); + efd->ef_id = evfd; + efd->ef_filt = filt; return (0); } static void -linux_eventfd_close(struct eventfd *e) +linux_eventfd_close(struct eventfd *efd) { - if (close(e->ef_id) < 0) + dbg_printf("eventfd=%i - closed", efd->ef_id); + if (close(efd->ef_id) < 0) dbg_perror("close(2)"); - e->ef_id = -1; + efd->ef_id = -1; } static int -linux_eventfd_raise(struct eventfd *e) +linux_eventfd_raise(struct eventfd *efd) { uint64_t counter; int rv = 0; - dbg_puts("raising event level"); + dbg_printf("eventfd=%i - raising event level", efd->ef_id); counter = 1; - if (write(e->ef_id, &counter, sizeof(counter)) < 0) { + if (write(efd->ef_id, &counter, sizeof(counter)) < 0) { switch (errno) { case EAGAIN: /* Not considered an error */ @@ -730,7 +733,7 @@ linux_eventfd_raise(struct eventfd *e) } static int -linux_eventfd_lower(struct eventfd *e) +linux_eventfd_lower(struct eventfd *efd) { uint64_t cur; ssize_t n; @@ -746,8 +749,8 @@ linux_eventfd_lower(struct eventfd *e) * linux_eventfd_lower, the eventfd state would * still be lowered. */ - dbg_puts("lowering event level"); - n = read(e->ef_id, &cur, sizeof(cur)); + dbg_printf("eventfd=%i - lowering event level", efd->ef_id); + n = read(efd->ef_id, &cur, sizeof(cur)); if (n < 0) { switch (errno) { case EAGAIN: @@ -771,9 +774,9 @@ linux_eventfd_lower(struct eventfd *e) } static int -linux_eventfd_descriptor(struct eventfd *e) +linux_eventfd_descriptor(struct eventfd *efd) { - return (e->ef_id); + return (efd->ef_id); } /** Determine what type of file descriptor the knote describes diff --git a/vendor/libkqueue/src/posix/eventfd.c b/vendor/libkqueue/src/posix/eventfd.c index f6016485a..349d36535 100644 --- a/vendor/libkqueue/src/posix/eventfd.c +++ b/vendor/libkqueue/src/posix/eventfd.c @@ -16,7 +16,7 @@ #include "../common/private.h" int -posix_eventfd_init(struct eventfd *e) +posix_eventfd_init(struct eventfd *efd, struct filter *filt) { int sd[2]; @@ -29,40 +29,45 @@ posix_eventfd_init(struct eventfd *e) close(sd[1]); return (-1); } - e->ef_wfd = sd[0]; - e->ef_id = sd[1]; + efd->ef_wfd = sd[0]; + efd->ef_id = sd[1]; + efd->ef_filt = filt; + + dbg_printf("eventfd=%i - created", efd->ef_id); return (0); } void -posix_eventfd_close(struct eventfd *e) +posix_eventfd_close(struct eventfd *efd) { - close(e->ef_id); - close(e->ef_wfd); - e->ef_id = -1; + dbg_printf("eventfd=%i - closed", efd->ef_id); + + close(efd->ef_id); + close(efd->ef_wfd); + efd->ef_id = -1; } int -posix_eventfd_raise(struct eventfd *e) +posix_eventfd_raise(struct eventfd *efd) { - dbg_puts("raising event level"); - if (write(e->ef_wfd, ".", 1) < 0) { + dbg_printf("eventfd=%i - raising event level", efd->ef_id); + if (write(efd->ef_wfd, ".", 1) < 0) { /* FIXME: handle EAGAIN and EINTR */ - dbg_printf("write(2) on fd %d: %s", e->ef_wfd, strerror(errno)); + dbg_printf("write(2) on fd %d: %s", efd->ef_wfd, strerror(errno)); return (-1); } return (0); } int -posix_eventfd_lower(struct eventfd *e) +posix_eventfd_lower(struct eventfd *efd) { char buf[1024]; /* Reset the counter */ - dbg_puts("lowering event level"); - if (read(e->ef_id, &buf, sizeof(buf)) < 0) { + dbg_printf("eventfd=%i - lowering event level", efd->ef_id); + if (read(efd->ef_id, &buf, sizeof(buf)) < 0) { /* FIXME: handle EAGAIN and EINTR */ /* FIXME: loop so as to consume all data.. may need mutex */ dbg_printf("read(2): %s", strerror(errno)); @@ -72,8 +77,8 @@ posix_eventfd_lower(struct eventfd *e) } int -posix_eventfd_descriptor(struct eventfd *e) +posix_eventfd_descriptor(struct eventfd *efd) { - return (e->ef_id); + return (efd->ef_id); } From 86956f846c7c4fc0905eb1dd7b5f728a27a7260a Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 2 Sep 2021 21:24:09 -0500 Subject: [PATCH 0889/1120] Add more asserts to linux/platform.c --- vendor/libkqueue/src/linux/platform.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 793a548c6..451e68ab6 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -574,6 +574,7 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven { struct knote *kn = epoll_udata->ud_kn; + assert(kn); if (el_p >= el_end) { oos: dbg_printf("no more available kevent slots, used %zu", el_p - el); @@ -595,6 +596,7 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven struct fd_state *fds = epoll_udata->ud_fds; struct knote *kn; + assert(fds); /* * FD is readable */ From 42ba673c31088471bde7c8bfa6e5ebc3a51d2b0c Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 2 Sep 2021 13:28:38 -0500 Subject: [PATCH 0890/1120] Rework posix/proc.c New version uses SIGCHLD to wake up waiter thread and scans pending PIDs. It probably won't scale well but it's the only way this can work using the POSIX API. Use waitid to avoid reaping processes. libkqueue doesn't reap PIDs so we shouldn't either. PIDs are placed in a mutex protected global tree. The same PID can be added EVFILT_PROC in multiple kqueues and all kqueues will be notified. --- vendor/libkqueue/src/linux/platform.h | 12 +- vendor/libkqueue/src/posix/platform.h | 26 +- vendor/libkqueue/src/posix/proc.c | 424 ++++++++++++++++++++------ 3 files changed, 365 insertions(+), 97 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index b6e005450..920623307 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -57,9 +57,11 @@ struct filter; * fall back to the POSIX EVFILT_PROC code. */ #ifdef SYS_pidfd_open -#define FILTER_PROC_PLATFORM_SPECIFIC int kn_procfd +#define KNOTE_PROC_PLATFORM_SPECIFIC int kn_procfd; +#define FILTER_PROC_PLATFORM_SPECIFIC #else #include "../posix/platform.h" +#define KNOTE_PROC_PLATFORM_SPECIFIC POSIX_KNOTE_PROC_PLATFORM_SPECIFIC #define FILTER_PROC_PLATFORM_SPECIFIC POSIX_FILTER_PROC_PLATFORM_SPECIFIC #endif @@ -217,10 +219,16 @@ struct fd_state { off_t size; \ int inotifyfd; \ } kn_vnode; \ - FILTER_PROC_PLATFORM_SPECIFIC; \ + KNOTE_PROC_PLATFORM_SPECIFIC; \ }; \ struct epoll_udata kn_udata /* Common struct passed to epoll */ +/** Additional members of struct filter + * + */ +#define FILTER_PLATFORM_SPECIFIC \ + FILTER_PROC_PLATFORM_SPECIFIC + /** Additional members of struct kqueue * */ diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index b437bffb8..7b1a657de 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -40,13 +40,35 @@ #define POSIX_EVENTFD_PLATFORM_SPECIFIC \ int ef_wfd -/** Additional members of 'struct eventfd' +/** Additional members of 'struct knote' + * + * These should be included in the platform's KNOTE_PLATFORM_SPECIFIC + * macro definition if using the POSIX proc filter. + */ +#define POSIX_KNOTE_PROC_PLATFORM_SPECIFIC \ + struct { \ + LIST_ENTRY(knote) kn_proc_waiter; \ + int kn_proc_status; \ + } + +/** Additional members of 'struct knote' + * + * These should be included in the platform's KNOTE_PLATFORM_SPECIFIC + * macro definition if using the POSIX filters. + */ +#define POSIX_PROC_PLATFORM_SPECIFIC \ + POSIX_KNOTE_PROC_PLATFORM_SPECIFIC + +/** Additional members of 'struct filter' * * These should be included in the platform's FILTER_PLATFORM_SPECIFIC * macro definition if using the POSIX proc filter. */ #define POSIX_FILTER_PROC_PLATFORM_SPECIFIC \ - struct eventfd kf_proc_eventfd + struct { \ + struct eventfd kf_proc_eventfd; \ + pthread_t kf_proc_thread_id; \ + } /** Additional members of 'struct filter' * diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 96feb7659..dfac0f377 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2021 Arran Cudbard-Bell * Copyright (c) 2009 Mark Heily * * Permission to use, copy, modify, and distribute this software for any @@ -21,27 +22,130 @@ #include -#include "private.h" +#include "../common/private.h" -pthread_cond_t wait_cond = PTHREAD_COND_INITIALIZER; -pthread_mutex_t wait_mtx = PTHREAD_MUTEX_INITIALIZER; - -struct evfilt_data { - pthread_t wthr_id; +/** An entry in the proc_pid tree + * + * This contains a list of PIDs all kqueues are interested in + * and a list of knotes that are waiting on notifications for + * those PIDs. + */ +struct proc_pid { + RB_ENTRY(proc_pid) ppd_entry; //!< Entry in the proc_pid_index tree. + pid_t ppd_pid; //!< PID we're waiting on. + LIST_HEAD(pid_waiters, knote) ppd_proc_waiters; //!< knotes that are waiting on this PID. }; +static pthread_mutex_t proc_init_mtx = PTHREAD_MUTEX_INITIALIZER; +static unsigned int proc_count = 0; +static pthread_t proc_wait_thread_id; + +/** The global PID tree + * + * Contains all the PIDs any kqueue is interested in waiting on + */ +static RB_HEAD(pid_index, proc_pid) proc_pid_index; +static pthread_mutex_t proc_pid_index_mtx = PTHREAD_MUTEX_INITIALIZER; + + +static int +proc_pid_cmp(struct proc_pid *a, struct proc_pid *b) +{ + return (a->ppd_pid > b->ppd_pid) - (a->ppd_pid < b->ppd_pid); +} + +RB_GENERATE(pid_index, proc_pid, ppd_entry, proc_pid_cmp) + +/** Notify all the waiters on a PID + * + * @note This must be called with the proc_pid_index_mtx held + * to prevent knotes/filters/kqueues being freed out from + * beneath us. When a filter is freed it will attempt + * to free all associated knotes, and will attempt to + * lock the proc_pid_index_mtx in evfilt_proc_knote_delete. + * If we hold this mutex then the deletion cannot proceed. + */ +static void +waiter_notify(struct proc_pid *ppd, int status) +{ + struct knote *kn; + struct filter *filt; + + while ((kn = LIST_FIRST(&ppd->ppd_proc_waiters))) { + kn->kn_proc_status = status; + + /* + * This operates in the context of the kqueue + * that the knote belongs to. We may up + * signalling multiple kqueues that the + * specified process exited, and for each one + * we need to call eventfd_raise. + */ + filt = knote_get_filter(kn); + dbg_printf("pid=%u exited, notifying kq=%u filter=%p kn=%p", + (unsigned int)ppd->ppd_pid, kn->kn_kq->kq_id, filt, kn); + pthread_mutex_lock(&filt->kf_knote_mtx); + kqops.eventfd_raise(&filt->kf_proc_eventfd); + LIST_INSERT_HEAD(&filt->kf_ready, kn, kn_ready); + pthread_mutex_unlock(&filt->kf_knote_mtx); + + LIST_REMOVE(kn, kn_proc_waiter); + } + + dbg_printf("pid=%u removing waiter list", (unsigned int)ppd->ppd_pid); + RB_REMOVE(pid_index, &proc_pid_index, ppd); + free(ppd); +} + +static int +waiter_siginfo_to_status(siginfo_t *info) +{ + int status = 0; + + /* + * Try and reconstruct the status code that would have been + * returned by waitpid. The OpenBSD man pages + * and observations of the macOS kqueue confirm this is what + * we should be returning in the data field of the kevent. + */ + switch (info->si_code) { + case CLD_EXITED: /* WIFEXITED - High byte contains status, low byte zeroed */ + status = info->si_status << 8; + dbg_printf("pid=%u exited, status %u", (unsigned int)info->si_pid, status); + break; + + case CLD_DUMPED: /* WIFSIGNALED/WCOREDUMP - Core flag set - Low 7 bits contains fatal signal */ + status |= 0x80; /* core flag */ + status = info->si_status & 0x7f; + dbg_printf("pid=%u dumped, status %u", (unsigned int)info->si_pid, status); + break; + + case CLD_KILLED: /* WIFSIGNALED - Low 7 bits contains fatal signal */ + status = info->si_status & 0x7f; + dbg_printf("pid=%u signalled, status %u", (unsigned int)info->si_pid, status); + break; + + default: /* The rest aren't valid exit states */ + status = -1; + } + + return status; +} + +/** This waiter thread serves all kqueues in a given process + * + */ static void * -wait_thread(void *arg) +wait_thread(UNUSED void *arg) { - struct filter *filt = (struct filter *) arg; - struct knote *dst; int status; + int ret; siginfo_t info; - pid_t pid; sigset_t sigmask; + struct proc_pid *ppd, *ppd_tmp; - /* Block all signals */ - sigfillset (&sigmask); + /* Block all signals except SIGCHLD */ + sigfillset(&sigmask); sigdelset(&sigmask, SIGCHLD); pthread_sigmask(SIG_BLOCK, &sigmask, NULL); @@ -49,67 +153,79 @@ wait_thread(void *arg) * etc. Max name length is 16 bytes. */ prctl(PR_SET_NAME, "libkqueue_wait", 0, 0, 0); - for (;;) { - /* Get the exit status _without_ reaping the process, waitpid() should still work in the caller */ - if (waitid(P_ALL, 0, &info, WEXITED | WNOWAIT) < 0) { - if (errno == ECHILD) { - dbg_puts("got ECHILD, waiting for wakeup condition"); - pthread_mutex_lock(&wait_mtx); - pthread_cond_wait(&wait_cond, &wait_mtx); - pthread_mutex_unlock(&wait_mtx); - dbg_puts("awoken from ECHILD-induced sleep"); - continue; - } - if (errno == EINTR) - continue; - dbg_printf("waitid(2): %s", strerror(errno)); + /* + * Only listen on SIGCHLD + */ + sigemptyset(&sigmask); + sigaddset(&sigmask, SIGCHLD); + pthread_sigmask(SIG_UNBLOCK, &sigmask, NULL); + + dbg_printf("started and waiting for SIGCHLD"); + + /* + * To avoid messing up the application linked to libkqueue + * and reaping all child processes we must use WNOWAIT in + * any *wait*() calls. Even for PIDs registered with the + * EV_PROC filter we're not meant to reap the process because + * we're trying to behave identically to BSD kqueue and BSD + * kqueue doesn't do this. + * + * Unfortunately waitid() will return the same PID repeatedly + * if passed P_ALL/WNOWAIT if the previously returned PID + * is not reaped. + * + * We can use SIGCHLD to get notified when a child process + * exits. Unfortunately Linux (in particular) will coalesce + * multiple signals sent to the same process, so we can't + * rely on sigwaitinfo alone. + * + * The final solution is to use sigwaitinfo() as a + * notification that a child exited, and then scan through + * the list of PIDs we're waiting on using waitid to see if + * any of those exited. + */ + while ((ret = sigwaitinfo(&sigmask, &info))) { + if (ret < 0) { + dbg_printf("sigwaitinfo(2): %s", strerror(errno)); + continue; } - /* Scan the wait queue to see if anyone is interested */ - pthread_mutex_lock(&filt->kf_mtx); - dst = knote_lookup(filt, pid); - if (!dst) - goto next; + dbg_printf("received SIGCHLD"); + pthread_mutex_lock(&proc_pid_index_mtx); /* - * Try and reconstruct the status code that would have been - * returned by waitpid. The OpenBSD man pages - * and observations of the macOS kqueue confirm this is what - * we should be returning in the data field of the kevent. + * Check if this is a process we want to monitor */ - switch (info.si_code) { - case CLD_EXITED: /* WIFEXITED - High byte contains status, low byte zeroed */ - status = info.si_status << 8; - dbg_printf("pid=%u exited, status %u", (unsigned int)info.si_pid, status); - break; - - case CLD_DUMPED: /* WIFSIGNALED/WCOREDUMP - Core flag set - Low 7 bits contains fatal signal */ - status |= 0x80; /* core flag */ - status = info.si_status & 0x7f; - dbg_printf("pid=%u dumped, status %u", (unsigned int)info.si_pid, status); - break; - - case CLD_KILLED: /* WIFSIGNALED - Low 7 bits contains fatal signal */ - status = info.si_status & 0x7f; - dbg_printf("pid=%u signalled, status %u", (unsigned int)info.si_pid, status); - break; - - default: /* The rest aren't valid exit states */ - goto next; + ppd = RB_FIND(pid_index, &proc_pid_index, &(struct proc_pid){ .ppd_pid = info.si_pid }); + if (ppd) { + status = waiter_siginfo_to_status(&info); + if (status >= 0) waiter_notify(ppd, status); /* If < 0 notification is spurious */ } - dst->kev.data = status; - dst->flags |= EV_EOF; /* Set in macOS and FreeBSD kqueue implementations */ - - LIST_REMOVE(dst, kn_list); - LIST_INSERT_HEAD(&filt->kf_eventlist, kn, kn_list); - filter_raise(filt); + /* + * Scan the list of outstanding PIDs to see if + * there are any we need to notify. + */ + RB_FOREACH_SAFE(ppd, pid_index, &proc_pid_index, ppd_tmp) { + again: + if (waitid(P_PID, ppd->ppd_pid, &info, WEXITED | WNOWAIT | WNOHANG) < 0) { + switch (errno) { + case ECHILD: + dbg_printf("waitid(2): pid=%u reaped too early - %s", ppd->ppd_pid, strerror(errno)); + continue; /* FIXME - Maybe produce an EV_ERROR for each of the knotes? */ + + case EINTR: + goto again; + } + } - next: - pthread_mutex_unlock(&filt->kf_mtx); + status = waiter_siginfo_to_status(&info); + if (status >= 0) waiter_notify(ppd, status); /* If < 0 notification is spurious */ + } + pthread_mutex_unlock(&proc_pid_index_mtx); } - /* TODO: error handling */ + dbg_printf("exited"); return (NULL); } @@ -117,70 +233,188 @@ wait_thread(void *arg) static int evfilt_proc_init(struct filter *filt) { - struct evfilt_data *ed; - - if ((ed = calloc(1, sizeof(*ed))) == NULL) + if (kqops.eventfd_init(&filt->kf_proc_eventfd, filt) < 0) { + error_0: return (-1); + } + + if (kqops.eventfd_register(filt->kf_kqueue, &filt->kf_proc_eventfd) < 0) { + error_1: + kqops.eventfd_close(&filt->kf_proc_eventfd); + goto error_0; + } - if (filter_socketpair(filt) < 0) - goto errout; - if (pthread_create(&ed->wthr_id, NULL, wait_thread, filt) != 0) - goto errout; + /* + * Initialise global resources (wait thread and PID tree). + */ + pthread_mutex_lock(&proc_init_mtx); + if (proc_count == 0) { + sigset_t sigmask; - return (0); + /* + * We do this at a process level to ensure + * that the wait thread is the only thing + * that receives SIGCHLD. + * + * The wait thread does not receive the + * SIGCHLD without this code. + */ + sigemptyset(&sigmask); + sigaddset(&sigmask, SIGCHLD); + pthread_sigmask(SIG_BLOCK, &sigmask, NULL); + + dbg_printf("creating wait thread"); -errout: - free(ed); - return (-1); + if (pthread_create(&proc_wait_thread_id, NULL, wait_thread, NULL) != 0) { + pthread_mutex_unlock(&proc_init_mtx); + goto error_1; + } + proc_count++; + } + pthread_mutex_unlock(&proc_init_mtx); + + return (0); } static void evfilt_proc_destroy(struct filter *filt) { - pthread_cancel(filt->kf_data->wthr_id); - close(filt->kf_pfd); + /* + * Free global resources like the wait thread + * and PID tree. + */ + pthread_mutex_lock(&proc_init_mtx); + if (--proc_count == 0) { + pthread_cancel(proc_wait_thread_id); + } + pthread_mutex_unlock(&proc_init_mtx); + + kqops.eventfd_unregister(filt->kf_kqueue, &filt->kf_proc_eventfd); + kqops.eventfd_close(&filt->kf_proc_eventfd); } static int -evfilt_proc_create(struct filter *filt, - struct knote *dst, const struct kevent *src) +evfilt_proc_knote_create(struct filter *filt, struct knote *kn) { - if (src->flags & EV_ADD && KNOTE_EMPTY(dst)) { - memcpy(&dst->kev, src, sizeof(*src)); - /* TODO: think about locking the mutex first.. */ - pthread_cond_signal(&wait_cond); + struct proc_pid *ppd; + + pthread_mutex_lock(&proc_pid_index_mtx); + ppd = RB_FIND(pid_index, &proc_pid_index, &(struct proc_pid){ .ppd_pid = kn->kev.ident }); + if (!ppd) { + dbg_printf("pid=%u adding waiter list", (unsigned int)kn->kev.ident); + ppd = calloc(1, sizeof(struct proc_pid)); + if (unlikely(!ppd)) { + pthread_mutex_unlock(&proc_pid_index_mtx); + return -1; + } + ppd->ppd_pid = kn->kev.ident; + RB_INSERT(pid_index, &proc_pid_index, ppd); } + LIST_INSERT_HEAD(&ppd->ppd_proc_waiters, kn, kn_proc_waiter); + pthread_mutex_unlock(&proc_pid_index_mtx); + + /* + * These get added by default on macOS (and likely FreeBSD) + * which make sense considering a process exiting is an + * edge triggered event, not a level triggered one. + */ + kn->kev.flags |= EV_ONESHOT; + kn->kev.flags |= EV_CLEAR; + + return (0); +} - if (src->flags & EV_ADD || src->flags & EV_ENABLE) { - /* Nothing to do.. */ +int +evfilt_proc_knote_modify(UNUSED struct filter *filt, UNUSED struct knote *kn, + UNUSED const struct kevent *kev) +{ + return (0); /* All work done in common code */ +} + +int +evfilt_proc_knote_delete(UNUSED struct filter *filt, struct knote *kn) +{ + struct proc_pid *ppd; + + pthread_mutex_lock(&proc_pid_index_mtx); + if (LIST_INSERTED(kn, kn_proc_waiter)) LIST_REMOVE(kn, kn_proc_waiter); + + /* + * ppd may have been removed already if there + * were no more waiters. + */ + ppd = RB_FIND(pid_index, &proc_pid_index, &(struct proc_pid){ .ppd_pid = kn->kev.ident }); + if (ppd) { + if (!LIST_FIRST(&ppd->ppd_proc_waiters)) { + dbg_printf("pid=%u removing waiter list", (unsigned int)ppd->ppd_pid); + RB_REMOVE(pid_index, &proc_pid_index, ppd); + free(ppd); + } else { + dbg_printf("pid=%u leaving waiter list", (unsigned int)ppd->ppd_pid); + } + } else { + dbg_printf("pid=%u waiter list already removed", (unsigned int)kn->kev.ident); } + pthread_mutex_unlock(&proc_pid_index_mtx); + + return (0); +} + +int +evfilt_proc_knote_disable(UNUSED struct filter *filt, struct knote *kn) +{ + /* + * Remove the knote from the waiter list but + * don't free the waiter list itself. + * + * If two knotes are waiting on a PID and one + * is disabled and the other is deleted, + * then the `struct proc_pid` will be freed, + * which is why we need to run the same logic + * as on create when re-enabling. + */ + pthread_mutex_lock(&proc_pid_index_mtx); + if (LIST_INSERTED(kn, kn_proc_waiter)) LIST_REMOVE(kn, kn_proc_waiter); + pthread_mutex_unlock(&proc_pid_index_mtx); return (0); } static int -evfilt_proc_copyout(struct kevent *dst, int nevents, struct filter *filt, +evfilt_proc_knote_copyout(struct kevent *dst, int nevents, struct filter *filt, struct knote *kn, void *ev) { - struct knote *kn; + struct knote *tmp; int events = 0; - LIST_FOREACH_SAFE(kn, &filt->kf_eventlist, kn_list) { + /* + * Prevent the waiter thread from modifying + * the knotes in the ready list whilst we're + * processing them. + */ + pthread_mutex_lock(&filt->kf_knote_mtx); + + /* + * kn arg is always NULL here, so we just reuse it + * for the loop. + */ + LIST_FOREACH_SAFE(kn, &filt->kf_ready, kn_ready, tmp) { if (++events > nevents) break; kevent_dump(&kn->kev); memcpy(dst, &kn->kev, sizeof(*dst)); dst->fflags = NOTE_EXIT; - + dst->flags |= EV_EOF; + dst->data = kn->kn_proc_status; if (knote_copyout_flag_actions(filt, kn) < 0) return -1; dst++; } - - if (!LIST_EMPTY(&filt->kf_eventlist)) - filter_raise(filt); + if (LIST_EMPTY(&filt->kf_ready)) + kqops.eventfd_lower(&filt->kf_proc_eventfd); + pthread_mutex_unlock(&filt->kf_knote_mtx); return (nevents); } @@ -189,6 +423,10 @@ const struct filter evfilt_proc = { .kf_id = EVFILT_PROC, .kf_init = evfilt_proc_init, .kf_destroy = evfilt_proc_destroy, - .kf_copyout = evfilt_proc_copyout, - .kn_create = evfilt_proc_create, + .kf_copyout = evfilt_proc_knote_copyout, + .kn_create = evfilt_proc_knote_create, + .kn_modify = evfilt_proc_knote_modify, + .kn_enable = evfilt_proc_knote_create, + .kn_disable = evfilt_proc_knote_disable, + .kn_delete = evfilt_proc_knote_delete }; From ef8198e666d1fe2e5b21016c87b81e003922cab2 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 3 Sep 2021 07:36:03 -0500 Subject: [PATCH 0891/1120] Add test for receiving EVFILT_PROC events from multiple kqueues --- vendor/libkqueue/test/proc.c | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/vendor/libkqueue/test/proc.c b/vendor/libkqueue/test/proc.c index 9f4dee824..4b42ce65c 100644 --- a/vendor/libkqueue/test/proc.c +++ b/vendor/libkqueue/test/proc.c @@ -169,6 +169,56 @@ test_kevent_proc_exit_status_error(struct test_context *ctx) test_no_kevents(ctx->kqfd); } +static void +test_kevent_proc_multiple_kqueue(struct test_context *ctx) +{ + struct kevent kev, buf_a, buf_b; + int fflags; + int kq_b; + + /* + * macOS requires NOTE_EXITSTATUS to get the + * exit code of the process, FreeBSD always + * provides it. + */ +#ifdef __APPLE__ + fflags = NOTE_EXIT | NOTE_EXITSTATUS; +#else + fflags = NOTE_EXIT; +#endif + + kq_b = kqueue(); + + /* Create a child that waits to be killed and then exits */ + pid = fork(); + if (pid == 0) { + usleep(100000); + printf(" -- child done sleeping, exiting (64)\n"); + testing_end_quiet(); + exit(64); + } + printf(" -- child created (pid %d)\n", (int) pid); + + test_no_kevents(ctx->kqfd); + test_no_kevents(kq_b); + + kevent_add(ctx->kqfd, &kev, pid, EVFILT_PROC, EV_ADD, fflags, 0, NULL); + kevent_add(kq_b, &kev, pid, EVFILT_PROC, EV_ADD, fflags, 0, NULL); + + kevent_get(&buf_a, ctx->kqfd, 1); + kevent_get(&buf_b, kq_b, 1); + + kev.data = 64 << 8; /* What we expected the process exit code to be */ + kev.flags = EV_ADD | EV_ONESHOT | EV_CLEAR | EV_EOF; + + kevent_cmp(&kev, &buf_a); + kevent_cmp(&kev, &buf_b); + test_no_kevents(ctx->kqfd); + test_no_kevents(kq_b); + + close(kq_b); +} + #ifdef TODO void test_kevent_signal_disable(struct test_context *ctx) @@ -309,6 +359,7 @@ test_evfilt_proc(struct test_context *ctx) test(kevent_proc_get, ctx); test(kevent_proc_exit_status_ok, ctx); test(kevent_proc_exit_status_error, ctx); + test(kevent_proc_multiple_kqueue, ctx); signal(SIGUSR1, SIG_DFL); From 8f926e858458e360ec3e038bb97db06bd8a35d5e Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 3 Sep 2021 07:58:33 -0500 Subject: [PATCH 0892/1120] Fix whitespace in BUGS.md --- vendor/libkqueue/BUGS.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/vendor/libkqueue/BUGS.md b/vendor/libkqueue/BUGS.md index 9f33f9e86..3274509f9 100644 --- a/vendor/libkqueue/BUGS.md +++ b/vendor/libkqueue/BUGS.md @@ -1,19 +1,19 @@ # libkqueue (userland) - + This documents the current behavioural differences or defficiencies of libkqueue vs the native BSD kqueue implementations. - + ## Common - + * We need to uninitialize library after `fork()` `using pthread_atfork()`. BSD kqueue file descriptors are not inherited by the fork copy and will be closed automatically in the fork. With libkqueue, because we don't unitialize the library, kqueue file descriptors will persist in the fork. - + * Some functions should crash instead of silently printing a debug message.. for example, `note_release()`. - + * There are a number of stub functions that silently fail or succeed. These need to be cleaned up; at a minimum, they should emit very loud debugging output saying "FIXME -- UNIMPLEMENTED". @@ -29,25 +29,25 @@ src/windows/read.c: return (-1); /* STUB */ src/windows/timer.c: return (0); /* STUB */ ``` - + * `kqueue()` should defer thread cancellation until the end. * `kevent()` should defer thread cancellation and call `pthread_testcancel()` before and after the call to `kevent_wait()`. This may require changing the way that `EINTR` is handled, to make sure that the `EINTR` is propagated up the call stack to `kevent()`. - + ## Linux - + * If a file descriptor outside of kqueue is closed, the internal kqueue state is not cleaned up. On Linux this is pretty much impossible to fix as there's no mechanism to retrieve file descriptor reference counts, and no way to be notified of when a file descriptor is closed. Applications should ensure that file descriptors are removed from the kqueue before they are closed. - + ## Solaris - + * Solaris unit test failure. ``` LD_LIBRARY_PATH="..:/usr/sfw/lib/64" ./kqtest @@ -61,17 +61,17 @@ [read.c:84]: Unexpected event:_test_no_kevents(): [ident=7, filter=-1, flags = 1 (EV_ADD), fflags = 0, data=0, udata=fffffd7fff08c6b4]: Error 0 ``` * If a file descriptor outside of kqueue is closed, the internal kqueue - state is not cleaned up. + state is not cleaned up. Applications should ensure that file descriptors are removed from the kqueue before they are closed. - + ## Windows - + * On Windows, you need to supply `-DMAKE_STATIC` in `CFLAGS` when building the static library. This does not apply when using cmake. - + * If a file descriptor outside of kqueue is closed, the internal kqueue - state is not cleaned up. + state is not cleaned up. Applications should ensure that file descriptors are removed from the kqueue before they are closed. From 9e4a6a8ef0cee52b35b7033a8fcc8e3f3cabc3e0 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 3 Sep 2021 07:58:47 -0500 Subject: [PATCH 0893/1120] Add notes about the current state of EVFILT_PROC --- vendor/libkqueue/BUGS.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/vendor/libkqueue/BUGS.md b/vendor/libkqueue/BUGS.md index 3274509f9..489ac4d17 100644 --- a/vendor/libkqueue/BUGS.md +++ b/vendor/libkqueue/BUGS.md @@ -46,6 +46,26 @@ Applications should ensure that file descriptors are removed from the kqueue before they are closed. + * `EVFILT_PROC` - Only `NOTE_EXIT` is currently supported. Other + functionality is possible, but it requires integrating with netlink to + receive notifications. + If building against Kernels < 5.3 (where `pidfd_open()` is not available) + the POSIX `EVFILT_PROC` code is used. The posix code requires that `SIGCHLD` + be delivered to its global waiter thread, so that the waiter can discover a + when child process exits. + `sigprocmask(2)` is used to mask `SIGCHLD` at a process level. If the + application unmasks `SIGCHLD` or installs a handler for it, the POSIX + `EVFILT_PROC` code will not function. + Native kqueue provides notifications for any process that is visible to the + application process, on Linux/POSIX platforms only direct children of the + application process can be monitored for exit. + If using the POSIX `EVFILT_PROC` the number of monitored processes should be + kept low (< 100). Because the Linux kernel coalesces `SIGCHLD` + (and other signals), the only way to reliably determine if a monitored process + has exited, is to loop through all PIDs registered by any kqueue when we + receive a `SIGCHLD`. This involves many calls to `waitid(2)` and may have + a negative performance impact. + ## Solaris * Solaris unit test failure. From e16068f20f6b3e3a505d5fbfcc91d85a37f93992 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 3 Sep 2021 08:12:59 -0500 Subject: [PATCH 0894/1120] Update release notes --- vendor/libkqueue/ChangeLog | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index a4178de72..6b922b75a 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -3,7 +3,12 @@ Unreleased Nothing here yet. - * Add support for monitoring process exit with EVFILT_PROC via pidfd for Linux >= 5.3 +0000-00-00 v2.4.1 +------------------------------------------------------------------------ + + * Add back support for monitoring process exit with EVFILT_PROC. + The is done with `pidfd_open(2)` for Linux >= 5.3, and via a new common POSIX + monitoring thread for Linux < 5.3 and other POSIX platforms. * Fix: Include errors (EV_ERROR), and changelist entries with EV_RECEIPT in eventlist. (Reported by: orbitz) From a800e3f6cffc0fc56737b135177baf4a50087530 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 3 Sep 2021 10:12:48 -0500 Subject: [PATCH 0895/1120] s/!LIST_FIRST/LIST_EMPTY/ in posix/proc --- vendor/libkqueue/src/posix/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index dfac0f377..4ddf90a52 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -345,7 +345,7 @@ evfilt_proc_knote_delete(UNUSED struct filter *filt, struct knote *kn) */ ppd = RB_FIND(pid_index, &proc_pid_index, &(struct proc_pid){ .ppd_pid = kn->kev.ident }); if (ppd) { - if (!LIST_FIRST(&ppd->ppd_proc_waiters)) { + if (LIST_EMPTY(&ppd->ppd_proc_waiters)) { dbg_printf("pid=%u removing waiter list", (unsigned int)ppd->ppd_pid); RB_REMOVE(pid_index, &proc_pid_index, ppd); free(ppd); From 3e1b8a7a15d6ac8a900e13200cd1cfc4ef560f71 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 3 Sep 2021 10:47:05 -0500 Subject: [PATCH 0896/1120] More notes on the posix/proc code --- vendor/libkqueue/src/linux/proc.c | 2 +- vendor/libkqueue/src/posix/proc.c | 87 ++++++++++++++++++++++++------- 2 files changed, 69 insertions(+), 20 deletions(-) diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index 30b572c30..ee105ed96 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -20,7 +20,7 @@ * isn't available there's currently no good fallback. * * If the build system detects SYS_pidfd_open is not available it will fall back - * to using posix/proc.c and not build this source file. + * to using posix/proc.c and won't build this source file. */ #include #include diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 4ddf90a52..df2c39b14 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -163,26 +163,74 @@ wait_thread(UNUSED void *arg) dbg_printf("started and waiting for SIGCHLD"); /* - * To avoid messing up the application linked to libkqueue - * and reaping all child processes we must use WNOWAIT in - * any *wait*() calls. Even for PIDs registered with the - * EV_PROC filter we're not meant to reap the process because - * we're trying to behave identically to BSD kqueue and BSD - * kqueue doesn't do this. + * Native kqueue implementations leave processes monitored + * with EVFILT_PROC + NOTE_EXIT un-reaped when they exit. * + * Applications using kqueue expect to be able to retrieve + * the process exit state using one of the *wait*() calls. + * + * So that these applications don't experience errors, + * processes must remain un-reaped so those subsequent + * *wait*() calls can succeed. + * + * Because processes must remain un-reaped we can only use + * calls which accept the WNOWAIT flag, and do not reap + * processes. + * + * The obvious solution is to use waitid(P_ALL,,,WNOWAIT), + * and only notify on the PIDs we're interested in. * Unfortunately waitid() will return the same PID repeatedly - * if passed P_ALL/WNOWAIT if the previously returned PID - * is not reaped. + * if the previously returned PID was not reaped. + * + * At first glance sigwaitinfo([SIGCHLD], ) appears to be + * another promising option. The siginfo_t populated by + * sigwaitinfo() contains all the information we need to + * raise a notification that a process has exited, and a + * SIGCHLD signal is raised every time a process exits. + * + * Unfortunately on Linux, SIGCHLD signals, along with all + * other signals, are coalesced. This means if two children + * exited before the wait thread was woken up from waiting + * on sigwaitinfo(), we'd only get the siginfo_t structure + * populated for one child. + * + * The only apparent fully kqueue compatible and POSIX + * compatible solution is to use sigwatinfo() to determine + * that _A_ child had exited, and then scan all PIDs we're + * interested in, passing them to waitid() in turn. + * + * This isn't a great solution for the following reasons: + * + * - SIGCHLD must be delivered to the wait thread in order + * for notifications to be sent out. + * If the application installs its own signal handler + * for SIGCHLD, or changes the process signal mask, + * we may never get notified when a child exits. + * + * - Scanning through all the monitored PIDs doesn't scale + * well, and involves many system calls. + * + * - Because only one thread can receive the SIGCHLD + * signal, all monitoring must be done in a single + * waiter thread. This introduces code complexity and + * contention around the global tree that holds the PIDs + * that are being monitored. + * + * Because of these limitations, on Linux >= 5.3 we use + * pidfd_open() to get a FD bound to a PID that we can + * monitor. Testing shows that multiple pidfds bound to + * the same PID will each receive a notification when + * that process exits. Using pidfd avoids the messiness + * of signals, the linear scans, and the global structures. * - * We can use SIGCHLD to get notified when a child process - * exits. Unfortunately Linux (in particular) will coalesce - * multiple signals sent to the same process, so we can't - * rely on sigwaitinfo alone. + * Unfortunately at the time of writing Linux 5.3 is still + * relatively new, and the feasibility of writing native + * solutions for platforms like Solaris hasn't been + * investigated. * - * The final solution is to use sigwaitinfo() as a - * notification that a child exited, and then scan through - * the list of PIDs we're waiting on using waitid to see if - * any of those exited. + * Until Linux 5.3 becomes more widely used, and we have + * a native solution for Solaris this POSIX EVFILT_PROC + * code must remain to provide a fallback mechanism. */ while ((ret = sigwaitinfo(&sigmask, &info))) { if (ret < 0) { @@ -256,8 +304,9 @@ evfilt_proc_init(struct filter *filt) * that the wait thread is the only thing * that receives SIGCHLD. * - * The wait thread does not receive the - * SIGCHLD without this code. + * The wait thread will not reliably receive + * a SIGCHLD signal if SIGCHLD is not + * blocked in all other threads. */ sigemptyset(&sigmask); sigaddset(&sigmask, SIGCHLD); @@ -371,7 +420,7 @@ evfilt_proc_knote_disable(UNUSED struct filter *filt, struct knote *kn) * is disabled and the other is deleted, * then the `struct proc_pid` will be freed, * which is why we need to run the same logic - * as on create when re-enabling. + * as knote_create when re-enabling. */ pthread_mutex_lock(&proc_pid_index_mtx); if (LIST_INSERTED(kn, kn_proc_waiter)) LIST_REMOVE(kn, kn_proc_waiter); From b6bf8f3aa889c8dabe1280c2cbeeba3a65681831 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Mon, 6 Sep 2021 15:30:40 -0300 Subject: [PATCH 0897/1120] proc: Fix missing mutex unlock It prevents potential dead-lock --- vendor/libkqueue/src/posix/proc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index df2c39b14..e487d188e 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -457,12 +457,17 @@ evfilt_proc_knote_copyout(struct kevent *dst, int nevents, struct filter *filt, dst->flags |= EV_EOF; dst->data = kn->kn_proc_status; - if (knote_copyout_flag_actions(filt, kn) < 0) return -1; + if (knote_copyout_flag_actions(filt, kn) < 0) { + pthread_mutex_unlock(&filt->kf_knote_mtx); + return -1; + } dst++; } + if (LIST_EMPTY(&filt->kf_ready)) kqops.eventfd_lower(&filt->kf_proc_eventfd); + pthread_mutex_unlock(&filt->kf_knote_mtx); return (nevents); From 4890548a90398af03c8529930c10adc3c3de283c Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 6 Sep 2021 20:27:43 -0500 Subject: [PATCH 0898/1120] The next release should be 2.5, given the extent of the changes --- vendor/libkqueue/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 6b922b75a..fdb194bb8 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -3,7 +3,7 @@ Unreleased Nothing here yet. -0000-00-00 v2.4.1 +2021-09-06 v2.5.0 ------------------------------------------------------------------------ * Add back support for monitoring process exit with EVFILT_PROC. From a1cc0814e5b221ec4ccedf80532edbf6511f7762 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 6 Sep 2021 20:28:23 -0500 Subject: [PATCH 0899/1120] Set version 2.5 in CMakeLists too --- vendor/libkqueue/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index b97b4848a..1f4b853c9 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -14,7 +14,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -set(PROJECT_VERSION 2.4.1) +set(PROJECT_VERSION 2.5.0) if(EXISTS "/etc/debian_version") cmake_minimum_required(VERSION 3.7.2) From 30d93c7361b17dcd74cdf9b8d87af313deb834ed Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 8 Sep 2021 07:12:25 -0500 Subject: [PATCH 0900/1120] Format the pthread emulation macros --- vendor/libkqueue/src/windows/platform.h | 33 ++++++++++++------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 0b641bd7a..95cdd139e 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -136,24 +136,23 @@ typedef int pid_t; /* Emulation of pthreads mutex functionality */ #define PTHREAD_PROCESS_SHARED 1 #define PTHREAD_PROCESS_PRIVATE 2 -typedef CRITICAL_SECTION pthread_mutex_t; -typedef CRITICAL_SECTION pthread_spinlock_t; -typedef CRITICAL_SECTION pthread_rwlock_t; -#define _cs_init(x) InitializeCriticalSection((x)) -#define _cs_lock(x) EnterCriticalSection ((x)) -#define _cs_unlock(x) LeaveCriticalSection ((x)) -#define pthread_mutex_lock _cs_lock -#define pthread_mutex_unlock _cs_unlock -#define pthread_mutex_init(x,y) _cs_init((x)) -#define pthread_spin_lock _cs_lock -#define pthread_spin_unlock _cs_unlock -#define pthread_spin_init(x,y) _cs_init((x)) -#define pthread_mutex_init(x,y) _cs_init((x)) +typedef CRITICAL_SECTION pthread_mutex_t; +typedef CRITICAL_SECTION pthread_spinlock_t; +typedef CRITICAL_SECTION pthread_rwlock_t; + +#define EnterCriticalSection(x) EnterCriticalSection ((x)) +#define pthread_mutex_lock EnterCriticalSection +#define pthread_mutex_unlock LeaveCriticalSection +#define pthread_mutex_init(x,y) InitializeCriticalSection((x)) +#define pthread_spin_lock EnterCriticalSection +#define pthread_spin_unlock LeaveCriticalSection +#define pthread_spin_init(x,y) InitializeCriticalSection((x)) +#define pthread_mutex_init(x,y) InitializeCriticalSection((x)) #define pthread_mutex_destroy(x) -#define pthread_rwlock_rdlock _cs_lock -#define pthread_rwlock_wrlock _cs_lock -#define pthread_rwlock_unlock _cs_unlock -#define pthread_rwlock_init(x,y) _cs_init((x)) +#define pthread_rwlock_rdlock EnterCriticalSection +#define pthread_rwlock_wrlock EnterCriticalSection +#define pthread_rwlock_unlock LeaveCriticalSection +#define pthread_rwlock_init(x,y) InitializeCriticalSection((x)) #endif /* ! _KQUEUE_WINDOWS_PLATFORM_H */ From 4ada2ccc3ab7f9955c0d7dde543caed50fb10edc Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 8 Sep 2021 07:13:16 -0500 Subject: [PATCH 0901/1120] All critical section locks on Windows are recursive anyway Closes #111 --- vendor/libkqueue/src/common/filter.c | 4 ++++ vendor/libkqueue/src/common/private.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index e23e33c1f..ba9c9d0b4 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -55,8 +55,10 @@ filter_register(struct kqueue *kq, const struct filter *src) * It's probably not a great idea, but it makes the code * simpler. */ +#ifndef _WIN32 pthread_mutexattr_init(&dst->kf_knote_mtx_attr); pthread_mutexattr_settype(&dst->kf_knote_mtx_attr, PTHREAD_MUTEX_RECURSIVE); +#endif pthread_mutex_init(&dst->kf_knote_mtx, &dst->kf_knote_mtx_attr); if (src->kf_id == 0) { dbg_puts("filter is not implemented"); @@ -132,7 +134,9 @@ filter_unregister_all(struct kqueue *kq) * ...and destroy the mutexes. */ pthread_mutex_destroy(&filt->kf_knote_mtx); +#ifndef _WIN32 pthread_mutexattr_destroy(&filt->kf_knote_mtx_attr); +#endif } memset(&kq->kq_filt[0], 0, sizeof(kq->kq_filt)); } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 32689b2b3..498de97f2 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -407,7 +407,9 @@ struct filter { pthread_mutex_t kf_knote_mtx; //!< Used to synchronise knote operations ///< (addition, removal, modification etc...) ///< on this filter. +#ifndef _WIN32 pthread_mutexattr_t kf_knote_mtx_attr; +#endif struct kqueue *kf_kqueue; //!< kqueue this filter is associated with. From 564d9df421ca42e2a3c9c62ee7f2ebe506630b89 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 8 Sep 2021 07:13:46 -0500 Subject: [PATCH 0902/1120] Remove hack from queue.h so we get LIST_HEAD on Windows Closes #111 --- vendor/libkqueue/src/common/queue.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/vendor/libkqueue/src/common/queue.h b/vendor/libkqueue/src/common/queue.h index 479207ff1..669e513f9 100644 --- a/vendor/libkqueue/src/common/queue.h +++ b/vendor/libkqueue/src/common/queue.h @@ -323,12 +323,7 @@ struct { \ (head2)->stqh_last = &STAILQ_FIRST(head2); \ } while (0) - -/* - * List declarations. - * NOTE: LIST_HEAD conflicts with a Linux macro. - */ -#define FIXME_LIST_HEAD(name, type) \ +#define LIST_HEAD(name, type) \ struct name { \ struct type *lh_first; /* first element */ \ } From e0f6636b2b4b1355558c8de2f53e5552984c3f0c Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 8 Sep 2021 07:14:19 -0500 Subject: [PATCH 0903/1120] Pass additional argument to pthread_mutex_init in kqueue.c Closes #111 --- vendor/libkqueue/src/common/kqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 835853a39..1e3c8c1f3 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -84,7 +84,7 @@ libkqueue_init(void) DEBUG_KQUEUE = 1; #ifdef _WIN32 - pthread_mutex_init(&kq_mtx); + pthread_mutex_init(&kq_mtx, NULL); /* Initialize the Winsock library */ WSADATA wsaData; if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) From 123400a631a41423116bb08da598f373304019c7 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 9 Sep 2021 08:34:01 -0500 Subject: [PATCH 0904/1120] Add debugging for struct epoll_event --- vendor/libkqueue/src/linux/platform.c | 82 ++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 451e68ab6..02e6e1fbf 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -545,12 +545,90 @@ static inline int linux_kevent_copyout_ev(struct kevent *el, int nevents, struct return rv; } +static const char * +udata_type(enum epoll_udata_type ud_type) +{ + const char *ud_name[] = { + [EPOLL_UDATA_KNOTE] = "EPOLL_UDATA_KNOTE", + [EPOLL_UDATA_FD_STATE] = "EPOLL_UDATA_FD_STATE", + [EPOLL_UDATA_EVENT_FD] = "EPOLL_UDATA_EVENT_FD", + }; + + if (ud_type < 0 || ud_type >= NUM_ELEMENTS(ud_name)) + return "EPOLL_UDATA_INVALID"; + else + return ud_name[ud_type]; +} + +static const char * +linux_epoll_udata_type_dump(const struct epoll_event *ev) +{ + static __thread char buf[64]; + enum epoll_udata_type ud_type; + + ud_type = ((struct epoll_udata *)(ev->data.ptr))->ud_type; + + snprintf(buf, sizeof(buf), "%d (%s)", + ud_type, udata_type(ud_type)); + return ((const char *) buf); +} + +static const char * +linux_epoll_events_dump(const struct epoll_event *ev) +{ + static __thread char buf[1024]; + size_t len; + +#define EEVENT_DUMP(attrib) \ + if (ev->events & attrib) \ + strncat((char *) buf, #attrib" ", 64); + + snprintf(buf, sizeof(buf), "events=0x%08x (", ev->events); + EEVENT_DUMP(EPOLLIN); + EEVENT_DUMP(EPOLLPRI); + EEVENT_DUMP(EPOLLOUT); + EEVENT_DUMP(EPOLLRDNORM); + EEVENT_DUMP(EPOLLRDBAND); + EEVENT_DUMP(EPOLLWRNORM); + EEVENT_DUMP(EPOLLWRBAND); + EEVENT_DUMP(EPOLLMSG); + EEVENT_DUMP(EPOLLERR); + EEVENT_DUMP(EPOLLHUP); + EEVENT_DUMP(EPOLLRDHUP); + EEVENT_DUMP(EPOLLONESHOT); + EEVENT_DUMP(EPOLLET); + + len = strlen(buf); + if (buf[len - 1] == ' ') buf[len - 1] = '\0'; /* Trim trailing space */ + strcat(buf, ")"); + +#undef EEVENT_DUMP + + return ((const char *) buf); +} + +const char * +linux_epoll_dump(const struct epoll_event *ev) +{ + static __thread char buf[2147]; + + snprintf((char *) buf, sizeof(buf), + "{ %s, udata=%p, udata_type=%s }", + linux_epoll_events_dump(ev), + ev->data.ptr, + linux_epoll_udata_type_dump(ev)); + + return ((const char *) buf); +} + int linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int nevents) { struct kevent *el_p = el, *el_end = el + nevents; int i; + dbg_printf("got %i events from epoll", nevents); + for (i = 0; i < nready; i++) { struct epoll_event *ev = &epoll_events[i]; /* Thread local storage populated in linux_kevent_wait */ struct epoll_udata *epoll_udata = ev->data.ptr; @@ -561,6 +639,8 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven continue; } + dbg_printf("[%i] %s", i, linux_epoll_dump(ev)); + /* * epoll event is associated with a single filter * so we just have one knote per event. @@ -641,8 +721,6 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven assert(efd); - dbg_printf("eventfd=%u - received event", (unsigned int)efd->ef_id); - rv = linux_kevent_copyout_ev(el_p, (el_end - el_p), ev, efd->ef_filt, NULL); if (rv < 0) goto done; el_p += rv; From 82f6e369bbd335544230ccff46e947d8c5cf1f35 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 9 Sep 2021 12:39:18 -0500 Subject: [PATCH 0905/1120] Cleanup duplicate dumping code in the Linux platform --- vendor/libkqueue/src/linux/platform.c | 114 ++++++++++---------------- vendor/libkqueue/src/linux/platform.h | 6 +- 2 files changed, 45 insertions(+), 75 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 02e6e1fbf..2d93d62b0 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -545,6 +545,25 @@ static inline int linux_kevent_copyout_ev(struct kevent *el, int nevents, struct return rv; } +char const *epoll_op_dump(int op) +{ + static __thread char buf[14]; + + buf[0] = '\0'; + +#define EPOP_DUMP(attrib) \ + if (op == attrib) { \ + strcpy(buf, #attrib); \ + return buf; \ + } + + EPOP_DUMP(EPOLL_CTL_MOD); + EPOP_DUMP(EPOLL_CTL_ADD); + EPOP_DUMP(EPOLL_CTL_DEL); + + return buf; +} + static const char * udata_type(enum epoll_udata_type ud_type) { @@ -561,7 +580,7 @@ udata_type(enum epoll_udata_type ud_type) } static const char * -linux_epoll_udata_type_dump(const struct epoll_event *ev) +epoll_udata_type_dump(const struct epoll_event *ev) { static __thread char buf[64]; enum epoll_udata_type ud_type; @@ -574,16 +593,16 @@ linux_epoll_udata_type_dump(const struct epoll_event *ev) } static const char * -linux_epoll_events_dump(const struct epoll_event *ev) +epoll_flags_dump(uint32_t events) { static __thread char buf[1024]; size_t len; #define EEVENT_DUMP(attrib) \ - if (ev->events & attrib) \ + if (events & attrib) \ strncat((char *) buf, #attrib" ", 64); - snprintf(buf, sizeof(buf), "events=0x%08x (", ev->events); + snprintf(buf, sizeof(buf), "events=0x%08x (", events); EEVENT_DUMP(EPOLLIN); EEVENT_DUMP(EPOLLPRI); EEVENT_DUMP(EPOLLOUT); @@ -608,15 +627,21 @@ linux_epoll_events_dump(const struct epoll_event *ev) } const char * -linux_epoll_dump(const struct epoll_event *ev) +epoll_event_flags_dump(const struct epoll_event *ev) +{ + return epoll_flags_dump(ev->events); +} + +const char * +epoll_event_dump(const struct epoll_event *ev) { static __thread char buf[2147]; snprintf((char *) buf, sizeof(buf), "{ %s, udata=%p, udata_type=%s }", - linux_epoll_events_dump(ev), + epoll_event_flags_dump(ev), ev->data.ptr, - linux_epoll_udata_type_dump(ev)); + epoll_udata_type_dump(ev)); return ((const char *) buf); } @@ -639,7 +664,7 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven continue; } - dbg_printf("[%i] %s", i, linux_epoll_dump(ev)); + dbg_printf("[%i] %s", i, epoll_event_dump(ev)); /* * epoll event is associated with a single filter @@ -1020,61 +1045,6 @@ linux_get_descriptor_type(struct knote *kn) return (0); } -char *epoll_event_op_dump(int op) -{ - static __thread char buf[14]; - - buf[0] = '\0'; - -#define EPOP_DUMP(attrib) \ - if (op == attrib) { \ - strcpy(buf, #attrib); \ - return buf; \ - } - - EPOP_DUMP(EPOLL_CTL_MOD); - EPOP_DUMP(EPOLL_CTL_ADD); - EPOP_DUMP(EPOLL_CTL_DEL); - - return buf; -} - -char *epoll_event_flags_dump(int events) -{ - static __thread char buf[128]; - - buf[0] = '\0'; - -#define EPEVT_DUMP(attrib) \ - if (events & attrib) strcat(buf, #attrib" "); - - EPEVT_DUMP(EPOLLIN); - EPEVT_DUMP(EPOLLOUT); -#if defined(HAVE_EPOLLRDHUP) - EPEVT_DUMP(EPOLLRDHUP); -#endif - EPEVT_DUMP(EPOLLONESHOT); - EPEVT_DUMP(EPOLLET); - - if (buf[0] != '\0') buf[strlen(buf) - 1] = '\0'; /* Trim trailing space */ - - return buf; -} - -char * -epoll_event_dump(struct epoll_event *evt) -{ - static __thread char buf[128]; - - if (evt == NULL) - return "(null)"; - - snprintf(buf, sizeof(buf), "{ data = %p, events = %s }", evt->data.ptr, epoll_event_flags_dump(evt->events)); - - return (buf); -#undef EPEVT_DUMP -} - /** Determine if two fd state entries are equal * * @param[in] a first entry. @@ -1178,7 +1148,7 @@ int epoll_fd_state_mod(struct fd_state **fds_p, struct knote *kn, int ev) fds = RB_FIND(fd_st, &kq->kq_fd_st, &query); if (!fds) { - dbg_printf("fd_state: new fd=%i events=0x%04x (%s)", fd, ev, epoll_event_flags_dump(ev)); + dbg_printf("fd_state: new fd=%i events=0x%08x (%s)", fd, ev, epoll_flags_dump(ev)); fds = malloc(sizeof(struct fd_state)); if (!fds) return (-1); @@ -1189,7 +1159,7 @@ int epoll_fd_state_mod(struct fd_state **fds_p, struct knote *kn, int ev) } else { mod: - dbg_printf("fd_state: mod fd=%i events=0x%04x (%s)", fd, ev, epoll_event_flags_dump(ev)); + dbg_printf("fd_state: mod fd=%i events=0x%08x (%s)", fd, ev, epoll_flags_dump(ev)); } } else goto mod; @@ -1246,7 +1216,7 @@ void epoll_fd_state_del(struct fd_state **fds_p, struct knote *kn, int ev) free(fds); *fds_p = NULL; } else { - dbg_printf("fd_state: mod fd=%i events=0x%04x (%s)", fds->fds_fd, ev, epoll_event_flags_dump(ev)); + dbg_printf("fd_state: mod fd=%i events=0x%08x (%s)", fds->fds_fd, ev, epoll_flags_dump(ev)); } kn->kn_fds = NULL; } @@ -1296,7 +1266,7 @@ epoll_update(int op, struct filter *filt, struct knote *kn, int ev, bool delete) */ have_ev = epoll_fd_state(&fds, kn, false); /* ...enabled only */ - dbg_printf("fd=%i have_ev=0x%04x (%s)", fd, have_ev, epoll_event_flags_dump(have_ev)); + dbg_printf("fd=%i have_ev=0x%04x (%s)", fd, have_ev, epoll_flags_dump(have_ev)); switch (op) { case EPOLL_CTL_ADD: want = have_ev | ev; /* This also preserves other option flags */ @@ -1314,7 +1284,7 @@ epoll_update(int op, struct filter *filt, struct knote *kn, int ev, bool delete) int to_delete; to_delete = epoll_fd_state(&fds, kn, true); /* ...disabled only */ - dbg_printf("fd=%i disabled_ev=0x%04x (%s)", fd, to_delete, epoll_event_flags_dump(to_delete)); + dbg_printf("fd=%i disabled_ev=0x%04x (%s)", fd, to_delete, epoll_flags_dump(to_delete)); to_delete &= EV_EPOLLINOUT(ev); if (to_delete) { @@ -1331,7 +1301,7 @@ epoll_update(int op, struct filter *filt, struct knote *kn, int ev, bool delete) int to_delete; to_delete = epoll_fd_state(&fds, kn, true); /* ...disabled only */ - dbg_printf("fd=%i disabled_ev=0x%04x (%s)", fd, to_delete, epoll_event_flags_dump(to_delete)); + dbg_printf("fd=%i disabled_ev=0x%04x (%s)", fd, to_delete, epoll_flags_dump(to_delete)); to_delete &= ~ev; if (to_delete) { @@ -1363,8 +1333,8 @@ epoll_update(int op, struct filter *filt, struct knote *kn, int ev, bool delete) dbg_printf("fd=%i op=0x%04x (%s) opn=0x%04x (%s) %s", fd, - op, epoll_event_op_dump(op), - opn, epoll_event_op_dump(opn), + op, epoll_op_dump(op), + opn, epoll_op_dump(opn), epoll_event_dump(EPOLL_EV_FDS(want, fds))); if (epoll_ctl(filter_epoll_fd(filt), opn, fd, EPOLL_EV_FDS(want, fds)) < 0) { @@ -1392,7 +1362,7 @@ epoll_update(int op, struct filter *filt, struct knote *kn, int ev, bool delete) kn_ev &= ~want_ev; /* If it wasn't wanted... */ if (kn_ev) { - dbg_printf("clearing fd=%i fds=%p ev=%s", fd, fds, epoll_event_flags_dump(kn_ev)); + dbg_printf("clearing fd=%i fds=%p ev=%s", fd, fds, epoll_flags_dump(kn_ev)); epoll_fd_state_del(&fds, kn, kn_ev); return (0); } diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 920623307..9b84ba579 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -248,9 +248,9 @@ int linux_fd_to_path(char *, size_t, int); /* epoll-related functions */ -char * epoll_event_op_dump(int); -char * epoll_event_flags_dump(int); -char * epoll_event_dump(struct epoll_event *); +char const * epoll_op_dump(int); +char const * epoll_event_flags_dump(const struct epoll_event *); +char const * epoll_event_dump(const struct epoll_event *); int epoll_fd_state(struct fd_state **, struct knote *, bool); int epoll_fd_state_init(struct fd_state **, struct knote *, int); From cafd97cf2c151960f14adc6dbc062e069406efac Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 9 Sep 2021 12:41:43 -0500 Subject: [PATCH 0906/1120] Deal with EOF on sockets in the Linux Platform Previously we'd just return EOF repeatedly. Now we record the EOF and unregister the FD from the event loop. --- vendor/libkqueue/src/common/private.h | 28 ++++++++++++--- vendor/libkqueue/src/linux/platform.c | 50 ++++++++++++++++++++++++--- vendor/libkqueue/src/linux/read.c | 21 ++++++++--- vendor/libkqueue/src/linux/write.c | 19 +++++++--- vendor/libkqueue/test/read.c | 24 +++++++++++-- 5 files changed, 123 insertions(+), 19 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 498de97f2..5f45b75e7 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -183,14 +183,14 @@ struct knote { /** Mark a knote as enabled */ -#define KNOTE_ENABLE(_kn) do { \ - (_kn)->kev.flags &= ~EV_DISABLE;\ +#define KNOTE_ENABLE(_kn) do { \ + (_kn)->kev.flags &= ~EV_DISABLE;\ } while (0/*CONSTCOND*/) /** Mark a knote as disabled */ -#define KNOTE_DISABLE(_kn) do { \ - (_kn)->kev.flags |= EV_DISABLE; \ +#define KNOTE_DISABLE(_kn) do { \ + (_kn)->kev.flags |= EV_DISABLE; \ } while (0/*CONSTCOND*/) /** Check if a knote is enabled @@ -201,6 +201,26 @@ struct knote { */ #define KNOTE_DISABLED(_kn) ((_kn)->kev.flags & EV_DISABLE) +/** Clear the EOF flags + */ +#define KNOTE_EOF_CLEAR(_kn) do { \ + (_kn)->kev.flags &= ~EV_EOF;\ +} while (0/*CONSTCOND*/) + +/** Mark a knote as EOF + */ +#define KNOTE_EOF_SET(_kn) do { \ + (_kn)->kev.flags |= EV_EOF; \ +} while (0/*CONSTCOND*/) + +/** Check if a knote is EOF + */ +#define KNOTE_IS_EOF(_kn) ((_kn)->kev.flags & EV_EOF) + +/** Check if a knote is EOF + */ +#define KNOTE_NOT_EOF(_kn) (!((_kn)->kev.flags & EV_EOF)) + /** A filter (discreet notification channel) within a kqueue * * Filters are discreet event notification facilities within a kqueue. diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 2d93d62b0..071df4d25 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -700,8 +700,49 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven { struct fd_state *fds = epoll_udata->ud_fds; struct knote *kn; - + struct filter *filt; assert(fds); + + /* + * Other side hung up. We assume this is + * for both reading and writing? + */ + if (ev->events & EPOLLHUP) { + if (fds->fds_read && KNOTE_NOT_EOF(fds->fds_read)) { + kn = fds->fds_read; + filt = knote_get_filter(kn); + + filt->kn_disable(filt, kn); + KNOTE_EOF_SET(kn); + } + if (fds->fds_write && KNOTE_NOT_EOF(fds->fds_write)) { + kn = fds->fds_write; + filt = knote_get_filter(kn); + + /* + * Set the EOF flag, and unregister the knote. + */ + filt->kn_disable(filt, kn); + KNOTE_EOF_SET(kn); + } + } + + /* + * Other side shutdown writing, but may still + * read... so we can still write? + * + * No idea why this event exists.. + */ + if (ev->events & EPOLLRDHUP) { + if (fds->fds_read && KNOTE_NOT_EOF(fds->fds_read)) { + kn = fds->fds_read; + filt = knote_get_filter(kn); + + filt->kn_disable(filt, kn); + KNOTE_EOF_SET(kn); + } + } + /* * FD is readable */ @@ -1099,8 +1140,8 @@ int epoll_fd_state(struct fd_state **fds_p, struct knote *kn, bool disabled) *fds_p = fds; - if (fds->fds_read && (disabled == ((kn->kev.flags & EV_DISABLE) != 0))) state |= EPOLLIN; - if (fds->fds_write && (disabled == ((kn->kev.flags & EV_DISABLE) != 0))) state |= EPOLLOUT; + state |= (fds->fds_read && (disabled == ((fds->fds_read->kev.flags & (EV_DISABLE | EV_EOF)) != 0))) * EPOLLIN; + state |= (fds->fds_write && (disabled == ((fds->fds_write->kev.flags & (EV_DISABLE | EV_EOF)) != 0))) * EPOLLOUT; return state; } @@ -1258,7 +1299,8 @@ epoll_update(int op, struct filter *filt, struct knote *kn, int ev, bool delete) #define EV_EPOLLINOUT(_x) ((_x) & (EPOLLIN | EPOLLOUT)) - if (kn->kev.flags & EV_DISABLE) dbg_printf("fd=%i kn=%p is disabled", fd, kn); + if (KNOTE_DISABLED(kn)) dbg_printf("fd=%i kn=%p is disabled", fd, kn); + if (KNOTE_IS_EOF(kn)) dbg_printf("fd=%i kn=%p is EOF", fd, kn); /* * Determine the current state of the file descriptor diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index 442e1d901..dbaf5f979 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -204,10 +204,21 @@ int evfilt_read_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { - (void) filt; - (void) kn; - (void) kev; - return (-1); /* STUB */ + /* + * re-enable a socket that was previously EOF'd + * + * restricted to sockets as this hasn't been tested with files. + */ + if (!(kn->kn_flags & KNFL_FILE)) { + if ((kev->flags & EV_CLEAR) && (KNOTE_IS_EOF(kn))) { + if (filt->kn_enable(filt, kn) < 0) + return -1; + KNOTE_EOF_CLEAR(kn); + } + return (0); + } + + return (-1); } int @@ -250,7 +261,7 @@ evfilt_read_knote_disable(struct filter *filt, struct knote *kn) dbg_perror("epoll_ctl(2)"); return (-1); } - kn->kn_registered = 1; + kn->kn_registered = 0; return (0); } diff --git a/vendor/libkqueue/src/linux/write.c b/vendor/libkqueue/src/linux/write.c index cdc312c25..f33416166 100644 --- a/vendor/libkqueue/src/linux/write.c +++ b/vendor/libkqueue/src/linux/write.c @@ -90,10 +90,21 @@ int evfilt_write_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { - (void) filt; - (void) kn; - (void) kev; - return (-1); /* STUB */ + /* + * re-enable a socket that was previously EOF'd + * + * restricted to sockets as this hasn't been tested with files. + */ + if (!(kn->kn_flags & KNFL_FILE)) { + if ((kev->flags & EV_CLEAR) && (KNOTE_IS_EOF(kn))) { + if (filt->kn_enable(filt, kn) < 0) + return -1; + KNOTE_EOF_CLEAR(kn); + } + return (0); + } + + return (-1); } int diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 0fa204444..5de09c8a9 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -374,8 +374,8 @@ test_kevent_socket_eof(struct test_context *ctx) kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD, 0, 0, &ctx->client_fd); test_no_kevents(ctx->kqfd); - //if (shutdown(ctx->server_fd, SHUT_RDWR) < 0) - // die("close(2)"); + if (shutdown(ctx->server_fd, SHUT_RDWR) < 0) + die("close(2)"); if (close(ctx->server_fd) < 0) die("close(2)"); @@ -383,6 +383,26 @@ test_kevent_socket_eof(struct test_context *ctx) kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); + /* + * When the last writer disconnects, the filter will + * set EV_EOF in flags. This may be cleared by passing + * in EV_CLEAR, at which point the filter will resume + * waiting for data to become available before return- + * ing. + * + * i.e. Once it's marked as EOF once, EOF should not be + * returned repeatedly. + */ + test_no_kevents(ctx->kqfd); + + /* modify the knote, setting EV_CLEAR - We should get another EOF */ + kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &ctx->client_fd); + + kev.flags ^= EV_CLEAR; + kev.flags |= EV_EOF; + kevent_get(&ret, ctx->kqfd, 1); + kevent_cmp(&kev, &ret); + /* Delete the watch */ kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_DELETE, 0, 0, &ctx->client_fd); } From 3ed5a6a891f0b2b5282b46ebce2a8bb94f31969f Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 9 Sep 2021 12:41:58 -0500 Subject: [PATCH 0907/1120] Debugging improvements --- vendor/libkqueue/src/common/kevent.c | 2 +- vendor/libkqueue/src/common/knote.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 51a3beb66..704b8fa89 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -291,7 +291,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, #ifndef NDEBUG if (DEBUG_KQUEUE) { myid = atomic_inc(&_kevent_counter); - dbg_printf("--- kevent %u --- (nchanges = %d nevents = %d)", myid, nchanges, nevents); + dbg_printf("--- START kevent %u --- (nchanges = %d nevents = %d)", myid, nchanges, nevents); } #endif diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 9bd6cffe1..73a9ab1c9 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -132,8 +132,10 @@ knote_delete(struct filter *filt, struct knote *kn) query.kev.ident = kn->kev.ident; pthread_mutex_lock(&filt->kf_knote_mtx); tmp = RB_FIND(knote_index, &filt->kf_index, &query); - if (tmp == kn) - RB_REMOVE(knote_index, &filt->kf_index, kn); + if (tmp != kn) + dbg_printf("kn=%p - conflicting entry in filter tree", kn); + + RB_REMOVE(knote_index, &filt->kf_index, kn); if (LIST_INSERTED(kn, kn_ready)) LIST_REMOVE(kn, kn_ready); From a4edac477876c9711cb73fc5527bd23c5d450241 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 9 Sep 2021 12:42:56 -0500 Subject: [PATCH 0908/1120] Loop through the list of waited on PIDs (if any) before calling sigwaitinfo This fixes a potential race between the thread starting, a waiter being added, and a process exiting. --- vendor/libkqueue/src/posix/proc.c | 33 +++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index e487d188e..a639347ec 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -139,7 +139,7 @@ static void * wait_thread(UNUSED void *arg) { int status; - int ret; + int ret = 0; siginfo_t info; sigset_t sigmask; struct proc_pid *ppd, *ppd_tmp; @@ -232,22 +232,33 @@ wait_thread(UNUSED void *arg) * a native solution for Solaris this POSIX EVFILT_PROC * code must remain to provide a fallback mechanism. */ - while ((ret = sigwaitinfo(&sigmask, &info))) { + do { if (ret < 0) { dbg_printf("sigwaitinfo(2): %s", strerror(errno)); continue; } - - dbg_printf("received SIGCHLD"); + dbg_printf("waiting for SIGCHLD"); pthread_mutex_lock(&proc_pid_index_mtx); + /* - * Check if this is a process we want to monitor + * Sig 0 is the NULL signal. This means it's the first + * iteration through the loop, and we just want to scan + * any existing PIDs. + * + * This fixes a potential race between the thread + * starting, EVFILT_PROC kevents being added, and a + * process exiting. */ - ppd = RB_FIND(pid_index, &proc_pid_index, &(struct proc_pid){ .ppd_pid = info.si_pid }); - if (ppd) { - status = waiter_siginfo_to_status(&info); - if (status >= 0) waiter_notify(ppd, status); /* If < 0 notification is spurious */ + if (ret > 0) { + /* + * Check if this is a process we want to monitor + */ + ppd = RB_FIND(pid_index, &proc_pid_index, &(struct proc_pid){ .ppd_pid = info.si_pid }); + if (ppd) { + status = waiter_siginfo_to_status(&info); + if (status >= 0) waiter_notify(ppd, status); /* If < 0 notification is spurious */ + } } /* @@ -271,7 +282,9 @@ wait_thread(UNUSED void *arg) if (status >= 0) waiter_notify(ppd, status); /* If < 0 notification is spurious */ } pthread_mutex_unlock(&proc_pid_index_mtx); - } + + dbg_printf("waiting for SIGCHLD"); + } while ((ret = sigwaitinfo(&sigmask, &info))); dbg_printf("exited"); From e5fadf31f4e25603f8003abe78ceb849e692526b Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 9 Sep 2021 12:59:23 -0500 Subject: [PATCH 0909/1120] Always enable the proc test --- vendor/libkqueue/test/main.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index fd37c7494..7b9ff179f 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -23,15 +23,6 @@ #include #endif -/* - * We need a fairly late kernel (>= 5.3) to have - * pidfd available on Linux which is required for - * EVFILT_PROC to function. - */ -#if !defined(__linux__) || defined(SYS_pidfd_open) -#define DO_PROC_TEST 1 -#endif - #include "common.h" unsigned int @@ -129,9 +120,7 @@ usage(void) "kqueue " "socket " "signal " -#ifdef DO_PROC_TEST "proc " -#endif "timer " "vnode " "user]\n" @@ -152,9 +141,7 @@ main(int argc, char **argv) // XXX-FIXME -- BROKEN ON LINUX WHEN RUN IN A SEPARATE THREAD { "signal", 1, test_evfilt_signal }, #endif -#ifdef DO_PROC_TEST { "proc", 1, test_evfilt_proc }, -#endif { "timer", 1, test_evfilt_timer }, #ifndef _WIN32 { "vnode", 1, test_evfilt_vnode }, From dd9ae36faaeea40e0ffe5918669978281a281f7d Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 9 Sep 2021 13:12:43 -0500 Subject: [PATCH 0910/1120] Update release notes and version --- vendor/libkqueue/CMakeLists.txt | 2 +- vendor/libkqueue/ChangeLog | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 1f4b853c9..d7eb197b0 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -14,7 +14,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -set(PROJECT_VERSION 2.5.0) +set(PROJECT_VERSION 2.5.1) if(EXISTS "/etc/debian_version") cmake_minimum_required(VERSION 3.7.2) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index fdb194bb8..d0045eb30 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -3,6 +3,22 @@ Unreleased Nothing here yet. +000-00-00 v2.5.1 +------------------------------------------------------------------------ + + * Fix: Compilation on Windows (Closes #111). + (Reported by: brechtsanders) + + * Fix: On Linux EPOLLHUP and EPOLLRDHUP did not set the EOF flag in kn->kev + and did not remove the EOF'd socket from epoll. The result was kevent + would return immediately. Additionally, where EPOLLIN was not set by + epoll, no kevent would be returned, and no EOF indication would be provided + to the caller. + linux/read.c and linux/write.c now exhibit the same behaviour as kqueue, + and will remove EOF'd sockets from EPOLL. The EOF condition can be cleared + by passing passing EV_ADD | EV_CLEAR, at which point notifications for the + socket will be produced once again. + 2021-09-06 v2.5.0 ------------------------------------------------------------------------ From ac44064c7dccdc270a5123adb749a19d934cada0 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 9 Sep 2021 14:28:20 -0500 Subject: [PATCH 0911/1120] Help detect use after free in debug builds --- vendor/libkqueue/src/common/knote.c | 3 +++ vendor/libkqueue/src/common/kqueue.c | 11 +++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 73a9ab1c9..1edbf2543 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -69,6 +69,9 @@ knote_release(struct knote *kn) if (atomic_dec(&kn->kn_ref) == 0) { if (kn->kn_flags & KNFL_KNOTE_DELETED) { dbg_printf("kn=%p - freeing", kn); +#ifndef NDEBUG + memset(kn, 0x42, sizeof(*kn)); +#endif free(kn); } else { dbg_puts("kn=%p - attempted to free knote without marking it as deleted"); diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 1e3c8c1f3..d92053b5b 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -130,6 +130,10 @@ kqueue_free(struct kqueue *kq) filter_unregister_all(kq); kqops.kqueue_free(kq); tracing_mutex_destroy(&kq->kq_mtx); + +#ifndef NDEBUG + memset(kq, 0x42, sizeof(*kq)); +#endif free(kq); } @@ -141,12 +145,7 @@ kqueue_free_by_id(int id) kq = map_delete(kqmap, id); if (!kq) return; - dbg_printf("kq=%p - freeing", kq); - - filter_unregister_all(kq); - kqops.kqueue_free(kq); - tracing_mutex_destroy(&kq->kq_mtx); - free(kq); + kqueue_free(kq); } struct kqueue * From 42dbeb4bc973e42c0c8c5a5c8d8a2ab8c068b7aa Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 9 Sep 2021 14:34:08 -0500 Subject: [PATCH 0912/1120] Fix various invalid indef checks cmake always defines the macro, so we need to check the value. --- vendor/libkqueue/config.h.in | 2 +- vendor/libkqueue/src/linux/platform.h | 5 ++++- vendor/libkqueue/src/linux/timer.c | 2 +- vendor/libkqueue/src/windows/platform.h | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/config.h.in b/vendor/libkqueue/config.h.in index 57352ee6e..2aab33e12 100644 --- a/vendor/libkqueue/config.h.in +++ b/vendor/libkqueue/config.h.in @@ -8,5 +8,5 @@ #cmakedefine01 HAVE_EPOLLRDHUP #cmakedefine01 HAVE_NOTE_TRUNCATE #cmakedefine01 HAVE_DECL_PPOLL +#cmakedefine01 HAVE_SYS_PIDFD_OPEN #cmakedefine01 HAVE_NOTE_REVOKE - diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 9b84ba579..425422544 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -55,8 +55,11 @@ struct filter; /* * Check to see if we have SYS_pidfd_open support if we don't, * fall back to the POSIX EVFILT_PROC code. + * + * Using the build system macro makes it slightly easier to + * toggle between POSIX/Linux implementations. */ -#ifdef SYS_pidfd_open +#if HAVE_SYS_PIDFD_OPEN #define KNOTE_PROC_PLATFORM_SPECIFIC int kn_procfd; #define FILTER_PROC_PLATFORM_SPECIFIC #else diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 6ae380cf9..05497d323 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -16,7 +16,7 @@ #include "private.h" -#ifndef HAVE_SYS_TIMERFD_H +#if HAVE_SYS_TIMERFD_H != 1 /* Android 4.0 does not have this header, but the kernel supports timerfds */ #ifndef SYS_timerfd_create diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 95cdd139e..6e95ccf07 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -125,7 +125,7 @@ typedef int nlink_t; typedef int timer_t; typedef int pthread_t; typedef int sigset_t; -#ifndef HAVE_SYS_TYPES_H +#if HAVE_SYS_TYPES_H != 1 typedef int pid_t; #endif From acd2dcea90845ae42bba731092859fd0a4872f04 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 9 Sep 2021 14:35:36 -0500 Subject: [PATCH 0913/1120] Increment proc count every time a kqueue is initialised Simplify signal handling... SIGCHLD should be blocked in the main thread and every other thread. sigwaitinfo examines _pending_ signals so isn't affected by the mask. --- vendor/libkqueue/src/posix/proc.c | 40 ++++++++++++++++++------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index a639347ec..33a037753 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -37,7 +37,7 @@ struct proc_pid { }; static pthread_mutex_t proc_init_mtx = PTHREAD_MUTEX_INITIALIZER; -static unsigned int proc_count = 0; +static int proc_count = 0; static pthread_t proc_wait_thread_id; /** The global PID tree @@ -144,23 +144,11 @@ wait_thread(UNUSED void *arg) sigset_t sigmask; struct proc_pid *ppd, *ppd_tmp; - /* Block all signals except SIGCHLD */ - sigfillset(&sigmask); - sigdelset(&sigmask, SIGCHLD); - pthread_sigmask(SIG_BLOCK, &sigmask, NULL); - /* Set the thread's name to something descriptive so it shows up in gdb, * etc. Max name length is 16 bytes. */ prctl(PR_SET_NAME, "libkqueue_wait", 0, 0, 0); - /* - * Only listen on SIGCHLD - */ - sigemptyset(&sigmask); - sigaddset(&sigmask, SIGCHLD); - pthread_sigmask(SIG_UNBLOCK, &sigmask, NULL); - - dbg_printf("started and waiting for SIGCHLD"); + dbg_printf("waiter thread started"); /* * Native kqueue implementations leave processes monitored @@ -232,12 +220,23 @@ wait_thread(UNUSED void *arg) * a native solution for Solaris this POSIX EVFILT_PROC * code must remain to provide a fallback mechanism. */ + + /* + * Block all signals - sigwaitinfo isn't affected by this + */ + sigfillset(&sigmask); + pthread_sigmask(SIG_BLOCK, &sigmask, NULL); + + /* + * Only listen on SIGCHLD wait sigwaitinfo + */ + sigemptyset(&sigmask); + sigaddset(&sigmask, SIGCHLD); do { if (ret < 0) { dbg_printf("sigwaitinfo(2): %s", strerror(errno)); continue; } - dbg_printf("waiting for SIGCHLD"); pthread_mutex_lock(&proc_pid_index_mtx); @@ -331,8 +330,8 @@ evfilt_proc_init(struct filter *filt) pthread_mutex_unlock(&proc_init_mtx); goto error_1; } - proc_count++; } + proc_count++; pthread_mutex_unlock(&proc_init_mtx); return (0); @@ -346,8 +345,17 @@ evfilt_proc_destroy(struct filter *filt) * and PID tree. */ pthread_mutex_lock(&proc_init_mtx); + assert(proc_count > 0); if (--proc_count == 0) { + void *retval; + pthread_cancel(proc_wait_thread_id); + if (pthread_join(proc_wait_thread_id, &retval) < 0) { + dbg_printf("pthread_join(2) %s", strerror(errno)); + } else { + assert(retval == PTHREAD_CANCELED); + dbg_puts("waiter thread joined"); + } } pthread_mutex_unlock(&proc_init_mtx); From e08d0cc0eb7ce5763f310d58169d30f0c19683c6 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 9 Sep 2021 16:45:58 -0500 Subject: [PATCH 0914/1120] Always produce a kevent if we get a socket error --- vendor/libkqueue/src/linux/platform.c | 43 +++++------ vendor/libkqueue/src/linux/read.c | 9 ++- vendor/libkqueue/src/linux/write.c | 18 +++-- vendor/libkqueue/test/read.c | 106 +++++++++++++++++++++++++- 4 files changed, 144 insertions(+), 32 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 071df4d25..5af191f58 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -704,43 +704,42 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven assert(fds); /* - * Other side hung up. We assume this is - * for both reading and writing? + * FD errored or the other side hung up + * + * kqueue doesn't seem to distinguish between + * EOF and ERROR, except that on error the data + * field is filled in. */ - if (ev->events & EPOLLHUP) { + if (ev->events & (EPOLLHUP | EPOLLRDHUP | EPOLLERR)) { if (fds->fds_read && KNOTE_NOT_EOF(fds->fds_read)) { + if (el_p >= el_end) goto oos; + kn = fds->fds_read; filt = knote_get_filter(kn); filt->kn_disable(filt, kn); KNOTE_EOF_SET(kn); - } - if (fds->fds_write && KNOTE_NOT_EOF(fds->fds_write)) { - kn = fds->fds_write; - filt = knote_get_filter(kn); - /* - * Set the EOF flag, and unregister the knote. - */ - filt->kn_disable(filt, kn); - KNOTE_EOF_SET(kn); + rv = linux_kevent_copyout_ev(el_p, (el_end - el_p), ev, &kq->kq_filt[~(kn->kev.filter)], kn); + if (rv < 0) goto done; + el_p += rv; } - } - /* - * Other side shutdown writing, but may still - * read... so we can still write? - * - * No idea why this event exists.. - */ - if (ev->events & EPOLLRDHUP) { - if (fds->fds_read && KNOTE_NOT_EOF(fds->fds_read)) { - kn = fds->fds_read; + /* Don't set write to EOF if we only got EPOLLRDHUP */ + if (fds->fds_write && KNOTE_NOT_EOF(fds->fds_write) && (ev->events & (EPOLLHUP | EPOLLERR))) { + if (el_p >= el_end) goto oos; + + kn = fds->fds_write; filt = knote_get_filter(kn); filt->kn_disable(filt, kn); KNOTE_EOF_SET(kn); + + rv = linux_kevent_copyout_ev(el_p, (el_end - el_p), ev, &kq->kq_filt[~(kn->kev.filter)], kn); + if (rv < 0) goto done; + el_p += rv; } + continue; } /* diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index dbaf5f979..27e8d9cf3 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -110,7 +110,14 @@ evfilt_read_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, if (src->kn_flags & KNFL_SOCKET) { ret = getsockopt(src->kev.ident, SOL_SOCKET, SO_ERROR, &serr, &slen); dst->fflags = ((ret < 0) ? errno : serr); - } else { dst->fflags = EIO; } + } else + dst->fflags = EIO; + + /* + * The only way we seem to be able to signal an error + * is by setting EOF on the socket. + */ + dst->flags |= EV_EOF; } if (src->kn_flags & KNFL_SOCKET_PASSIVE) { diff --git a/vendor/libkqueue/src/linux/write.c b/vendor/libkqueue/src/linux/write.c index f33416166..290626739 100644 --- a/vendor/libkqueue/src/linux/write.c +++ b/vendor/libkqueue/src/linux/write.c @@ -31,22 +31,26 @@ evfilt_write_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt epoll_event_dump(ev); memcpy(dst, &src->kev, sizeof(*dst)); -#if defined(HAVE_EPOLLRDHUP) - if (ev->events & EPOLLRDHUP || ev->events & EPOLLHUP) - dst->flags |= EV_EOF; -#else + if (ev->events & EPOLLHUP) dst->flags |= EV_EOF; -#endif + if (ev->events & EPOLLERR) { if (src->kn_flags & KNFL_SOCKET) { ret = getsockopt(src->kev.ident, SOL_SOCKET, SO_ERROR, &serr, &slen); dst->fflags = ((ret < 0) ? errno : serr); - } else { dst->fflags = EIO; } + } else + dst->fflags = EIO; + + /* + * The only way we seem to be able to signal an error + * is by setting EOF on the socket. + */ + dst->flags |= EV_EOF; } /* On return, data contains the the amount of space remaining in the write buffer */ - if (ioctl(dst->ident, SIOCOUTQ, &dst->data) < 0) { + if (!(dst->flags & EV_EOF) && (ioctl(dst->ident, SIOCOUTQ, &dst->data) < 0)) { /* race condition with socket close, so ignore this error */ dbg_puts("ioctl(2) of socket failed"); dst->data = 0; diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 5de09c8a9..a8d7658fb 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -366,9 +366,10 @@ test_kevent_socket_lowat(struct test_context *ctx) #endif void -test_kevent_socket_eof(struct test_context *ctx) +test_kevent_socket_eof_shutdown(struct test_context *ctx) { struct kevent kev, ret; + uint8_t buff[1024]; /* Re-add the watch and make sure no events are pending */ kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD, 0, 0, &ctx->client_fd); @@ -405,6 +406,105 @@ test_kevent_socket_eof(struct test_context *ctx) /* Delete the watch */ kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_DELETE, 0, 0, &ctx->client_fd); + + close(ctx->client_fd); + close(ctx->listen_fd); + + /* Recreate the socket pair */ + create_socket_connection(&ctx->client_fd, &ctx->server_fd, &ctx->listen_fd); +} + +void +test_kevent_socket_eof_close(struct test_context *ctx) +{ + struct kevent kev, ret; + + /* Re-add the watch and make sure no events are pending */ + kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD, 0, 0, &ctx->client_fd); + test_no_kevents(ctx->kqfd); + + if (close(ctx->server_fd) < 0) + die("close(2)"); + + kev.flags |= EV_EOF; + kevent_get(&ret, ctx->kqfd, 1); + kevent_cmp(&kev, &ret); + + /* + * When the last writer disconnects, the filter will + * set EV_EOF in flags. This may be cleared by passing + * in EV_CLEAR, at which point the filter will resume + * waiting for data to become available before return- + * ing. + * + * i.e. Once it's marked as EOF once, EOF should not be + * returned repeatedly. + */ + test_no_kevents(ctx->kqfd); + + /* modify the knote, setting EV_CLEAR - We should get another EOF */ + kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &ctx->client_fd); + + kev.flags ^= EV_CLEAR; + kev.flags |= EV_EOF; + kevent_get(&ret, ctx->kqfd, 1); + kevent_cmp(&kev, &ret); + + /* Delete the watch */ + kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_DELETE, 0, 0, &ctx->client_fd); + + close(ctx->client_fd); + close(ctx->listen_fd); + + /* Recreate the socket pair */ + create_socket_connection(&ctx->client_fd, &ctx->server_fd, &ctx->listen_fd); +} + +void +test_kevent_socket_eof_shutdown_local(struct test_context *ctx) +{ + struct kevent kev, ret; + + /* Re-add the watch and make sure no events are pending */ + kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD, 0, 0, &ctx->client_fd); + test_no_kevents(ctx->kqfd); + + if (shutdown(ctx->client_fd, SHUT_RDWR) < 0) + die("shutdown(2)"); + + kev.flags |= EV_EOF; + kevent_get(&ret, ctx->kqfd, 1); + kevent_cmp(&kev, &ret); + + /* + * When the last writer disconnects, the filter will + * set EV_EOF in flags. This may be cleared by passing + * in EV_CLEAR, at which point the filter will resume + * waiting for data to become available before return- + * ing. + * + * i.e. Once it's marked as EOF once, EOF should not be + * returned repeatedly. + */ + test_no_kevents(ctx->kqfd); + + /* modify the knote, setting EV_CLEAR - We should get another EOF */ + kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &ctx->client_fd); + + kev.flags ^= EV_CLEAR; + kev.flags |= EV_EOF; + kevent_get(&ret, ctx->kqfd, 1); + kevent_cmp(&kev, &ret); + + /* Delete the watch */ + kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_DELETE, 0, 0, &ctx->client_fd); + + close(ctx->client_fd); + close(ctx->server_fd); + close(ctx->listen_fd); + + /* Recreate the socket pair */ + create_socket_connection(&ctx->client_fd, &ctx->server_fd, &ctx->listen_fd); } /* Test if EVFILT_READ works with regular files */ @@ -490,7 +590,9 @@ test_evfilt_read(struct test_context *ctx) test(kevent_socket_dispatch, ctx); #endif test(kevent_socket_listen_backlog, ctx); - test(kevent_socket_eof, ctx); + test(kevent_socket_eof_shutdown, ctx); + test(kevent_socket_eof_close, ctx); + test(kevent_socket_eof_shutdown_local, ctx); test(kevent_regular_file, ctx); close(ctx->client_fd); close(ctx->server_fd); From eaf155c14da7ff941cb00bf719f8a51c7b58a4b4 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 9 Sep 2021 17:56:18 -0500 Subject: [PATCH 0915/1120] Fix test_eve_receipt on FreeBSD --- vendor/libkqueue/test/kqueue.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/vendor/libkqueue/test/kqueue.c b/vendor/libkqueue/test/kqueue.c index 3657763bd..79c815616 100644 --- a/vendor/libkqueue/test/kqueue.c +++ b/vendor/libkqueue/test/kqueue.c @@ -169,6 +169,14 @@ test_ev_receipt(struct test_context *ctx) kevent_rv_cmp(1, kevent(ctx->kqfd, &kev, 1, &buf, 1, NULL)); +#ifdef __FreeBSD__ + /* + * macOS and libkqueue both return + * EV_RECEIPT here FreeBSD does not. + */ + kev->flags ^= EV_RECEIPT; +#endif + kevent_cmp(&kev, &buf); } #endif From 3341026d687a493f5b98e26a1932c96763ffe601 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 9 Sep 2021 19:57:01 -0500 Subject: [PATCH 0916/1120] Adapt the tests to pass on macOS (next FreeBSD) --- vendor/libkqueue/test/common.h | 9 +++ vendor/libkqueue/test/kevent.c | 26 ++++++++ vendor/libkqueue/test/read.c | 109 ++++++--------------------------- vendor/libkqueue/test/user.c | 45 +++++++------- 4 files changed, 76 insertions(+), 113 deletions(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index cde544417..aa866ec75 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -140,6 +140,15 @@ kevent_add(int kqfd, struct kevent *kev, intptr_t data, void *udata); +void +kevent_add_with_receipt(int kqfd, struct kevent *kev, + uintptr_t ident, + short filter, + u_short flags, + u_int fflags, + intptr_t data, + void *udata); + /* Checks if any events are pending, which is an error. */ #define test_no_kevents(a) _test_no_kevents(a, __FILE__, __LINE__) void _test_no_kevents(int, const char *, int); diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/kevent.c index ba83f545c..8056d6146 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/kevent.c @@ -258,6 +258,32 @@ kevent_add(int kqfd, struct kevent *kev, } } +/** Check kqueue echo's the event back to use correctly + * + */ +void +kevent_add_with_receipt(int kqfd, struct kevent *kev, + uintptr_t ident, + short filter, + u_short flags, + u_int fflags, + intptr_t data, + void *udata) +{ + struct kevent receipt; + + EV_SET(kev, ident, filter, flags | EV_RECEIPT, fflags, data, NULL); + if (kevent(kqfd, kev, 1, &receipt, 1, NULL) < 0) { + printf("Unable to add the following kevent:\n%s\n", + kevent_to_str(kev)); + die("kevent"); + } + + kev->flags |= EV_ERROR; + kevent_cmp(kev, &receipt); + kev->flags ^= EV_ERROR; /* We don't expect this in future events */ +} + void _kevent_cmp(struct kevent *expected, struct kevent *got, const char *file, int line) { diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index a8d7658fb..169877354 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -366,13 +366,12 @@ test_kevent_socket_lowat(struct test_context *ctx) #endif void -test_kevent_socket_eof_shutdown(struct test_context *ctx) +test_kevent_socket_eof_clear(struct test_context *ctx) { struct kevent kev, ret; uint8_t buff[1024]; - /* Re-add the watch and make sure no events are pending */ - kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD, 0, 0, &ctx->client_fd); + kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &ctx->client_fd); test_no_kevents(ctx->kqfd); if (shutdown(ctx->server_fd, SHUT_RDWR) < 0) @@ -381,28 +380,10 @@ test_kevent_socket_eof_shutdown(struct test_context *ctx) die("close(2)"); kev.flags |= EV_EOF; - kevent_get(&ret, ctx->kqfd, 1); + kevent_get(&ret, ctx->kqfd, 1); /* edge triggered means no more events */ kevent_cmp(&kev, &ret); - /* - * When the last writer disconnects, the filter will - * set EV_EOF in flags. This may be cleared by passing - * in EV_CLEAR, at which point the filter will resume - * waiting for data to become available before return- - * ing. - * - * i.e. Once it's marked as EOF once, EOF should not be - * returned repeatedly. - */ - test_no_kevents(ctx->kqfd); - - /* modify the knote, setting EV_CLEAR - We should get another EOF */ - kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &ctx->client_fd); - - kev.flags ^= EV_CLEAR; - kev.flags |= EV_EOF; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + test_no_kevents(ctx->kqfd);; /* Delete the watch */ kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_DELETE, 0, 0, &ctx->client_fd); @@ -415,92 +396,43 @@ test_kevent_socket_eof_shutdown(struct test_context *ctx) } void -test_kevent_socket_eof_close(struct test_context *ctx) +test_kevent_socket_eof(struct test_context *ctx) { struct kevent kev, ret; + uint8_t buff[1024]; - /* Re-add the watch and make sure no events are pending */ - kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD, 0, 0, &ctx->client_fd); + kevent_add_with_receipt(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD, 0, 0, &ctx->client_fd); test_no_kevents(ctx->kqfd); - if (close(ctx->server_fd) < 0) + if (shutdown(ctx->server_fd, SHUT_RDWR) < 0) die("close(2)"); kev.flags |= EV_EOF; kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); - /* - * When the last writer disconnects, the filter will - * set EV_EOF in flags. This may be cleared by passing - * in EV_CLEAR, at which point the filter will resume - * waiting for data to become available before return- - * ing. - * - * i.e. Once it's marked as EOF once, EOF should not be - * returned repeatedly. - */ - test_no_kevents(ctx->kqfd); - - /* modify the knote, setting EV_CLEAR - We should get another EOF */ - kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &ctx->client_fd); - - kev.flags ^= EV_CLEAR; - kev.flags |= EV_EOF; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); - - /* Delete the watch */ - kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_DELETE, 0, 0, &ctx->client_fd); - - close(ctx->client_fd); - close(ctx->listen_fd); - - /* Recreate the socket pair */ - create_socket_connection(&ctx->client_fd, &ctx->server_fd, &ctx->listen_fd); -} - -void -test_kevent_socket_eof_shutdown_local(struct test_context *ctx) -{ - struct kevent kev, ret; - - /* Re-add the watch and make sure no events are pending */ - kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD, 0, 0, &ctx->client_fd); - test_no_kevents(ctx->kqfd); - - if (shutdown(ctx->client_fd, SHUT_RDWR) < 0) - die("shutdown(2)"); - - kev.flags |= EV_EOF; + /* Will repeatedly return EOF */ kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); /* - * When the last writer disconnects, the filter will - * set EV_EOF in flags. This may be cleared by passing - * in EV_CLEAR, at which point the filter will resume - * waiting for data to become available before return- - * ing. + * The kqueue man page on FreeBSD states that EV_CLEAR + * can be used to clear EOF, but in practice this appears + * to do nothing with sockets... * - * i.e. Once it's marked as EOF once, EOF should not be - * returned repeatedly. + * Additionally setting EV_CLEAR on a socket after it's + * been added does nothing, even though kqueue returns + * the flag with EV_RECEIPT. */ - test_no_kevents(ctx->kqfd); - - /* modify the knote, setting EV_CLEAR - We should get another EOF */ - kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &ctx->client_fd); + kevent_add_with_receipt(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &ctx->client_fd); - kev.flags ^= EV_CLEAR; kev.flags |= EV_EOF; + kev.flags ^= EV_CLEAR; + kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); - /* Delete the watch */ - kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_DELETE, 0, 0, &ctx->client_fd); - close(ctx->client_fd); - close(ctx->server_fd); close(ctx->listen_fd); /* Recreate the socket pair */ @@ -590,9 +522,8 @@ test_evfilt_read(struct test_context *ctx) test(kevent_socket_dispatch, ctx); #endif test(kevent_socket_listen_backlog, ctx); - test(kevent_socket_eof_shutdown, ctx); - test(kevent_socket_eof_close, ctx); - test(kevent_socket_eof_shutdown_local, ctx); + test(kevent_socket_eof_clear, ctx); + test(kevent_socket_eof, ctx); test(kevent_regular_file, ctx); close(ctx->client_fd); close(ctx->server_fd); diff --git a/vendor/libkqueue/test/user.c b/vendor/libkqueue/test/user.c index 0e5eb83a0..8ee77edde 100644 --- a/vendor/libkqueue/test/user.c +++ b/vendor/libkqueue/test/user.c @@ -31,17 +31,16 @@ test_kevent_user_add_and_delete(struct test_context *ctx) static void test_kevent_user_get(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, tmp, ret; test_no_kevents(ctx->kqfd); /* Add the event, and then trigger it */ kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, NULL); - kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + kevent_add(ctx->kqfd, &tmp, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; - kev.flags = EV_CLEAR; kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); @@ -51,7 +50,7 @@ test_kevent_user_get(struct test_context *ctx) static void test_kevent_user_get_hires(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, tmp, ret; struct timespec timeo = { .tv_sec = 0, .tv_nsec = 500000 @@ -61,11 +60,10 @@ test_kevent_user_get_hires(struct test_context *ctx) /* Add the event, and then trigger it */ kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, NULL); - kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + kevent_add(ctx->kqfd, &tmp, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; - kev.flags = EV_CLEAR; kevent_get_hires(&ret, ctx->kqfd, &timeo); kevent_cmp(&kev, &ret); @@ -75,21 +73,22 @@ test_kevent_user_get_hires(struct test_context *ctx) static void test_kevent_user_disable_and_enable(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, tmp, ret; test_no_kevents(ctx->kqfd); kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL); - kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_DISABLE, 0, 0, NULL); + kev.flags |= EV_CLEAR; /* set automatically by kqueue */ + + kevent_add(ctx->kqfd, &tmp, 1, EVFILT_USER, EV_DISABLE, 0, 0, NULL); /* Trigger the event, but since it is disabled, nothing will happen. */ - kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + kevent_add(ctx->kqfd, &tmp, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); test_no_kevents(ctx->kqfd); - kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ENABLE, 0, 0, NULL); - kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + kevent_add(ctx->kqfd, &tmp, 1, EVFILT_USER, EV_ENABLE, 0, 0, NULL); + kevent_add(ctx->kqfd, &tmp, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); - kev.flags = EV_CLEAR; kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; kevent_get(&ret, ctx->kqfd, 1); @@ -99,14 +98,13 @@ test_kevent_user_disable_and_enable(struct test_context *ctx) static void test_kevent_user_oneshot(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, tmp, ret; test_no_kevents(ctx->kqfd); kevent_add(ctx->kqfd, &kev, 2, EVFILT_USER, EV_ADD | EV_ONESHOT, 0, 0, NULL); - kevent_add(ctx->kqfd, &kev, 2, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + kevent_add(ctx->kqfd, &tmp, 2, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); - kev.flags = EV_ONESHOT; kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; kevent_get(&ret, ctx->kqfd, 1); @@ -118,7 +116,7 @@ test_kevent_user_oneshot(struct test_context *ctx) static void test_kevent_user_multi_trigger_merged(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, tmp, ret; int i; test_no_kevents(ctx->kqfd); @@ -126,9 +124,8 @@ test_kevent_user_multi_trigger_merged(struct test_context *ctx) kevent_add(ctx->kqfd, &kev, 2, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, NULL); for (i = 0; i < 10; i++) - kevent_add(ctx->kqfd, &kev, 2, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + kevent_add(ctx->kqfd, &tmp, 2, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); - kev.flags = EV_CLEAR; kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; kevent_get(&ret, ctx->kqfd, 1); @@ -141,18 +138,19 @@ test_kevent_user_multi_trigger_merged(struct test_context *ctx) void test_kevent_user_dispatch(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, tmp, ret; test_no_kevents(ctx->kqfd); /* Add the event, and then trigger it */ kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ADD | EV_CLEAR | EV_DISPATCH, 0, 0, NULL); - kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + kevent_add(ctx->kqfd, &tmp, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); /* Retrieve one event */ kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; - kev.flags = EV_CLEAR; + + kev.flags ^= EV_DISPATCH; kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); @@ -161,14 +159,13 @@ test_kevent_user_dispatch(struct test_context *ctx) /* Re-enable the kevent */ /* FIXME- is EV_DISPATCH needed when rearming ? */ - kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, EV_ENABLE | EV_CLEAR | EV_DISPATCH, 0, 0, NULL); + kevent_add(ctx->kqfd, &tmp, 1, EVFILT_USER, EV_ENABLE | EV_CLEAR | EV_DISPATCH, 0, 0, NULL); test_no_kevents(ctx->kqfd); /* Trigger the event */ - kevent_add(ctx->kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + kevent_add(ctx->kqfd, &tmp, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; - kev.flags = EV_CLEAR; kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); test_no_kevents(ctx->kqfd); From 2da9f6f26dae532536ef6706e3d056b94a73cea7 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 10 Sep 2021 11:05:41 -0500 Subject: [PATCH 0917/1120] Ignore macOS artifacts --- vendor/libkqueue/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/.gitignore b/vendor/libkqueue/.gitignore index c106de061..2e9b559d6 100644 --- a/vendor/libkqueue/.gitignore +++ b/vendor/libkqueue/.gitignore @@ -1,4 +1,5 @@ .vagrant/ +.DS_Store config.h *.pc *.log From 3984f80c41e078ec1ad40354cc16c3e7ed8cfd84 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 10 Sep 2021 11:21:26 -0500 Subject: [PATCH 0918/1120] Adapt tests to pass on macOS 11.5.2 && FreeBSD 13 --- vendor/libkqueue/test/CMakeLists.txt | 2 +- vendor/libkqueue/test/{kevent.c => common.c} | 36 ++++++++++++++++++-- vendor/libkqueue/test/common.h | 18 ++++++---- vendor/libkqueue/test/kqueue.c | 2 +- vendor/libkqueue/test/read.c | 3 +- vendor/libkqueue/test/signal.c | 21 +++--------- 6 files changed, 53 insertions(+), 29 deletions(-) rename vendor/libkqueue/test/{kevent.c => common.c} (89%) diff --git a/vendor/libkqueue/test/CMakeLists.txt b/vendor/libkqueue/test/CMakeLists.txt index 260caf310..468eda7f0 100644 --- a/vendor/libkqueue/test/CMakeLists.txt +++ b/vendor/libkqueue/test/CMakeLists.txt @@ -16,7 +16,7 @@ project(libkqueue-test LANGUAGES C) set(LIBKQUEUE_TEST_SOURCES - kevent.c + common.c kqueue.c main.c read.c diff --git a/vendor/libkqueue/test/kevent.c b/vendor/libkqueue/test/common.c similarity index 89% rename from vendor/libkqueue/test/kevent.c rename to vendor/libkqueue/test/common.c index 8056d6146..0458281cd 100644 --- a/vendor/libkqueue/test/kevent.c +++ b/vendor/libkqueue/test/common.c @@ -260,15 +260,28 @@ kevent_add(int kqfd, struct kevent *kev, /** Check kqueue echo's the event back to use correctly * + * @param[in] kqfd we're adding events to. + * @param[out] kev the event we got passed back in + * the receipt. + * @param[in] ident Identifier for the event. + * @param[in] filter to add event to. + * @param[in] flags to set. + * @param[in] fflags to set. + * @param[in] data to set. + * @param[in] udata to set. + * @param[in] file this function was called from. + * @param[in] line this function was called from. */ void -kevent_add_with_receipt(int kqfd, struct kevent *kev, +_kevent_add_with_receipt(int kqfd, struct kevent *kev, uintptr_t ident, short filter, u_short flags, u_int fflags, intptr_t data, - void *udata) + void *udata, + char const *file, + int line) { struct kevent receipt; @@ -279,9 +292,26 @@ kevent_add_with_receipt(int kqfd, struct kevent *kev, die("kevent"); } + +#ifdef __FreeBSD__ + /* + * FreeBSD doesn't return EV_RECEIPT in the receipt + * but does return it in all future kevents. + */ + kev->flags ^= EV_RECEIPT; +#endif + kev->flags |= EV_ERROR; - kevent_cmp(kev, &receipt); + _kevent_cmp(kev, &receipt, file, line); kev->flags ^= EV_ERROR; /* We don't expect this in future events */ + +#ifdef __FreeBSD__ + /* + * Add this back as it'll be returned in future + * kevents. + */ + kev->flags |= EV_RECEIPT; +#endif } void diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index aa866ec75..eb43feddb 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -48,11 +48,11 @@ #include #if !defined(__APPLE__) && !defined(__FreeBSD__) -# include "config.h" +# include "config.h" #endif #if defined(__FreeBSD__) -# include +# include #endif #ifndef _WIN32 @@ -66,8 +66,8 @@ #include #include #else -# include "include/sys/event.h" -# include "src/windows/platform.h" +# include "include/sys/event.h" +# include "src/windows/platform.h" #endif /** Convenience macros @@ -140,17 +140,21 @@ kevent_add(int kqfd, struct kevent *kev, intptr_t data, void *udata); + +#define kevent_add_with_receipt(...) _kevent_add_with_receipt(__VA_ARGS__, __FILE__, __LINE__) void -kevent_add_with_receipt(int kqfd, struct kevent *kev, +_kevent_add_with_receipt(int kqfd, struct kevent *kev, uintptr_t ident, short filter, u_short flags, u_int fflags, intptr_t data, - void *udata); + void *udata, + char const *file, + int line); /* Checks if any events are pending, which is an error. */ -#define test_no_kevents(a) _test_no_kevents(a, __FILE__, __LINE__) +#define test_no_kevents(_kq) _test_no_kevents(_kq, __FILE__, __LINE__) void _test_no_kevents(int, const char *, int); unsigned int print_fd_table(void); diff --git a/vendor/libkqueue/test/kqueue.c b/vendor/libkqueue/test/kqueue.c index 79c815616..ac133cec1 100644 --- a/vendor/libkqueue/test/kqueue.c +++ b/vendor/libkqueue/test/kqueue.c @@ -174,7 +174,7 @@ test_ev_receipt(struct test_context *ctx) * macOS and libkqueue both return * EV_RECEIPT here FreeBSD does not. */ - kev->flags ^= EV_RECEIPT; + kev.flags ^= EV_RECEIPT; #endif kevent_cmp(&kev, &buf); diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 169877354..54e24aa04 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -424,8 +424,9 @@ test_kevent_socket_eof(struct test_context *ctx) * been added does nothing, even though kqueue returns * the flag with EV_RECEIPT. */ - kevent_add_with_receipt(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &ctx->client_fd); + kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &ctx->client_fd); + kev.flags |= EV_RECEIPT; kev.flags |= EV_EOF; kev.flags ^= EV_CLEAR; diff --git a/vendor/libkqueue/test/signal.c b/vendor/libkqueue/test/signal.c index dfde4fc07..d39b3d1f4 100644 --- a/vendor/libkqueue/test/signal.c +++ b/vendor/libkqueue/test/signal.c @@ -152,28 +152,17 @@ test_kevent_signal_dispatch(struct test_context *ctx) kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); - /* - * On macOS 11.5.2 the signal generated below is still - * delivered when the filter is next re-enabled. - * - * It's not clear if this is expected behaviour or not. - * EV_DISPATCH isn't even mentioned in man kqueue... - */ -#ifndef __APPLE__ - /* Confirm that the knote is disabled */ + /* Generate a pending signal, this should get delivered once the filter is enabled again */ if (kill(getpid(), SIGUSR1) < 0) die("kill"); test_no_kevents(ctx->kqfd); -#endif - /* Enable the knote and make sure no events are pending */ + /* Enable the knote, our pending signal should now get delivered */ kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE | EV_DISPATCH, 0, 0, NULL); - test_no_kevents(ctx->kqfd); - /* Get the next event */ - if (kill(getpid(), SIGUSR1) < 0) - die("kill"); - kev.flags = EV_ADD | EV_CLEAR | EV_DISPATCH; + kev.flags ^= EV_ENABLE; + kev.flags |= EV_ADD; + kev.flags |= EV_CLEAR; kev.data = 1; kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); From 71845ba864c771f2c78bc59b47486da1453aec49 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 10 Sep 2021 11:56:32 -0500 Subject: [PATCH 0919/1120] Add a Github actions workflow for running the tests on FreeBSD and macOS --- .../.github/workflows/ci-freebsd.yml | 33 +++++++++++++++++++ .../libkqueue/.github/workflows/ci-macos.yml | 24 ++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 vendor/libkqueue/.github/workflows/ci-freebsd.yml create mode 100644 vendor/libkqueue/.github/workflows/ci-macos.yml diff --git a/vendor/libkqueue/.github/workflows/ci-freebsd.yml b/vendor/libkqueue/.github/workflows/ci-freebsd.yml new file mode 100644 index 000000000..e42f125e6 --- /dev/null +++ b/vendor/libkqueue/.github/workflows/ci-freebsd.yml @@ -0,0 +1,33 @@ +name: CI tests FreeBSD + +on: + push: + branches: + - master + paths: + - 'test/*' + +jobs: + freebsd-tests: + runs-on: macos-latest + name: "FreeBSD tests" + steps: + - uses: actions/checkout@v2 + with: + path: libkqueue + + - name: libkqueue test suite + uses: vmactions/freebsd-vm@v0.1.5 + with: + usesh: true + sync: sshfs + prepare: | + pkg install -y \ + cmake \ + llvm \ + run: | + freebsd-version + cd libkqueue + cmake . test/CMakeLists.txt + make -C ./test + test/libkqueue-test diff --git a/vendor/libkqueue/.github/workflows/ci-macos.yml b/vendor/libkqueue/.github/workflows/ci-macos.yml new file mode 100644 index 000000000..07e0b358f --- /dev/null +++ b/vendor/libkqueue/.github/workflows/ci-macos.yml @@ -0,0 +1,24 @@ +name: CI tests macOS + +on: + push: + branches: + - master + paths: + - 'test/*' + +jobs: + macos-tests: + runs-on: macos-latest + name: "macOS tests" + steps: + - uses: actions/checkout@v2 + + - name: Build and configure + run: | + cmake . test/CMakeLists.txt + make -C test/ + + - name: libkqueue test suite + run: | + ./test/libkqueue-test From 3b421fe4caeef017f63695b53fb3edbd71779e5e Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 10 Sep 2021 13:04:00 -0500 Subject: [PATCH 0920/1120] Disable parts of test_kevent_timer_dispatch, turns out native kqueue is buggy Add toggle to expose tests which fail with native kqueue implementations --- vendor/libkqueue/README.md | 9 ++++++--- vendor/libkqueue/test/CMakeLists.txt | 3 +++ vendor/libkqueue/test/common.h | 2 ++ vendor/libkqueue/test/config.h.in | 1 + vendor/libkqueue/test/timer.c | 24 ++++++++++++++++++------ 5 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 vendor/libkqueue/test/config.h.in diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index 0ac51363a..def48189a 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -8,7 +8,7 @@ libkqueue acts as a translator between the kevent structure and the native kernel facilities on Linux, Android, Solaris, and Windows. libkqueue is not perfect, and you may need to change the behaviour of your application -to work around limitations on a given platform. Please see [BUGS](BUGS.md) for known +to work around limitations on a given platform. Please see [BUGS](BUGS.md) for known behavioural differences between libkqueue and BSD kqueues. Supported Event Types @@ -83,12 +83,15 @@ Running Unit Tests Build & Running only the test suite ----------------------------------- -Helpful to see the behavior of the tests on systems with native `kqueue`, e.g: OSX, FreeBSD +Helpful to see the behavior of the tests on systems with native `kqueue`, e.g: macOS, FreeBSD - cmake . --config test/CMakeLists.txt + cmake . test/CMakeLists.txt make -C test/ ./test/libkqueue-test +To enable tests which expose bugs in native kqueue implementations pass `-DWITH_NATIVE_KQUEUE_BUGS=1` to cmake. +i.e. `cmake . test/CMakeLists.txt -DWITH_NATIVE_KQUEUE_BUGS=1`. + Debugging --------- diff --git a/vendor/libkqueue/test/CMakeLists.txt b/vendor/libkqueue/test/CMakeLists.txt index 468eda7f0..5d87d526c 100644 --- a/vendor/libkqueue/test/CMakeLists.txt +++ b/vendor/libkqueue/test/CMakeLists.txt @@ -31,6 +31,9 @@ if(UNIX) signal.c) endif() +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/config.h) + add_executable(libkqueue-test ${LIBKQUEUE_TEST_SOURCES}) target_include_directories(libkqueue-test PRIVATE diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index eb43feddb..ed99c3857 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -70,6 +70,8 @@ # include "src/windows/platform.h" #endif +#include "config.h" + /** Convenience macros * */ diff --git a/vendor/libkqueue/test/config.h.in b/vendor/libkqueue/test/config.h.in new file mode 100644 index 000000000..41364bd18 --- /dev/null +++ b/vendor/libkqueue/test/config.h.in @@ -0,0 +1 @@ +#cmakedefine01 WITH_NATIVE_KQUEUE_BUGS diff --git a/vendor/libkqueue/test/timer.c b/vendor/libkqueue/test/timer.c index eedf7df29..c62f6e5da 100644 --- a/vendor/libkqueue/test/timer.c +++ b/vendor/libkqueue/test/timer.c @@ -125,7 +125,7 @@ test_kevent_timer_dispatch(struct test_context *ctx) test_no_kevents(ctx->kqfd); - kevent_add(ctx->kqfd, &kev, 4, EVFILT_TIMER, EV_ADD | EV_DISPATCH, 0, 800, NULL); + kevent_add(ctx->kqfd, &kev, 4, EVFILT_TIMER, EV_ADD | EV_DISPATCH, 0, 200, NULL); /* Get one event */ kev.flags = EV_ADD | EV_CLEAR | EV_DISPATCH; @@ -133,24 +133,36 @@ test_kevent_timer_dispatch(struct test_context *ctx) kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); - /* Confirm that the knote is disabled */ - sleep(1); + /* Confirm that the knote is disabled due to EV_DISPATCH */ + usleep(500000); /* 500 ms */ test_no_kevents(ctx->kqfd); +#if WITH_NATIVE_KQUEUE_BUGS || (!defined(__APPLE__) && !defined(__FreeBSD__)) + /* + * macOS and FreeBSD both share the same bug. + * + * When a timer event with EV_DISPATCH is re-enabled + * although the EV_DISPATCH flag is high in the + * returned event the timer filter behaves as if + * EV_DISPATCH it's not set and will fire multiple + * times. + */ + /* Enable the knote and make sure no events are pending */ - kevent_add(ctx->kqfd, &kev, 4, EVFILT_TIMER, EV_ENABLE | EV_DISPATCH, 0, 800, NULL); + kevent_add(ctx->kqfd, &kev, 4, EVFILT_TIMER, EV_ENABLE | EV_DISPATCH, 0, 200, NULL); test_no_kevents(ctx->kqfd); /* Get the next event */ - sleep(1); + usleep(1000000); /* 1000 ms */ kev.flags = EV_ADD | EV_CLEAR | EV_DISPATCH; kev.data = 1; kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); +#endif /* Remove the knote and ensure the event no longer fires */ kevent_add(ctx->kqfd, &kev, 4, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); - sleep(1); + usleep(500000); /* 500 ms */ test_no_kevents(ctx->kqfd); } #endif /* EV_DISPATCH */ From 8b45b603d3f2cb40451448849b1d474987025891 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 10 Sep 2021 16:47:35 -0500 Subject: [PATCH 0921/1120] Allow user to specify individual test numbers or a range for test for a given test suite i.e. socket:0-2 runs socket tests 0, 1, 2. --- vendor/libkqueue/test/common.h | 26 +++++---- vendor/libkqueue/test/main.c | 97 +++++++++++++++++++++++++++++----- vendor/libkqueue/test/test.c | 3 +- 3 files changed, 103 insertions(+), 23 deletions(-) diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index ed99c3857..f5ca0bfd2 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -80,14 +80,19 @@ struct test_context; struct unit_test { - const char *ut_name; - int ut_enabled; - void (*ut_func)(struct test_context *); + const char *ut_name; + int ut_enabled; + void (*ut_func)(struct test_context *); + int ut_start; + int ut_end; + unsigned int ut_num; }; #define MAX_TESTS 50 struct test_context { struct unit_test tests[MAX_TESTS]; + struct unit_test *test; /* Current test being run */ + char *cur_test_id; int iterations; int iteration; @@ -113,12 +118,15 @@ void test_evfilt_proc(struct test_context *); void test_evfilt_user(struct test_context *); #endif -#define test(f,ctx,...) do { \ - assert(ctx != NULL); \ - test_begin(ctx, "test_"#f"()\t"__VA_ARGS__); \ - errno = 0; \ - test_##f(ctx); \ - test_end(ctx); \ +#define test(f, ctx ,...) do { \ + if ((ctx->test->ut_num >= ctx->test->ut_start) && (ctx->test->ut_num <= ctx->test->ut_end)) {\ + assert(ctx != NULL); \ + test_begin(ctx, "test_"#f"()\t"__VA_ARGS__); \ + errno = 0; \ + test_##f(ctx); \ + test_end(ctx); \ + } \ + ctx->test->ut_num++; \ } while (/*CONSTCOND*/0) extern const char * kevent_to_str(struct kevent *); diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 7b9ff179f..562e054d2 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -14,6 +14,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include + #if defined(__linux__) || defined(__FreeBSD__) #include #include @@ -75,8 +77,10 @@ run_iteration(struct test_context *ctx) struct unit_test *test; for (test = ctx->tests; test->ut_name != NULL; test++) { - if (test->ut_enabled) + if (test->ut_enabled) { + ctx->test = test; /* Record the current test */ test->ut_func(ctx); + } } free(ctx); } @@ -90,7 +94,6 @@ test_harness(struct unit_test tests[MAX_TESTS], int iterations) printf("Running %d iterations\n", iterations); testing_begin(); - if ((kqfd = kqueue()) < 0) die("kqueue()"); n = 0; @@ -116,7 +119,8 @@ usage(void) printf("usage: [-hn] [testclass ...]\n" " -h This message\n" " -n Number of iterations (default: 1)\n" - " testclass Tests suites to run: [" + " testclass[:|:-] Tests suites to run:\n" + " [" "kqueue " "socket " "signal " @@ -134,20 +138,41 @@ int main(int argc, char **argv) { struct unit_test tests[MAX_TESTS] = { - { "kqueue", 1, test_kqueue }, + { .ut_name = "kqueue", + .ut_enabled = 1, + .ut_func = test_kqueue, + .ut_end = INT_MAX }, - { "socket", 1, test_evfilt_read }, + { .ut_name = "socket", + .ut_enabled = 1, + .ut_func = test_evfilt_read, + .ut_end = INT_MAX }, #if !defined(_WIN32) && !defined(__ANDROID__) // XXX-FIXME -- BROKEN ON LINUX WHEN RUN IN A SEPARATE THREAD - { "signal", 1, test_evfilt_signal }, + { .ut_name = "signal", + .ut_enabled = 1, + .ut_func = test_evfilt_signal, + .ut_end = INT_MAX }, #endif - { "proc", 1, test_evfilt_proc }, - { "timer", 1, test_evfilt_timer }, + { .ut_name = "proc", + .ut_enabled = 1, + .ut_func = test_evfilt_proc, + .ut_end = INT_MAX }, + { .ut_name = "timer", + .ut_enabled = 1, + .ut_func = test_evfilt_timer, + .ut_end = INT_MAX }, #ifndef _WIN32 - { "vnode", 1, test_evfilt_vnode }, + { .ut_name = "vnode", + .ut_enabled = 1, + .ut_func = test_evfilt_vnode, + .ut_end = INT_MAX }, #endif #ifdef EVFILT_USER - { "user", 1, test_evfilt_user }, + { .ut_name = "user", + .ut_enabled = 1, + .ut_func = test_evfilt_user, + .ut_end = INT_MAX }, #endif { NULL, 0, NULL }, }; @@ -190,17 +215,63 @@ main(int argc, char **argv) match = 0; arg = argv[i]; for (test = tests; test->ut_name != NULL; test++) { - if (strcmp(arg, test->ut_name) == 0) { + size_t namelen = strlen(test->ut_name); + char const *p; + char *q; + + if (strncmp(arg, test->ut_name, strlen(test->ut_name)) == 0) { test->ut_enabled = 1; match = 1; + + p = arg + namelen; + + /* + * Test name includes a test range + */ + if (*p == ':') { + p++; + + test->ut_start = strtoul(p, &q, 10); + if (p == q) + goto invalid_option; + p = q; + + /* + * Range is in the format - + */ + if (*p == '-') { + p++; + test->ut_end = strtoul(p, &q, 10); + if (p == q) + goto invalid_option; + printf("enabled test: %s (%u-%u)\n", test->ut_name, test->ut_start, test->ut_end); + /* + * Range is in the format + */ + } else if (*p == '\0') { + test->ut_end = test->ut_start; + printf("enabled test: %s (%u)\n", test->ut_name, test->ut_start); + /* + * Range is invalid + */ + } else + goto invalid_option; + /* + * Test name does not include a range + */ + } else if (*p == '\0') { + test->ut_start = 0; + test->ut_end = INT_MAX; + printf("enabled test: %s\n", test->ut_name); + } else + goto invalid_option; break; } } if (!match) { + invalid_option: printf("ERROR: invalid option: %s\n", arg); exit(1); - } else { - printf("enabled test: %s\n", arg); } } #endif diff --git a/vendor/libkqueue/test/test.c b/vendor/libkqueue/test/test.c index 895e9de79..c77ae1bec 100644 --- a/vendor/libkqueue/test/test.c +++ b/vendor/libkqueue/test/test.c @@ -61,8 +61,9 @@ test_begin(struct test_context *ctx, const char *func) free(ctx->cur_test_id); ctx->cur_test_id = strdup(func); - printf("%d: %s\n", testnum++, ctx->cur_test_id); + printf("%d: %s\n", ctx->test->ut_num, ctx->cur_test_id); //TODO: redirect stdout/err to logfile + testnum++; } void From 6eb095c8836236fbe6b8326dfe4814a918afc556 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 10 Sep 2021 16:53:01 -0500 Subject: [PATCH 0922/1120] Don't record EOF state for linx/read and linux/write Turns out the native kqueue behaviour is pretty poor here. EV_CLEAR basically does nothing for connected sockets. --- vendor/libkqueue/ChangeLog | 11 ++---- vendor/libkqueue/src/linux/platform.c | 48 +++------------------------ vendor/libkqueue/src/linux/read.c | 23 ++++++------- vendor/libkqueue/src/linux/write.c | 23 ++++++------- 4 files changed, 28 insertions(+), 77 deletions(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index d0045eb30..5ce88b422 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -9,15 +9,8 @@ Nothing here yet. * Fix: Compilation on Windows (Closes #111). (Reported by: brechtsanders) - * Fix: On Linux EPOLLHUP and EPOLLRDHUP did not set the EOF flag in kn->kev - and did not remove the EOF'd socket from epoll. The result was kevent - would return immediately. Additionally, where EPOLLIN was not set by - epoll, no kevent would be returned, and no EOF indication would be provided - to the caller. - linux/read.c and linux/write.c now exhibit the same behaviour as kqueue, - and will remove EOF'd sockets from EPOLL. The EOF condition can be cleared - by passing passing EV_ADD | EV_CLEAR, at which point notifications for the - socket will be produced once again. + * Fix: On Linux EPOLLERR, EPOLLHUP and EPOLLRDHUP on sockets would not + produce a kevent and no EOF indication would be provided to the caller. 2021-09-06 v2.5.0 ------------------------------------------------------------------------ diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 5af191f58..ca8a13f30 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -700,52 +700,12 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven { struct fd_state *fds = epoll_udata->ud_fds; struct knote *kn; - struct filter *filt; assert(fds); /* - * FD errored or the other side hung up - * - * kqueue doesn't seem to distinguish between - * EOF and ERROR, except that on error the data - * field is filled in. + * FD, or errored, or other side shutdown */ - if (ev->events & (EPOLLHUP | EPOLLRDHUP | EPOLLERR)) { - if (fds->fds_read && KNOTE_NOT_EOF(fds->fds_read)) { - if (el_p >= el_end) goto oos; - - kn = fds->fds_read; - filt = knote_get_filter(kn); - - filt->kn_disable(filt, kn); - KNOTE_EOF_SET(kn); - - rv = linux_kevent_copyout_ev(el_p, (el_end - el_p), ev, &kq->kq_filt[~(kn->kev.filter)], kn); - if (rv < 0) goto done; - el_p += rv; - } - - /* Don't set write to EOF if we only got EPOLLRDHUP */ - if (fds->fds_write && KNOTE_NOT_EOF(fds->fds_write) && (ev->events & (EPOLLHUP | EPOLLERR))) { - if (el_p >= el_end) goto oos; - - kn = fds->fds_write; - filt = knote_get_filter(kn); - - filt->kn_disable(filt, kn); - KNOTE_EOF_SET(kn); - - rv = linux_kevent_copyout_ev(el_p, (el_end - el_p), ev, &kq->kq_filt[~(kn->kev.filter)], kn); - if (rv < 0) goto done; - el_p += rv; - } - continue; - } - - /* - * FD is readable - */ - if (ev->events & EPOLLIN) { + if (ev->events & (EPOLLIN | EPOLLHUP | EPOLLRDHUP | EPOLLERR)) { if (el_p >= el_end) goto oos; kn = fds->fds_read; @@ -764,9 +724,9 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven } /* - * FD is writable + * FD is writable, or errored, or other side shutdown */ - if (ev->events & EPOLLOUT) { + if (ev->events & (EPOLLOUT | POLLHUP | EPOLLERR)) { if (el_p >= el_end) goto oos; kn = fds->fds_write; diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index 27e8d9cf3..19bb01bae 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -208,21 +208,20 @@ evfilt_read_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_read_knote_modify(struct filter *filt, struct knote *kn, +evfilt_read_knote_modify(UNUSED struct filter *filt, struct knote *kn, const struct kevent *kev) { - /* - * re-enable a socket that was previously EOF'd - * - * restricted to sockets as this hasn't been tested with files. - */ if (!(kn->kn_flags & KNFL_FILE)) { - if ((kev->flags & EV_CLEAR) && (KNOTE_IS_EOF(kn))) { - if (filt->kn_enable(filt, kn) < 0) - return -1; - KNOTE_EOF_CLEAR(kn); - } - return (0); + /* + * This should reset the EOF sate of the socket. + * but it's not even clear what that really means. + * + * With the native kqueue implementations it + * basically does nothing. + */ + if ((kev->flags & EV_CLEAR)) + return (0); + return (-1); } return (-1); diff --git a/vendor/libkqueue/src/linux/write.c b/vendor/libkqueue/src/linux/write.c index 290626739..0f94145b7 100644 --- a/vendor/libkqueue/src/linux/write.c +++ b/vendor/libkqueue/src/linux/write.c @@ -91,21 +91,20 @@ evfilt_write_knote_create(struct filter *filt, struct knote *kn) } int -evfilt_write_knote_modify(struct filter *filt, struct knote *kn, +evfilt_write_knote_modify(UNUSED struct filter *filt, struct knote *kn, const struct kevent *kev) { - /* - * re-enable a socket that was previously EOF'd - * - * restricted to sockets as this hasn't been tested with files. - */ if (!(kn->kn_flags & KNFL_FILE)) { - if ((kev->flags & EV_CLEAR) && (KNOTE_IS_EOF(kn))) { - if (filt->kn_enable(filt, kn) < 0) - return -1; - KNOTE_EOF_CLEAR(kn); - } - return (0); + /* + * This should reset the EOF sate of the socket. + * but it's not even clear what that really means. + * + * With the native kqueue implementations it + * basically does nothing. + */ + if ((kev->flags & EV_CLEAR)) + return (0); + return (-1); } return (-1); From c8f7f4e79709025ada438ce04fa277093bbd5873 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 10 Sep 2021 17:04:31 -0500 Subject: [PATCH 0923/1120] There's no reason to differ in our output from FreeBSD kqueue ...it just makes writing tests more complicated --- vendor/libkqueue/src/linux/user.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index 82faffdbc..5ba33689e 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -85,11 +85,6 @@ linux_evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct filter memcpy(dst, &src->kev, sizeof(*dst)); dst->fflags &= ~NOTE_FFCTRLMASK; //FIXME: Not sure if needed dst->fflags &= ~NOTE_TRIGGER; - if (src->kev.flags & EV_ADD) { - /* NOTE: True on FreeBSD but not consistent behavior with - other filters. */ - dst->flags &= ~EV_ADD; - } if (src->kev.flags & EV_CLEAR) src->kev.fflags &= ~NOTE_TRIGGER; if (src->kev.flags & (EV_DISPATCH | EV_CLEAR | EV_ONESHOT)) { From faa35589cd906927d3a3be4d90a63f1c3440dcb0 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 10 Sep 2021 17:04:55 -0500 Subject: [PATCH 0924/1120] Only change udata if the modify succeeded --- vendor/libkqueue/src/common/kevent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 704b8fa89..af0368672 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -202,8 +202,8 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) } else if (src->flags & EV_ENABLE) { rv = knote_enable(filt, kn); } else if (src->flags & EV_ADD || src->flags == 0 || src->flags & EV_RECEIPT) { - kn->kev.udata = src->udata; rv = filt->kn_modify(filt, kn, src); + if (rv == 0) kn->kev.udata = src->udata; dbg_printf("kn=%p - kn_modify rv=%d", kn, rv); } From 69b79cf00984f91d6760ae6e9b42a65937926d8b Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 10 Sep 2021 17:24:02 -0500 Subject: [PATCH 0925/1120] Only FreeBSD is broken. macOS and libkqueue do the right thing in test_kevent_timer_dispatch --- vendor/libkqueue/test/timer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/test/timer.c b/vendor/libkqueue/test/timer.c index c62f6e5da..e98c6467e 100644 --- a/vendor/libkqueue/test/timer.c +++ b/vendor/libkqueue/test/timer.c @@ -137,7 +137,7 @@ test_kevent_timer_dispatch(struct test_context *ctx) usleep(500000); /* 500 ms */ test_no_kevents(ctx->kqfd); -#if WITH_NATIVE_KQUEUE_BUGS || (!defined(__APPLE__) && !defined(__FreeBSD__)) +#if WITH_NATIVE_KQUEUE_BUGS || !defined(__FreeBSD__) /* * macOS and FreeBSD both share the same bug. * @@ -153,9 +153,9 @@ test_kevent_timer_dispatch(struct test_context *ctx) test_no_kevents(ctx->kqfd); /* Get the next event */ - usleep(1000000); /* 1000 ms */ + usleep(1100000); /* 1100 ms */ kev.flags = EV_ADD | EV_CLEAR | EV_DISPATCH; - kev.data = 1; + kev.data = 5; kevent_get(&ret, ctx->kqfd, 1); kevent_cmp(&kev, &ret); #endif From 355b04186e33dc55a22194ccccb755237d41a498 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 10 Sep 2021 17:33:44 -0500 Subject: [PATCH 0926/1120] We shouldn't reset the signalfd if a signal event is added FreeBSD kqueue will immediately report any pending signals when the event is created or re-enabled. --- vendor/libkqueue/src/linux/signal.c | 3 +-- vendor/libkqueue/test/signal.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index e785f96c0..158581f9a 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -88,6 +88,7 @@ signalfd_create(int epoll_fd, struct knote *kn, int signum) /* Create a signalfd */ sigemptyset(&sigmask); sigaddset(&sigmask, signum); + sigfd = signalfd(-1, &sigmask, flags); /* WORKAROUND: Flags are broken on kernels older than Linux 2.6.27 */ @@ -110,8 +111,6 @@ signalfd_create(int epoll_fd, struct knote *kn, int signum) goto errout; } - signalfd_reset(sigfd); - if (signalfd_add(epoll_fd, sigfd, kn) < 0) goto errout; diff --git a/vendor/libkqueue/test/signal.c b/vendor/libkqueue/test/signal.c index d39b3d1f4..c88d726b0 100644 --- a/vendor/libkqueue/test/signal.c +++ b/vendor/libkqueue/test/signal.c @@ -40,6 +40,23 @@ test_kevent_signal_get(struct test_context *ctx) kevent_cmp(&kev, &ret); } +void +test_kevent_signal_get_pending(struct test_context *ctx) +{ + struct kevent kev, ret; + + /* A pending signal should be reported as soon as the event is added */ + if (kill(getpid(), SIGUSR1) < 0) + die("kill"); + + kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); + + kev.flags |= EV_CLEAR; + kev.data = 1; + kevent_get(&ret, ctx->kqfd, 1); + kevent_cmp(&kev, &ret); +} + void test_kevent_signal_disable(struct test_context *ctx) { @@ -183,6 +200,7 @@ test_evfilt_signal(struct test_context *ctx) test(kevent_signal_add, ctx); test(kevent_signal_del, ctx); test(kevent_signal_get, ctx); + test(kevent_signal_get_pending, ctx); test(kevent_signal_disable, ctx); test(kevent_signal_enable, ctx); test(kevent_signal_oneshot, ctx); From 087a30419bd2881299fedb25249b00b0ed7a54c6 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 10 Sep 2021 18:36:47 -0500 Subject: [PATCH 0927/1120] Remove travis, switch main build/test to GitHub actions --- .../libkqueue/.github/workflows/ci-linux.yml | 96 +++++++++++++++++++ vendor/libkqueue/.travis.yml | 45 --------- vendor/libkqueue/scripts/travis/build.sh | 40 -------- 3 files changed, 96 insertions(+), 85 deletions(-) create mode 100644 vendor/libkqueue/.github/workflows/ci-linux.yml delete mode 100644 vendor/libkqueue/.travis.yml delete mode 100755 vendor/libkqueue/scripts/travis/build.sh diff --git a/vendor/libkqueue/.github/workflows/ci-linux.yml b/vendor/libkqueue/.github/workflows/ci-linux.yml new file mode 100644 index 000000000..be273d8e0 --- /dev/null +++ b/vendor/libkqueue/.github/workflows/ci-linux.yml @@ -0,0 +1,96 @@ +name: CI Linux + +on: + push: + branches: + - master + pull_request: + +env: + ASAN_OPTIONS: symbolize=1 detect_leaks=1 detect_stack_use_after_return=1 + LSAN_OPTIONS: fast_unwind_on_malloc=0:malloc_context_size=50 + KQUEUE_DEBUG: yes + M_PERTURB: "0x42" + +jobs: + linux-build-and-test: + strategy: + fail-fast: false + matrix: + env: + - { CC: gcc, OS: ubuntu-20.04, NAME: release-gcc, BUILD_TYPE: Release } + - { CC: clang, OS: ubuntu-20.04, NAME: release-clang, BUILD_TYPE: Release } + - { CC: clang, OS: ubuntu-20.04, NAME: debug-asan, BUILD_TYPE: Debug, ENABLE_ASAN: YES, ENABLE_LSAN: YES, ENABLE_UBSAN: YES } + - { CC: clang, OS: ubuntu-20.04, NAME: debug-tsan, BUILD_TYPE: Debug, ENABLE_TSAN: YES } + # Older kernel triggers a switch to posix/proc as it doesn't support pidfd. + - { CC: clang, OS: ubuntu-18.04, NAME: debug-asan-posix-proc, BUILD_TYPE: Debug, ENABLE_ASAN: YES, ENABLE_LSAN: YES, ENABLE_UBSAN: YES } + - { CC: clang, OS: ubuntu-18.04, NAME: debug-tsan-posix-proc, BUILD_TYPE: Debug, ENABLE_TSAN: YES } + + runs-on: ${{ matrix.env.OS }} + + env: ${{ matrix.env }} + + name: "${{ matrix.env.NAME }}" + + steps: + - uses: actions/checkout@v2 + + - name: Add llvm source + if: ${{ matrix.env.CC == 'clang' && matrix.env.OS == 'ubuntu-18.04' }} + uses: myci-actions/add-deb-repo@10 + with: + repo: deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main + repo-name: llvm-toolchain + keys-asc: https://apt.llvm.org/llvm-snapshot.gpg.key + + - name: Add GCC source + if: ${{ matrix.env.CC == 'gcc' && matrix.env.OS == 'ubuntu-18.04' }} + run: | + sudo add-apt-repository ppa:ubuntu-toolchain-r/test + + - name: Install LLVM 10 + if: ${{ matrix.env.CC == 'clang' }} + run: | + sudo apt-get install -y --no-install-recommends clang-10 llvm-10 gdb + sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-10 60 && sudo update-alternatives --set clang /usr/bin/clang-10 + sudo update-alternatives --install /usr/bin/llvm-symbolizer llvm-symbolizer /usr/bin/llvm-symbolizer-10 60 && sudo update-alternatives --set llvm-symbolizer /usr/bin/llvm-symbolizer-10 + + - name: Install GCC 7 + if: ${{ matrix.env.CC == 'gcc' }} + run: | + sudo apt-get install -y --no-install-recommends gcc-7 gccgo-7 gdb + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 9999 && sudo update-alternatives --config gcc + + - name: Install other build deps + run: | + sudo apt-get install -y \ + build-essential \ + debhelper \ + devscripts \ + dh-make \ + fakeroot + + - name: Configure build system + run: | + cmake . -G "Unix Makefiles" \ + -DCMAKE_INSTALL_PREFIX="/usr" \ + -DCMAKE_INSTALL_LIBDIR="lib" \ + -DCMAKE_VERBOSE_MAKEFILE:BOOL="ON" \ + -DENABLE_TESTING="YES" \ + -DENABLE_ASAN="${ENABLE_ASAN:-NO}" \ + -DENABLE_LSAN="${ENABLE_LSAN:-NO}" \ + -DENABLE_UBSAN="${ENABLE_UBSAN:-NO}" \ + -DENABLE_TSAN="${ENABLE_TSAN:-NO}" \ + -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" + + - name: Build libkqueue + run: make -j2 + + - name: Run tests + run: test/libkqueue-test + + - name: Build debian packages + run: cpack -G DEB + + - name: Install debian packages + run: sudo apt-get install -y ./*.deb diff --git a/vendor/libkqueue/.travis.yml b/vendor/libkqueue/.travis.yml deleted file mode 100644 index f42311ab9..000000000 --- a/vendor/libkqueue/.travis.yml +++ /dev/null @@ -1,45 +0,0 @@ -language: c -compiler: -- clang -- gcc -cache: - apt: true -dist: bionic -env: - global: - - KQUEUE_DEBUG="yes" - - M_PERTURB=0x42 - matrix: - - BUILD_TYPE=Release - - BUILD_TYPE=Debug ENABLE_ASAN=YES ENABLE_LSAN=YES ENABLE_UBSAN=YES ASAN_OPTIONS="symbolize=1 detect_leaks=1 detect_stack_use_after_return=1" LSAN_OPTIONS="fast_unwind_on_malloc=0:malloc_context_size=50" - - BUILD_TYPE=Debug ENABLE_TSAN=YES -addons: - apt: - config: - retries: true - sources: - - sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main' - key_url: https://apt.llvm.org/llvm-snapshot.gpg.key - # For newer GCC - - ubuntu-toolchain-r-test - packages: - - build-essential - - clang-10 - - debhelper - - devscripts - - dh-make - - fakeroot - - gcc-7 - - gccgo-7 - - gdb - # Needed for llvm-symbolizer - - llvm-10 -before_install: -- if [ "${CC}" == 'gcc' ]; then sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 9999 && sudo update-alternatives --config gcc; fi -- if [ "${CC}" == 'clang' ]; then sudo rm -rf /usr/local/clang-*; fi -- if [ "${CC}" == 'clang' ]; then sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-10 9999 && sudo update-alternatives --config clang; fi -- if [ "${CC}" == 'clang' ]; then sudo update-alternatives --install /usr/bin/llvm-symbolizer llvm-symbolizer /usr/bin/llvm-symbolizer-10 9999 && sudo update-alternatives --config llvm-symbolizer; fi -before_script: -- ./scripts/travis/build.sh -script: -- make ARGS="-V" test diff --git a/vendor/libkqueue/scripts/travis/build.sh b/vendor/libkqueue/scripts/travis/build.sh deleted file mode 100755 index 4833469ed..000000000 --- a/vendor/libkqueue/scripts/travis/build.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash -e -# Author: Jorge Pereira -# - -function fatal() { - echo "$0: ERROR: $@" - exit 1 -} - -if [[ ! "${BUILD_TYPE}" =~ Debug|Release ]]; then - fatal "The 'BUILD_TYPE' should be 'Debug' or 'Release'." -fi - -if ! cmake . -G "Unix Makefiles" \ - -DCMAKE_INSTALL_PREFIX="/usr" \ - -DCMAKE_INSTALL_LIBDIR="lib" \ - -DCMAKE_VERBOSE_MAKEFILE:BOOL="ON" \ - -DENABLE_TESTING="YES" \ - -DENABLE_ASAN="${ENABLE_ASAN:-NO}" \ - -DENABLE_LSAN="${ENABLE_LSAN:-NO}" \ - -DENABLE_UBSAN="${ENABLE_UBSAN:-NO}" \ - -DENABLE_TSAN="${ENABLE_TSAN:-NO}" \ - -DCMAKE_BUILD_TYPE="${BUILD_TYPE}"; then - fatal "Failed during cmake build configuration" -fi - -# -# Build the libkqueue -# -echo "Starting compilation" -if ! make -j8; then - fatal "Failed during compilation" -fi - -# -# Build the *.deb packages -# -if ! cpack -G DEB; then - fatal "Failed when building debian packages" -fi From 7b3010f9a91da925b84c812f21f6b59d2b619dfe Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 10 Sep 2021 18:49:34 -0500 Subject: [PATCH 0928/1120] Add badges for the main build and test targets --- vendor/libkqueue/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index def48189a..f41401f63 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -1,7 +1,9 @@ libkqueue ========= -[![Build Status](https://travis-ci.com/mheily/libkqueue.svg?branch=master)](https://travis-ci.com/mheily/libkqueue) +[![CI Linux](https://github.com/mheily/libkqueue/actions/workflows/ci-linux.yml/badge.svg)](https://github.com/mheily/libkqueue/actions/workflows/ci-linux.yml) +[![CI tests FreeBSD](https://github.com/mheily/libkqueue/actions/workflows/ci-freebsd.yml/badge.svg)](https://github.com/mheily/libkqueue/actions/workflows/ci-freebsd.yml) +[![CI tests macOS](https://github.com/mheily/libkqueue/actions/workflows/ci-macos.yml/badge.svg)](https://github.com/mheily/libkqueue/actions/workflows/ci-macos.yml) A user space implementation of the kqueue(2) kernel event notification mechanism libkqueue acts as a translator between the kevent structure and the native From 16d0f2fb12cbdee7d8e1b7573bdde7677b50df23 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 11 Sep 2021 10:03:20 -0500 Subject: [PATCH 0929/1120] Update changelog --- vendor/libkqueue/ChangeLog | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 5ce88b422..419166141 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -9,8 +9,23 @@ Nothing here yet. * Fix: Compilation on Windows (Closes #111). (Reported by: brechtsanders) - * Fix: On Linux EPOLLERR, EPOLLHUP and EPOLLRDHUP on sockets would not - produce a kevent and no EOF indication would be provided to the caller. + * Fix: linux/read linux/write EPOLLERR, EPOLLHUP and EPOLLRDHUP on + sockets would not produce a kevent and no EOF indication would be + provided to the caller. + + * Fix: linux/signal pending signals of the type specified in a new + signal event were reset when that event was added to a kqueue. + + * Fix: Multiple instances of posix/proc wait thread may have been + spawned on repeated kqueue creation/destruction. This may have + lead to missed process exit notifications. + + * Fix: Potential race between posix/proc waiter thread starting and + events being added. + + * Fix: udata should not be modified if the knote modification fails. + + * Test suites now pass on macOS 11.5.2 and FreeBSD 13. 2021-09-06 v2.5.0 ------------------------------------------------------------------------ From e96e34a536b42ad62cfaf2bf0b46707f65033384 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 11 Sep 2021 12:46:44 -0500 Subject: [PATCH 0930/1120] Move android hacks into linux platform --- vendor/libkqueue/src/common/private.h | 4 ---- vendor/libkqueue/src/linux/platform.h | 6 +++++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 5f45b75e7..0e249b1fa 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -104,10 +104,6 @@ struct evfilt_data; #include "debug.h" -/* Workaround for Android */ -#ifndef EPOLLONESHOT -# define EPOLLONESHOT (1 << 30) -#endif /** An eventfd provides a mechanism to signal the eventing system that an event has occurred * diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 425422544..ca7bc401f 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -51,7 +51,6 @@ struct filter; #include #include - /* * Check to see if we have SYS_pidfd_open support if we don't, * fall back to the POSIX EVFILT_PROC code. @@ -90,6 +89,11 @@ struct filter; extern long int syscall (long int __sysno, ...); #endif +/* Workaround for Android */ +#ifndef EPOLLONESHOT +# define EPOLLONESHOT (1 << 30) +#endif + /* Convenience macros to access the epoll descriptor for the kqueue */ #define kqueue_epoll_fd(kq) ((kq)->epollfd) #define filter_epoll_fd(filt) ((filt)->kf_kqueue->epollfd) From 384dc2edfccd727db620ea04919c452d0b26612d Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 11 Sep 2021 12:48:10 -0500 Subject: [PATCH 0931/1120] Fix EV_DISPATCH so it can be set/unset during modification --- vendor/libkqueue/src/common/kevent.c | 12 +++++++++++- vendor/libkqueue/src/common/private.h | 7 ++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index af0368672..a381bb245 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -203,7 +203,17 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) rv = knote_enable(filt, kn); } else if (src->flags & EV_ADD || src->flags == 0 || src->flags & EV_RECEIPT) { rv = filt->kn_modify(filt, kn, src); - if (rv == 0) kn->kev.udata = src->udata; + + /* + * Implement changes common to all filters + */ + if (rv == 0) { + /* update udata */ + kn->kev.udata = src->udata; + + /* sync up the dispatch bit */ + COPY_FLAGS_BIT(kn->kev, (*src), EV_DISPATCH); + } dbg_printf("kn=%p - kn_modify rv=%d", kn, rv); } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 0e249b1fa..99bd12180 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -102,8 +102,13 @@ struct evfilt_data; #define UNUSED_NDEBUG #endif -#include "debug.h" +/* + * Bit twiddling + */ +#define COPY_FLAGS_BIT(_dst, _src, _flag) (_dst).flags = ((_dst).flags & ~(_flag)) | ((_src).flags & (_flag)) +#define COPY_FFLAGS_BIT(_dst, _src, _flag) (_dst).fflags = ((_dst).fflags & ~(_flag)) | ((_src).fflags & (_flag)) +#include "debug.h" /** An eventfd provides a mechanism to signal the eventing system that an event has occurred * From 5ef4d031aecc4d959faf52143f502b61073f5316 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 13 Sep 2021 10:26:31 -0500 Subject: [PATCH 0932/1120] linux/platform: We now need to check to make sure the knotes aren't NULL --- vendor/libkqueue/src/linux/platform.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index ca8a13f30..4c9ffef15 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -705,19 +705,9 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven /* * FD, or errored, or other side shutdown */ - if (ev->events & (EPOLLIN | EPOLLHUP | EPOLLRDHUP | EPOLLERR)) { + if ((kn = fds->fds_read) && (ev->events & (EPOLLIN | EPOLLHUP | EPOLLRDHUP | EPOLLERR))) { if (el_p >= el_end) goto oos; - kn = fds->fds_read; - - /* - * We shouldn't receive events we didn't register for - * This assume's the Linux's epoll implementation isn't - * complete garbage... so um... this assert may need - * to be removed later. - */ - assert(kn); - rv = linux_kevent_copyout_ev(el_p, (el_end - el_p), ev, &kq->kq_filt[~(kn->kev.filter)], kn); if (rv < 0) goto done; el_p += rv; @@ -726,13 +716,9 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven /* * FD is writable, or errored, or other side shutdown */ - if (ev->events & (EPOLLOUT | POLLHUP | EPOLLERR)) { + if ((kn = fds->fds_write) && (ev->events & (EPOLLOUT | POLLHUP | EPOLLERR))) { if (el_p >= el_end) goto oos; - kn = fds->fds_write; - - assert(kn); /* We shouldn't receive events we didn't request */ - rv = linux_kevent_copyout_ev(el_p, (el_end - el_p), ev, &kq->kq_filt[~(kn->kev.filter)], kn); if (rv < 0) goto done; el_p += rv; From 8e9967c261cb73b8bd8fe2150e6d6fe36023923a Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 13 Sep 2021 10:44:28 -0500 Subject: [PATCH 0933/1120] Pass in number of events to kevent_get --- vendor/libkqueue/test/common.c | 16 ++++--- vendor/libkqueue/test/common.h | 7 +-- vendor/libkqueue/test/proc.c | 32 +++++++------- vendor/libkqueue/test/read.c | 80 +++++++++++++++++----------------- vendor/libkqueue/test/signal.c | 40 ++++++++--------- vendor/libkqueue/test/timer.c | 38 ++++++++-------- vendor/libkqueue/test/user.c | 40 ++++++++--------- vendor/libkqueue/test/vnode.c | 18 ++++---- 8 files changed, 137 insertions(+), 134 deletions(-) diff --git a/vendor/libkqueue/test/common.c b/vendor/libkqueue/test/common.c index 0458281cd..0107de9cf 100644 --- a/vendor/libkqueue/test/common.c +++ b/vendor/libkqueue/test/common.c @@ -38,15 +38,17 @@ _test_no_kevents(int kqfd, const char *file, int line) /* Retrieve a single kevent */ void -kevent_get(struct kevent *kev, int kqfd, int expect) +kevent_get(struct kevent kev[], int numevents, int kqfd, int expect) { struct kevent buf; int nfds; - if (kev == NULL) + if (kev == NULL) { kev = &buf; + numevents = 1; + } - kevent_rv_cmp(expect, kevent(kqfd, NULL, 0, kev, 1, NULL)); + kevent_rv_cmp(expect, kevent(kqfd, NULL, 0, kev, numevents, NULL)); } /** @@ -56,11 +58,11 @@ kevent_get(struct kevent *kev, int kqfd, int expect) * 1 = Success */ int -kevent_get_timeout(struct kevent *kev, int fd, struct timespec *ts) +kevent_get_timeout(struct kevent kev[], int numevents, int fd, struct timespec *ts) { int nfds; - nfds = kevent(fd, NULL, 0, kev, 1, ts); + nfds = kevent(fd, NULL, 0, kev, numevents, ts); if (nfds < 0) { err(1, "kevent(2)"); } else if (nfds == 0) { @@ -75,11 +77,11 @@ kevent_get_timeout(struct kevent *kev, int fd, struct timespec *ts) This test exercises that codepath. */ void -kevent_get_hires(struct kevent *kev, int kqfd, struct timespec *ts) +kevent_get_hires(struct kevent kev[], int numevents, int kqfd, struct timespec *ts) { int nfds; - nfds = kevent(kqfd, NULL, 0, kev, 1, ts); + nfds = kevent(kqfd, NULL, 0, kev, numevents, ts); if (nfds < 1) die("kevent(2)"); } diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index f5ca0bfd2..04dafdba4 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -130,9 +130,10 @@ void test_evfilt_user(struct test_context *); } while (/*CONSTCOND*/0) extern const char * kevent_to_str(struct kevent *); -void kevent_get(struct kevent *, int, int); -void kevent_get_hires(struct kevent *, int, struct timespec *); -int kevent_get_timeout(struct kevent *, int, struct timespec *); +void kevent_get(struct kevent kev[], int numevents, int kqfd, int expect_rv); +void kevent_get_hires(struct kevent kev[], int numevents, int kqfd, struct timespec *timeout); +int kevent_get_timeout(struct kevent kev[], int numevents, int kqfd, struct timespec *timeout); + void kevent_update(int kqfd, struct kevent *kev); #define kevent_cmp(a,b) _kevent_cmp(a,b, __FILE__, __LINE__) diff --git a/vendor/libkqueue/test/proc.c b/vendor/libkqueue/test/proc.c index 4b42ce65c..982db2b4d 100644 --- a/vendor/libkqueue/test/proc.c +++ b/vendor/libkqueue/test/proc.c @@ -51,7 +51,7 @@ test_kevent_proc_delete(struct test_context *ctx) static void test_kevent_proc_get(struct test_context *ctx) { - struct kevent kev, buf; + struct kevent kev, buf[1]; int fflags; /* @@ -82,19 +82,19 @@ test_kevent_proc_get(struct test_context *ctx) printf(" -- killing process %d\n", (int) pid); if (kill(pid, SIGKILL) < 0) die("kill"); - kevent_get(&buf, ctx->kqfd, 1); + kevent_get(buf, NUM_ELEMENTS(buf), ctx->kqfd, 1); kev.data = SIGKILL; /* What we expected the process exit code to be */ kev.flags = EV_ADD | EV_ONESHOT | EV_CLEAR | EV_EOF; - kevent_cmp(&kev, &buf); + kevent_cmp(&kev, buf); test_no_kevents(ctx->kqfd); } static void test_kevent_proc_exit_status_ok(struct test_context *ctx) { - struct kevent kev, buf; + struct kevent kev, buf[1]; int fflags; /* @@ -121,19 +121,19 @@ test_kevent_proc_exit_status_ok(struct test_context *ctx) test_no_kevents(ctx->kqfd); kevent_add(ctx->kqfd, &kev, pid, EVFILT_PROC, EV_ADD, fflags, 0, NULL); - kevent_get(&buf, ctx->kqfd, 1); + kevent_get(buf, NUM_ELEMENTS(buf), ctx->kqfd, 1); kev.data = 0; /* What we expected the process exit code to be */ kev.flags = EV_ADD | EV_ONESHOT | EV_CLEAR | EV_EOF; - kevent_cmp(&kev, &buf); + kevent_cmp(&kev, buf); test_no_kevents(ctx->kqfd); } static void test_kevent_proc_exit_status_error(struct test_context *ctx) { - struct kevent kev, buf; + struct kevent kev, buf[1]; int fflags; /* @@ -160,19 +160,19 @@ test_kevent_proc_exit_status_error(struct test_context *ctx) test_no_kevents(ctx->kqfd); kevent_add(ctx->kqfd, &kev, pid, EVFILT_PROC, EV_ADD, fflags, 0, NULL); - kevent_get(&buf, ctx->kqfd, 1); + kevent_get(buf, NUM_ELEMENTS(buf), ctx->kqfd, 1); kev.data = 64 << 8; /* What we expected the process exit code to be */ kev.flags = EV_ADD | EV_ONESHOT | EV_CLEAR | EV_EOF; - kevent_cmp(&kev, &buf); + kevent_cmp(&kev, buf); test_no_kevents(ctx->kqfd); } static void test_kevent_proc_multiple_kqueue(struct test_context *ctx) { - struct kevent kev, buf_a, buf_b; + struct kevent kev, buf_a[1], buf_b[1]; int fflags; int kq_b; @@ -205,14 +205,14 @@ test_kevent_proc_multiple_kqueue(struct test_context *ctx) kevent_add(ctx->kqfd, &kev, pid, EVFILT_PROC, EV_ADD, fflags, 0, NULL); kevent_add(kq_b, &kev, pid, EVFILT_PROC, EV_ADD, fflags, 0, NULL); - kevent_get(&buf_a, ctx->kqfd, 1); - kevent_get(&buf_b, kq_b, 1); + kevent_get(buf_a, NUM_ELEMENTS(buf_a), ctx->kqfd, 1); + kevent_get(buf_b, NUM_ELEMENTS(buf_b), kq_b, 1); kev.data = 64 << 8; /* What we expected the process exit code to be */ kev.flags = EV_ADD | EV_ONESHOT | EV_CLEAR | EV_EOF; - kevent_cmp(&kev, &buf_a); - kevent_cmp(&kev, &buf_b); + kevent_cmp(&kev, buf_a); + kevent_cmp(&kev, buf_b); test_no_kevents(ctx->kqfd); test_no_kevents(kq_b); @@ -271,7 +271,7 @@ test_kevent_signal_enable(struct test_context *ctx) #else kev.data = 2; // one extra time from test_kevent_signal_disable() #endif - kevent_get(&buf, ctx->kqfd, 1) + kevent_get(buf, NUM_ELEMENTS(buf), ctx->kqfd, 1) kevent_cmp(&kev, &buf); /* Delete the watch */ @@ -328,7 +328,7 @@ test_kevent_signal_oneshot(struct test_context *ctx) kev.flags |= EV_CLEAR; kev.data = 1; - kevent_get(&buf, ctx->kqfd, 1) + kevent_get(buf, NUM_ELEMENTS(buf), ctx->kqfd, 1) kevent_cmp(&kev, &buf); /* Send another one and make sure we get no events */ diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 54e24aa04..0bca69adf 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -119,7 +119,7 @@ test_kevent_socket_add_without_ev_add(struct test_context *ctx) void test_kevent_socket_get(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; EV_SET(&kev, ctx->client_fd, EVFILT_READ, EV_ADD, 0, 0, &ctx->client_fd); kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); @@ -127,8 +127,8 @@ test_kevent_socket_get(struct test_context *ctx) kevent_socket_fill(ctx, 1); kev.data = 1; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); kevent_socket_drain(ctx); test_no_kevents(ctx->kqfd); @@ -140,7 +140,7 @@ test_kevent_socket_get(struct test_context *ctx) void test_kevent_socket_clear(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; test_no_kevents(ctx->kqfd); kevent_socket_drain(ctx); @@ -166,8 +166,8 @@ test_kevent_socket_clear(struct test_context *ctx) kev.data = 2; #endif - kevent_get(&ret, ctx->kqfd, 1); /* data is pending, so we should get an event */ - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); /* data is pending, so we should get an event */ + kevent_cmp(&kev, ret); /* We filled twice, but drain once. Edge-triggered would not generate additional events. @@ -183,7 +183,7 @@ test_kevent_socket_clear(struct test_context *ctx) void test_kevent_socket_disable_and_enable(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; /* Add an event, then disable it. */ EV_SET(&kev, ctx->client_fd, EVFILT_READ, EV_ADD, 0, 0, &ctx->client_fd); @@ -200,8 +200,8 @@ test_kevent_socket_disable_and_enable(struct test_context *ctx) kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); kev.flags = EV_ADD; kev.data = 1; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); kevent_socket_drain(ctx); @@ -224,7 +224,7 @@ test_kevent_socket_del(struct test_context *ctx) void test_kevent_socket_oneshot(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; /* Re-add the watch and make sure no events are pending */ kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &ctx->client_fd); @@ -232,8 +232,8 @@ test_kevent_socket_oneshot(struct test_context *ctx) kevent_socket_fill(ctx, 1); kev.data = 1; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); test_no_kevents(ctx->kqfd); @@ -254,7 +254,7 @@ test_kevent_socket_oneshot(struct test_context *ctx) void test_kevent_socket_listen_backlog(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; struct sockaddr_in sain; socklen_t sa_len = sizeof(sain); int one = 1; @@ -294,8 +294,8 @@ test_kevent_socket_listen_backlog(struct test_context *ctx) /* Verify that data=1 */ kev.data = 1; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); test_no_kevents(ctx->kqfd); close(clnt); @@ -306,7 +306,7 @@ test_kevent_socket_listen_backlog(struct test_context *ctx) void test_kevent_socket_dispatch(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; /* Re-add the watch and make sure no events are pending */ kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &ctx->client_fd); @@ -316,8 +316,8 @@ test_kevent_socket_dispatch(struct test_context *ctx) specified. */ kevent_socket_fill(ctx, 1); kev.data = 1; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); test_no_kevents(ctx->kqfd); /* Re-enable the kevent */ @@ -325,8 +325,8 @@ test_kevent_socket_dispatch(struct test_context *ctx) kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ENABLE | EV_DISPATCH, 0, 0, &ctx->client_fd); kev.data = 1; kev.flags = EV_ADD | EV_DISPATCH; /* FIXME: may not be portable */ - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); test_no_kevents(ctx->kqfd); /* Since the knote is disabled, the EV_DELETE operation succeeds. */ @@ -368,7 +368,7 @@ test_kevent_socket_lowat(struct test_context *ctx) void test_kevent_socket_eof_clear(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; uint8_t buff[1024]; kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &ctx->client_fd); @@ -380,8 +380,8 @@ test_kevent_socket_eof_clear(struct test_context *ctx) die("close(2)"); kev.flags |= EV_EOF; - kevent_get(&ret, ctx->kqfd, 1); /* edge triggered means no more events */ - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); /* edge triggered means no more events */ + kevent_cmp(&kev, ret); test_no_kevents(ctx->kqfd);; @@ -398,7 +398,7 @@ test_kevent_socket_eof_clear(struct test_context *ctx) void test_kevent_socket_eof(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; uint8_t buff[1024]; kevent_add_with_receipt(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD, 0, 0, &ctx->client_fd); @@ -408,12 +408,12 @@ test_kevent_socket_eof(struct test_context *ctx) die("close(2)"); kev.flags |= EV_EOF; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); /* Will repeatedly return EOF */ - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); /* * The kqueue man page on FreeBSD states that EV_CLEAR @@ -430,8 +430,8 @@ test_kevent_socket_eof(struct test_context *ctx) kev.flags |= EV_EOF; kev.flags ^= EV_CLEAR; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); close(ctx->client_fd); close(ctx->listen_fd); @@ -444,7 +444,7 @@ test_kevent_socket_eof(struct test_context *ctx) void test_kevent_regular_file(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; off_t curpos; int fd; @@ -454,22 +454,22 @@ test_kevent_regular_file(struct test_context *ctx) EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, &fd); kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); - kevent_get(&ret, ctx->kqfd, 1); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); /* Set file position to EOF-1 */ - ret.data--; - if ((curpos = lseek(fd, ret.data, SEEK_SET)) != ret.data) { + ret->data--; + if ((curpos = lseek(fd, ret->data, SEEK_SET)) != ret->data) { printf("seek to %u failed with rv=%lu\n", - (unsigned int) ret.data, (unsigned long) curpos); + (unsigned int) ret->data, (unsigned long) curpos); abort(); } /* Set file position to EOF */ - kevent_get(NULL, ctx->kqfd, 1); - ret.data = curpos + 1; - if ((curpos = lseek(fd, ret.data, SEEK_SET)) != ret.data) { + kevent_get(NULL, 0, ctx->kqfd, 1); + ret->data = curpos + 1; + if ((curpos = lseek(fd, ret->data, SEEK_SET)) != ret->data) { printf("seek to %u failed with rv=%lu\n", - (unsigned int) ret.data, (unsigned long) curpos); + (unsigned int) ret->data, (unsigned long) curpos); abort(); } @@ -485,7 +485,7 @@ test_kevent_regular_file(struct test_context *ctx) void test_transition_from_write_to_read(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; int kqfd; int sd[2]; diff --git a/vendor/libkqueue/test/signal.c b/vendor/libkqueue/test/signal.c index c88d726b0..837173942 100644 --- a/vendor/libkqueue/test/signal.c +++ b/vendor/libkqueue/test/signal.c @@ -27,7 +27,7 @@ test_kevent_signal_add(struct test_context *ctx) void test_kevent_signal_get(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); @@ -36,14 +36,14 @@ test_kevent_signal_get(struct test_context *ctx) kev.flags |= EV_CLEAR; kev.data = 1; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); } void test_kevent_signal_get_pending(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; /* A pending signal should be reported as soon as the event is added */ if (kill(getpid(), SIGUSR1) < 0) @@ -53,8 +53,8 @@ test_kevent_signal_get_pending(struct test_context *ctx) kev.flags |= EV_CLEAR; kev.data = 1; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); } void @@ -73,7 +73,7 @@ test_kevent_signal_disable(struct test_context *ctx) void test_kevent_signal_enable(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL); @@ -86,8 +86,8 @@ test_kevent_signal_enable(struct test_context *ctx) #else kev.data = 2; // one extra time from test_kevent_signal_disable() #endif - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); /* Delete the watch */ kev.flags = EV_DELETE; @@ -112,7 +112,7 @@ test_kevent_signal_del(struct test_context *ctx) void test_kevent_signal_oneshot(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL); @@ -121,8 +121,8 @@ test_kevent_signal_oneshot(struct test_context *ctx) kev.flags |= EV_CLEAR; kev.data = 1; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); /* Send another one and make sure we get no events */ test_no_kevents(ctx->kqfd); @@ -134,7 +134,7 @@ test_kevent_signal_oneshot(struct test_context *ctx) void test_kevent_signal_modify(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, ((void *)-1)); @@ -144,8 +144,8 @@ test_kevent_signal_modify(struct test_context *ctx) kev.flags |= EV_CLEAR; kev.data = 1; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); test_kevent_signal_del(ctx); } @@ -154,7 +154,7 @@ test_kevent_signal_modify(struct test_context *ctx) void test_kevent_signal_dispatch(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; test_no_kevents(ctx->kqfd); @@ -166,8 +166,8 @@ test_kevent_signal_dispatch(struct test_context *ctx) die("kill"); kev.flags |= EV_CLEAR; kev.data = 1; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); /* Generate a pending signal, this should get delivered once the filter is enabled again */ if (kill(getpid(), SIGUSR1) < 0) @@ -181,8 +181,8 @@ test_kevent_signal_dispatch(struct test_context *ctx) kev.flags |= EV_ADD; kev.flags |= EV_CLEAR; kev.data = 1; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); /* Remove the knote and ensure the event no longer fires */ kevent_add(ctx->kqfd, &kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL); diff --git a/vendor/libkqueue/test/timer.c b/vendor/libkqueue/test/timer.c index e98c6467e..894cf145c 100644 --- a/vendor/libkqueue/test/timer.c +++ b/vendor/libkqueue/test/timer.c @@ -37,14 +37,14 @@ test_kevent_timer_del(struct test_context *ctx) void test_kevent_timer_get(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; kevent_add(ctx->kqfd, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL); kev.flags |= EV_CLEAR; kev.data = 1; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); kevent_add(ctx->kqfd, &kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); } @@ -52,7 +52,7 @@ test_kevent_timer_get(struct test_context *ctx) static void test_kevent_timer_oneshot(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; test_no_kevents(ctx->kqfd); @@ -61,8 +61,8 @@ test_kevent_timer_oneshot(struct test_context *ctx) /* Retrieve the event */ kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT; kev.data = 1; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); /* Check if the event occurs again */ sleep(3); @@ -72,7 +72,7 @@ test_kevent_timer_oneshot(struct test_context *ctx) static void test_kevent_timer_periodic(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; test_no_kevents(ctx->kqfd); @@ -81,13 +81,13 @@ test_kevent_timer_periodic(struct test_context *ctx) /* Retrieve the event */ kev.flags = EV_ADD | EV_CLEAR; kev.data = 1; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); /* Check if the event occurs again */ sleep(1); - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); /* Delete the event */ kev.flags = EV_DELETE; @@ -97,7 +97,7 @@ test_kevent_timer_periodic(struct test_context *ctx) static void test_kevent_timer_disable_and_enable(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; test_no_kevents(ctx->kqfd); @@ -113,15 +113,15 @@ test_kevent_timer_disable_and_enable(struct test_context *ctx) kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT; kev.data = 1; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); } #ifdef EV_DISPATCH void test_kevent_timer_dispatch(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; test_no_kevents(ctx->kqfd); @@ -130,8 +130,8 @@ test_kevent_timer_dispatch(struct test_context *ctx) /* Get one event */ kev.flags = EV_ADD | EV_CLEAR | EV_DISPATCH; kev.data = 1; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); /* Confirm that the knote is disabled due to EV_DISPATCH */ usleep(500000); /* 500 ms */ @@ -156,8 +156,8 @@ test_kevent_timer_dispatch(struct test_context *ctx) usleep(1100000); /* 1100 ms */ kev.flags = EV_ADD | EV_CLEAR | EV_DISPATCH; kev.data = 5; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); #endif /* Remove the knote and ensure the event no longer fires */ diff --git a/vendor/libkqueue/test/user.c b/vendor/libkqueue/test/user.c index 8ee77edde..ee448f6cd 100644 --- a/vendor/libkqueue/test/user.c +++ b/vendor/libkqueue/test/user.c @@ -31,7 +31,7 @@ test_kevent_user_add_and_delete(struct test_context *ctx) static void test_kevent_user_get(struct test_context *ctx) { - struct kevent kev, tmp, ret; + struct kevent kev, tmp, ret[1]; test_no_kevents(ctx->kqfd); @@ -41,8 +41,8 @@ test_kevent_user_get(struct test_context *ctx) kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); test_no_kevents(ctx->kqfd); } @@ -50,7 +50,7 @@ test_kevent_user_get(struct test_context *ctx) static void test_kevent_user_get_hires(struct test_context *ctx) { - struct kevent kev, tmp, ret; + struct kevent kev, tmp, ret[1]; struct timespec timeo = { .tv_sec = 0, .tv_nsec = 500000 @@ -64,8 +64,8 @@ test_kevent_user_get_hires(struct test_context *ctx) kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; - kevent_get_hires(&ret, ctx->kqfd, &timeo); - kevent_cmp(&kev, &ret); + kevent_get_hires(ret, NUM_ELEMENTS(ret), ctx->kqfd, &timeo); + kevent_cmp(&kev, ret); test_no_kevents(ctx->kqfd); } @@ -73,7 +73,7 @@ test_kevent_user_get_hires(struct test_context *ctx) static void test_kevent_user_disable_and_enable(struct test_context *ctx) { - struct kevent kev, tmp, ret; + struct kevent kev, tmp, ret[1]; test_no_kevents(ctx->kqfd); @@ -91,14 +91,14 @@ test_kevent_user_disable_and_enable(struct test_context *ctx) kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); } static void test_kevent_user_oneshot(struct test_context *ctx) { - struct kevent kev, tmp, ret; + struct kevent kev, tmp, ret[1]; test_no_kevents(ctx->kqfd); @@ -107,8 +107,8 @@ test_kevent_user_oneshot(struct test_context *ctx) kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); test_no_kevents(ctx->kqfd); } @@ -116,7 +116,7 @@ test_kevent_user_oneshot(struct test_context *ctx) static void test_kevent_user_multi_trigger_merged(struct test_context *ctx) { - struct kevent kev, tmp, ret; + struct kevent kev, tmp, ret[1]; int i; test_no_kevents(ctx->kqfd); @@ -128,8 +128,8 @@ test_kevent_user_multi_trigger_merged(struct test_context *ctx) kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); test_no_kevents(ctx->kqfd); } @@ -138,7 +138,7 @@ test_kevent_user_multi_trigger_merged(struct test_context *ctx) void test_kevent_user_dispatch(struct test_context *ctx) { - struct kevent kev, tmp, ret; + struct kevent kev, tmp, ret[1]; test_no_kevents(ctx->kqfd); @@ -151,8 +151,8 @@ test_kevent_user_dispatch(struct test_context *ctx) kev.fflags &= ~NOTE_TRIGGER; kev.flags ^= EV_DISPATCH; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); /* Confirm that the knote is disabled automatically */ test_no_kevents(ctx->kqfd); @@ -166,8 +166,8 @@ test_kevent_user_dispatch(struct test_context *ctx) kevent_add(ctx->kqfd, &tmp, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); kev.fflags &= ~NOTE_FFCTRLMASK; kev.fflags &= ~NOTE_TRIGGER; - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); test_no_kevents(ctx->kqfd); /* Delete the watch */ diff --git a/vendor/libkqueue/test/vnode.c b/vendor/libkqueue/test/vnode.c index 4e7f7d43f..2786a9217 100644 --- a/vendor/libkqueue/test/vnode.c +++ b/vendor/libkqueue/test/vnode.c @@ -85,14 +85,14 @@ test_kevent_vnode_add(struct test_context *ctx) void test_kevent_vnode_note_delete(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; kevent_add(ctx->kqfd, &kev, ctx->vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, NULL); if (unlink(ctx->testfile) < 0) die("unlink"); - kevent_get(&ret, ctx->kqfd, 1); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); /* * FIXME - macOS 11.5.2 also sets NOTE_LINK. @@ -104,13 +104,13 @@ test_kevent_vnode_note_delete(struct test_context *ctx) kev.fflags |= NOTE_LINK; #endif - kevent_cmp(&kev, &ret); + kevent_cmp(&kev, ret); } void test_kevent_vnode_note_write(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; kevent_add(ctx->kqfd, &kev, ctx->vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_WRITE, 0, NULL); @@ -123,8 +123,8 @@ test_kevent_vnode_note_write(struct test_context *ctx) #ifndef __APPLE__ kev.fflags |= NOTE_EXTEND; #endif - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); } void @@ -205,7 +205,7 @@ test_kevent_vnode_disable_and_enable(struct test_context *ctx) void test_kevent_vnode_dispatch(struct test_context *ctx) { - struct kevent kev, ret; + struct kevent kev, ret[1]; test_no_kevents(ctx->kqfd); @@ -230,8 +230,8 @@ test_kevent_vnode_dispatch(struct test_context *ctx) kev.flags = EV_ADD | EV_DISPATCH; /* FIXME: may not be portable */ kev.fflags = NOTE_ATTRIB; testfile_touch(ctx->testfile); - kevent_get(&ret, ctx->kqfd, 1); - kevent_cmp(&kev, &ret); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); test_no_kevents(ctx->kqfd); /* Delete the watch */ From 0be56be41e2c4d3094ea68a42f4313d8ddffdec7 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 13 Sep 2021 10:44:40 -0500 Subject: [PATCH 0934/1120] Display the correct number of ready events --- vendor/libkqueue/src/linux/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 4c9ffef15..b5df7e482 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -652,7 +652,7 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven struct kevent *el_p = el, *el_end = el + nevents; int i; - dbg_printf("got %i events from epoll", nevents); + dbg_printf("got %i events from epoll", nready); for (i = 0; i < nready; i++) { struct epoll_event *ev = &epoll_events[i]; /* Thread local storage populated in linux_kevent_wait */ From d81d8da72ad15f8fe01b796443b09addcbb366f0 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 13 Sep 2021 11:35:45 -0500 Subject: [PATCH 0935/1120] Add more EOF tests --- vendor/libkqueue/test/proc.c | 8 +-- vendor/libkqueue/test/read.c | 116 ++++++++++++++++++++++++++++++++++- 2 files changed, 117 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/test/proc.c b/vendor/libkqueue/test/proc.c index 982db2b4d..046ec9d4e 100644 --- a/vendor/libkqueue/test/proc.c +++ b/vendor/libkqueue/test/proc.c @@ -51,7 +51,7 @@ test_kevent_proc_delete(struct test_context *ctx) static void test_kevent_proc_get(struct test_context *ctx) { - struct kevent kev, buf[1]; + struct kevent kev, buf[2]; int fflags; /* @@ -94,7 +94,7 @@ test_kevent_proc_get(struct test_context *ctx) static void test_kevent_proc_exit_status_ok(struct test_context *ctx) { - struct kevent kev, buf[1]; + struct kevent kev, buf[2]; int fflags; /* @@ -133,7 +133,7 @@ test_kevent_proc_exit_status_ok(struct test_context *ctx) static void test_kevent_proc_exit_status_error(struct test_context *ctx) { - struct kevent kev, buf[1]; + struct kevent kev, buf[2]; int fflags; /* @@ -172,7 +172,7 @@ test_kevent_proc_exit_status_error(struct test_context *ctx) static void test_kevent_proc_multiple_kqueue(struct test_context *ctx) { - struct kevent kev, buf_a[1], buf_b[1]; + struct kevent kev, buf_a[2], buf_b[2]; int fflags; int kq_b; diff --git a/vendor/libkqueue/test/read.c b/vendor/libkqueue/test/read.c index 0bca69adf..b93b63e5e 100644 --- a/vendor/libkqueue/test/read.c +++ b/vendor/libkqueue/test/read.c @@ -375,7 +375,7 @@ test_kevent_socket_eof_clear(struct test_context *ctx) test_no_kevents(ctx->kqfd); if (shutdown(ctx->server_fd, SHUT_RDWR) < 0) - die("close(2)"); + die("shutdown(2)"); if (close(ctx->server_fd) < 0) die("close(2)"); @@ -395,17 +395,21 @@ test_kevent_socket_eof_clear(struct test_context *ctx) create_socket_connection(&ctx->client_fd, &ctx->server_fd, &ctx->listen_fd); } +/* + * Different from the pipe eof test, as we get EPOLLRDHUP with EPOLLIN on close + * on Linux. + */ void test_kevent_socket_eof(struct test_context *ctx) { - struct kevent kev, ret[1]; + struct kevent kev, ret[10]; uint8_t buff[1024]; kevent_add_with_receipt(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_ADD, 0, 0, &ctx->client_fd); test_no_kevents(ctx->kqfd); if (shutdown(ctx->server_fd, SHUT_RDWR) < 0) - die("close(2)"); + die("shutdown(2)"); kev.flags |= EV_EOF; kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); @@ -433,13 +437,117 @@ test_kevent_socket_eof(struct test_context *ctx) kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); kevent_cmp(&kev, ret); + kevent_add(ctx->kqfd, &kev, ctx->client_fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); + close(ctx->client_fd); + close(ctx->server_fd); close(ctx->listen_fd); /* Recreate the socket pair */ create_socket_connection(&ctx->client_fd, &ctx->server_fd, &ctx->listen_fd); } +/* + * Different from the socket eof test, as we get EPOLLHUP with no EPOLLIN on close + * on Linux. + */ +void +test_kevent_pipe_eof(struct test_context *ctx) +{ + struct kevent kev, ret[256]; + int pipefd[2]; + uint8_t buff[1024]; + + if (pipe(pipefd) < 0) + die("pipe(2)"); + + kevent_add_with_receipt(ctx->kqfd, &kev, pipefd[0], EVFILT_READ, EV_ADD, 0, 0, &pipefd[0]); + test_no_kevents(ctx->kqfd); + + if (close(pipefd[1]) < 0) + die("close(2)"); + + kev.flags |= EV_EOF; + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); + + /* Will repeatedly return EOF */ + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); + + /* + * The kqueue man page on FreeBSD states that EV_CLEAR + * can be used to clear EOF, but in practice this appears + * to do nothing with sockets... + * + * Additionally setting EV_CLEAR on a socket after it's + * been added does nothing, even though kqueue returns + * the flag with EV_RECEIPT. + */ + kevent_add(ctx->kqfd, &kev, pipefd[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &pipefd[0]); + + kev.flags |= EV_RECEIPT; + kev.flags |= EV_EOF; + kev.flags ^= EV_CLEAR; + + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); + + kevent_add(ctx->kqfd, &kev, pipefd[0], EVFILT_READ, EV_DELETE, 0, 0, NULL); + + close(pipefd[0]); + close(pipefd[1]); +} + +void +test_kevent_pipe_eof_multi(struct test_context *ctx) +{ + struct kevent kev, ret[256]; + int pipefd_a[2], pipefd_b[2]; + uint8_t buff[1024]; + + if (pipe(pipefd_a) < 0) + die("pipe(2)"); + + if (pipe(pipefd_b) < 0) + die("pipe(2)"); + + kevent_add_with_receipt(ctx->kqfd, &kev, pipefd_a[0], EVFILT_READ, EV_ADD, 0, 0, &pipefd_a[0]); + kevent_add_with_receipt(ctx->kqfd, &kev, pipefd_b[0], EVFILT_READ, EV_ADD, 0, 0, &pipefd_b[0]); + test_no_kevents(ctx->kqfd); + + if (close(pipefd_a[1]) < 0) + die("close(2)"); + if (close(pipefd_b[1]) < 0) + die("close(2)"); + + kev.flags |= EV_EOF; + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 2); + + kev.ident = ret[0].ident; + kevent_cmp(&kev, &ret[0]); + + kev.ident = ret[1].ident; + kevent_cmp(&kev, &ret[1]); + + /* Will repeatedly return EOF */ + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 2); + + kev.ident = ret[0].ident; + kevent_cmp(&kev, &ret[0]); + + kev.ident = ret[1].ident; + kevent_cmp(&kev, &ret[1]); + + kevent_add(ctx->kqfd, &kev, pipefd_a[0], EVFILT_READ, EV_DELETE, 0, 0, NULL); + kevent_add(ctx->kqfd, &kev, pipefd_b[0], EVFILT_READ, EV_DELETE, 0, 0, NULL); + + close(pipefd_a[0]); + close(pipefd_a[1]); + close(pipefd_b[0]); + close(pipefd_b[1]); +} + /* Test if EVFILT_READ works with regular files */ void test_kevent_regular_file(struct test_context *ctx) @@ -525,6 +633,8 @@ test_evfilt_read(struct test_context *ctx) test(kevent_socket_listen_backlog, ctx); test(kevent_socket_eof_clear, ctx); test(kevent_socket_eof, ctx); + test(kevent_pipe_eof, ctx); + test(kevent_pipe_eof_multi, ctx); test(kevent_regular_file, ctx); close(ctx->client_fd); close(ctx->server_fd); From 1ce076b70fb0b8eaf77d40c5980f3928476691c8 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 13 Sep 2021 11:41:29 -0500 Subject: [PATCH 0936/1120] linux/platform: Use macro from retrieving filter add additional debugging --- vendor/libkqueue/src/linux/platform.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index b5df7e482..78a74eb60 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -525,6 +525,8 @@ static inline int linux_kevent_copyout_ev(struct kevent *el, int nevents, struct int rv; rv = filt->kf_copyout(el, nevents, filt, kn, ev); + dbg_printf("rv=%i", rv); + if (unlikely(rv < 0)) { dbg_puts("knote_copyout failed"); assert(0); @@ -686,7 +688,7 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven goto done; } - rv = linux_kevent_copyout_ev(el_p, (el_end - el_p), ev, &kq->kq_filt[~(kn->kev.filter)], kn); + rv = linux_kevent_copyout_ev(el_p, (el_end - el_p), ev, knote_get_filter(kn), kn); if (rv < 0) goto done; el_p += rv; } @@ -708,7 +710,7 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven if ((kn = fds->fds_read) && (ev->events & (EPOLLIN | EPOLLHUP | EPOLLRDHUP | EPOLLERR))) { if (el_p >= el_end) goto oos; - rv = linux_kevent_copyout_ev(el_p, (el_end - el_p), ev, &kq->kq_filt[~(kn->kev.filter)], kn); + rv = linux_kevent_copyout_ev(el_p, (el_end - el_p), ev, knote_get_filter(kn), kn); if (rv < 0) goto done; el_p += rv; } @@ -719,7 +721,7 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven if ((kn = fds->fds_write) && (ev->events & (EPOLLOUT | POLLHUP | EPOLLERR))) { if (el_p >= el_end) goto oos; - rv = linux_kevent_copyout_ev(el_p, (el_end - el_p), ev, &kq->kq_filt[~(kn->kev.filter)], kn); + rv = linux_kevent_copyout_ev(el_p, (el_end - el_p), ev, knote_get_filter(kn), kn); if (rv < 0) goto done; el_p += rv; } From 9415c892b1ad643d4e14d5e699797cc9700bbd0f Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 13 Sep 2021 11:52:37 -0500 Subject: [PATCH 0937/1120] posix/proc: Return the correct number of events Remove knotes from the readylist once they've been copied out --- vendor/libkqueue/src/posix/proc.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 33a037753..bee443758 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -455,7 +455,7 @@ evfilt_proc_knote_copyout(struct kevent *dst, int nevents, struct filter *filt, struct knote *kn, void *ev) { struct knote *tmp; - int events = 0; + struct kevent *dst_p = dst, *dst_end = dst_p + nevents; /* * Prevent the waiter thread from modifying @@ -469,21 +469,23 @@ evfilt_proc_knote_copyout(struct kevent *dst, int nevents, struct filter *filt, * for the loop. */ LIST_FOREACH_SAFE(kn, &filt->kf_ready, kn_ready, tmp) { - if (++events > nevents) + if (dst_p >= dst_end) break; kevent_dump(&kn->kev); - memcpy(dst, &kn->kev, sizeof(*dst)); - dst->fflags = NOTE_EXIT; - dst->flags |= EV_EOF; - dst->data = kn->kn_proc_status; + memcpy(dst_p, &kn->kev, sizeof(*dst)); + dst_p->fflags = NOTE_EXIT; + dst_p->flags |= EV_EOF; + dst_p->data = kn->kn_proc_status; if (knote_copyout_flag_actions(filt, kn) < 0) { pthread_mutex_unlock(&filt->kf_knote_mtx); return -1; } - dst++; + LIST_REMOVE(kn, kn_ready); /* do this last */ + + dst_p++; } if (LIST_EMPTY(&filt->kf_ready)) @@ -491,7 +493,7 @@ evfilt_proc_knote_copyout(struct kevent *dst, int nevents, struct filter *filt, pthread_mutex_unlock(&filt->kf_knote_mtx); - return (nevents); + return (dst_p - dst); } const struct filter evfilt_proc = { From e470ae51f647477689a057a2485f1aaf248a254f Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 13 Sep 2021 12:20:47 -0500 Subject: [PATCH 0938/1120] posix/proc: Fix knote remove/free order --- vendor/libkqueue/src/common/private.h | 4 ++-- vendor/libkqueue/src/posix/proc.c | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 99bd12180..072eedcd7 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -617,9 +617,9 @@ static inline int knote_copyout_flag_actions(struct filter *filt, struct knote * */ if (kn->kev.flags & EV_DISPATCH) rv = knote_disable(filt, kn); - if (kn->kev.flags & EV_ONESHOT) { + + if (kn->kev.flags & EV_ONESHOT) rv = knote_delete(filt, kn); - } return rv; } diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index bee443758..9514a701f 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -454,7 +454,6 @@ static int evfilt_proc_knote_copyout(struct kevent *dst, int nevents, struct filter *filt, struct knote *kn, void *ev) { - struct knote *tmp; struct kevent *dst_p = dst, *dst_end = dst_p + nevents; /* @@ -464,11 +463,13 @@ evfilt_proc_knote_copyout(struct kevent *dst, int nevents, struct filter *filt, */ pthread_mutex_lock(&filt->kf_knote_mtx); + assert(!LIST_EMPTY(&filt->kf_ready)); + /* * kn arg is always NULL here, so we just reuse it * for the loop. */ - LIST_FOREACH_SAFE(kn, &filt->kf_ready, kn_ready, tmp) { + while ((kn = LIST_FIRST(&filt->kf_ready))) { if (dst_p >= dst_end) break; @@ -478,13 +479,14 @@ evfilt_proc_knote_copyout(struct kevent *dst, int nevents, struct filter *filt, dst_p->flags |= EV_EOF; dst_p->data = kn->kn_proc_status; + LIST_REMOVE(kn, kn_ready); /* knote_copyout_flag_actions may free the knote */ + if (knote_copyout_flag_actions(filt, kn) < 0) { + LIST_INSERT_HEAD(&filt->kf_ready, kn, kn_ready); pthread_mutex_unlock(&filt->kf_knote_mtx); return -1; } - LIST_REMOVE(kn, kn_ready); /* do this last */ - dst_p++; } From ec5cde777cb7548ecbf7146f032fd59c88c01f57 Mon Sep 17 00:00:00 2001 From: David Miller Date: Mon, 13 Sep 2021 15:36:58 -0400 Subject: [PATCH 0939/1120] Fix macro param typo --- vendor/libkqueue/src/windows/platform.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 6e95ccf07..aef6c96e5 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -49,7 +49,7 @@ #define atomic_dec(value) InterlockedDecrement((LONG volatile *)value) #define atomic_cas(p, oval, nval) (InterlockedCompareExchange(p, nval, oval) == oval) #define atomic_ptr_cas(p, oval, nval) (InterlockedCompareExchangePointer(p, nval, oval) == oval) -#define atomic_ptr_swap(p, oval) InterlockedExchangePointer(p, nval) +#define atomic_ptr_swap(p, oval) InterlockedExchangePointer(p, oval) #define atomic_ptr_load(p) (*p) From f0282aa80e37bc9b394e281abf722895630b94b5 Mon Sep 17 00:00:00 2001 From: David Miller Date: Mon, 13 Sep 2021 15:40:39 -0400 Subject: [PATCH 0940/1120] Change configure path of libkqueue.pc for embedding --- vendor/libkqueue/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index d7eb197b0..0c085463b 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -245,8 +245,8 @@ if(ENABLE_TESTING) add_subdirectory(test) endif() -configure_file("${CMAKE_SOURCE_DIR}/libkqueue.pc.in" - "${CMAKE_BINARY_DIR}/libkqueue.pc" +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/libkqueue.pc.in" + "${CMAKE_CURRENT_BINARY_DIR}/libkqueue.pc" @ONLY) # From 76f4355a9354e7450248e3732bdfefb1b1c3bd30 Mon Sep 17 00:00:00 2001 From: David Miller Date: Mon, 13 Sep 2021 16:03:22 -0400 Subject: [PATCH 0941/1120] update configure_file path likewise --- vendor/libkqueue/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 0c085463b..22a2a4ba7 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -34,8 +34,8 @@ execute_process(COMMAND git rev-parse --short=8 HEAD project(libkqueue VERSION ${PROJECT_VERSION} LANGUAGES C) -configure_file(include/sys/libkqueue_version.h.in - include/sys/libkqueue_version.h @ONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/sys/libkqueue_version.h.in + ${CMAKE_CURRENT_SOURCE_DIR}/include/sys/libkqueue_version.h @ONLY) enable_testing() From acd252b6cafd68ccc7446c08a4145eb20b0e1d5a Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 13 Sep 2021 20:04:40 -0500 Subject: [PATCH 0942/1120] Print out CMAKE_C_FLAGS_DEBUG --- vendor/libkqueue/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 22a2a4ba7..54c5d0f40 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -102,6 +102,8 @@ if(DEBUG_FSANITIZERFLAGS) string (REPLACE ";" "," DEBUG_FSANITIZERFLAGS "${DEBUG_FSANITIZERFLAGS}") set(CMAKE_C_FLAGS_DEBUG "-fsanitize=${DEBUG_FSANITIZERFLAGS} ${CMAKE_C_FLAGS_DEBUG}") set(CMAKE_LD_FLAGS_DEBUG "-fsanitize=${DEBUG_FSANITIZERFLAGS} ${CMAKE_LD_FLAGS_DEBUG}") + MESSAGE("CMAKE_C_FLAGS_DEBUG are \"${CMAKE_C_FLAGS_DEBUG}\"") + MESSAGE("CMAKE_LD_FLAGS_DEBUG are \"${CMAKE_LD_FLAGS_DEBUG}\"") endif() option(STATIC_KQUEUE "build libkqueue as static library" OFF) From 1fb0e004c06ced846fa71c072e8f23681c77d381 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 13 Sep 2021 20:22:43 -0500 Subject: [PATCH 0943/1120] We need to allow build type to be cached otherwise the correct cflags aren't used Closes #114 --- vendor/libkqueue/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 54c5d0f40..c22a9857c 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -361,5 +361,3 @@ unset(ENABLE_ASAN CACHE) unset(ENABLE_LSAN CACHE) unset(ENABLE_UBSAN CACHE) unset(ENABLE_TSAN CACHE) -unset(ENABLE_TESTING CACHE) -unset(CMAKE_BUILD_TYPE CACHE) From a1f936f1c38bee7c3bb258a20ca7efe141821614 Mon Sep 17 00:00:00 2001 From: Matthew Newton Date: Mon, 11 Oct 2021 13:29:57 +0100 Subject: [PATCH 0944/1120] use correct output dir --- vendor/libkqueue/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index c22a9857c..cbb762679 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -35,7 +35,7 @@ execute_process(COMMAND git rev-parse --short=8 HEAD project(libkqueue VERSION ${PROJECT_VERSION} LANGUAGES C) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/sys/libkqueue_version.h.in - ${CMAKE_CURRENT_SOURCE_DIR}/include/sys/libkqueue_version.h @ONLY) + ${CMAKE_CURRENT_BINARY_DIR}/include/sys/libkqueue_version.h @ONLY) enable_testing() From 17d937d5b612aef435a11a977cc3106e30a78093 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 19 Oct 2021 13:44:49 -0500 Subject: [PATCH 0945/1120] posix/proc: Fix deadlock --- vendor/libkqueue/src/posix/proc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 9514a701f..d6186f1f1 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -270,6 +270,7 @@ wait_thread(UNUSED void *arg) switch (errno) { case ECHILD: dbg_printf("waitid(2): pid=%u reaped too early - %s", ppd->ppd_pid, strerror(errno)); + pthread_mutex_unlock(&proc_pid_index_mtx); continue; /* FIXME - Maybe produce an EV_ERROR for each of the knotes? */ case EINTR: From bf4a30323904b2f4885b06bc31b0493eb1614dcc Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 19 Oct 2021 14:00:34 -0500 Subject: [PATCH 0946/1120] Produce an error for each of the knotes --- vendor/libkqueue/src/posix/proc.c | 38 ++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index d6186f1f1..05b83870a 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -97,6 +97,32 @@ waiter_notify(struct proc_pid *ppd, int status) free(ppd); } +static void +waiter_notify_error(struct proc_pid *ppd, int wait_errno) +{ + struct knote *kn; + struct filter *filt; + + while ((kn = LIST_FIRST(&ppd->ppd_proc_waiters))) { + kn->kev.flags |= EV_ERROR; + kn->kev.data = wait_errno; + + filt = knote_get_filter(kn); + dbg_printf("pid=%u errored (%s), notifying kq=%u filter=%p kn=%p", + (unsigned int)ppd->ppd_pid, strerror(errno), kn->kn_kq->kq_id, filt, kn); + pthread_mutex_lock(&filt->kf_knote_mtx); + kqops.eventfd_raise(&filt->kf_proc_eventfd); + LIST_INSERT_HEAD(&filt->kf_ready, kn, kn_ready); + pthread_mutex_unlock(&filt->kf_knote_mtx); + + LIST_REMOVE(kn, kn_proc_waiter); + } + + dbg_printf("pid=%u removing waiter list", (unsigned int)ppd->ppd_pid); + RB_REMOVE(pid_index, &proc_pid_index, ppd); + free(ppd); +} + static int waiter_siginfo_to_status(siginfo_t *info) { @@ -270,8 +296,12 @@ wait_thread(UNUSED void *arg) switch (errno) { case ECHILD: dbg_printf("waitid(2): pid=%u reaped too early - %s", ppd->ppd_pid, strerror(errno)); + + waiter_notify_error(ppd, errno); + pthread_mutex_unlock(&proc_pid_index_mtx); - continue; /* FIXME - Maybe produce an EV_ERROR for each of the knotes? */ + + continue; case EINTR: goto again; @@ -370,6 +400,12 @@ evfilt_proc_knote_create(struct filter *filt, struct knote *kn) struct proc_pid *ppd; pthread_mutex_lock(&proc_pid_index_mtx); + /* + * Fixme - We should probably check to see if the PID exists + * here and error out early instead of waiting for the waiter + * loop to tell us. + */ + ppd = RB_FIND(pid_index, &proc_pid_index, &(struct proc_pid){ .ppd_pid = kn->kev.ident }); if (!ppd) { dbg_printf("pid=%u adding waiter list", (unsigned int)kn->kev.ident); From ca523a0601145580a4f5953de335ba2f89723beb Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 19 Oct 2021 14:33:29 -0500 Subject: [PATCH 0947/1120] Produce debug output when running tests --- vendor/libkqueue/.github/workflows/ci-linux.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/.github/workflows/ci-linux.yml b/vendor/libkqueue/.github/workflows/ci-linux.yml index be273d8e0..122f2fc34 100644 --- a/vendor/libkqueue/.github/workflows/ci-linux.yml +++ b/vendor/libkqueue/.github/workflows/ci-linux.yml @@ -87,6 +87,8 @@ jobs: run: make -j2 - name: Run tests + env: + KQUEUE_DEBUG: 1 run: test/libkqueue-test - name: Build debian packages From c6816d3ded11f6e73274c9793ea4a33e68136a23 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 21 Oct 2021 21:32:20 -0400 Subject: [PATCH 0948/1120] Set SOVERSION to 0 Closes #100 --- vendor/libkqueue/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index cbb762679..1b6e5d1dd 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -212,7 +212,10 @@ else() endif() add_library(kqueue ${LIBRARY_TYPE} ${LIBKQUEUE_SOURCES} ${LIBKQUEUE_HEADERS}) -set_target_properties(kqueue PROPERTIES SOVERSION ${PROJECT_VERSION}) + +# We should have absolute ABI compatibility between versions as none +# of the public function signatures of variables will change. +set_target_properties(kqueue PROPERTIES SOVERSION 0) if(WIN32) target_compile_definitions(kqueue PRIVATE _USRDLL;_WINDLL) From aaa7a89e944817700fe1d023754a78d7cec98bdc Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 21 Oct 2021 21:32:52 -0400 Subject: [PATCH 0949/1120] For git builds set the release version --- vendor/libkqueue/CMakeLists.txt | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 1b6e5d1dd..4bfdbf393 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -14,7 +14,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -set(PROJECT_VERSION 2.5.1) +set(PROJECT_VERSION 2.5.2) if(EXISTS "/etc/debian_version") cmake_minimum_required(VERSION 3.7.2) @@ -32,6 +32,19 @@ execute_process(COMMAND git rev-parse --short=8 HEAD OUTPUT_VARIABLE LIBKQUEUE_VERSION_COMMIT OUTPUT_STRIP_TRAILING_WHITESPACE) +execute_process(COMMAND sh -c "git describe --tags --match 'v*' | grep '-' | cut -d- -f2" + OUTPUT_VARIABLE PROJECT_VERSION_RELEASE + OUTPUT_STRIP_TRAILING_WHITESPACE) + +if(PROJECT_VERSION_RELEASE STREQUAL "") + MESSAGE("Version ${PROJECT_VERSION} (${LIBKQUEUE_VERSION_COMMIT})") + unset(PROJECT_VERSION_RELEASE) +else() + # Release 1 is the default, so we need to start at release 2 + MATH(EXPR PROJECT_VERSION_RELEASE "${PROJECT_VERSION_RELEASE}+1") + MESSAGE("Version ${PROJECT_VERSION}-${PROJECT_VERSION_RELEASE} (${LIBKQUEUE_VERSION_COMMIT})") +endif() + project(libkqueue VERSION ${PROJECT_VERSION} LANGUAGES C) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/sys/libkqueue_version.h.in @@ -288,7 +301,6 @@ set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) -set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Mark Heily ") # Specify the location of source files to be installed by the debuginfo package set(CPACK_BUILD_SOURCE_DIRS ${CMAKE_SOURCE_DIR}/src) @@ -334,6 +346,10 @@ set(CPACK_RPM_MAIN_DEBUGINFO_PACKAGE ON) set(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE ON) set(CPACK_RPM_MAIN_BUILD_SOURCE_DIRS_PREFIX /usr/src/debug/${PROJECT_NAME}-${PROJECT_VERSION}) +if (PROJECT_VERSION_RELEASE) +set(CPACK_RPM_PACKAGE_RELEASE ${PROJECT_VERSION_RELEASE}) +endif() + # # DEB Specific configuration # @@ -349,6 +365,11 @@ set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) # Use default Debian package nam set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON) +if (PROJECT_VERSION_RELEASE) +set(CPACK_DEBIAN_PACKAGE_RELEASE ${PROJECT_VERSION_RELEASE}) +endif() + +set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Mark Heily ") include(CPack) add_custom_target(tarball git archive -o "libkqueue-${PROJECT_VERSION}.tar.gz" --prefix "libkqueue-${PROJECT_VERSION}/" HEAD) From e02aecbd54f02b0aef0b6149c97f1d64bb27d521 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sun, 24 Oct 2021 10:26:34 -0400 Subject: [PATCH 0950/1120] Set the library search path in libkqueue.pc Closes #117 --- vendor/libkqueue/ChangeLog | 3 ++- vendor/libkqueue/libkqueue.pc.in | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 419166141..d690d7f09 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,7 +1,8 @@ Unreleased ------------------------------------------------------------------------ -Nothing here yet. + * Fix: Set the library search path in libkqueue.pc (Closes #117) + (Reported by: Grant Erickson) 000-00-00 v2.5.1 ------------------------------------------------------------------------ diff --git a/vendor/libkqueue/libkqueue.pc.in b/vendor/libkqueue/libkqueue.pc.in index f633f1fcc..534d57910 100644 --- a/vendor/libkqueue/libkqueue.pc.in +++ b/vendor/libkqueue/libkqueue.pc.in @@ -7,6 +7,6 @@ Name: libkqueue Description: Emulates FreeBSD kqueue(2) on other platforms Version: @PROJECT_VERSION@ Requires: -Libs: -lkqueue +Libs: -L${libdir} -lkqueue Libs.private: -lpthread -lrt Cflags: -I${includedir}/kqueue From 29377433abfb59936e989d2dfc37e3edd37ba9c6 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 24 Oct 2021 11:33:57 -0400 Subject: [PATCH 0951/1120] Implement evfilt_timer_knote_modify for Linux Fixes #116 --- vendor/libkqueue/src/linux/timer.c | 22 ++++++++-- vendor/libkqueue/test/common.c | 9 ++++ vendor/libkqueue/test/common.h | 1 + vendor/libkqueue/test/timer.c | 68 +++++++++++++++++++++++++++++- 4 files changed, 94 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 05497d323..cfec2c8f6 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -202,10 +202,24 @@ int evfilt_timer_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) { - (void)filt; - (void)kn; - (void)kev; - return (0); /* STUB */ + struct itimerspec ts; + int flags; + + dbg_printf("timer_fd=%i - modified", kn->kn_timerfd); + + convert_timedata_to_itimerspec(&ts, kev->data, kev->fflags, + kev->flags & EV_ONESHOT); + flags = (kev->fflags & NOTE_ABSOLUTE) ? TFD_TIMER_ABSTIME : 0; + if (timerfd_settime(kn->kn_timerfd, flags, &ts, NULL) < 0) { + dbg_printf("timerfd_settime(2): %s", strerror(errno)); + return (-1); + } + + kn->kev.fflags = kev->fflags; + kn->kev.flags = kev->flags; + kn->kev.data = kev->data; + + return (0); } int diff --git a/vendor/libkqueue/test/common.c b/vendor/libkqueue/test/common.c index 0107de9cf..17876f65f 100644 --- a/vendor/libkqueue/test/common.c +++ b/vendor/libkqueue/test/common.c @@ -243,6 +243,15 @@ kevent_update(int kqfd, struct kevent *kev) } } +void +kevent_update_expect_fail(int kqfd, struct kevent *kev) +{ + if (kevent(kqfd, kev, 1, NULL, 0, NULL) >= 0) { + printf("Performing update should fail"); + die("kevent"); + } +} + void kevent_add(int kqfd, struct kevent *kev, uintptr_t ident, diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index 04dafdba4..f875ba7a8 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -135,6 +135,7 @@ void kevent_get_hires(struct kevent kev[], int numevents, int kqfd, struct times int kevent_get_timeout(struct kevent kev[], int numevents, int kqfd, struct timespec *timeout); void kevent_update(int kqfd, struct kevent *kev); +void kevent_update_expect_fail(int kqfd, struct kevent *kev); #define kevent_cmp(a,b) _kevent_cmp(a,b, __FILE__, __LINE__) void _kevent_cmp(struct kevent *expected, struct kevent *got, const char *file, int line); diff --git a/vendor/libkqueue/test/timer.c b/vendor/libkqueue/test/timer.c index 894cf145c..add2ae46e 100644 --- a/vendor/libkqueue/test/timer.c +++ b/vendor/libkqueue/test/timer.c @@ -56,7 +56,7 @@ test_kevent_timer_oneshot(struct test_context *ctx) test_no_kevents(ctx->kqfd); - kevent_add(ctx->kqfd, &kev, 2, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 500,NULL); + kevent_add(ctx->kqfd, &kev, 2, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 500, NULL); /* Retrieve the event */ kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT; @@ -76,7 +76,7 @@ test_kevent_timer_periodic(struct test_context *ctx) test_no_kevents(ctx->kqfd); - kevent_add(ctx->kqfd, &kev, 3, EVFILT_TIMER, EV_ADD, 0, 1000,NULL); + kevent_add(ctx->kqfd, &kev, 3, EVFILT_TIMER, EV_ADD, 0, 1000, NULL); /* Retrieve the event */ kev.flags = EV_ADD | EV_CLEAR; @@ -94,6 +94,68 @@ test_kevent_timer_periodic(struct test_context *ctx) kevent_update(ctx->kqfd, &kev); } +static void +test_kevent_timer_periodic_modify(struct test_context *ctx) +{ + struct kevent kev, ret[1]; + + test_no_kevents(ctx->kqfd); + + kevent_add(ctx->kqfd, &kev, 3, EVFILT_TIMER, EV_ADD, 0, 1000, NULL); + + /* Retrieve the event */ + kev.flags = EV_ADD | EV_CLEAR; + kev.data = 1; + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); + + /* Check if the event occurs again */ + kevent_add(ctx->kqfd, &kev, 3, EVFILT_TIMER, EV_ADD, 0, 500, NULL); + sleep(1); + kev.data = 2; /* Should have fired twice */ + + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); + + /* Delete the event */ + kev.flags = EV_DELETE; + kevent_update(ctx->kqfd, &kev); +} + +static void +test_kevent_timer_periodic_to_oneshot(struct test_context *ctx) +{ + struct kevent kev, ret[1]; + + test_no_kevents(ctx->kqfd); + + kevent_add(ctx->kqfd, &kev, 3, EVFILT_TIMER, EV_ADD, 0, 1000, NULL); + + /* Retrieve the event */ + kev.flags = EV_ADD | EV_CLEAR; + kev.data = 1; + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); + + /* Check if the event occurs again */ + sleep(1); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); + + /* Switch to oneshot */ + kevent_add(ctx->kqfd, &kev, 3, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 500, NULL); + + sleep(1); + kev.data = 1; /* Should have fired one */ + + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + kevent_cmp(&kev, ret); + + /* Delete the event */ + kev.flags = EV_DELETE; + kevent_update_expect_fail(ctx->kqfd, &kev); +} + static void test_kevent_timer_disable_and_enable(struct test_context *ctx) { @@ -175,6 +237,8 @@ test_evfilt_timer(struct test_context *ctx) test(kevent_timer_get, ctx); test(kevent_timer_oneshot, ctx); test(kevent_timer_periodic, ctx); + test(kevent_timer_periodic_modify, ctx); + test(kevent_timer_periodic_to_oneshot, ctx); test(kevent_timer_disable_and_enable, ctx); #ifdef EV_DISPATCH test(kevent_timer_dispatch, ctx); From 2e43825870f4ca65cc7cf408c907c56c1c0d7311 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 24 Oct 2021 11:36:55 -0400 Subject: [PATCH 0952/1120] Fix up flags after modifying timer events --- vendor/libkqueue/test/timer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/test/timer.c b/vendor/libkqueue/test/timer.c index add2ae46e..e8aa832e9 100644 --- a/vendor/libkqueue/test/timer.c +++ b/vendor/libkqueue/test/timer.c @@ -111,6 +111,7 @@ test_kevent_timer_periodic_modify(struct test_context *ctx) /* Check if the event occurs again */ kevent_add(ctx->kqfd, &kev, 3, EVFILT_TIMER, EV_ADD, 0, 500, NULL); + kev.flags = EV_ADD | EV_CLEAR; sleep(1); kev.data = 2; /* Should have fired twice */ @@ -144,6 +145,7 @@ test_kevent_timer_periodic_to_oneshot(struct test_context *ctx) /* Switch to oneshot */ kevent_add(ctx->kqfd, &kev, 3, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 500, NULL); + kev.flags = EV_ADD | EV_CLEAR; sleep(1); kev.data = 1; /* Should have fired one */ From e506090068d38badb39338dbd1b00bf8d6dd2214 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 24 Oct 2021 11:54:31 -0400 Subject: [PATCH 0953/1120] Don't clear the clear flag when modifying timers --- vendor/libkqueue/src/linux/timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index cfec2c8f6..59514b5b6 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -215,8 +215,8 @@ evfilt_timer_knote_modify(struct filter *filt, struct knote *kn, return (-1); } + kn->kev.flags = kev->flags | EV_CLEAR; kn->kev.fflags = kev->fflags; - kn->kev.flags = kev->flags; kn->kev.data = kev->data; return (0); From be94e07e709826691215734b02bb0dfc339dca2a Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 24 Oct 2021 12:04:43 -0400 Subject: [PATCH 0954/1120] Disable test_kevent_timer_periodic_to_oneshot except for libkqueue --- vendor/libkqueue/test/timer.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/vendor/libkqueue/test/timer.c b/vendor/libkqueue/test/timer.c index e8aa832e9..fc4f78ede 100644 --- a/vendor/libkqueue/test/timer.c +++ b/vendor/libkqueue/test/timer.c @@ -123,6 +123,11 @@ test_kevent_timer_periodic_modify(struct test_context *ctx) kevent_update(ctx->kqfd, &kev); } +/* + * This appears to be a bug in the Linux/FreeBSD implementation where + * it won't allow you to modify an existing event to make it oneshot. + */ +#if WITH_NATIVE_KQUEUE_BUGS static void test_kevent_timer_periodic_to_oneshot(struct test_context *ctx) { @@ -157,6 +162,7 @@ test_kevent_timer_periodic_to_oneshot(struct test_context *ctx) kev.flags = EV_DELETE; kevent_update_expect_fail(ctx->kqfd, &kev); } +#endif static void test_kevent_timer_disable_and_enable(struct test_context *ctx) @@ -240,7 +246,9 @@ test_evfilt_timer(struct test_context *ctx) test(kevent_timer_oneshot, ctx); test(kevent_timer_periodic, ctx); test(kevent_timer_periodic_modify, ctx); +#if WITH_NATIVE_KQUEUE_BUGS test(kevent_timer_periodic_to_oneshot, ctx); +#endif test(kevent_timer_disable_and_enable, ctx); #ifdef EV_DISPATCH test(kevent_timer_dispatch, ctx); From 3d204d44af6d5d450bdd1e9128f249657d06d01c Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 24 Oct 2021 12:21:12 -0400 Subject: [PATCH 0955/1120] Notes on packaging changes, and other fixes. --- vendor/libkqueue/ChangeLog | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index d690d7f09..a01c91d3d 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,11 +1,18 @@ Unreleased ------------------------------------------------------------------------ + * Fix: Allow EVFILT_TIMER filters to be modified on Linux + (Closes #116) (Reported by: Grant Erickson). + * Fix: Set the library search path in libkqueue.pc (Closes #117) (Reported by: Grant Erickson) - -000-00-00 v2.5.1 ------------------------------------------------------------------------- + + * Fix: posix/proc will now no longer deadlock if the PID being + monitored is reaped outside of libkqueue, or has exited before + we start monitoring. + + * Fix: posix/proc all waiters will now be informed if monitoring + a PID fails, i.e. if the PID is reaped outside of libkqueue. * Fix: Compilation on Windows (Closes #111). (Reported by: brechtsanders) @@ -27,6 +34,12 @@ Unreleased * Fix: udata should not be modified if the knote modification fails. * Test suites now pass on macOS 11.5.2 and FreeBSD 13. + + * Packaging: We now set the release number if the current checked + out commit does not match a release tag. For example if the + current number of commits between the last release tag and HEAD + is 2, then the release will be `-3`. This allows easy upgrading + of packages between releases. 2021-09-06 v2.5.0 ------------------------------------------------------------------------ From c464d4973c8f0ece3e926ca3277fd69cf4bd87ae Mon Sep 17 00:00:00 2001 From: Grant Erickson Date: Sat, 30 Oct 2021 11:36:44 -0700 Subject: [PATCH 0956/1120] Added fflags for EVFILT_TIMER. --- vendor/libkqueue/src/common/kevent.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index a381bb245..12902f916 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -76,6 +76,13 @@ kevent_fflags_dump(const struct kevent *kev) KEVFFL_DUMP(NOTE_EXEC); break; + case EVFILT_TIMER: + KEVFFL_DUMP(NOTE_SECONDS); + KEVFFL_DUMP(NOTE_USECONDS); + KEVFFL_DUMP(NOTE_NSECONDS); + KEVFFL_DUMP(NOTE_ABSOLUTE); + break; + default: break; } From bb72c0041c83c43825619c3aa2009c07ca920e77 Mon Sep 17 00:00:00 2001 From: Grant Erickson Date: Sat, 30 Oct 2021 11:52:31 -0700 Subject: [PATCH 0957/1120] Correctly scale useconds to nseconds when NOTE_USECONDS is asserted in fflags. --- vendor/libkqueue/src/linux/timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 59514b5b6..3fb5a5873 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -93,7 +93,7 @@ convert_timedata_to_itimerspec(struct itimerspec *dst, long src, switch (flags & NOTE_TIMER_MASK) { case NOTE_USECONDS: sec = src / 1000000; - nsec = (src % 1000000); + nsec = (src % 1000000) * 1000; break; case NOTE_NSECONDS: From 2cb18a430d1d33e69c3b8effed243e686b1fb9d4 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Fri, 19 Nov 2021 12:04:01 -0300 Subject: [PATCH 0958/1120] Fix missing define --- vendor/libkqueue/src/common/private.h | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 072eedcd7..47053f2d8 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -99,6 +99,7 @@ struct evfilt_data; #define unlikely(x) (x) #define VISIBLE #define HIDDEN +#define UNUSED #define UNUSED_NDEBUG #endif From 07d2f58c2d5c56c3c63593ca74714e95b09f4815 Mon Sep 17 00:00:00 2001 From: Jorge Pereira Date: Fri, 19 Nov 2021 11:46:05 -0300 Subject: [PATCH 0959/1120] Add CI flow for Windows --- .../.github/workflows/ci-windows.yml | 28 +++++++++++++++++++ vendor/libkqueue/README.md | 1 + 2 files changed, 29 insertions(+) create mode 100644 vendor/libkqueue/.github/workflows/ci-windows.yml diff --git a/vendor/libkqueue/.github/workflows/ci-windows.yml b/vendor/libkqueue/.github/workflows/ci-windows.yml new file mode 100644 index 000000000..12396c483 --- /dev/null +++ b/vendor/libkqueue/.github/workflows/ci-windows.yml @@ -0,0 +1,28 @@ +name: CI Windows + +on: + push: + branches: + - master + pull_request: + +env: + KQUEUE_DEBUG: yes + +jobs: + windows-build: + runs-on: windows-2019 + name: CI-windows (build) + + steps: + - uses: actions/checkout@v2 + + - name: Configure build system + run: | + cmake --version + cmake -S . -B build_x64 -A x64 -G "Visual Studio 16 2019" -DSTATICLIB=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_VERBOSE_MAKEFILE=ON + + - name: Build libkqueue + run: | + cmake --build build_x64 --target install --config Release --parallel 1 + diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index f41401f63..9d6756fda 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -4,6 +4,7 @@ libkqueue [![CI Linux](https://github.com/mheily/libkqueue/actions/workflows/ci-linux.yml/badge.svg)](https://github.com/mheily/libkqueue/actions/workflows/ci-linux.yml) [![CI tests FreeBSD](https://github.com/mheily/libkqueue/actions/workflows/ci-freebsd.yml/badge.svg)](https://github.com/mheily/libkqueue/actions/workflows/ci-freebsd.yml) [![CI tests macOS](https://github.com/mheily/libkqueue/actions/workflows/ci-macos.yml/badge.svg)](https://github.com/mheily/libkqueue/actions/workflows/ci-macos.yml) +[![CI tests Windows](https://github.com/mheily/libkqueue/actions/workflows/ci-windows.yml/badge.svg)](https://github.com/mheily/libkqueue/actions/workflows/ci-windows.yml) A user space implementation of the kqueue(2) kernel event notification mechanism libkqueue acts as a translator between the kevent structure and the native From e052fbf955a26f1342813f0cf7e9856eb4aa64ba Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 20 Jan 2022 10:33:06 -0500 Subject: [PATCH 0960/1120] Switch to tracing mutexes for kf_knote_mtx --- vendor/libkqueue/src/common/filter.c | 4 ++-- vendor/libkqueue/src/common/knote.c | 20 ++++++++++---------- vendor/libkqueue/src/common/private.h | 2 +- vendor/libkqueue/src/posix/proc.c | 14 +++++++------- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index ba9c9d0b4..3bee03281 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -59,7 +59,7 @@ filter_register(struct kqueue *kq, const struct filter *src) pthread_mutexattr_init(&dst->kf_knote_mtx_attr); pthread_mutexattr_settype(&dst->kf_knote_mtx_attr, PTHREAD_MUTEX_RECURSIVE); #endif - pthread_mutex_init(&dst->kf_knote_mtx, &dst->kf_knote_mtx_attr); + tracing_mutex_init(&dst->kf_knote_mtx, &dst->kf_knote_mtx_attr); if (src->kf_id == 0) { dbg_puts("filter is not implemented"); return (0); @@ -133,7 +133,7 @@ filter_unregister_all(struct kqueue *kq) /* * ...and destroy the mutexes. */ - pthread_mutex_destroy(&filt->kf_knote_mtx); + tracing_mutex_destroy(&filt->kf_knote_mtx); #ifndef _WIN32 pthread_mutexattr_destroy(&filt->kf_knote_mtx_attr); #endif diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 1edbf2543..d53c5d2cd 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -84,9 +84,9 @@ knote_release(struct knote *kn) void knote_insert(struct filter *filt, struct knote *kn) { - pthread_mutex_lock(&filt->kf_knote_mtx); + tracing_mutex_lock(&filt->kf_knote_mtx); RB_INSERT(knote_index, &filt->kf_index, kn); - pthread_mutex_unlock(&filt->kf_knote_mtx); + tracing_mutex_unlock(&filt->kf_knote_mtx); } struct knote * @@ -97,9 +97,9 @@ knote_lookup(struct filter *filt, uintptr_t ident) query.kev.ident = ident; - pthread_mutex_lock(&filt->kf_knote_mtx); + tracing_mutex_lock(&filt->kf_knote_mtx); ent = RB_FIND(knote_index, &filt->kf_index, &query); - pthread_mutex_unlock(&filt->kf_knote_mtx); + tracing_mutex_unlock(&filt->kf_knote_mtx); return (ent); } @@ -108,10 +108,10 @@ int knote_delete_all(struct filter *filt) { struct knote *kn, *tmp; - pthread_mutex_lock(&filt->kf_knote_mtx); + tracing_mutex_lock(&filt->kf_knote_mtx); RB_FOREACH_SAFE(kn, knote_index, &filt->kf_index, tmp) knote_delete(filt, kn); - pthread_mutex_unlock(&filt->kf_knote_mtx); + tracing_mutex_unlock(&filt->kf_knote_mtx); return (0); } @@ -133,7 +133,7 @@ knote_delete(struct filter *filt, struct knote *kn) * thread before we acquired the knotelist lock. */ query.kev.ident = kn->kev.ident; - pthread_mutex_lock(&filt->kf_knote_mtx); + tracing_mutex_lock(&filt->kf_knote_mtx); tmp = RB_FIND(knote_index, &filt->kf_index, &query); if (tmp != kn) dbg_printf("kn=%p - conflicting entry in filter tree", kn); @@ -142,7 +142,7 @@ knote_delete(struct filter *filt, struct knote *kn) if (LIST_INSERTED(kn, kn_ready)) LIST_REMOVE(kn, kn_ready); - pthread_mutex_unlock(&filt->kf_knote_mtx); + tracing_mutex_unlock(&filt->kf_knote_mtx); rv = filt->kn_delete(filt, kn); dbg_printf("kn=%p - kn_delete rv=%i", kn, rv); @@ -164,10 +164,10 @@ knote_disable(struct filter *filt, struct knote *kn) rv = filt->kn_disable(filt, kn); dbg_printf("kn=%p - kn_disable rv=%i", kn, rv); if (rv == 0) { - pthread_mutex_lock(&filt->kf_knote_mtx); + tracing_mutex_lock(&filt->kf_knote_mtx); if (LIST_INSERTED(kn, kn_ready)) /* No longer marked as ready if disabled */ LIST_REMOVE(kn, kn_ready); - pthread_mutex_unlock(&filt->kf_knote_mtx); + tracing_mutex_unlock(&filt->kf_knote_mtx); KNOTE_DISABLE(kn); /* set the disable flag */ } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 47053f2d8..d8130bee4 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -426,7 +426,7 @@ struct filter { ///< with eventfds. ///< This is not used by all filters. - pthread_mutex_t kf_knote_mtx; //!< Used to synchronise knote operations + tracing_mutex_t kf_knote_mtx; //!< Used to synchronise knote operations ///< (addition, removal, modification etc...) ///< on this filter. #ifndef _WIN32 diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 05b83870a..8ac208b92 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -84,10 +84,10 @@ waiter_notify(struct proc_pid *ppd, int status) filt = knote_get_filter(kn); dbg_printf("pid=%u exited, notifying kq=%u filter=%p kn=%p", (unsigned int)ppd->ppd_pid, kn->kn_kq->kq_id, filt, kn); - pthread_mutex_lock(&filt->kf_knote_mtx); + tracing_mutex_lock(&filt->kf_knote_mtx); kqops.eventfd_raise(&filt->kf_proc_eventfd); LIST_INSERT_HEAD(&filt->kf_ready, kn, kn_ready); - pthread_mutex_unlock(&filt->kf_knote_mtx); + tracing_mutex_unlock(&filt->kf_knote_mtx); LIST_REMOVE(kn, kn_proc_waiter); } @@ -110,10 +110,10 @@ waiter_notify_error(struct proc_pid *ppd, int wait_errno) filt = knote_get_filter(kn); dbg_printf("pid=%u errored (%s), notifying kq=%u filter=%p kn=%p", (unsigned int)ppd->ppd_pid, strerror(errno), kn->kn_kq->kq_id, filt, kn); - pthread_mutex_lock(&filt->kf_knote_mtx); + tracing_mutex_lock(&filt->kf_knote_mtx); kqops.eventfd_raise(&filt->kf_proc_eventfd); LIST_INSERT_HEAD(&filt->kf_ready, kn, kn_ready); - pthread_mutex_unlock(&filt->kf_knote_mtx); + tracing_mutex_unlock(&filt->kf_knote_mtx); LIST_REMOVE(kn, kn_proc_waiter); } @@ -498,7 +498,7 @@ evfilt_proc_knote_copyout(struct kevent *dst, int nevents, struct filter *filt, * the knotes in the ready list whilst we're * processing them. */ - pthread_mutex_lock(&filt->kf_knote_mtx); + tracing_mutex_lock(&filt->kf_knote_mtx); assert(!LIST_EMPTY(&filt->kf_ready)); @@ -520,7 +520,7 @@ evfilt_proc_knote_copyout(struct kevent *dst, int nevents, struct filter *filt, if (knote_copyout_flag_actions(filt, kn) < 0) { LIST_INSERT_HEAD(&filt->kf_ready, kn, kn_ready); - pthread_mutex_unlock(&filt->kf_knote_mtx); + tracing_mutex_unlock(&filt->kf_knote_mtx); return -1; } @@ -530,7 +530,7 @@ evfilt_proc_knote_copyout(struct kevent *dst, int nevents, struct filter *filt, if (LIST_EMPTY(&filt->kf_ready)) kqops.eventfd_lower(&filt->kf_proc_eventfd); - pthread_mutex_unlock(&filt->kf_knote_mtx); + tracing_mutex_unlock(&filt->kf_knote_mtx); return (dst_p - dst); } From 98cf0328c429e5d836c99e8a488a9e821fd54ba2 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 20 Jan 2022 15:12:21 -0500 Subject: [PATCH 0961/1120] Use tracing mutexes for global locks in posix/proc.c --- vendor/libkqueue/src/common/debug.h | 3 ++ vendor/libkqueue/src/posix/proc.c | 57 ++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index 430830290..6fc9f2564 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -95,6 +95,8 @@ typedef struct { int mtx_owner; } tracing_mutex_t; +# define TRACING_MUTEX_INITIALIZER { .mtx_lock = PTHREAD_MUTEX_INITIALIZER, .mtx_status = MTX_UNLOCKED, .mtx_owner = -1 } + # define tracing_mutex_init(mtx, attr) do { \ pthread_mutex_init(&(mtx)->mtx_lock, (attr)); \ (mtx)->mtx_status = MTX_UNLOCKED; \ @@ -137,6 +139,7 @@ typedef struct { # define MTX_UNLOCKED # define MTX_LOCKED # define tracing_mutex_t pthread_mutex_t +# define TRACING_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER # define tracing_mutex_init pthread_mutex_init # define tracing_mutex_destroy pthread_mutex_destroy # define tracing_mutex_assert(x,y) diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 8ac208b92..6498b4f59 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -36,7 +36,7 @@ struct proc_pid { LIST_HEAD(pid_waiters, knote) ppd_proc_waiters; //!< knotes that are waiting on this PID. }; -static pthread_mutex_t proc_init_mtx = PTHREAD_MUTEX_INITIALIZER; +static tracing_mutex_t proc_init_mtx = TRACING_MUTEX_INITIALIZER; static int proc_count = 0; static pthread_t proc_wait_thread_id; @@ -45,8 +45,10 @@ static pthread_t proc_wait_thread_id; * Contains all the PIDs any kqueue is interested in waiting on */ static RB_HEAD(pid_index, proc_pid) proc_pid_index; -static pthread_mutex_t proc_pid_index_mtx = PTHREAD_MUTEX_INITIALIZER; - +static tracing_mutex_t proc_pid_index_mtx = TRACING_MUTEX_INITIALIZER; +#ifndef _WIN32 +pthread_mutexattr_t proc_pid_index_mtx_attr; +#endif static int proc_pid_cmp(struct proc_pid *a, struct proc_pid *b) @@ -264,7 +266,7 @@ wait_thread(UNUSED void *arg) continue; } - pthread_mutex_lock(&proc_pid_index_mtx); + tracing_mutex_lock(&proc_pid_index_mtx); /* * Sig 0 is the NULL signal. This means it's the first @@ -299,7 +301,7 @@ wait_thread(UNUSED void *arg) waiter_notify_error(ppd, errno); - pthread_mutex_unlock(&proc_pid_index_mtx); + tracing_mutex_unlock(&proc_pid_index_mtx); continue; @@ -311,7 +313,7 @@ wait_thread(UNUSED void *arg) status = waiter_siginfo_to_status(&info); if (status >= 0) waiter_notify(ppd, status); /* If < 0 notification is spurious */ } - pthread_mutex_unlock(&proc_pid_index_mtx); + tracing_mutex_unlock(&proc_pid_index_mtx); dbg_printf("waiting for SIGCHLD"); } while ((ret = sigwaitinfo(&sigmask, &info))); @@ -324,6 +326,8 @@ wait_thread(UNUSED void *arg) static int evfilt_proc_init(struct filter *filt) { + static bool global_init = false; + if (kqops.eventfd_init(&filt->kf_proc_eventfd, filt) < 0) { error_0: return (-1); @@ -338,7 +342,24 @@ evfilt_proc_init(struct filter *filt) /* * Initialise global resources (wait thread and PID tree). */ - pthread_mutex_lock(&proc_init_mtx); + tracing_mutex_lock(&proc_init_mtx); + + /* + * Initialise the global PID index tree. This needs to be + * recursive as the delete/enable/disable functions all + * need to lock the mutex, and they may be called indirectly + * in the copyout function (which already locks this mutex), + * as well as by other kqueue code. + */ + if (!global_init) { +#ifndef _WIN32 + pthread_mutexattr_init(&proc_pid_index_mtx_attr); + pthread_mutexattr_settype(&proc_pid_index_mtx_attr, PTHREAD_MUTEX_RECURSIVE); +#endif + tracing_mutex_init(&proc_pid_index_mtx, &proc_pid_index_mtx_attr); + global_init = true; + } + if (proc_count == 0) { sigset_t sigmask; @@ -358,12 +379,12 @@ evfilt_proc_init(struct filter *filt) dbg_printf("creating wait thread"); if (pthread_create(&proc_wait_thread_id, NULL, wait_thread, NULL) != 0) { - pthread_mutex_unlock(&proc_init_mtx); + tracing_mutex_unlock(&proc_init_mtx); goto error_1; } } proc_count++; - pthread_mutex_unlock(&proc_init_mtx); + tracing_mutex_unlock(&proc_init_mtx); return (0); } @@ -375,7 +396,7 @@ evfilt_proc_destroy(struct filter *filt) * Free global resources like the wait thread * and PID tree. */ - pthread_mutex_lock(&proc_init_mtx); + tracing_mutex_lock(&proc_init_mtx); assert(proc_count > 0); if (--proc_count == 0) { void *retval; @@ -388,7 +409,7 @@ evfilt_proc_destroy(struct filter *filt) dbg_puts("waiter thread joined"); } } - pthread_mutex_unlock(&proc_init_mtx); + tracing_mutex_unlock(&proc_init_mtx); kqops.eventfd_unregister(filt->kf_kqueue, &filt->kf_proc_eventfd); kqops.eventfd_close(&filt->kf_proc_eventfd); @@ -399,7 +420,7 @@ evfilt_proc_knote_create(struct filter *filt, struct knote *kn) { struct proc_pid *ppd; - pthread_mutex_lock(&proc_pid_index_mtx); + tracing_mutex_lock(&proc_pid_index_mtx); /* * Fixme - We should probably check to see if the PID exists * here and error out early instead of waiting for the waiter @@ -411,14 +432,14 @@ evfilt_proc_knote_create(struct filter *filt, struct knote *kn) dbg_printf("pid=%u adding waiter list", (unsigned int)kn->kev.ident); ppd = calloc(1, sizeof(struct proc_pid)); if (unlikely(!ppd)) { - pthread_mutex_unlock(&proc_pid_index_mtx); + tracing_mutex_unlock(&proc_pid_index_mtx); return -1; } ppd->ppd_pid = kn->kev.ident; RB_INSERT(pid_index, &proc_pid_index, ppd); } LIST_INSERT_HEAD(&ppd->ppd_proc_waiters, kn, kn_proc_waiter); - pthread_mutex_unlock(&proc_pid_index_mtx); + tracing_mutex_unlock(&proc_pid_index_mtx); /* * These get added by default on macOS (and likely FreeBSD) @@ -443,7 +464,7 @@ evfilt_proc_knote_delete(UNUSED struct filter *filt, struct knote *kn) { struct proc_pid *ppd; - pthread_mutex_lock(&proc_pid_index_mtx); + tracing_mutex_lock(&proc_pid_index_mtx); if (LIST_INSERTED(kn, kn_proc_waiter)) LIST_REMOVE(kn, kn_proc_waiter); /* @@ -462,7 +483,7 @@ evfilt_proc_knote_delete(UNUSED struct filter *filt, struct knote *kn) } else { dbg_printf("pid=%u waiter list already removed", (unsigned int)kn->kev.ident); } - pthread_mutex_unlock(&proc_pid_index_mtx); + tracing_mutex_unlock(&proc_pid_index_mtx); return (0); } @@ -480,9 +501,9 @@ evfilt_proc_knote_disable(UNUSED struct filter *filt, struct knote *kn) * which is why we need to run the same logic * as knote_create when re-enabling. */ - pthread_mutex_lock(&proc_pid_index_mtx); + tracing_mutex_lock(&proc_pid_index_mtx); if (LIST_INSERTED(kn, kn_proc_waiter)) LIST_REMOVE(kn, kn_proc_waiter); - pthread_mutex_unlock(&proc_pid_index_mtx); + tracing_mutex_unlock(&proc_pid_index_mtx); return (0); } From ff145cd9993e82170fb15269e6361f1dc3871219 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 20 Jan 2022 15:14:29 -0500 Subject: [PATCH 0962/1120] Use proc_pid_index_mtx to protect both the ready lists, and watch lists This avoids a deadlock between a waiter thread attempting to notify a kqueue that an event is ready, and a kqueue deleting a PID notification request. --- vendor/libkqueue/src/posix/proc.c | 44 +++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 6498b4f59..66ba5aeb2 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -86,10 +86,8 @@ waiter_notify(struct proc_pid *ppd, int status) filt = knote_get_filter(kn); dbg_printf("pid=%u exited, notifying kq=%u filter=%p kn=%p", (unsigned int)ppd->ppd_pid, kn->kn_kq->kq_id, filt, kn); - tracing_mutex_lock(&filt->kf_knote_mtx); kqops.eventfd_raise(&filt->kf_proc_eventfd); - LIST_INSERT_HEAD(&filt->kf_ready, kn, kn_ready); - tracing_mutex_unlock(&filt->kf_knote_mtx); + LIST_INSERT_HEAD(&filt->kf_ready, kn, kn_ready); /* protected by proc_pid_index_mtx */ LIST_REMOVE(kn, kn_proc_waiter); } @@ -112,10 +110,8 @@ waiter_notify_error(struct proc_pid *ppd, int wait_errno) filt = knote_get_filter(kn); dbg_printf("pid=%u errored (%s), notifying kq=%u filter=%p kn=%p", (unsigned int)ppd->ppd_pid, strerror(errno), kn->kn_kq->kq_id, filt, kn); - tracing_mutex_lock(&filt->kf_knote_mtx); kqops.eventfd_raise(&filt->kf_proc_eventfd); - LIST_INSERT_HEAD(&filt->kf_ready, kn, kn_ready); - tracing_mutex_unlock(&filt->kf_knote_mtx); + LIST_INSERT_HEAD(&filt->kf_ready, kn, kn_ready); /* protected by proc_pid_index_mtx */ LIST_REMOVE(kn, kn_proc_waiter); } @@ -266,6 +262,15 @@ wait_thread(UNUSED void *arg) continue; } + /* + * The knote_* functions (i.e. those that could free a + * knote). + * + * All attempt to take this lock before modifying the + * knotes, wo we shouldn't have any issues here with + * knotes being freed out from underneath the waiter + * thread. + */ tracing_mutex_lock(&proc_pid_index_mtx); /* @@ -518,9 +523,27 @@ evfilt_proc_knote_copyout(struct kevent *dst, int nevents, struct filter *filt, * Prevent the waiter thread from modifying * the knotes in the ready list whilst we're * processing them. + * + * At first glance this wouldn't appear to + * require a global lock. The issue is that + * if we use filter-specific locks to protect + * the kf_ready list, we can get into a deadlock + * where the waiter thread holds the lock on + * proc_pid_index_mtx, and it attempting to lock + * the filter lock to insert new ready + * notifications, and we're holding the filter + * lock, and attempting to delete a knote, + * which requires holding the proc_pid_index_mtx. + * + * This was seen in the real world and caused + * major issues. + * + * By using a single lock we ensure either the + * waiter thread is notifying kqueue isntances + * data is ready, or a kqueue is copying out + * notifications, so no deadlock can occur. */ - tracing_mutex_lock(&filt->kf_knote_mtx); - + tracing_mutex_lock(&proc_pid_index_mtx); assert(!LIST_EMPTY(&filt->kf_ready)); /* @@ -541,7 +564,7 @@ evfilt_proc_knote_copyout(struct kevent *dst, int nevents, struct filter *filt, if (knote_copyout_flag_actions(filt, kn) < 0) { LIST_INSERT_HEAD(&filt->kf_ready, kn, kn_ready); - tracing_mutex_unlock(&filt->kf_knote_mtx); + tracing_mutex_unlock(&proc_pid_index_mtx); return -1; } @@ -550,8 +573,7 @@ evfilt_proc_knote_copyout(struct kevent *dst, int nevents, struct filter *filt, if (LIST_EMPTY(&filt->kf_ready)) kqops.eventfd_lower(&filt->kf_proc_eventfd); - - tracing_mutex_unlock(&filt->kf_knote_mtx); + tracing_mutex_unlock(&proc_pid_index_mtx); return (dst_p - dst); } From 783556845f8eee3c50dcdc3656a965cb78d5d60a Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 21 Jan 2022 13:08:59 -0500 Subject: [PATCH 0963/1120] Add EVFILT_LIBKQUEUE --- vendor/libkqueue/.gitignore | 2 +- vendor/libkqueue/CMakeLists.txt | 18 ++- vendor/libkqueue/include/sys/event.h | 12 +- vendor/libkqueue/src/common/filter.c | 2 + vendor/libkqueue/src/common/kevent.c | 106 +++++++++++++----- vendor/libkqueue/src/common/libkqueue.c | 95 ++++++++++++++++ vendor/libkqueue/src/common/private.h | 16 ++- .../common/version.h.in} | 1 + vendor/libkqueue/test/CMakeLists.txt | 3 +- vendor/libkqueue/test/common.c | 13 ++- vendor/libkqueue/test/common.h | 1 + vendor/libkqueue/test/libkqueue.c | 61 ++++++++++ vendor/libkqueue/test/main.c | 9 +- 13 files changed, 298 insertions(+), 41 deletions(-) create mode 100644 vendor/libkqueue/src/common/libkqueue.c rename vendor/libkqueue/{include/sys/libkqueue_version.h.in => src/common/version.h.in} (95%) create mode 100644 vendor/libkqueue/test/libkqueue.c diff --git a/vendor/libkqueue/.gitignore b/vendor/libkqueue/.gitignore index 2e9b559d6..dba027135 100644 --- a/vendor/libkqueue/.gitignore +++ b/vendor/libkqueue/.gitignore @@ -23,4 +23,4 @@ test/CMakeCache.txt test/CMakeFiles/ test/cmake_install.cmake test/libkqueue-test -include/sys/libkqueue_version.h +src/common/version.h diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 4bfdbf393..9658e6b61 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -25,13 +25,17 @@ else() endif() cmake_policy(SET CMP0063 OLD) -# Both variables used in include/sys/libkqueue_version.h.in +# Both variables used in src/common/version.h.in string(TIMESTAMP PROJECT_VERSION_DATE "%b %d %Y at %H:%M:%S") execute_process(COMMAND git rev-parse --short=8 HEAD OUTPUT_VARIABLE LIBKQUEUE_VERSION_COMMIT OUTPUT_STRIP_TRAILING_WHITESPACE) +if(LIBKQUEUE_VERSION_COMMIT STREQUAL "") + unset(LIBKQUEUE_VERSION_COMMIT) +endif() + execute_process(COMMAND sh -c "git describe --tags --match 'v*' | grep '-' | cut -d- -f2" OUTPUT_VARIABLE PROJECT_VERSION_RELEASE OUTPUT_STRIP_TRAILING_WHITESPACE) @@ -43,12 +47,13 @@ else() # Release 1 is the default, so we need to start at release 2 MATH(EXPR PROJECT_VERSION_RELEASE "${PROJECT_VERSION_RELEASE}+1") MESSAGE("Version ${PROJECT_VERSION}-${PROJECT_VERSION_RELEASE} (${LIBKQUEUE_VERSION_COMMIT})") + set(LIBKQUEUE_VERSION_RELEASE ${PROJECT_VERSION_RELEASE}) endif() project(libkqueue VERSION ${PROJECT_VERSION} LANGUAGES C) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/sys/libkqueue_version.h.in - ${CMAKE_CURRENT_BINARY_DIR}/include/sys/libkqueue_version.h @ONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/common/version.h.in + ${CMAKE_CURRENT_BINARY_DIR}/src/common/version.h @ONLY) enable_testing() @@ -162,10 +167,12 @@ set(LIBKQUEUE_SOURCES src/common/kevent.c src/common/knote.c src/common/kqueue.c + src/common/libkqueue.c src/common/map.c src/common/private.h src/common/queue.h - src/common/tree.h) + src/common/tree.h + src/common/version.h) if(CMAKE_SYSTEM_NAME MATCHES Windows) list(APPEND LIBKQUEUE_SOURCES @@ -226,7 +233,7 @@ endif() add_library(kqueue ${LIBRARY_TYPE} ${LIBKQUEUE_SOURCES} ${LIBKQUEUE_HEADERS}) -# We should have absolute ABI compatibility between versions as none +# We should have absolute ABI compatibility between versions as none # of the public function signatures of variables will change. set_target_properties(kqueue PROPERTIES SOVERSION 0) @@ -276,7 +283,6 @@ set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION ${CMAKE_INSTALL_FULL_MANDIR} install(FILES "${CMAKE_SOURCE_DIR}/include/sys/event.h" - "${CMAKE_CURRENT_BINARY_DIR}/include/sys/libkqueue_version.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/kqueue/sys" COMPONENT headers) diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index c9d7ef972..0e1887faf 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -41,7 +41,6 @@ #else # include #endif -# include #define LIBKQUEUE 1 #endif @@ -102,7 +101,8 @@ struct kevent { #define EVFILT_FS (-9) //!< Filesystem events. #define EVFILT_LIO (-10) //!< Attached to lio requests. #define EVFILT_USER (-11) //!< User events. -#define EVFILT_SYSCOUNT 11 +#define EVFILT_LIBKQUEUE (-12) //!< libkqueue specific filter. +#define EVFILT_SYSCOUNT 12 /** @} */ /** @name Actions @@ -232,6 +232,14 @@ struct kevent { #define NOTE_ABSOLUTE 0x0008 //!< Data is an absolute timeout. /** @} */ +/** @name Data/hint flags for EVFILT_TIMER as suported and defined in kevent64 + * + * @{ + */ +#define NOTE_VERSION 0x0001 //!< Version number as MMmmpprr. +#define NOTE_VERSION_STR 0x0002 //!< Version number string. +/** @} */ + #ifndef __KERNEL__ #ifdef __cplusplus extern "C" { diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index 3bee03281..2a97cce47 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -26,6 +26,7 @@ extern const struct filter evfilt_vnode; extern const struct filter evfilt_proc; extern const struct filter evfilt_timer; extern const struct filter evfilt_user; +extern const struct filter evfilt_libkqueue; static int filter_register(struct kqueue *kq, const struct filter *src) @@ -102,6 +103,7 @@ filter_register_all(struct kqueue *kq) rv += filter_register(kq, &evfilt_proc); rv += filter_register(kq, &evfilt_timer); rv += filter_register(kq, &evfilt_user); + rv += filter_register(kq, &evfilt_libkqueue); if (rv != 0) { filter_unregister_all(kq); return (-1); diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 12902f916..3818c4a84 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -83,6 +83,10 @@ kevent_fflags_dump(const struct kevent *kev) KEVFFL_DUMP(NOTE_ABSOLUTE); break; + case EVFILT_LIBKQUEUE: + KEVFFL_DUMP(NOTE_VERSION); + break; + default: break; } @@ -143,8 +147,22 @@ kevent_dump(const struct kevent *kev) return ((const char *) buf); } +/** Process a single entry in the changelist + * + * @param[out] out The knote the src kevent resolved to (if any). + * @param[in] kq to apply the change against. + * @param[in] src the change being applied. + * @return + * - 1 on success. Caller should add a receipt entry based on the kev + * contained within the knote. This is used for the EVFILT_LIBKQUEUE + * to support its use as a query interface. + * - 0 on success. Caller should add a receipt entry if EV_RECEIPT was + * set in the src kevent. + * - -1 on failure. Caller should add a receipt entry containing the error. + * in the data field. + */ static int -kevent_copyin_one(struct kqueue *kq, const struct kevent *src) +kevent_copyin_one(const struct knote **out, struct kqueue *kq, const struct kevent *src) { struct knote *kn = NULL; struct filter *filt; @@ -166,36 +184,39 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) if (src->flags & EV_ADD) { if ((kn = knote_new()) == NULL) { errno = ENOENT; + *out = NULL; return (-1); } memcpy(&kn->kev, src, sizeof(kn->kev)); kn->kev.flags &= ~EV_ENABLE; - kn->kev.flags |= EV_ADD;//FIXME why? kn->kn_kq = kq; assert(filt->kn_create); - if (filt->kn_create(filt, kn) < 0) { + rv = filt->kn_create(filt, kn); + if (rv < 0) { dbg_puts("kn_create failed"); kn->kn_flags |= KNFL_KNOTE_DELETED; knote_release(kn); errno = EFAULT; + *out = NULL; return (-1); } knote_insert(filt, kn); dbg_printf("kn=%p - created knote %s", kn, kevent_dump(src)); + *out = kn; /* XXX- FIXME Needs to be handled in kn_create() to prevent races */ if (src->flags & EV_DISABLE) { kn->kev.flags |= EV_DISABLE; - return (filt->kn_disable(filt, kn)); + return filt->kn_disable(filt, kn); } //........................................ - - return (0); + return (rv); } else { dbg_printf("ident=%u - no knote found", (unsigned int)src->ident); errno = ENOENT; + *out = NULL; return (-1); } } else { @@ -210,7 +231,6 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) rv = knote_enable(filt, kn); } else if (src->flags & EV_ADD || src->flags == 0 || src->flags & EV_RECEIPT) { rv = filt->kn_modify(filt, kn, src); - /* * Implement changes common to all filters */ @@ -223,6 +243,7 @@ kevent_copyin_one(struct kqueue *kq, const struct kevent *src) } dbg_printf("kn=%p - kn_modify rv=%d", kn, rv); } + *out = kn; return (rv); } @@ -233,39 +254,68 @@ kevent_copyin(struct kqueue *kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents) { int status; + int rv; struct kevent *el_p = eventlist, *el_end = el_p + nevents; dbg_printf("nchanges=%d nevents=%d", nchanges, nevents); + +#define CHECK_EVENTLIST_SPACE \ + do { \ + if (el_p == el_end) { \ + if (errno == 0) errno = EFAULT; \ + return (-1); \ + } \ + } while (0) + for (struct kevent const *cl_p = changelist, *cl_end = cl_p + nchanges; cl_p < cl_end; cl_p++) { - if (kevent_copyin_one(kq, cl_p) < 0) { + const struct knote *kn; + + rv = kevent_copyin_one(&kn, kq, cl_p); + if (rv == 1) { + if (el_p == el_end) { + errno = EFAULT; + return (-1); + } + memcpy(el_p, &kn->kev, sizeof(*el_p)); + el_p->flags |= EV_RECEIPT; + el_p++; + + } else if (rv < 0) { dbg_printf("errno=%s", strerror(errno)); + /* + * We're out of kevent entries, just return -1 and leave + * the errno set. This is... odd, because it means the + * caller won't have any idea which entries in the + * changelist were processed. But I guess the + * requirement here is for the caller to always provide + * a kevent array with >= entries as the changelist. + */ + if (el_p == el_end) + return (-1); status = errno; - } else if (cl_p->flags & EV_RECEIPT) { - status = 0; - } else { - continue; - } + errno = 0; /* Reset back to 0 if we recorded the error as a kevent */ + + receipt: + memcpy(el_p, cl_p, sizeof(*el_p)); + el_p->flags |= EV_ERROR; /* This is set both on error and for EV_RECEIPT */ + el_p->data = status; + el_p++; /* - * We're out of kevent entries, just return -1 and leave - * the errno set. This is... odd, because it means the - * caller won't have any idea which entries in the - * changelist were processed. But I guess the - * requirement here is for the caller to always provide - * a kevent array with >= entries as the changelist. + * This allows our custom filter to create eventlist + * entries in response to queries. */ - if (el_p == el_end) - return (-1); - - memcpy(el_p, cl_p, sizeof(*cl_p)); - el_p->flags |= EV_ERROR; /* This is set both on error and for EV_RECEIPT */ - el_p->data = status; - el_p++; - - errno = 0; /* Reset back to 0 if we recorded the error as a kevent */ + } else if (cl_p->flags & EV_RECEIPT) { + status = 0; + if (el_p == el_end) { + errno = EFAULT; + return (-1); + } + goto receipt; + } } return (el_p - eventlist); diff --git a/vendor/libkqueue/src/common/libkqueue.c b/vendor/libkqueue/src/common/libkqueue.c new file mode 100644 index 000000000..1e4a90cdd --- /dev/null +++ b/vendor/libkqueue/src/common/libkqueue.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2022 Arran Cudbard-Bell + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "private.h" + +int +common_libkqueue_knote_create(struct filter *filt, struct knote *kn) +{ + kn->kev.flags |= EV_RECEIPT; /* Causes the knote to be copied to the eventlist */ + + switch (kn->kev.fflags) { + case NOTE_VERSION_STR: + kn->kev.udata = LIBKQUEUE_VERSION_STRING +# ifdef LIBKQUEUE_VERSION_RELEASE + "-" STRINGIFY(LIBKQUEUE_VERSION_RELEASE) +# endif +# ifdef LIBKQUEUE_VERSION_COMMIT + " (git #"LIBKQUEUE_VERSION_COMMIT")" +# endif +# ifdef LIBKQUEUE_VERSION_DATE + " built "LIBKQUEUE_VERSION_DATE +# endif + ; + break; + + case NOTE_VERSION: + kn->kev.data = ((uint32_t)LIBKQUEUE_VERSION_MAJOR << 24) | + ((uint32_t)LIBKQUEUE_VERSION_MINOR << 16) | + ((uint32_t)LIBKQUEUE_VERSION_PATCH << 8) +#ifdef LIBKQUEUE_VERSION_RELEASE + | (uint32_t)LIBKQUEUE_VERSION_RELEASE +#endif + ; + break; + + default: + return (-1); + } + + return (1); /* Provide receipt */ +} + +int +common_libkqueue_knote_copyout(UNUSED struct kevent *dst, UNUSED int nevents, UNUSED struct filter *filt, + UNUSED struct knote *kn, UNUSED void *ev) +{ + return (-1); +} + +int +common_libkqueue_knote_modify(struct filter *filt, struct knote *kn, const struct kevent *kev) +{ + memcpy(&kn->kev, kev, sizeof(kn->kev)); + return common_libkqueue_knote_create(filt, kn); +} + +int +common_libkqueue_knote_delete(UNUSED struct filter *filt, UNUSED struct knote *kn) +{ + return (0); +} + +int +common_libkqueue_knote_enable(UNUSED struct filter *filt, UNUSED struct knote *kn) +{ + return (0); +} + +int +common_libkqueue_knote_disable(UNUSED struct filter *filt, UNUSED struct knote *kn) +{ + return (0); +} + +const struct filter evfilt_libkqueue = { + .kf_id = EVFILT_LIBKQUEUE, + .kf_copyout = common_libkqueue_knote_copyout, + .kn_create = common_libkqueue_knote_create, + .kn_modify = common_libkqueue_knote_modify, + .kn_delete = common_libkqueue_knote_delete, + .kn_enable = common_libkqueue_knote_enable, + .kn_disable = common_libkqueue_knote_disable +}; diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index d8130bee4..f8a578e07 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -29,8 +29,9 @@ #include #include "config.h" -#include "tree.h" #include "sys/event.h" +#include "tree.h" +#include "version.h" /* Maximum events returnable in a single kevent() call */ #define MAX_KEVENT 512 @@ -76,6 +77,9 @@ struct evfilt_data; */ #define NUM_ELEMENTS(_t) (sizeof((_t)) / sizeof(*(_t))) +#define XSTRINGIFY(x) #x +#define STRINGIFY(x) XSTRINGIFY(x) + #if defined(__clang__) || defined(__GNUC__) /* * Branch prediction macros @@ -295,6 +299,8 @@ struct filter { * @param[in] filt the knote is associated with. * @param[in] kn to initialise. * @return + * - 1 to create an entry in the eventlist using the contents + * of kn->kev. * - 0 on success. * - -1 on failure setting errno. */ @@ -323,6 +329,8 @@ struct filter { * modification. * * @return + * - 1 to create an entry in the eventlist using the contents + * of kn->kev. * - 0 on success. * - -1 on failure setting errno. */ @@ -349,6 +357,8 @@ struct filter { * @param[in] filt the knote is associated with. * @param[in] kn to delete. * @return + * - 1 to create an entry in the eventlist using the contents + * of kn->kev. * - 0 on success. * - -1 on failure setting errno. */ @@ -374,6 +384,8 @@ struct filter { * @param[in] filt the knote is associated with. * @param[in] kn to enable. * @return + * - 1 to create an entry in the eventlist using the contents + * of kn->kev. * - 0 on success. * - -1 on failure setting errno. */ @@ -398,6 +410,8 @@ struct filter { * @param[in] filt the knote is associated with. * @param[in] kn to disable. * @return + * - 1 to create an entry in the eventlist using the contents + * of kn->kev. * - 0 on success. * - -1 on failure setting errno. */ diff --git a/vendor/libkqueue/include/sys/libkqueue_version.h.in b/vendor/libkqueue/src/common/version.h.in similarity index 95% rename from vendor/libkqueue/include/sys/libkqueue_version.h.in rename to vendor/libkqueue/src/common/version.h.in index a0b087c4a..5e297899e 100644 --- a/vendor/libkqueue/include/sys/libkqueue_version.h.in +++ b/vendor/libkqueue/src/common/version.h.in @@ -24,6 +24,7 @@ #define LIBKQUEUE_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ #define LIBKQUEUE_VERSION_MINOR @PROJECT_VERSION_MINOR@ #define LIBKQUEUE_VERSION_PATCH @PROJECT_VERSION_PATCH@ +#cmakedefine LIBKQUEUE_VERSION_RELEASE @PROJECT_VERSION_RELEASE@ #define LIBKQUEUE_VERSION_DATE "@PROJECT_VERSION_DATE@" #cmakedefine LIBKQUEUE_VERSION_COMMIT "@LIBKQUEUE_VERSION_COMMIT@" diff --git a/vendor/libkqueue/test/CMakeLists.txt b/vendor/libkqueue/test/CMakeLists.txt index 5d87d526c..6d8c11e45 100644 --- a/vendor/libkqueue/test/CMakeLists.txt +++ b/vendor/libkqueue/test/CMakeLists.txt @@ -18,9 +18,10 @@ project(libkqueue-test LANGUAGES C) set(LIBKQUEUE_TEST_SOURCES common.c kqueue.c + libkqueue.c main.c - read.c proc.c + read.c test.c timer.c user.c diff --git a/vendor/libkqueue/test/common.c b/vendor/libkqueue/test/common.c index 17876f65f..e3fbca016 100644 --- a/vendor/libkqueue/test/common.c +++ b/vendor/libkqueue/test/common.c @@ -105,7 +105,11 @@ filter_name(short filt) #ifdef EVFILT_LIO [~EVFILT_LIO] = "EVFILT_LIO", #endif - [~EVFILT_USER] = "EVFILT_USER" + [~EVFILT_USER] = "EVFILT_USER", + +#ifdef EVFILT_LIBKQUEUE + [~EVFILT_LIBKQUEUE] = "EVFILT_LIBKQUEUE" +#endif }; id = ~filt; @@ -174,6 +178,13 @@ kevent_fflags_dump(struct kevent *kev) #endif break; +#ifdef EVFILT_LIBKQUEUE + case EVFILT_LIBKQUEUE: + KEVFFL_DUMP(NOTE_VERSION); + KEVFFL_DUMP(NOTE_VERSION_STR); + break; +#endif + default: break; } diff --git a/vendor/libkqueue/test/common.h b/vendor/libkqueue/test/common.h index f875ba7a8..69e20431f 100644 --- a/vendor/libkqueue/test/common.h +++ b/vendor/libkqueue/test/common.h @@ -117,6 +117,7 @@ void test_evfilt_proc(struct test_context *); #ifdef EVFILT_USER void test_evfilt_user(struct test_context *); #endif +void test_evfilt_libkqueue(struct test_context *); #define test(f, ctx ,...) do { \ if ((ctx->test->ut_num >= ctx->test->ut_start) && (ctx->test->ut_num <= ctx->test->ut_end)) {\ diff --git a/vendor/libkqueue/test/libkqueue.c b/vendor/libkqueue/test/libkqueue.c new file mode 100644 index 000000000..a7c86cf44 --- /dev/null +++ b/vendor/libkqueue/test/libkqueue.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2022 Arran Cudbard-Bell + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "common.h" + +#ifdef EVFILT_LIBKQUEUE +static void +test_libkqueue_version(struct test_context *ctx) +{ + struct kevent kev, receipt; + + EV_SET(&kev, 0, EVFILT_LIBKQUEUE, EV_ADD, NOTE_VERSION, 0, NULL); + if (kevent(ctx->kqfd, &kev, 1, &receipt, 1, &(struct timespec){}) != 1) { + printf("Unable to add the following kevent:\n%s\n", + kevent_to_str(&kev)); + die("kevent"); + } + + if (receipt.data == 0) { + printf("No version number returned"); + die("kevent"); + } +} + +static void +test_libkqueue_version_str(struct test_context *ctx) +{ + struct kevent kev, receipt; + + EV_SET(&kev, 0, EVFILT_LIBKQUEUE, EV_ADD, NOTE_VERSION_STR, 0, NULL); + if (kevent(ctx->kqfd, &kev, 1, &receipt, 1, &(struct timespec){}) != 1) { + printf("Unable to add the following kevent:\n%s\n", + kevent_to_str(&kev)); + die("kevent"); + } + + if (strlen((char *)receipt.udata) < 8) { + printf("No version number returned"); + die("kevent"); + } +} + +void +test_evfilt_libkqueue(struct test_context *ctx) +{ + test(libkqueue_version, ctx); + test(libkqueue_version_str, ctx); +} +#endif diff --git a/vendor/libkqueue/test/main.c b/vendor/libkqueue/test/main.c index 562e054d2..e5c0dece6 100644 --- a/vendor/libkqueue/test/main.c +++ b/vendor/libkqueue/test/main.c @@ -127,7 +127,8 @@ usage(void) "proc " "timer " "vnode " - "user]\n" + "user " + "libkqueue]\n" " All tests are run by default\n" "\n" ); @@ -174,7 +175,13 @@ main(int argc, char **argv) .ut_func = test_evfilt_user, .ut_end = INT_MAX }, #endif +#ifdef EVFILT_LIBKQUEUE + { .ut_name = "libkqueue", + .ut_enabled = 1, + .ut_func = test_evfilt_libkqueue, + .ut_end = INT_MAX }, { NULL, 0, NULL }, +#endif }; struct unit_test *test; int c, i, iterations; From 9dab2f8b73ce03609ce584270c6d55ba122085a7 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 24 Jan 2022 10:54:45 -0600 Subject: [PATCH 0964/1120] See if windows can pick up the version.h header in the top level.... --- vendor/libkqueue/.gitignore | 2 +- vendor/libkqueue/CMakeLists.txt | 9 ++++----- vendor/libkqueue/{src/common => }/version.h.in | 0 3 files changed, 5 insertions(+), 6 deletions(-) rename vendor/libkqueue/{src/common => }/version.h.in (100%) diff --git a/vendor/libkqueue/.gitignore b/vendor/libkqueue/.gitignore index dba027135..1eec65e4e 100644 --- a/vendor/libkqueue/.gitignore +++ b/vendor/libkqueue/.gitignore @@ -23,4 +23,4 @@ test/CMakeCache.txt test/CMakeFiles/ test/cmake_install.cmake test/libkqueue-test -src/common/version.h +version.h diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 9658e6b61..8b78d500c 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -25,7 +25,7 @@ else() endif() cmake_policy(SET CMP0063 OLD) -# Both variables used in src/common/version.h.in +# Both variables used in src/version.h.in string(TIMESTAMP PROJECT_VERSION_DATE "%b %d %Y at %H:%M:%S") execute_process(COMMAND git rev-parse --short=8 HEAD @@ -52,8 +52,8 @@ endif() project(libkqueue VERSION ${PROJECT_VERSION} LANGUAGES C) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/common/version.h.in - ${CMAKE_CURRENT_BINARY_DIR}/src/common/version.h @ONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in + ${CMAKE_CURRENT_BINARY_DIR}/version.h @ONLY) enable_testing() @@ -171,8 +171,7 @@ set(LIBKQUEUE_SOURCES src/common/map.c src/common/private.h src/common/queue.h - src/common/tree.h - src/common/version.h) + src/common/tree.h) if(CMAKE_SYSTEM_NAME MATCHES Windows) list(APPEND LIBKQUEUE_SOURCES diff --git a/vendor/libkqueue/src/common/version.h.in b/vendor/libkqueue/version.h.in similarity index 100% rename from vendor/libkqueue/src/common/version.h.in rename to vendor/libkqueue/version.h.in From 0b78ad91169b5bdf0e5ae2bfc22c94a00056b677 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 24 Jan 2022 10:55:15 -0600 Subject: [PATCH 0965/1120] Remove trailing whitespace in ChangeLog --- vendor/libkqueue/ChangeLog | 41 +++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index a01c91d3d..553f15718 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,46 +1,51 @@ Unreleased ------------------------------------------------------------------------ - * Fix: Allow EVFILT_TIMER filters to be modified on Linux + * Fix: Allow EVFILT_TIMER filters to be modified on Linux (Closes #116) (Reported by: Grant Erickson). - + * Fix: Set the library search path in libkqueue.pc (Closes #117) (Reported by: Grant Erickson) - - * Fix: posix/proc will now no longer deadlock if the PID being - monitored is reaped outside of libkqueue, or has exited before + + * Fix: posix/proc will now no longer deadlock if the PID being + monitored is reaped outside of libkqueue, or has exited before we start monitoring. - + * Fix: posix/proc all waiters will now be informed if monitoring a PID fails, i.e. if the PID is reaped outside of libkqueue. * Fix: Compilation on Windows (Closes #111). (Reported by: brechtsanders) - * Fix: linux/read linux/write EPOLLERR, EPOLLHUP and EPOLLRDHUP on - sockets would not produce a kevent and no EOF indication would be + * Fix: linux/read linux/write EPOLLERR, EPOLLHUP and EPOLLRDHUP on + sockets would not produce a kevent and no EOF indication would be provided to the caller. - + * Fix: linux/signal pending signals of the type specified in a new signal event were reset when that event was added to a kqueue. - - * Fix: Multiple instances of posix/proc wait thread may have been - spawned on repeated kqueue creation/destruction. This may have + + * Fix: Multiple instances of posix/proc wait thread may have been + spawned on repeated kqueue creation/destruction. This may have lead to missed process exit notifications. - + * Fix: Potential race between posix/proc waiter thread starting and events being added. - + + * Fix: Deadlock between posix/proc waiter thread and kqueues. + * Fix: udata should not be modified if the knote modification fails. - + * Test suites now pass on macOS 11.5.2 and FreeBSD 13. - - * Packaging: We now set the release number if the current checked - out commit does not match a release tag. For example if the + + * Packaging: We now set the release number if the current checked + out commit does not match a release tag. For example if the current number of commits between the last release tag and HEAD is 2, then the release will be `-3`. This allows easy upgrading of packages between releases. + * Add EVFILT_LIBKQUEUE to expose libkqueue specific configuration + options. + 2021-09-06 v2.5.0 ------------------------------------------------------------------------ From 88fdc2020f253bd7f7a6577a2850e13c72b224f9 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 24 Jan 2022 11:44:57 -0600 Subject: [PATCH 0966/1120] Add example for using EVFILT_LIBKQUEUE --- vendor/libkqueue/README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index 9d6756fda..5c4649f00 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -112,6 +112,26 @@ When building under clang and some later versions of GCC, you can add the follow - `-DENABLE_TSAN=YES`, enables thread sanitizer (detects races). - `-DENABLE_UBSAN=YES`, enables undefined behaviour sanitizer (detects misaligned accesses, interger wrap, divide by zero etc...). +libkqueue filter +---------------- + +The libkqueue filter `EVFILT_LIBKQUEUE` exposes runtime configuration options and data. When querying/configuring libkqueue +using `EVFILT_LIBKQUEUE` the `flags` field should be set to `EV_ADD`, and the `fflags` field should be one of the +following: + +- `NOTE_VERSION` return the current version as a 32 unsigned integer in the format `MMmmpprr` (`Major`, `minor`, `patch`, `release`) in the `data` field of an entry in the eventlist. +- `NOTE_VERSION_STR` return the current version as a string in the `udata` field of an entry in the eventlist. + +Example - retrieving version string: + + struct kevent kev, receipt; + + EV_SET(&kev, 0, EVFILT_LIBKQUEUE, EV_ADD, NOTE_VERSION_STR, 0, NULL); + if (kevent(kqfd, &kev, 1, &receipt, 1, &(struct timespec){}) != 1) { + //error + } + printf("libkqueue version - %s", (char *)receipt.udata); + Building Applications --------------------- From 6b1918c14291cfd0f6ac91265565bf90dbe7c6a7 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 26 Jan 2022 09:01:44 -0600 Subject: [PATCH 0967/1120] Split up the EVFILT_PROC bugs --- vendor/libkqueue/BUGS.md | 46 ++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/vendor/libkqueue/BUGS.md b/vendor/libkqueue/BUGS.md index 489ac4d17..e26692c32 100644 --- a/vendor/libkqueue/BUGS.md +++ b/vendor/libkqueue/BUGS.md @@ -37,34 +37,44 @@ way that `EINTR` is handled, to make sure that the `EINTR` is propagated up the call stack to `kevent()`. + ## POSIX + + * `EVFILT_PROC` - The POSIX implmentation requires that `SIGCHLD` + be delivered to its global waiter thread so that the waiter can discover a + when child process exits.sigprocmask(2)` is used to mask `SIGCHLD` at a process + level. If the application unmasks `SIGCHLD` or installs a handler for it, + the POSIX `EVFILT_PROC` code will not function. + + * `EVFILT_PROC` - If using the POSIX `EVFILT_PROC` the number of monitored + processes should be kept low (< 100). Because the Linux kernel coalesces + `SIGCHLD` (and other signals), the only way to reliably determine if a + monitored process has exited, is to loop through all PIDs registered by any + kqueue when we receive a `SIGCHLD`. This involves many calls to `waitid(2)` + and may have a negative performance impact. + + * `EVFILT_PROC` - The notification list of the global waiter thread, and the + ready lists of individual kqueues share the same mutex. This may cause + performance issues where large numbers of processes are monitored. + ## Linux - * If a file descriptor outside of kqueue is closed, the internal kqueue + * If a file descriptor outside of kqueue is closed, the internal kqueue state is not cleaned up. On Linux this is pretty much impossible to fix as there's no mechanism to retrieve file descriptor reference - counts, and no way to be notified of when a file descriptor is closed. + counts and no way to be notified of when a file descriptor is closed. Applications should ensure that file descriptors are removed from the kqueue before they are closed. - * `EVFILT_PROC` - Only `NOTE_EXIT` is currently supported. Other + * `EVFILT_PROC` - Only `NOTE_EXIT` is currently supported. Other functionality is possible, but it requires integrating with netlink to receive notifications. If building against Kernels < 5.3 (where `pidfd_open()` is not available) - the POSIX `EVFILT_PROC` code is used. The posix code requires that `SIGCHLD` - be delivered to its global waiter thread, so that the waiter can discover a - when child process exits. - `sigprocmask(2)` is used to mask `SIGCHLD` at a process level. If the - application unmasks `SIGCHLD` or installs a handler for it, the POSIX - `EVFILT_PROC` code will not function. - Native kqueue provides notifications for any process that is visible to the - application process, on Linux/POSIX platforms only direct children of the - application process can be monitored for exit. - If using the POSIX `EVFILT_PROC` the number of monitored processes should be - kept low (< 100). Because the Linux kernel coalesces `SIGCHLD` - (and other signals), the only way to reliably determine if a monitored process - has exited, is to loop through all PIDs registered by any kqueue when we - receive a `SIGCHLD`. This involves many calls to `waitid(2)` and may have - a negative performance impact. + the POSIX `EVFILT_PROC` code is used. See the POSIX section above for + limitations of the POSIX `EVFILT_PROC` code. + + * `EVFILT_PROC` - Native kqueue provides notifications for any process that + is visible to the application process. On Linux/POSIX platforms only direct + children of the application process can be monitored for exit. ## Solaris From 56ee223f7f65bf7ebcfd27048899bd36cfd0a5da Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 26 Jan 2022 09:04:10 -0600 Subject: [PATCH 0968/1120] Fix backticks --- vendor/libkqueue/BUGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/BUGS.md b/vendor/libkqueue/BUGS.md index e26692c32..8e17bbfc7 100644 --- a/vendor/libkqueue/BUGS.md +++ b/vendor/libkqueue/BUGS.md @@ -41,7 +41,7 @@ * `EVFILT_PROC` - The POSIX implmentation requires that `SIGCHLD` be delivered to its global waiter thread so that the waiter can discover a - when child process exits.sigprocmask(2)` is used to mask `SIGCHLD` at a process + when child process `exits.sigprocmask(2)` is used to mask `SIGCHLD` at a process level. If the application unmasks `SIGCHLD` or installs a handler for it, the POSIX `EVFILT_PROC` code will not function. From f272b997967514ab041cac184575cd5c8cecef71 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 26 Jan 2022 09:04:36 -0600 Subject: [PATCH 0969/1120] ...and again --- vendor/libkqueue/BUGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/BUGS.md b/vendor/libkqueue/BUGS.md index 8e17bbfc7..b2f9d96bb 100644 --- a/vendor/libkqueue/BUGS.md +++ b/vendor/libkqueue/BUGS.md @@ -41,7 +41,7 @@ * `EVFILT_PROC` - The POSIX implmentation requires that `SIGCHLD` be delivered to its global waiter thread so that the waiter can discover a - when child process `exits.sigprocmask(2)` is used to mask `SIGCHLD` at a process + when child process exits `sigprocmask(2)` is used to mask `SIGCHLD` at a process level. If the application unmasks `SIGCHLD` or installs a handler for it, the POSIX `EVFILT_PROC` code will not function. From a3b3e7320750bdb49f10c0570aa27ef22ba1922f Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 2 Feb 2022 16:33:38 -0500 Subject: [PATCH 0970/1120] Fix debian package dependencies for intra release versions --- vendor/libkqueue/CMakeLists.txt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 8b78d500c..684532a47 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -302,7 +302,7 @@ install(FILES COMPONENT pkgconfig) set(CPACK_PACKAGE_NAME ${PROJECT_NAME}) -set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) +# CPACK_PACKAGE_VERSION is set automatically set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) @@ -363,18 +363,26 @@ set(CPACK_DEBIAN_MAIN_PACKAGE_SECTION "libs") set(CPACK_DEBIAN_DEVEL_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-dev") set(CPACK_DEBIAN_DEVEL_PACKAGE_SECTION "libdevel") -set(CPACK_DEBIAN_DEVEL_PACKAGE_DEPENDS "${CPACK_PACKAGE_NAME} (= ${PROJECT_VERSION})") set(CPACK_DEB_COMPONENT_INSTALL ON) # Enable component based packaging (generate multiple packages) set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) # Use default Debian package naming scheme set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON) +# +# We need to setup the package dependencies manually +# when we're using a release version to ensure the +# library package is in sync with the headers. +# if (PROJECT_VERSION_RELEASE) +set(CPACK_DEBIAN_DEVEL_PACKAGE_DEPENDS "${CPACK_PACKAGE_NAME} (= ${PROJECT_VERSION}-${PROJECT_VERSION_RELEASE})") set(CPACK_DEBIAN_PACKAGE_RELEASE ${PROJECT_VERSION_RELEASE}) +else() +set(CPACK_DEBIAN_DEVEL_PACKAGE_DEPENDS "${CPACK_PACKAGE_NAME} (= ${PROJECT_VERSION})") endif() set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Mark Heily ") +set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/mheily/libkqueue") include(CPack) add_custom_target(tarball git archive -o "libkqueue-${PROJECT_VERSION}.tar.gz" --prefix "libkqueue-${PROJECT_VERSION}/" HEAD) From 5f80d3873f455400abe31eb7d98a6d4e4345e729 Mon Sep 17 00:00:00 2001 From: Matthew Newton Date: Mon, 7 Mar 2022 19:44:17 +0000 Subject: [PATCH 0971/1120] allow overriding version e.g. for when building release packages where the version comes from the git tag --- vendor/libkqueue/CMakeLists.txt | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 684532a47..4125529dd 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -36,18 +36,27 @@ if(LIBKQUEUE_VERSION_COMMIT STREQUAL "") unset(LIBKQUEUE_VERSION_COMMIT) endif() -execute_process(COMMAND sh -c "git describe --tags --match 'v*' | grep '-' | cut -d- -f2" - OUTPUT_VARIABLE PROJECT_VERSION_RELEASE - OUTPUT_STRIP_TRAILING_WHITESPACE) - -if(PROJECT_VERSION_RELEASE STREQUAL "") - MESSAGE("Version ${PROJECT_VERSION} (${LIBKQUEUE_VERSION_COMMIT})") - unset(PROJECT_VERSION_RELEASE) +# The version may be overridden when building packages by defining +# VERSION_OVERRIDE. Otherwise try to pull the number of commits +# since last tag from git to get a unique version number. +if(VERSION_OVERRIDE) + MESSAGE("Version ${VERSION_OVERRIDE} (${LIBKQUEUE_VERSION_COMMIT}) [override]") + set(PROJECT_VERSION "${VERSION_OVERRIDE}") + set(CPACK_PACKAGE_VERSION "${VERSION_OVERRIDE}") else() - # Release 1 is the default, so we need to start at release 2 - MATH(EXPR PROJECT_VERSION_RELEASE "${PROJECT_VERSION_RELEASE}+1") - MESSAGE("Version ${PROJECT_VERSION}-${PROJECT_VERSION_RELEASE} (${LIBKQUEUE_VERSION_COMMIT})") - set(LIBKQUEUE_VERSION_RELEASE ${PROJECT_VERSION_RELEASE}) + execute_process(COMMAND sh -c "git describe --tags --match 'v*' | grep '-' | cut -d- -f2" + OUTPUT_VARIABLE PROJECT_VERSION_RELEASE + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if(PROJECT_VERSION_RELEASE STREQUAL "") + MESSAGE("Version ${PROJECT_VERSION} (${LIBKQUEUE_VERSION_COMMIT})") + unset(PROJECT_VERSION_RELEASE) + else() + # Release 1 is the default, so we need to start at release 2 + MATH(EXPR PROJECT_VERSION_RELEASE "${PROJECT_VERSION_RELEASE}+1") + MESSAGE("Version ${PROJECT_VERSION}-${PROJECT_VERSION_RELEASE} (${LIBKQUEUE_VERSION_COMMIT})") + set(LIBKQUEUE_VERSION_RELEASE ${PROJECT_VERSION_RELEASE}) + endif() endif() project(libkqueue VERSION ${PROJECT_VERSION} From a7eb540c25c3754c960227ede5822aa369e219d9 Mon Sep 17 00:00:00 2001 From: Matthew Newton Date: Mon, 7 Mar 2022 20:25:11 +0000 Subject: [PATCH 0972/1120] remove libkqueue-version.h from debian package --- vendor/libkqueue/pkg/debian/libkqueue-dev.install | 1 - 1 file changed, 1 deletion(-) diff --git a/vendor/libkqueue/pkg/debian/libkqueue-dev.install b/vendor/libkqueue/pkg/debian/libkqueue-dev.install index 763a6b2c9..88848c03e 100644 --- a/vendor/libkqueue/pkg/debian/libkqueue-dev.install +++ b/vendor/libkqueue/pkg/debian/libkqueue-dev.install @@ -1,4 +1,3 @@ usr/lib/*/pkgconfig/libkqueue.pc usr/include/kqueue/sys/event.h -usr/include/kqueue/sys/libkqueue_version.h usr/share/man/man2/* From 9d4b50d1b747bc78366a7c4c40e81746a8e8118c Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 17 Mar 2022 14:48:33 -0400 Subject: [PATCH 0973/1120] Simplify some of the synchronisation for the monitoring thread --- vendor/libkqueue/src/linux/platform.c | 84 ++++++++++++++++----------- 1 file changed, 50 insertions(+), 34 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 78a74eb60..aa97b3e87 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -36,8 +36,9 @@ extern pthread_mutex_t kq_mtx; */ static pthread_t monitoring_thread; static pid_t monitoring_tid; /* Monitoring thread */ -pthread_once_t monitoring_thread_initialized = PTHREAD_ONCE_INIT; -pthread_cond_t monitoring_thread_cond = PTHREAD_COND_INITIALIZER; + +static pthread_mutex_t monitoring_thread_mtx = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t monitoring_thread_cond = PTHREAD_COND_INITIALIZER; /* * Number of active kqueues. @@ -66,9 +67,15 @@ static int nb_max_fd; static void linux_kqueue_cleanup(struct kqueue *kq); -static bool end_monitoring_thread = false; - -static void +/** Clean up a kqueue from the perspective of the monitoring thread + * + * Called with the kq_mtx held. + * + * @return + * - 0 if the monitoring thread should exit. + * - 1 if the monitoring thread should continue. + */ +static int monitoring_thread_kq_cleanup(int signal_fd, bool ignore_use_count) { int fd; @@ -128,7 +135,8 @@ monitoring_thread_kq_cleanup(int signal_fd, bool ignore_use_count) /* * Stop thread if all kqueues have been closed */ - if (kqueue_cnt == 0) end_monitoring_thread = true; + if (kqueue_cnt == 0) return (0); + return (1); } static void @@ -136,9 +144,6 @@ monitoring_thread_cleanup(void *arg) { int i; - /* Reset so that thread can be restarted */ - monitoring_thread_initialized = PTHREAD_ONCE_INIT; - for (i = 0; i < nb_max_fd; i++) { if (fd_use_cnt[i] > 0) { int fd; @@ -149,7 +154,7 @@ monitoring_thread_cleanup(void *arg) dbg_printf("fd=%i - forcefully cleaning up, use_count=%u: %s", fd, fd_use_cnt[fd], strerror(errno)); fd_use_cnt[fd] = 0; - monitoring_thread_kq_cleanup(i, true); + (void)monitoring_thread_kq_cleanup(i, true); fd_use_cnt[fd] = 0; } } @@ -162,14 +167,15 @@ monitoring_thread_cleanup(void *arg) free(fd_use_cnt); fd_use_cnt = NULL; - (void) pthread_mutex_unlock(&kq_mtx); + /* Reset so that thread can be restarted */ + monitoring_tid = 0; } /* * Monitoring thread that loops on waiting for signals to be received */ static void * -monitoring_thread_loop(void *arg) +monitoring_thread_loop(UNUSED void *arg) { int res = 0; siginfo_t info; @@ -193,8 +199,6 @@ monitoring_thread_loop(void *arg) sigemptyset(&monitoring_sig_set); sigaddset(&monitoring_sig_set, MONITORING_THREAD_SIGNAL); - end_monitoring_thread = false; /* reset */ - monitoring_tid = syscall(SYS_gettid); dbg_printf("tid=%u - monitoring thread started", monitoring_tid); @@ -216,10 +220,9 @@ monitoring_thread_loop(void *arg) /* * Now that thread is initialized, let kqueue init resume */ - pthread_mutex_lock(arg); /* Must try to lock to ensure parent is waiting on signal */ + pthread_mutex_lock(&monitoring_thread_mtx); /* Must try to lock to ensure parent is waiting on signal */ pthread_cond_signal(&monitoring_thread_cond); - pthread_mutex_unlock(arg); - pthread_detach(pthread_self()); + pthread_mutex_unlock(&monitoring_thread_mtx); pthread_cleanup_push(monitoring_thread_cleanup, NULL) while (true) { @@ -232,35 +235,43 @@ monitoring_thread_loop(void *arg) (void) pthread_mutex_lock(&kq_mtx); if (res != -1) { dbg_printf("fd=%i - freeing kqueue due to fd closure", fd_map[info.si_fd]); - monitoring_thread_kq_cleanup(info.si_fd, false); + + /* + * If no more kqueues... exit. + */ + if (monitoring_thread_kq_cleanup(info.si_fd, false) == 0) + break; } else { dbg_perror("sigwaitinfo returned early"); } - - if (end_monitoring_thread) - break; - (void) pthread_mutex_unlock(&kq_mtx); } - pthread_cleanup_pop(true); + pthread_cleanup_pop(true); /* Executes the cleanup function (monitoring_thread_cleanup) */ + (void) pthread_mutex_unlock(&kq_mtx); return NULL; } -static void +static int linux_kqueue_start_thread(void) { - static pthread_mutex_t mt_mtx = PTHREAD_MUTEX_INITIALIZER; - - pthread_mutex_lock(&mt_mtx); - - if (pthread_create(&monitoring_thread, NULL, &monitoring_thread_loop, &mt_mtx)) { + pthread_mutex_lock(&monitoring_thread_mtx); + if (pthread_create(&monitoring_thread, NULL, &monitoring_thread_loop, &monitoring_thread_mtx)) { dbg_perror("linux_kqueue_start_thread failure"); + pthread_mutex_unlock(&monitoring_thread_mtx); + + return (-1); } + /* + * Ensures resources are released without an explicit join + */ + pthread_detach(monitoring_thread); /* Wait for thread creating to be done as we need monitoring_tid to be available */ - pthread_cond_wait(&monitoring_thread_cond, &mt_mtx); /* unlocks mt_mtx allowing child to lock it */ - pthread_mutex_unlock(&mt_mtx); + pthread_cond_wait(&monitoring_thread_cond, &monitoring_thread_mtx); /* unlocks mt_mtx allowing child to lock it */ + pthread_mutex_unlock(&monitoring_thread_mtx); + + return (0); } static int @@ -347,7 +358,12 @@ linux_kqueue_init(struct kqueue *kq) kqueue_cnt++; /* Start monitoring thread during first initialization */ - (void) pthread_once(&monitoring_thread_initialized, linux_kqueue_start_thread); + if (monitoring_tid == 0) { + if (linux_kqueue_start_thread() < 0) { + pthread_mutex_unlock(&kq_mtx); + return (-1); + } + } /* Update pipe FD map */ fd_map[kq->pipefd[0]] = kq->pipefd[1]; @@ -760,10 +776,10 @@ linux_eventfd_register(struct kqueue *kq, struct eventfd *efd) if (epoll_ctl(kq->epollfd, EPOLL_CTL_ADD, kqops.eventfd_descriptor(efd), EPOLL_EV_EVENTFD(EPOLLIN, efd)) < 0) { dbg_perror("epoll_ctl(2)"); - return -1; + return (-1); } - return 0; + return (0); } void From 60965ce495877584af9a76a1430525794b981403 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 17 Mar 2022 18:48:42 -0400 Subject: [PATCH 0974/1120] Typo --- vendor/libkqueue/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index 5c4649f00..fa39acea5 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -119,7 +119,7 @@ The libkqueue filter `EVFILT_LIBKQUEUE` exposes runtime configuration options an using `EVFILT_LIBKQUEUE` the `flags` field should be set to `EV_ADD`, and the `fflags` field should be one of the following: -- `NOTE_VERSION` return the current version as a 32 unsigned integer in the format `MMmmpprr` (`Major`, `minor`, `patch`, `release`) in the `data` field of an entry in the eventlist. +- `NOTE_VERSION` return the current version as a 32bit unsigned integer in the format `MMmmpprr` (`Major`, `minor`, `patch`, `release`) in the `data` field of an entry in the eventlist. - `NOTE_VERSION_STR` return the current version as a string in the `udata` field of an entry in the eventlist. Example - retrieving version string: From 81a6743ccd9bc636a36a6395928ae1d3dfd297fe Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 10:47:59 -0400 Subject: [PATCH 0975/1120] cache fds->fds_write to avoid ASAN complaints --- vendor/libkqueue/src/linux/platform.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index aa97b3e87..10c1bd72b 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -717,9 +717,15 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven case EPOLL_UDATA_FD_STATE: { struct fd_state *fds = epoll_udata->ud_fds; - struct knote *kn; + struct knote *kn, *write; assert(fds); + /* + * fds can be freed after the first linux_kevent_copyout_ev + * so cache the pointer value here. + */ + write = fds->fds_write; + /* * FD, or errored, or other side shutdown */ @@ -734,7 +740,7 @@ linux_kevent_copyout(struct kqueue *kq, int nready, struct kevent *el, int neven /* * FD is writable, or errored, or other side shutdown */ - if ((kn = fds->fds_write) && (ev->events & (EPOLLOUT | POLLHUP | EPOLLERR))) { + if ((kn = write) && (ev->events & (EPOLLOUT | POLLHUP | EPOLLERR))) { if (el_p >= el_end) goto oos; rv = linux_kevent_copyout_ev(el_p, (el_end - el_p), ev, knote_get_filter(kn), kn); From 37620eddcc0238af709d0a4c6243de856a9b2ce8 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 10:48:12 -0400 Subject: [PATCH 0976/1120] decrement kqueue_cnt on error --- vendor/libkqueue/src/linux/platform.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 10c1bd72b..8a0e62a62 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -360,8 +360,9 @@ linux_kqueue_init(struct kqueue *kq) /* Start monitoring thread during first initialization */ if (monitoring_tid == 0) { if (linux_kqueue_start_thread() < 0) { - pthread_mutex_unlock(&kq_mtx); - return (-1); + kqueue_cnt--; + (void) pthread_mutex_unlock(&kq_mtx); + goto error; } } From fe97081a55b04b4a285b11a68ab8129c118a61bb Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 11:19:19 -0400 Subject: [PATCH 0977/1120] Print what triggered the monitoring thread exit --- vendor/libkqueue/src/linux/platform.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 8a0e62a62..3f9372378 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -40,6 +40,11 @@ static pid_t monitoring_tid; /* Monitoring thread */ static pthread_mutex_t monitoring_thread_mtx = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t monitoring_thread_cond = PTHREAD_COND_INITIALIZER; +/* + * Monitoring thread is exiting because the process is terminating + */ +static bool monitoring_thread_on_exit = true; + /* * Number of active kqueues. * When the last kqueue is closed, the monitoring thread can be stopped. @@ -160,7 +165,8 @@ monitoring_thread_cleanup(void *arg) } } - dbg_printf("tid=%u - monitoring thread exiting", monitoring_tid); + dbg_printf("tid=%u - monitoring thread exiting (%s)", + monitoring_tid, monitoring_thread_on_exit ? "process term" : "no kqueues"); /* Free thread resources */ free(fd_map); fd_map = NULL; @@ -246,7 +252,9 @@ monitoring_thread_loop(UNUSED void *arg) } (void) pthread_mutex_unlock(&kq_mtx); } + monitoring_thread_on_exit = false; pthread_cleanup_pop(true); /* Executes the cleanup function (monitoring_thread_cleanup) */ + monitoring_thread_on_exit = true; (void) pthread_mutex_unlock(&kq_mtx); return NULL; From 6607684d2f2fa8533696f1c811a5b67791a82030 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 14:13:33 -0400 Subject: [PATCH 0978/1120] Print line numbers for lock and unlock --- vendor/libkqueue/src/common/debug.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index 6fc9f2564..54f1ff8cb 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -115,9 +115,9 @@ typedef struct { } while (0) # define tracing_mutex_lock(x) do { \ - dbg_printf("waiting for %s", #x); \ + dbg_printf("[%i]: waiting for %s", __LINE__, #x); \ pthread_mutex_lock(&((x)->mtx_lock)); \ - dbg_printf("locked %s", #x); \ + dbg_printf("[%i]: locked %s", __LINE__, #x); \ (x)->mtx_owner = THREAD_ID; \ (x)->mtx_status = MTX_LOCKED; \ } while (0) @@ -126,7 +126,7 @@ typedef struct { (x)->mtx_status = MTX_UNLOCKED; \ (x)->mtx_owner = -1; \ pthread_mutex_unlock(&((x)->mtx_lock)); \ - dbg_printf("unlocked %s", # x); \ + dbg_printf("[%i]: unlocked %s", __LINE__, # x); \ } while (0) #else /* NDEBUG */ From f539927ba7e2e9308b3695c50f9b51ced6bac83e Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 14:15:09 -0400 Subject: [PATCH 0979/1120] Use a tracing mutex for kq_mtx --- vendor/libkqueue/src/common/kqueue.c | 19 ++++++++++--------- vendor/libkqueue/src/linux/platform.c | 16 ++++++++-------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index d92053b5b..998f95204 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -20,12 +20,12 @@ int DEBUG_KQUEUE = 0; char *KQUEUE_DEBUG_IDENT = "KQ"; +tracing_mutex_t kq_mtx = TRACING_MUTEX_INITIALIZER; + #ifdef _WIN32 static LONG kq_init_begin = 0; static int kq_init_complete = 0; -pthread_mutex_t kq_mtx; #else -pthread_mutex_t kq_mtx = PTHREAD_MUTEX_INITIALIZER; pthread_once_t kq_is_initialized = PTHREAD_ONCE_INIT; #endif @@ -84,7 +84,7 @@ libkqueue_init(void) DEBUG_KQUEUE = 1; #ifdef _WIN32 - pthread_mutex_init(&kq_mtx, NULL); + tracing_mutex_init(&kq_mtx, NULL); /* Initialize the Winsock library */ WSADATA wsaData; if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) @@ -168,11 +168,11 @@ kqueue(void) } } - pthread_mutex_init(&kq_mtx, NULL); + tracing_mutex_init(&kq_mtx, NULL); #else - (void) pthread_mutex_lock(&kq_mtx); + tracing_mutex_lock(&kq_mtx); (void) pthread_once(&kq_is_initialized, libkqueue_init); - (void) pthread_mutex_unlock(&kq_mtx); + tracing_mutex_unlock(&kq_mtx); #endif kq = calloc(1, sizeof(*kq)); @@ -183,6 +183,7 @@ kqueue(void) if (kqops.kqueue_init(kq) < 0) { error: + dbg_printf("kq=%p - init failed", kq); tracing_mutex_destroy(&kq->kq_mtx); free(kq); return (-1); @@ -191,18 +192,18 @@ kqueue(void) dbg_printf("kq=%p - alloced with fd=%d", kq, kq->kq_id); /* Delete and insert should be atomic */ - (void) pthread_mutex_lock(&kq_mtx); + tracing_mutex_lock(&kq_mtx); kqueue_free_by_id(kq->kq_id); /* Free any old map entries */ if (map_insert(kqmap, kq->kq_id, kq) < 0) { dbg_printf("kq=%p - map insertion failed, freeing", kq); filter_unregister_all(kq); - pthread_mutex_unlock(&kq_mtx); + tracing_mutex_unlock(&kq_mtx); goto error; } - pthread_mutex_unlock(&kq_mtx); + tracing_mutex_unlock(&kq_mtx); return (kq->kq_id); } diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 3f9372378..86b3eb08c 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -30,7 +30,7 @@ */ static __thread struct epoll_event epoll_events[MAX_KEVENT]; -extern pthread_mutex_t kq_mtx; +extern tracing_mutex_t kq_mtx; /* * Monitoring thread that takes care of cleaning up kqueues (on linux only) */ @@ -238,7 +238,7 @@ monitoring_thread_loop(UNUSED void *arg) * should be performed on the kqueue. */ res = sigwaitinfo(&monitoring_sig_set, &info); - (void) pthread_mutex_lock(&kq_mtx); + tracing_mutex_lock(&kq_mtx); if (res != -1) { dbg_printf("fd=%i - freeing kqueue due to fd closure", fd_map[info.si_fd]); @@ -250,12 +250,12 @@ monitoring_thread_loop(UNUSED void *arg) } else { dbg_perror("sigwaitinfo returned early"); } - (void) pthread_mutex_unlock(&kq_mtx); + tracing_mutex_unlock(&kq_mtx); } monitoring_thread_on_exit = false; pthread_cleanup_pop(true); /* Executes the cleanup function (monitoring_thread_cleanup) */ monitoring_thread_on_exit = true; - (void) pthread_mutex_unlock(&kq_mtx); + tracing_mutex_unlock(&kq_mtx); return NULL; } @@ -355,7 +355,7 @@ linux_kqueue_init(struct kqueue *kq) goto error; } - (void) pthread_mutex_lock(&kq_mtx); + tracing_mutex_lock(&kq_mtx); /* * Increment kqueue counter - must be incremented before @@ -369,7 +369,7 @@ linux_kqueue_init(struct kqueue *kq) if (monitoring_tid == 0) { if (linux_kqueue_start_thread() < 0) { kqueue_cnt--; - (void) pthread_mutex_unlock(&kq_mtx); + tracing_mutex_unlock(&kq_mtx); goto error; } } @@ -391,12 +391,12 @@ linux_kqueue_init(struct kqueue *kq) if (fcntl(kq->pipefd[0], F_SETOWN_EX, &sig_owner) < 0) { dbg_printf("fd=%i - failed settting F_SETOWN to tid=%u: %s", monitoring_tid, kq->pipefd[0], strerror(errno)); kqueue_cnt--; - (void) pthread_mutex_unlock(&kq_mtx); + tracing_mutex_unlock(&kq_mtx); goto error; } dbg_printf("kq=%p - monitoring fd=%i for closure", kq, kq->pipefd[0]); - (void) pthread_mutex_unlock(&kq_mtx); + tracing_mutex_unlock(&kq_mtx); return (0); } From 9236fd6f8881f65596e831c9e36adc713912ee74 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 15:44:27 -0400 Subject: [PATCH 0980/1120] Keep kq_mtx locked for the entire init/free process This makes it significantly easier to deal with FD reuse for the Linux monitoring code. Remove explicit kq_mtx lock/unlock in linux init (not needed). Simplify kqueue use tracking. --- vendor/libkqueue/src/common/kqueue.c | 13 ++- vendor/libkqueue/src/linux/platform.c | 118 ++++++++++++++------------ 2 files changed, 72 insertions(+), 59 deletions(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 998f95204..5acc7c726 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -181,6 +181,15 @@ kqueue(void) tracing_mutex_init(&kq->kq_mtx, NULL); + /* + * Init, delete and insert should be atomic + * this is mainly for the monitoring thread + * on Linux, to ensure if an FD gets reused + * for a new KQ, the signal handler doesn't + * accidentally free up memory allocated to + * the new KQ. + */ + tracing_mutex_lock(&kq_mtx); if (kqops.kqueue_init(kq) < 0) { error: dbg_printf("kq=%p - init failed", kq); @@ -191,9 +200,6 @@ kqueue(void) dbg_printf("kq=%p - alloced with fd=%d", kq, kq->kq_id); - /* Delete and insert should be atomic */ - tracing_mutex_lock(&kq_mtx); - kqueue_free_by_id(kq->kq_id); /* Free any old map entries */ if (map_insert(kqmap, kq->kq_id, kq) < 0) { @@ -202,7 +208,6 @@ kqueue(void) tracing_mutex_unlock(&kq_mtx); goto error; } - tracing_mutex_unlock(&kq_mtx); return (kq->kq_id); diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 86b3eb08c..2d7090da5 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -63,14 +63,14 @@ static int *fd_map; /* * Map kqueue id to counter for kq cleanups. * When use counter is at 0, cleanup can be performed by signal handler. - * Otherwise, it means cleanup was already performed for this FD in linux_kqueue_free. + * Otherwise, it means cleanup was already performed for this FD in linux_kqueue_reused. */ static unsigned int *fd_use_cnt; static int nb_max_fd; static void -linux_kqueue_cleanup(struct kqueue *kq); +linux_kqueue_free(struct kqueue *kq); /** Clean up a kqueue from the perspective of the monitoring thread * @@ -81,7 +81,7 @@ linux_kqueue_cleanup(struct kqueue *kq); * - 1 if the monitoring thread should continue. */ static int -monitoring_thread_kq_cleanup(int signal_fd, bool ignore_use_count) +monitoring_thread_kq_cleanup(int signal_fd) { int fd; struct kqueue *kq; @@ -105,38 +105,31 @@ monitoring_thread_kq_cleanup(int signal_fd, bool ignore_use_count) } /* - * If kqueue instance for this FD hasn't been cleaned yet - * - * The issue the fd_use_cnt array prevents, is where kqueue - * allocates a KQ, and takes the opportunity to cleanup an - * old KQ instance, and this happens before the monitoring - * thread is woken up to reap the KQ itself. + * Decrement use counter as signal handler has been run for + * this FD. We rely on using an RT signal so that multiple + * signals are queued. + */ + fd_use_cnt[signal_fd]--; + assert(fd_use_cnt[signal_fd] >= 0); + + /* + * If kqueue instance for this FD hasn't been cleaned up yet * - * If the KQ has already been freed, we don't want to do - * anything here, as that will destroy the newly allocated - * KQ that shares an identifier with the old KQ. + * When the main kqueue code frees a kq, the file descriptor + * of the kq often gets reused. * - * It's a counter because multiple signals may be queued. + * We maintain a count of how many allocations have been + * performed against a given file descriptor ID, and only + * free the kqueue here if that count is zero. */ - if (ignore_use_count || (fd_use_cnt[fd] == 0)) { - dbg_printf("kq=%p - fd=%i use_count=%u cleaning up...", kq, fd, fd_use_cnt[fd]); + if (fd_use_cnt[signal_fd] == 0) { + dbg_printf("kq=%p - fd=%i use_count=%u cleaning up...", kq, fd, fd_use_cnt[signal_fd]); kqueue_free(kq); } else { - dbg_printf("kq=%p - fd=%i use_count=%u skipping...", kq, fd, fd_use_cnt[fd]); + dbg_printf("kq=%p - fd=%i use_count=%u skipping...", kq, fd, fd_use_cnt[signal_fd]); } check_count: - /* - * Forcefully cleaning up like this breaks use counting - * so we reset the use count to 0, and don't allow it to - * go below 0 if we later receive delayed signals. - */ - if (ignore_use_count) { - fd_use_cnt[fd] = 0; - } else if (fd_use_cnt[fd] > 0) { - fd_use_cnt[fd]--; /* Decrement use counter as signal handler has been run for this FD */ - } - /* * Stop thread if all kqueues have been closed */ @@ -149,6 +142,8 @@ monitoring_thread_cleanup(void *arg) { int i; + dbg_printf("scanning FDs 0-%i", nb_max_fd); + for (i = 0; i < nb_max_fd; i++) { if (fd_use_cnt[i] > 0) { int fd; @@ -157,10 +152,9 @@ monitoring_thread_cleanup(void *arg) dbg_printf("Checking rfd=%i wfd=%i", i, fd); if (fcntl(fd, F_GETFD) < 0) { dbg_printf("fd=%i - forcefully cleaning up, use_count=%u: %s", - fd, fd_use_cnt[fd], strerror(errno)); - fd_use_cnt[fd] = 0; - (void)monitoring_thread_kq_cleanup(i, true); - fd_use_cnt[fd] = 0; + fd, fd_use_cnt[i], errno == EBADF ? "File descriptor already closed" : strerror(errno)); + fd_use_cnt[i] = 1; + (void)monitoring_thread_kq_cleanup(i); } } } @@ -175,6 +169,7 @@ monitoring_thread_cleanup(void *arg) /* Reset so that thread can be restarted */ monitoring_tid = 0; + monitoring_thread = 0; } /* @@ -238,6 +233,11 @@ monitoring_thread_loop(UNUSED void *arg) * should be performed on the kqueue. */ res = sigwaitinfo(&monitoring_sig_set, &info); + + /* + * Don't allow cancellation in the middle of cleaning up resources + */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); tracing_mutex_lock(&kq_mtx); if (res != -1) { dbg_printf("fd=%i - freeing kqueue due to fd closure", fd_map[info.si_fd]); @@ -245,13 +245,15 @@ monitoring_thread_loop(UNUSED void *arg) /* * If no more kqueues... exit. */ - if (monitoring_thread_kq_cleanup(info.si_fd, false) == 0) + if (monitoring_thread_kq_cleanup(info.si_fd) == 0) break; } else { dbg_perror("sigwaitinfo returned early"); } tracing_mutex_unlock(&kq_mtx); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); } + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); monitoring_thread_on_exit = false; pthread_cleanup_pop(true); /* Executes the cleanup function (monitoring_thread_cleanup) */ monitoring_thread_on_exit = true; @@ -260,9 +262,26 @@ monitoring_thread_loop(UNUSED void *arg) return NULL; } +/* + * We have to use this instead of pthread_detach as there + * seems to be some sort of race with LSAN and thread cleanup + * on exit, and if we don't explicitly join the monitoring + * thread, LSAN reports kqueues as leaked. + */ +static void +linux_monitor_thread_join(void) +{ + if (monitoring_thread) { + pthread_cancel(monitoring_thread); + pthread_join(monitoring_thread, NULL); + } +} + static int linux_kqueue_start_thread(void) { + static bool done_at_exit_handler; + pthread_mutex_lock(&monitoring_thread_mtx); if (pthread_create(&monitoring_thread, NULL, &monitoring_thread_loop, &monitoring_thread_mtx)) { dbg_perror("linux_kqueue_start_thread failure"); @@ -273,7 +292,10 @@ linux_kqueue_start_thread(void) /* * Ensures resources are released without an explicit join */ - pthread_detach(monitoring_thread); + if (!done_at_exit_handler) { + atexit(linux_monitor_thread_join); + done_at_exit_handler = true; + } /* Wait for thread creating to be done as we need monitoring_tid to be available */ pthread_cond_wait(&monitoring_thread_cond, &monitoring_thread_mtx); /* unlocks mt_mtx allowing child to lock it */ @@ -348,6 +370,9 @@ linux_kqueue_init(struct kqueue *kq) * * We may want to make this configurable at runtime later * so we won't conflict with the application. + * + * Note: MONITORING_THREAD_SIGNAL must be >= SIGRTMIN so that + * multiple signals are queued. */ if (fcntl(kq->pipefd[0], F_SETSIG, MONITORING_THREAD_SIGNAL) < 0) { dbg_printf("fd=%i - failed settting F_SETSIG sig=%u: %s", @@ -355,8 +380,6 @@ linux_kqueue_init(struct kqueue *kq) goto error; } - tracing_mutex_lock(&kq_mtx); - /* * Increment kqueue counter - must be incremented before * starting the monitoring thread in case there's a spurious @@ -369,13 +392,15 @@ linux_kqueue_init(struct kqueue *kq) if (monitoring_tid == 0) { if (linux_kqueue_start_thread() < 0) { kqueue_cnt--; - tracing_mutex_unlock(&kq_mtx); goto error; } } /* Update pipe FD map */ - fd_map[kq->pipefd[0]] = kq->pipefd[1]; + fd_map[kq->pipefd[0]] = kq->kq_id; + + /* Mark this id as in use */ + fd_use_cnt[kq->pipefd[0]]++; dbg_printf("active_kqueues=%u", kqueue_cnt); @@ -396,8 +421,6 @@ linux_kqueue_init(struct kqueue *kq) } dbg_printf("kq=%p - monitoring fd=%i for closure", kq, kq->pipefd[0]); - tracing_mutex_unlock(&kq_mtx); - return (0); } @@ -409,7 +432,7 @@ linux_kqueue_init(struct kqueue *kq) * - false if epoll fd was already closed */ static void -linux_kqueue_cleanup(struct kqueue *kq) +linux_kqueue_free(struct kqueue *kq) { char buffer; ssize_t ret; @@ -458,21 +481,6 @@ linux_kqueue_cleanup(struct kqueue *kq) dbg_printf("kq=%p - cleaned up kqueue, active_kqueues=%u", kq, kqueue_cnt); } -/** Explicitly free the kqueue - * - * This is only called from the public kqueue function when a map - * slot is going to be re-used, so it's an indicator that the - * KQ fd is in use, and we shouldn't attempt to free it if we - * receive a signal in the monitoring thread. - */ -static void -linux_kqueue_free(struct kqueue *kq) -{ - linux_kqueue_cleanup(kq); - fd_use_cnt[kq->kq_id]++; - dbg_printf("kq=%p - increased fd=%i use_count=%u", kq, kq->kq_id, fd_use_cnt[kq->kq_id]); -} - static int linux_kevent_wait_hires( struct kqueue *kq, From ed31fdc75df2b6d2bb8151223b74d34eaba6bc01 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 16:08:41 -0400 Subject: [PATCH 0981/1120] Split FD scan code --- vendor/libkqueue/src/linux/platform.c | 62 +++++++++++++++++++++------ 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 2d7090da5..e719a29ab 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -104,13 +104,18 @@ monitoring_thread_kq_cleanup(int signal_fd) goto check_count; } + /* + * We should never have more pending signals than we have + * allocated kqueues against a given ID. + */ + assert(fd_use_cnt[signal_fd] > 0); + /* * Decrement use counter as signal handler has been run for * this FD. We rely on using an RT signal so that multiple * signals are queued. */ fd_use_cnt[signal_fd]--; - assert(fd_use_cnt[signal_fd] >= 0); /* * If kqueue instance for this FD hasn't been cleaned up yet @@ -138,26 +143,56 @@ monitoring_thread_kq_cleanup(int signal_fd) } static void -monitoring_thread_cleanup(void *arg) +monitoring_thread_scan_for_closed(void) { int i; dbg_printf("scanning FDs 0-%i", nb_max_fd); for (i = 0; i < nb_max_fd; i++) { - if (fd_use_cnt[i] > 0) { - int fd; - - fd = fd_map[i]; - dbg_printf("Checking rfd=%i wfd=%i", i, fd); - if (fcntl(fd, F_GETFD) < 0) { - dbg_printf("fd=%i - forcefully cleaning up, use_count=%u: %s", - fd, fd_use_cnt[i], errno == EBADF ? "File descriptor already closed" : strerror(errno)); - fd_use_cnt[i] = 1; - (void)monitoring_thread_kq_cleanup(i); - } + int fd; + + if (fd_use_cnt[i] == 0) continue; + + fd = fd_map[i]; + dbg_printf("Checking rfd=%i wfd=%i", i, fd); + if (fcntl(fd, F_GETFD) < 0) { + dbg_printf("fd=%i - forcefully cleaning up, use_count=%u: %s", + fd, fd_use_cnt[i], errno == EBADF ? "File descriptor already closed" : strerror(errno)); + + /* next call decrements */ + fd_use_cnt[i] = 1; + (void)monitoring_thread_kq_cleanup(i); } + + /* + * stop scanning if all the kqueues have been + * cleaned up. + */ + if (kqueue_cnt == 0) + break; } +} + +static void +monitoring_thread_cleanup(void *arg) +{ + /* + * If the entire process is exiting, then scan through + * all the in use file descriptors, checking to see if + * they've been closed or not. + * + * We do this because we don't reliably receive all the + * close MONITORING_THREAD_SIGNALs before the process + * exits, and this avoids ASAN or valgrind raising + * spurious memory leaks. + * + * If the user _hasn't_ closed a KQ fd, then we don't + * free the underlying memory, and it'll be correctly + * reported as a memory leak. + */ + if (monitoring_thread_on_exit) + monitoring_thread_scan_for_closed(); dbg_printf("tid=%u - monitoring thread exiting (%s)", monitoring_tid, monitoring_thread_on_exit ? "process term" : "no kqueues"); @@ -169,7 +204,6 @@ monitoring_thread_cleanup(void *arg) /* Reset so that thread can be restarted */ monitoring_tid = 0; - monitoring_thread = 0; } /* From 8b056ea470476bb7a59e9aaada5159eba4c75649 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 17:20:34 -0400 Subject: [PATCH 0982/1120] Use separate kq_mtx init for windows --- vendor/libkqueue/src/common/kqueue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 5acc7c726..3c91d2d2d 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -20,12 +20,12 @@ int DEBUG_KQUEUE = 0; char *KQUEUE_DEBUG_IDENT = "KQ"; -tracing_mutex_t kq_mtx = TRACING_MUTEX_INITIALIZER; - #ifdef _WIN32 +tracing_mutex_t kq_mtx; static LONG kq_init_begin = 0; static int kq_init_complete = 0; #else +tracing_mutex_t kq_mtx = TRACING_MUTEX_INITIALIZER; pthread_once_t kq_is_initialized = PTHREAD_ONCE_INIT; #endif From acf016fb9b042764e38e54c18692f750f2894be4 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 17:25:45 -0400 Subject: [PATCH 0983/1120] Add global init/free --- vendor/libkqueue/src/common/kqueue.c | 18 +++++++++++++++++- vendor/libkqueue/src/common/private.h | 10 ++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 3c91d2d2d..42fe1a207 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -73,6 +73,15 @@ get_fd_used(void) static struct map *kqmap; +void +libkqueue_free(void) +{ + dbg_puts("Releasing library resources"); + + if (kqops.libkqueue_free) + kqops.libkqueue_free(); +} + void libkqueue_init(void) { @@ -107,10 +116,17 @@ libkqueue_init(void) abort(); if (knote_init() < 0) abort(); - dbg_puts("library initialization complete"); + #ifdef _WIN32 kq_init_complete = 1; #endif + + if (kqops.libkqueue_init) + kqops.libkqueue_init(); + + dbg_puts("library initialization complete"); + + atexit(libkqueue_free); } void diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index f8a578e07..c75bee1d6 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -478,6 +478,16 @@ struct kqueue { * */ struct kqueue_vtable { + /** Called once on startup + * + */ + void (*libkqueue_init)(void); + + /** Called at exit + * + */ + void (*libkqueue_free)(void); + /** Called once for every kqueue created * */ From a3f944bdd33bd13abfb940883d27cff78ef2b5fe Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 17:29:54 -0400 Subject: [PATCH 0984/1120] Close all file descriptors for linux on fork --- vendor/libkqueue/BUGS.md | 48 ++++++++------- vendor/libkqueue/src/linux/platform.c | 84 ++++++++++++++++++--------- 2 files changed, 85 insertions(+), 47 deletions(-) diff --git a/vendor/libkqueue/BUGS.md b/vendor/libkqueue/BUGS.md index b2f9d96bb..7503c1b3a 100644 --- a/vendor/libkqueue/BUGS.md +++ b/vendor/libkqueue/BUGS.md @@ -5,12 +5,6 @@ ## Common - * We need to uninitialize library after `fork()` `using pthread_atfork()`. - BSD kqueue file descriptors are not inherited by the fork copy and - will be closed automatically in the fork. With libkqueue, because - we don't unitialize the library, kqueue file descriptors will persist - in the fork. - * Some functions should crash instead of silently printing a debug message.. for example, `note_release()`. @@ -38,24 +32,24 @@ the call stack to `kevent()`. ## POSIX - + * `EVFILT_PROC` - The POSIX implmentation requires that `SIGCHLD` be delivered to its global waiter thread so that the waiter can discover a - when child process exits `sigprocmask(2)` is used to mask `SIGCHLD` at a process - level. If the application unmasks `SIGCHLD` or installs a handler for it, + when child process exits `sigprocmask(2)` is used to mask `SIGCHLD` at a process + level. If the application unmasks `SIGCHLD` or installs a handler for it, the POSIX `EVFILT_PROC` code will not function. - - * `EVFILT_PROC` - If using the POSIX `EVFILT_PROC` the number of monitored - processes should be kept low (< 100). Because the Linux kernel coalesces - `SIGCHLD` (and other signals), the only way to reliably determine if a - monitored process has exited, is to loop through all PIDs registered by any - kqueue when we receive a `SIGCHLD`. This involves many calls to `waitid(2)` + + * `EVFILT_PROC` - If using the POSIX `EVFILT_PROC` the number of monitored + processes should be kept low (< 100). Because the Linux kernel coalesces + `SIGCHLD` (and other signals), the only way to reliably determine if a + monitored process has exited, is to loop through all PIDs registered by any + kqueue when we receive a `SIGCHLD`. This involves many calls to `waitid(2)` and may have a negative performance impact. - + * `EVFILT_PROC` - The notification list of the global waiter thread, and the - ready lists of individual kqueues share the same mutex. This may cause + ready lists of individual kqueues share the same mutex. This may cause performance issues where large numbers of processes are monitored. - + ## Linux * If a file descriptor outside of kqueue is closed, the internal kqueue @@ -71,9 +65,9 @@ If building against Kernels < 5.3 (where `pidfd_open()` is not available) the POSIX `EVFILT_PROC` code is used. See the POSIX section above for limitations of the POSIX `EVFILT_PROC` code. - - * `EVFILT_PROC` - Native kqueue provides notifications for any process that - is visible to the application process. On Linux/POSIX platforms only direct + + * `EVFILT_PROC` - Native kqueue provides notifications for any process that + is visible to the application process. On Linux/POSIX platforms only direct children of the application process can be monitored for exit. ## Solaris @@ -95,6 +89,12 @@ Applications should ensure that file descriptors are removed from the kqueue before they are closed. + * We need to uninitialize library after `fork()` `using pthread_atfork()`. + BSD kqueue file descriptors are not inherited by the fork copy and + will be closed automatically in the fork. With libkqueue, because + we don't unitialize the library, kqueue file descriptors will persist + in the fork. + ## Windows * On Windows, you need to supply `-DMAKE_STATIC` in `CFLAGS` when building the @@ -105,6 +105,12 @@ Applications should ensure that file descriptors are removed from the kqueue before they are closed. + * We need to uninitialize library after `fork()` `using pthread_atfork()`. + BSD kqueue file descriptors are not inherited by the fork copy and + will be closed automatically in the fork. With libkqueue, because + we don't unitialize the library, kqueue file descriptors will persist + in the fork. + # libkqueue (kernel) * When passing a knote pointer to the kernel, the reference count of diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index e719a29ab..606f64a89 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -147,9 +147,15 @@ monitoring_thread_scan_for_closed(void) { int i; + /* + * Avoid debug output below + */ + if (kqueue_cnt == 0) + return; + dbg_printf("scanning FDs 0-%i", nb_max_fd); - for (i = 0; i < nb_max_fd; i++) { + for (i = 0; (kqueue_cnt > 0) && (i < nb_max_fd); i++) { int fd; if (fd_use_cnt[i] == 0) continue; @@ -164,18 +170,11 @@ monitoring_thread_scan_for_closed(void) fd_use_cnt[i] = 1; (void)monitoring_thread_kq_cleanup(i); } - - /* - * stop scanning if all the kqueues have been - * cleaned up. - */ - if (kqueue_cnt == 0) - break; } } static void -monitoring_thread_cleanup(void *arg) +monitoring_thread_cleanup(UNUSED void *arg) { /* * If the entire process is exiting, then scan through @@ -296,6 +295,23 @@ monitoring_thread_loop(UNUSED void *arg) return NULL; } +static int +linux_kqueue_start_thread(void) +{ + pthread_mutex_lock(&monitoring_thread_mtx); + if (pthread_create(&monitoring_thread, NULL, &monitoring_thread_loop, &monitoring_thread_mtx)) { + dbg_perror("linux_kqueue_start_thread failure"); + pthread_mutex_unlock(&monitoring_thread_mtx); + + return (-1); + } + /* Wait for thread creating to be done as we need monitoring_tid to be available */ + pthread_cond_wait(&monitoring_thread_cond, &monitoring_thread_mtx); /* unlocks mt_mtx allowing child to lock it */ + pthread_mutex_unlock(&monitoring_thread_mtx); + + return (0); +} + /* * We have to use this instead of pthread_detach as there * seems to be some sort of race with LSAN and thread cleanup @@ -311,31 +327,45 @@ linux_monitor_thread_join(void) } } -static int -linux_kqueue_start_thread(void) +static void +linux_at_fork(void) { - static bool done_at_exit_handler; + int i; - pthread_mutex_lock(&monitoring_thread_mtx); - if (pthread_create(&monitoring_thread, NULL, &monitoring_thread_loop, &monitoring_thread_mtx)) { - dbg_perror("linux_kqueue_start_thread failure"); - pthread_mutex_unlock(&monitoring_thread_mtx); + /* + * forcefully close all outstanding kqueues + */ + tracing_mutex_lock(&kq_mtx); + for (i = 0; (kqueue_cnt > 0) && (i < nb_max_fd); i++) { + if (fd_use_cnt[i] == 0) continue; - return (-1); + dbg_printf("Closing kq fd=%i due to fork", i); + close(i); + fd_use_cnt[i] = 1; + (void)monitoring_thread_kq_cleanup(i); } + tracing_mutex_unlock(&kq_mtx); + /* - * Ensures resources are released without an explicit join + * re-initialises everything so that the child could + * in theory allocate a new set of kqueues. + * + * Children don't appear to inherit pending signals + * so this should all still work as intended. */ - if (!done_at_exit_handler) { - atexit(linux_monitor_thread_join); - done_at_exit_handler = true; - } + linux_monitor_thread_join(); +} - /* Wait for thread creating to be done as we need monitoring_tid to be available */ - pthread_cond_wait(&monitoring_thread_cond, &monitoring_thread_mtx); /* unlocks mt_mtx allowing child to lock it */ - pthread_mutex_unlock(&monitoring_thread_mtx); +static void +linux_libkqueue_free(void) +{ + linux_monitor_thread_join(); +} - return (0); +static void +linux_libkqueue_init(void) +{ + pthread_atfork(NULL, NULL, linux_at_fork); } static int @@ -1483,6 +1513,8 @@ linux_fd_to_path(char *buf, size_t bufsz, int fd) } const struct kqueue_vtable kqops = { + .libkqueue_init = linux_libkqueue_init, + .libkqueue_free = linux_libkqueue_free, .kqueue_init = linux_kqueue_init, .kqueue_free = linux_kqueue_free, .kevent_wait = linux_kevent_wait, From d2722036a5506a45e56ca035f9cf2510b698c734 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 20:10:58 -0400 Subject: [PATCH 0985/1120] Actually zero out fields in linked lists, don't just pretend --- vendor/libkqueue/src/common/private.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index c75bee1d6..bde0a90e8 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -62,6 +62,12 @@ struct evfilt_data; */ #define LIST_INSERTED(elm, field) (((elm)->field.le_next) || ((elm)->field.le_prev)) +/** Have the trashit macro set the "trashed" value to NULL, so the LIST_INSERTED macro works + * + */ +#undef TRASHIT +#define TRASHIT(x) x = NULL + /** On Linux LIST_FOREACH_SAFE isn't provided * */ From d0055326c591a22f2529c940112bc232aa4032e8 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 21:01:29 -0400 Subject: [PATCH 0986/1120] More verbose errors on close failure --- vendor/libkqueue/src/linux/platform.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 606f64a89..55a984ea0 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -506,7 +506,7 @@ linux_kqueue_free(struct kqueue *kq) dbg_printf("epoll_fd=%i - closed", kq->epollfd); if (close(kq->epollfd) < 0) - dbg_perror("close(2)"); + dbg_perror("close(2) - epoll_fd=%i", kq->epollfd); kq->epollfd = -1; } @@ -522,7 +522,7 @@ linux_kqueue_free(struct kqueue *kq) dbg_puts("kqueue wasn't closed"); if (close(kq->pipefd[1]) < 0) - dbg_perror("close(2)"); + dbg_perror("close(2) - pipefd[1]=%i", kq->pipefd[1]); kq->pipefd[1] = -1; } else if (ret > 0) { // Shouldn't happen unless data is written to kqueue FD @@ -536,7 +536,7 @@ linux_kqueue_free(struct kqueue *kq) dbg_printf("kq_fd=%i - closed", pipefd); if (close(pipefd) < 0) - dbg_perror("close(2)"); + dbg_perror("close(2) - pipefd[0]=%i", kq->pipefd[0]); kq->pipefd[0] = -1; } From 611d5a7293c7c0cd07ab3dcb77c5621d453f5b49 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 21:02:23 -0400 Subject: [PATCH 0987/1120] Don't just pretend to remove things from lists... --- vendor/libkqueue/src/common/knote.c | 4 ++-- vendor/libkqueue/src/common/private.h | 9 ++++++--- vendor/libkqueue/src/posix/proc.c | 10 +++++----- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index d53c5d2cd..81d25640e 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -141,7 +141,7 @@ knote_delete(struct filter *filt, struct knote *kn) RB_REMOVE(knote_index, &filt->kf_index, kn); if (LIST_INSERTED(kn, kn_ready)) - LIST_REMOVE(kn, kn_ready); + LIST_REMOVE_ZERO(kn, kn_ready); tracing_mutex_unlock(&filt->kf_knote_mtx); rv = filt->kn_delete(filt, kn); @@ -166,7 +166,7 @@ knote_disable(struct filter *filt, struct knote *kn) if (rv == 0) { tracing_mutex_lock(&filt->kf_knote_mtx); if (LIST_INSERTED(kn, kn_ready)) /* No longer marked as ready if disabled */ - LIST_REMOVE(kn, kn_ready); + LIST_REMOVE_ZERO(kn, kn_ready); tracing_mutex_unlock(&filt->kf_knote_mtx); KNOTE_DISABLE(kn); /* set the disable flag */ } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index bde0a90e8..0ef1278d8 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -62,11 +62,14 @@ struct evfilt_data; */ #define LIST_INSERTED(elm, field) (((elm)->field.le_next) || ((elm)->field.le_prev)) -/** Have the trashit macro set the "trashed" value to NULL, so the LIST_INSERTED macro works +/** Variant of LIST_REMOVE which sets next/prev fields to NULL so that LIST_INSERTED works * */ -#undef TRASHIT -#define TRASHIT(x) x = NULL +#define LIST_REMOVE_ZERO(elm, field) do { \ + LIST_REMOVE(elm, field); \ + (elm)->field.le_next = NULL; \ + (elm)->field.le_prev = NULL; \ +} while(0) /** On Linux LIST_FOREACH_SAFE isn't provided * diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 66ba5aeb2..4a86a4de7 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -89,7 +89,7 @@ waiter_notify(struct proc_pid *ppd, int status) kqops.eventfd_raise(&filt->kf_proc_eventfd); LIST_INSERT_HEAD(&filt->kf_ready, kn, kn_ready); /* protected by proc_pid_index_mtx */ - LIST_REMOVE(kn, kn_proc_waiter); + LIST_REMOVE_ZERO(kn, kn_proc_waiter); } dbg_printf("pid=%u removing waiter list", (unsigned int)ppd->ppd_pid); @@ -113,7 +113,7 @@ waiter_notify_error(struct proc_pid *ppd, int wait_errno) kqops.eventfd_raise(&filt->kf_proc_eventfd); LIST_INSERT_HEAD(&filt->kf_ready, kn, kn_ready); /* protected by proc_pid_index_mtx */ - LIST_REMOVE(kn, kn_proc_waiter); + LIST_REMOVE_ZERO(kn, kn_proc_waiter); } dbg_printf("pid=%u removing waiter list", (unsigned int)ppd->ppd_pid); @@ -470,7 +470,7 @@ evfilt_proc_knote_delete(UNUSED struct filter *filt, struct knote *kn) struct proc_pid *ppd; tracing_mutex_lock(&proc_pid_index_mtx); - if (LIST_INSERTED(kn, kn_proc_waiter)) LIST_REMOVE(kn, kn_proc_waiter); + if (LIST_INSERTED(kn, kn_proc_waiter)) LIST_REMOVE_ZERO(kn, kn_proc_waiter); /* * ppd may have been removed already if there @@ -507,7 +507,7 @@ evfilt_proc_knote_disable(UNUSED struct filter *filt, struct knote *kn) * as knote_create when re-enabling. */ tracing_mutex_lock(&proc_pid_index_mtx); - if (LIST_INSERTED(kn, kn_proc_waiter)) LIST_REMOVE(kn, kn_proc_waiter); + if (LIST_INSERTED(kn, kn_proc_waiter)) LIST_REMOVE_ZERO(kn, kn_proc_waiter); tracing_mutex_unlock(&proc_pid_index_mtx); return (0); @@ -560,7 +560,7 @@ evfilt_proc_knote_copyout(struct kevent *dst, int nevents, struct filter *filt, dst_p->flags |= EV_EOF; dst_p->data = kn->kn_proc_status; - LIST_REMOVE(kn, kn_ready); /* knote_copyout_flag_actions may free the knote */ + LIST_REMOVE_ZERO(kn, kn_ready); /* knote_copyout_flag_actions may free the knote */ if (knote_copyout_flag_actions(filt, kn) < 0) { LIST_INSERT_HEAD(&filt->kf_ready, kn, kn_ready); From 7dd07d5d2637ee8477e67ea3d31c057ee7aba811 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 22:04:29 -0400 Subject: [PATCH 0988/1120] Better errors on eventfd reg/dereg --- vendor/libkqueue/src/linux/platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 55a984ea0..f2e182bd1 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -862,7 +862,7 @@ linux_eventfd_register(struct kqueue *kq, struct eventfd *efd) EVENTFD_UDATA(efd); /* setup udata for the efd */ if (epoll_ctl(kq->epollfd, EPOLL_CTL_ADD, kqops.eventfd_descriptor(efd), EPOLL_EV_EVENTFD(EPOLLIN, efd)) < 0) { - dbg_perror("epoll_ctl(2)"); + dbg_perror("epoll_ctl(2) - register epoll_fd=%i eventfd=%i", kq->epollfd, kqops.eventfd_descriptor(efd)); return (-1); } @@ -873,7 +873,7 @@ void linux_eventfd_unregister(struct kqueue *kq, struct eventfd *efd) { if (epoll_ctl(kq->epollfd, EPOLL_CTL_DEL, kqops.eventfd_descriptor(efd), NULL) < 0) - dbg_perror("epoll_ctl(2)"); + dbg_perror("epoll_ctl(2) - unregister epoll_fd=%i eventfd=%i", kq->epollfd, kqops.eventfd_descriptor(efd)); } static int From 628f381f254d3096574cd8087d10583af48da911 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 22:04:49 -0400 Subject: [PATCH 0989/1120] Better errors when close fails --- vendor/libkqueue/src/linux/platform.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index f2e182bd1..b7df51d0f 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -521,8 +521,11 @@ linux_kqueue_free(struct kqueue *kq) // Shoudn't happen unless kqops.kqueue_free is called on an open FD dbg_puts("kqueue wasn't closed"); - if (close(kq->pipefd[1]) < 0) + if (close(kq->pipefd[1]) < 0) { dbg_perror("close(2) - pipefd[1]=%i", kq->pipefd[1]); + } else { + dbg_printf("pipefd[1]=%i - closed", kq->pipefd[1]); + } kq->pipefd[1] = -1; } else if (ret > 0) { // Shouldn't happen unless data is written to kqueue FD @@ -533,10 +536,11 @@ linux_kqueue_free(struct kqueue *kq) pipefd = kq->pipefd[0]; if (pipefd > 0) { - dbg_printf("kq_fd=%i - closed", pipefd); - - if (close(pipefd) < 0) - dbg_perror("close(2) - pipefd[0]=%i", kq->pipefd[0]); + if (close(pipefd) < 0) { + dbg_perror("close(2) - kq_fd=%i", kq->pipefd[0]); + } else { + dbg_printf("kq_fd=%i - closed", kq->pipefd[0]); + } kq->pipefd[0] = -1; } From f49c8cf3bf3f3d1fac0581c02a9463c5ead5d8bd Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 22:11:12 -0400 Subject: [PATCH 0990/1120] don't bother locking/unlocking the mutex on EINTR in the linux cleanup thread --- vendor/libkqueue/src/linux/platform.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index b7df51d0f..a3fa78ea4 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -266,6 +266,10 @@ monitoring_thread_loop(UNUSED void *arg) * should be performed on the kqueue. */ res = sigwaitinfo(&monitoring_sig_set, &info); + if ((res == -1) && (errno = EINTR)) { + dbg_printf("sigwaitinfo(2): %s", strerror(errno)); + continue; + } /* * Don't allow cancellation in the middle of cleaning up resources From 74021c0b3477f34735e7db2a6f4f263b4940fa64 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 22:11:29 -0400 Subject: [PATCH 0991/1120] debug message consistency --- vendor/libkqueue/src/linux/platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index a3fa78ea4..26da1b0c5 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -153,7 +153,7 @@ monitoring_thread_scan_for_closed(void) if (kqueue_cnt == 0) return; - dbg_printf("scanning FDs 0-%i", nb_max_fd); + dbg_printf("scanning fds 0-%i", nb_max_fd); for (i = 0; (kqueue_cnt > 0) && (i < nb_max_fd); i++) { int fd; @@ -161,7 +161,7 @@ monitoring_thread_scan_for_closed(void) if (fd_use_cnt[i] == 0) continue; fd = fd_map[i]; - dbg_printf("Checking rfd=%i wfd=%i", i, fd); + dbg_printf("checking rfd=%i wfd=%i", i, fd); if (fcntl(fd, F_GETFD) < 0) { dbg_printf("fd=%i - forcefully cleaning up, use_count=%u: %s", fd, fd_use_cnt[i], errno == EBADF ? "File descriptor already closed" : strerror(errno)); From fa26ea85f742ea7870d4d8cfabb9eb17b82fb015 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 22:11:49 -0400 Subject: [PATCH 0992/1120] Close the epollfd immediately when closing kqueues on fork --- vendor/libkqueue/src/linux/platform.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 26da1b0c5..827424ce2 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -81,7 +81,7 @@ linux_kqueue_free(struct kqueue *kq); * - 1 if the monitoring thread should continue. */ static int -monitoring_thread_kq_cleanup(int signal_fd) +monitoring_thread_kq_cleanup(int signal_fd, bool closed_on_fork) { int fd; struct kqueue *kq; @@ -104,6 +104,23 @@ monitoring_thread_kq_cleanup(int signal_fd) goto check_count; } + /* + * On fork the epoll fd is inherited by the child process + * Any modifications made by the child affect the parent's + * epoll instance. + * + * So... if we remove file descriptors in the child, then + * we can break functionality for the parent. + * + * Our only option is to close the epollfd, and check for + * an invalid epollfd when deregistering file descriptors + * and ignore the operation. + */ + if (closed_on_fork) { + close(kq->epollfd); + kq->epollfd = -1; + } + /* * We should never have more pending signals than we have * allocated kqueues against a given ID. @@ -168,7 +185,7 @@ monitoring_thread_scan_for_closed(void) /* next call decrements */ fd_use_cnt[i] = 1; - (void)monitoring_thread_kq_cleanup(i); + (void)monitoring_thread_kq_cleanup(i, false); } } } @@ -282,7 +299,7 @@ monitoring_thread_loop(UNUSED void *arg) /* * If no more kqueues... exit. */ - if (monitoring_thread_kq_cleanup(info.si_fd) == 0) + if (monitoring_thread_kq_cleanup(info.si_fd, false) == 0) break; } else { dbg_perror("sigwaitinfo returned early"); @@ -346,7 +363,8 @@ linux_at_fork(void) dbg_printf("Closing kq fd=%i due to fork", i); close(i); fd_use_cnt[i] = 1; - (void)monitoring_thread_kq_cleanup(i); + + (void)monitoring_thread_kq_cleanup(i, true); } tracing_mutex_unlock(&kq_mtx); From afc55e4cc1fabdfec5473641cdcbb220ea250489 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 22:13:27 -0400 Subject: [PATCH 0993/1120] Remove assert --- vendor/libkqueue/src/posix/proc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 4a86a4de7..bfeda87f6 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -404,13 +404,10 @@ evfilt_proc_destroy(struct filter *filt) tracing_mutex_lock(&proc_init_mtx); assert(proc_count > 0); if (--proc_count == 0) { - void *retval; - pthread_cancel(proc_wait_thread_id); - if (pthread_join(proc_wait_thread_id, &retval) < 0) { + if (pthread_join(proc_wait_thread_id, NULL) < 0) { dbg_printf("pthread_join(2) %s", strerror(errno)); } else { - assert(retval == PTHREAD_CANCELED); dbg_puts("waiter thread joined"); } } From b46b28ea241a0545f52739874782f7ad32051ee3 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 22:31:28 -0400 Subject: [PATCH 0994/1120] more debug output... --- vendor/libkqueue/src/common/kqueue.c | 2 +- vendor/libkqueue/src/linux/platform.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 42fe1a207..9dad164bd 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -76,7 +76,7 @@ static struct map *kqmap; void libkqueue_free(void) { - dbg_puts("Releasing library resources"); + dbg_puts("releasing library resources"); if (kqops.libkqueue_free) kqops.libkqueue_free(); diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 827424ce2..e5036b8fe 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -343,7 +343,9 @@ static void linux_monitor_thread_join(void) { if (monitoring_thread) { - pthread_cancel(monitoring_thread); + dbg_printf("tid=%u - signalling to exit", monitoring_tid); + if (pthread_cancel(monitoring_thread) < 0) + dbg_perror("tid=%u - signalling failed", monitoring_tid); pthread_join(monitoring_thread, NULL); } } From da4f0e716eb2c49f27d7c54b9b97cd35b5bdd879 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 22:41:03 -0400 Subject: [PATCH 0995/1120] don't cancel the monitoring thread twice --- vendor/libkqueue/src/linux/platform.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index e5036b8fe..1dcd570eb 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -342,12 +342,16 @@ linux_kqueue_start_thread(void) static void linux_monitor_thread_join(void) { - if (monitoring_thread) { + static tracing_mutex_t signal_mtx = TRACING_MUTEX_INITIALIZER; + + tracing_mutex_lock(&signal_mtx); + if (monitoring_tid) { dbg_printf("tid=%u - signalling to exit", monitoring_tid); if (pthread_cancel(monitoring_thread) < 0) dbg_perror("tid=%u - signalling failed", monitoring_tid); pthread_join(monitoring_thread, NULL); } + tracing_mutex_unlock(&signal_mtx); } static void From e75c0f5ed3cc69dc7ec0d87c1cd3565de6f8d9c9 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 23:04:42 -0400 Subject: [PATCH 0996/1120] don't re-enable cancellation, it's not necessary --- vendor/libkqueue/src/linux/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 1dcd570eb..3c81df999 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -285,6 +285,7 @@ monitoring_thread_loop(UNUSED void *arg) res = sigwaitinfo(&monitoring_sig_set, &info); if ((res == -1) && (errno = EINTR)) { dbg_printf("sigwaitinfo(2): %s", strerror(errno)); + pthread_testcancel(); continue; } @@ -307,7 +308,6 @@ monitoring_thread_loop(UNUSED void *arg) tracing_mutex_unlock(&kq_mtx); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); } - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); monitoring_thread_on_exit = false; pthread_cleanup_pop(true); /* Executes the cleanup function (monitoring_thread_cleanup) */ monitoring_thread_on_exit = true; From 5a04b011106e0df584f9bfc872a4dc4f2db054c9 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 23:15:49 -0400 Subject: [PATCH 0997/1120] Add trylock macro --- vendor/libkqueue/src/common/debug.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index 54f1ff8cb..6b079c74d 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -122,6 +122,18 @@ typedef struct { (x)->mtx_status = MTX_LOCKED; \ } while (0) +# define tracing_mutex_trylock(ret, x) do { \ + dbg_printf("[%i]: waiting for %s", __LINE__, #x); \ + ret = pthread_mutex_trylock(&((x)->mtx_lock)); \ + if (ret == 0) { \ + dbg_printf("[%i]: locked %s", __LINE__, #x); \ + (x)->mtx_owner = THREAD_ID; \ + (x)->mtx_status = MTX_LOCKED; \ + } else { \ + dbg_printf("[%i]: locking %s failed - %s", __LINE__, #x, strerror(ret)); \ + } \ +} while (0) + # define tracing_mutex_unlock(x) do { \ (x)->mtx_status = MTX_UNLOCKED; \ (x)->mtx_owner = -1; \ @@ -144,6 +156,7 @@ typedef struct { # define tracing_mutex_destroy pthread_mutex_destroy # define tracing_mutex_assert(x,y) # define tracing_mutex_lock pthread_mutex_lock +# define tracing_mutex_trylock(ret,x) do { ret = pthread_mutex_trylock(x); } while (0) # define tracing_mutex_unlock pthread_mutex_unlock #endif From 5f5829a821524a27ce0720ee3221ebf15aac119f Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 18 Mar 2022 23:16:05 -0400 Subject: [PATCH 0998/1120] Use trylock to try and fix deadlock... --- vendor/libkqueue/src/linux/platform.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 3c81df999..67b245634 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -285,7 +285,6 @@ monitoring_thread_loop(UNUSED void *arg) res = sigwaitinfo(&monitoring_sig_set, &info); if ((res == -1) && (errno = EINTR)) { dbg_printf("sigwaitinfo(2): %s", strerror(errno)); - pthread_testcancel(); continue; } @@ -343,15 +342,18 @@ static void linux_monitor_thread_join(void) { static tracing_mutex_t signal_mtx = TRACING_MUTEX_INITIALIZER; - - tracing_mutex_lock(&signal_mtx); - if (monitoring_tid) { - dbg_printf("tid=%u - signalling to exit", monitoring_tid); - if (pthread_cancel(monitoring_thread) < 0) - dbg_perror("tid=%u - signalling failed", monitoring_tid); - pthread_join(monitoring_thread, NULL); + int ret; + + tracing_mutex_trylock(ret, &signal_mtx); + if (ret == 0) { + if (monitoring_tid) { + dbg_printf("tid=%u - signalling to exit", monitoring_tid); + if (pthread_cancel(monitoring_thread) < 0) + dbg_perror("tid=%u - signalling failed", monitoring_tid); + pthread_join(monitoring_thread, NULL); + } + tracing_mutex_unlock(&signal_mtx); } - tracing_mutex_unlock(&signal_mtx); } static void From 7d227e0c27a54716f219cfc82184466040422a52 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 19 Mar 2022 08:57:38 -0400 Subject: [PATCH 0999/1120] Set a timeout of 5 minutes on all jobs --- vendor/libkqueue/.github/workflows/ci-freebsd.yml | 1 + vendor/libkqueue/.github/workflows/ci-linux.yml | 1 + vendor/libkqueue/.github/workflows/ci-macos.yml | 1 + vendor/libkqueue/.github/workflows/ci-windows.yml | 1 + 4 files changed, 4 insertions(+) diff --git a/vendor/libkqueue/.github/workflows/ci-freebsd.yml b/vendor/libkqueue/.github/workflows/ci-freebsd.yml index e42f125e6..abed74c12 100644 --- a/vendor/libkqueue/.github/workflows/ci-freebsd.yml +++ b/vendor/libkqueue/.github/workflows/ci-freebsd.yml @@ -9,6 +9,7 @@ on: jobs: freebsd-tests: + timeout-minutes: 5 runs-on: macos-latest name: "FreeBSD tests" steps: diff --git a/vendor/libkqueue/.github/workflows/ci-linux.yml b/vendor/libkqueue/.github/workflows/ci-linux.yml index 122f2fc34..13d9c6f36 100644 --- a/vendor/libkqueue/.github/workflows/ci-linux.yml +++ b/vendor/libkqueue/.github/workflows/ci-linux.yml @@ -14,6 +14,7 @@ env: jobs: linux-build-and-test: + timeout-minutes: 5 strategy: fail-fast: false matrix: diff --git a/vendor/libkqueue/.github/workflows/ci-macos.yml b/vendor/libkqueue/.github/workflows/ci-macos.yml index 07e0b358f..708375670 100644 --- a/vendor/libkqueue/.github/workflows/ci-macos.yml +++ b/vendor/libkqueue/.github/workflows/ci-macos.yml @@ -9,6 +9,7 @@ on: jobs: macos-tests: + timeout-minutes: 5 runs-on: macos-latest name: "macOS tests" steps: diff --git a/vendor/libkqueue/.github/workflows/ci-windows.yml b/vendor/libkqueue/.github/workflows/ci-windows.yml index 12396c483..c74d918f6 100644 --- a/vendor/libkqueue/.github/workflows/ci-windows.yml +++ b/vendor/libkqueue/.github/workflows/ci-windows.yml @@ -11,6 +11,7 @@ env: jobs: windows-build: + timeout-minutes: 5 runs-on: windows-2019 name: CI-windows (build) From 783d2f63d2e08e479b48c1ff2ea2ec1313ef0e0f Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 19 Mar 2022 09:53:22 -0400 Subject: [PATCH 1000/1120] Simplify cleanup code Don't attempt to cancel the monitor thread on fork, it's likely not duplicated. --- vendor/libkqueue/src/linux/platform.c | 127 +++++++++++--------------- 1 file changed, 55 insertions(+), 72 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 67b245634..ae653c437 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -17,6 +17,7 @@ #define _GNU_SOURCE #include #include +#include #include #include @@ -75,13 +76,9 @@ linux_kqueue_free(struct kqueue *kq); /** Clean up a kqueue from the perspective of the monitoring thread * * Called with the kq_mtx held. - * - * @return - * - 0 if the monitoring thread should exit. - * - 1 if the monitoring thread should continue. */ -static int -monitoring_thread_kq_cleanup(int signal_fd, bool closed_on_fork) +static void +linux_kqueue_cleanup(int signal_fd, bool closed_on_fork) { int fd; struct kqueue *kq; @@ -94,14 +91,14 @@ monitoring_thread_kq_cleanup(int signal_fd, bool closed_on_fork) if (fd < 0) { /* Should not happen */ dbg_printf("fd=%i - not a known FD", fd); - goto check_count; + return; } kq = kqueue_lookup(fd); if (!kq) { /* Should not happen */ dbg_printf("fd=%i - no kqueue associated", fd); - goto check_count; + return; } /* @@ -150,44 +147,6 @@ monitoring_thread_kq_cleanup(int signal_fd, bool closed_on_fork) } else { dbg_printf("kq=%p - fd=%i use_count=%u skipping...", kq, fd, fd_use_cnt[signal_fd]); } - -check_count: - /* - * Stop thread if all kqueues have been closed - */ - if (kqueue_cnt == 0) return (0); - return (1); -} - -static void -monitoring_thread_scan_for_closed(void) -{ - int i; - - /* - * Avoid debug output below - */ - if (kqueue_cnt == 0) - return; - - dbg_printf("scanning fds 0-%i", nb_max_fd); - - for (i = 0; (kqueue_cnt > 0) && (i < nb_max_fd); i++) { - int fd; - - if (fd_use_cnt[i] == 0) continue; - - fd = fd_map[i]; - dbg_printf("checking rfd=%i wfd=%i", i, fd); - if (fcntl(fd, F_GETFD) < 0) { - dbg_printf("fd=%i - forcefully cleaning up, use_count=%u: %s", - fd, fd_use_cnt[i], errno == EBADF ? "File descriptor already closed" : strerror(errno)); - - /* next call decrements */ - fd_use_cnt[i] = 1; - (void)monitoring_thread_kq_cleanup(i, false); - } - } } static void @@ -207,8 +166,28 @@ monitoring_thread_cleanup(UNUSED void *arg) * free the underlying memory, and it'll be correctly * reported as a memory leak. */ - if (monitoring_thread_on_exit) - monitoring_thread_scan_for_closed(); + if (monitoring_thread_on_exit && (kqueue_cnt > 0)) { + int i; + + dbg_printf("scanning fds 0-%i", nb_max_fd); + + for (i = 0; (kqueue_cnt > 0) && (i < nb_max_fd); i++) { + int fd; + + if (fd_use_cnt[i] == 0) continue; + + fd = fd_map[i]; + dbg_printf("checking rfd=%i wfd=%i", i, fd); + if (fcntl(fd, F_GETFD) < 0) { + dbg_printf("fd=%i - forcefully cleaning up, use_count=%u: %s", + fd, fd_use_cnt[i], errno == EBADF ? "File descriptor already closed" : strerror(errno)); + + /* next call decrements */ + fd_use_cnt[i] = 1; + (void)linux_kqueue_cleanup(i, false); + } + } + } dbg_printf("tid=%u - monitoring thread exiting (%s)", monitoring_tid, monitoring_thread_on_exit ? "process term" : "no kqueues"); @@ -297,9 +276,14 @@ monitoring_thread_loop(UNUSED void *arg) dbg_printf("fd=%i - freeing kqueue due to fd closure", fd_map[info.si_fd]); /* - * If no more kqueues... exit. + * Release resources used by this kqueue */ - if (monitoring_thread_kq_cleanup(info.si_fd, false) == 0) + linux_kqueue_cleanup(info.si_fd, false); + + /* + * Exit if there are no more kqueues to monitor + */ + if (kqueue_cnt == 0) break; } else { dbg_perror("sigwaitinfo returned early"); @@ -319,7 +303,7 @@ static int linux_kqueue_start_thread(void) { pthread_mutex_lock(&monitoring_thread_mtx); - if (pthread_create(&monitoring_thread, NULL, &monitoring_thread_loop, &monitoring_thread_mtx)) { + if (pthread_create(&monitoring_thread, NULL, &monitoring_thread_loop, NULL)) { dbg_perror("linux_kqueue_start_thread failure"); pthread_mutex_unlock(&monitoring_thread_mtx); @@ -341,18 +325,20 @@ linux_kqueue_start_thread(void) static void linux_monitor_thread_join(void) { - static tracing_mutex_t signal_mtx = TRACING_MUTEX_INITIALIZER; - int ret; - - tracing_mutex_trylock(ret, &signal_mtx); - if (ret == 0) { - if (monitoring_tid) { - dbg_printf("tid=%u - signalling to exit", monitoring_tid); - if (pthread_cancel(monitoring_thread) < 0) - dbg_perror("tid=%u - signalling failed", monitoring_tid); - pthread_join(monitoring_thread, NULL); + if (monitoring_tid) { + void *retval; + int ret; + + dbg_printf("tid=%u - cancelling", monitoring_tid); + ret = pthread_cancel(monitoring_thread); + if (ret != 0) + dbg_printf("tid=%u - cancel failed: %s", monitoring_tid, strerror(ret)); + ret = pthread_join(monitoring_thread, &retval); + if (ret == 0) { + dbg_printf("tid=%u - joined with exit_status=%" PRIuPTR, monitoring_tid, (uintptr_t)retval); + } else { + dbg_printf("tid=%u - join failed: %s", monitoring_tid, strerror(ret)); } - tracing_mutex_unlock(&signal_mtx); } } @@ -361,6 +347,12 @@ linux_at_fork(void) { int i; + /* + * We don't have to cancel the monitor thread + * here as fork() typically only duplicates + * the thread which called it. + */ + /* * forcefully close all outstanding kqueues */ @@ -372,18 +364,9 @@ linux_at_fork(void) close(i); fd_use_cnt[i] = 1; - (void)monitoring_thread_kq_cleanup(i, true); + (void)linux_kqueue_cleanup(i, true); } tracing_mutex_unlock(&kq_mtx); - - /* - * re-initialises everything so that the child could - * in theory allocate a new set of kqueues. - * - * Children don't appear to inherit pending signals - * so this should all still work as intended. - */ - linux_monitor_thread_join(); } static void From 8df2c933418d4418be44919537ae390168853757 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 19 Mar 2022 12:19:05 -0400 Subject: [PATCH 1001/1120] Print out monitoring thread details correctly --- vendor/libkqueue/src/linux/platform.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index ae653c437..e9e10c7e4 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -328,16 +328,17 @@ linux_monitor_thread_join(void) if (monitoring_tid) { void *retval; int ret; + pid_t our_monitoring_tid = monitoring_tid; /* Gets trashed when the thread exits */ dbg_printf("tid=%u - cancelling", monitoring_tid); ret = pthread_cancel(monitoring_thread); if (ret != 0) - dbg_printf("tid=%u - cancel failed: %s", monitoring_tid, strerror(ret)); + dbg_printf("tid=%u - cancel failed: %s", our_monitoring_tid, strerror(ret)); ret = pthread_join(monitoring_thread, &retval); if (ret == 0) { - dbg_printf("tid=%u - joined with exit_status=%" PRIuPTR, monitoring_tid, (uintptr_t)retval); + dbg_printf("tid=%u - joined with exit_status=%" PRIdPTR, our_monitoring_tid, (intptr_t)retval); } else { - dbg_printf("tid=%u - join failed: %s", monitoring_tid, strerror(ret)); + dbg_printf("tid=%u - join failed: %s", our_monitoring_tid, strerror(ret)); } } } From dc231c2262a13056c0459b6a8d1f9b85cdd1a8f9 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 19 Mar 2022 13:38:51 -0400 Subject: [PATCH 1002/1120] add central dispatch callbacks for platform and filters These are for init, fork and free --- vendor/libkqueue/src/common/filter.c | 55 +++++++++++++++++++++++++++ vendor/libkqueue/src/common/kqueue.c | 16 ++++++++ vendor/libkqueue/src/common/private.h | 24 ++++++++++++ vendor/libkqueue/src/linux/platform.c | 10 +---- vendor/libkqueue/src/posix/proc.c | 53 +++++++++++++------------- 5 files changed, 123 insertions(+), 35 deletions(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index 2a97cce47..f5085ba27 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -28,6 +28,61 @@ extern const struct filter evfilt_timer; extern const struct filter evfilt_user; extern const struct filter evfilt_libkqueue; +void +filter_init_all(void) +{ +#define FILTER_INIT(filt) \ +do { \ + if (filt.libkqueue_init) \ + filt.libkqueue_init(); \ +} while (0) + + FILTER_INIT(evfilt_read); + FILTER_INIT(evfilt_write); + FILTER_INIT(evfilt_signal); + FILTER_INIT(evfilt_vnode); + FILTER_INIT(evfilt_proc); + FILTER_INIT(evfilt_timer); + FILTER_INIT(evfilt_user); + FILTER_INIT(evfilt_libkqueue); +} + +void +filter_fork_all(void) +{ +#define FILTER_FORK(filt) do { \ + if (filt.libkqueue_fork) \ + filt.libkqueue_fork(); \ +} while (0) + + FILTER_FORK(evfilt_read); + FILTER_FORK(evfilt_write); + FILTER_FORK(evfilt_signal); + FILTER_FORK(evfilt_vnode); + FILTER_FORK(evfilt_proc); + FILTER_FORK(evfilt_timer); + FILTER_FORK(evfilt_user); + FILTER_FORK(evfilt_libkqueue); +} + +void +filter_free_all(void) +{ +#define FILTER_FREE(filt) do { \ + if (filt.libkqueue_free) \ + filt.libkqueue_free(); \ +} while (0) + + FILTER_FREE(evfilt_read); + FILTER_FREE(evfilt_write); + FILTER_FREE(evfilt_signal); + FILTER_FREE(evfilt_vnode); + FILTER_FREE(evfilt_proc); + FILTER_FREE(evfilt_timer); + FILTER_FREE(evfilt_user); + FILTER_FREE(evfilt_libkqueue); +} + static int filter_register(struct kqueue *kq, const struct filter *src) { diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 9dad164bd..83a182813 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -78,10 +78,23 @@ libkqueue_free(void) { dbg_puts("releasing library resources"); + filter_free_all(); + if (kqops.libkqueue_free) kqops.libkqueue_free(); } +void +libkqueue_fork(void) +{ + dbg_puts("cleaning up forked resources"); + + filter_fork_all(); + + if (kqops.libkqueue_fork) + kqops.libkqueue_fork(); +} + void libkqueue_init(void) { @@ -124,8 +137,11 @@ libkqueue_init(void) if (kqops.libkqueue_init) kqops.libkqueue_init(); + filter_init_all(); + dbg_puts("library initialization complete"); + pthread_atfork(NULL, NULL, libkqueue_fork); atexit(libkqueue_free); } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 0ef1278d8..4e4b8d730 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -258,6 +258,21 @@ struct knote { struct filter { short kf_id; //!< EVFILT_* facility this filter provides. + /** Called once on startup + * + */ + void (*libkqueue_init)(void); + + /** Called on fork (for the child) + * + */ + void (*libkqueue_fork)(void); + + /** Called at exit + * + */ + void (*libkqueue_free)(void); + /** Perform initialisation for this filter * * This is called once per filer per kqueue as the kqueue is initialised. @@ -492,6 +507,11 @@ struct kqueue_vtable { */ void (*libkqueue_init)(void); + /** Called on fork (for the child) + * + */ + void (*libkqueue_fork)(void); + /** Called at exit * */ @@ -660,6 +680,10 @@ static inline int knote_copyout_flag_actions(struct filter *filt, struct knote * #define knote_get_filter(knt) &((knt)->kn_kq->kq_filt[~(knt)->kev.filter]) +void filter_init_all(void); +void filter_fork_all(void); +void filter_free_all(void); + int filter_lookup(struct filter **, struct kqueue *, short); int filter_register_all(struct kqueue *); void filter_unregister_all(struct kqueue *); diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index e9e10c7e4..d699c5bb3 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -344,7 +344,7 @@ linux_monitor_thread_join(void) } static void -linux_at_fork(void) +linux_libkqueue_fork(void) { int i; @@ -376,12 +376,6 @@ linux_libkqueue_free(void) linux_monitor_thread_join(); } -static void -linux_libkqueue_init(void) -{ - pthread_atfork(NULL, NULL, linux_at_fork); -} - static int linux_kqueue_init(struct kqueue *kq) { @@ -1531,7 +1525,7 @@ linux_fd_to_path(char *buf, size_t bufsz, int fd) } const struct kqueue_vtable kqops = { - .libkqueue_init = linux_libkqueue_init, + .libkqueue_fork = linux_libkqueue_fork, .libkqueue_free = linux_libkqueue_free, .kqueue_init = linux_kqueue_init, .kqueue_free = linux_kqueue_free, diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index bfeda87f6..d6ced9b0c 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -328,11 +328,25 @@ wait_thread(UNUSED void *arg) return (NULL); } +static void +evfilt_proc_libkqueue_init(void) +{ + /* + * Initialise the global PID index tree. This needs to be + * recursive as the delete/enable/disable functions all + * need to lock the mutex, and they may be called indirectly + * in the copyout function (which already locks this mutex), + * as well as by other kqueue code. + */ +#ifndef _WIN32 + pthread_mutexattr_init(&proc_pid_index_mtx_attr); + pthread_mutexattr_settype(&proc_pid_index_mtx_attr, PTHREAD_MUTEX_RECURSIVE); +#endif + tracing_mutex_init(&proc_pid_index_mtx, &proc_pid_index_mtx_attr); +} static int evfilt_proc_init(struct filter *filt) { - static bool global_init = false; - if (kqops.eventfd_init(&filt->kf_proc_eventfd, filt) < 0) { error_0: return (-1); @@ -349,22 +363,6 @@ evfilt_proc_init(struct filter *filt) */ tracing_mutex_lock(&proc_init_mtx); - /* - * Initialise the global PID index tree. This needs to be - * recursive as the delete/enable/disable functions all - * need to lock the mutex, and they may be called indirectly - * in the copyout function (which already locks this mutex), - * as well as by other kqueue code. - */ - if (!global_init) { -#ifndef _WIN32 - pthread_mutexattr_init(&proc_pid_index_mtx_attr); - pthread_mutexattr_settype(&proc_pid_index_mtx_attr, PTHREAD_MUTEX_RECURSIVE); -#endif - tracing_mutex_init(&proc_pid_index_mtx, &proc_pid_index_mtx_attr); - global_init = true; - } - if (proc_count == 0) { sigset_t sigmask; @@ -576,13 +574,14 @@ evfilt_proc_knote_copyout(struct kevent *dst, int nevents, struct filter *filt, } const struct filter evfilt_proc = { - .kf_id = EVFILT_PROC, - .kf_init = evfilt_proc_init, - .kf_destroy = evfilt_proc_destroy, - .kf_copyout = evfilt_proc_knote_copyout, - .kn_create = evfilt_proc_knote_create, - .kn_modify = evfilt_proc_knote_modify, - .kn_enable = evfilt_proc_knote_create, - .kn_disable = evfilt_proc_knote_disable, - .kn_delete = evfilt_proc_knote_delete + .libkqueue_init = evfilt_proc_libkqueue_init, + .kf_id = EVFILT_PROC, + .kf_init = evfilt_proc_init, + .kf_destroy = evfilt_proc_destroy, + .kf_copyout = evfilt_proc_knote_copyout, + .kn_create = evfilt_proc_knote_create, + .kn_modify = evfilt_proc_knote_modify, + .kn_enable = evfilt_proc_knote_create, + .kn_disable = evfilt_proc_knote_disable, + .kn_delete = evfilt_proc_knote_delete }; From 692123fbf96f3d1adba0f7c9b610ac499873f598 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 19 Mar 2022 13:39:27 -0400 Subject: [PATCH 1003/1120] don't free the waiter thread in posix proc on fork --- vendor/libkqueue/src/posix/proc.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index d6ced9b0c..697f81add 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -344,6 +344,18 @@ evfilt_proc_libkqueue_init(void) #endif tracing_mutex_init(&proc_pid_index_mtx, &proc_pid_index_mtx_attr); } + +static void +evfilt_proc_libkqueue_fork(void) +{ + /* + * The wait thread isn't duplicated in the forked copy + * of the process, and we need to prevent a cancellation + * request being sent to it when all the knotes are freed. + */ + proc_wait_thread_id = 0; +} + static int evfilt_proc_init(struct filter *filt) { @@ -401,7 +413,11 @@ evfilt_proc_destroy(struct filter *filt) */ tracing_mutex_lock(&proc_init_mtx); assert(proc_count > 0); - if (--proc_count == 0) { + /* + * Only cancel the wait thread if we're not + * in a forked copy. + */ + if ((--proc_count == 0) && (proc_wait_thread_id > 0)) { pthread_cancel(proc_wait_thread_id); if (pthread_join(proc_wait_thread_id, NULL) < 0) { dbg_printf("pthread_join(2) %s", strerror(errno)); @@ -575,6 +591,7 @@ evfilt_proc_knote_copyout(struct kevent *dst, int nevents, struct filter *filt, const struct filter evfilt_proc = { .libkqueue_init = evfilt_proc_libkqueue_init, + .libkqueue_fork = evfilt_proc_libkqueue_fork, .kf_id = EVFILT_PROC, .kf_init = evfilt_proc_init, .kf_destroy = evfilt_proc_destroy, From b3db9d0e8ba03a79fb7b30149aba4257bb752b2d Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 19 Mar 2022 13:48:05 -0400 Subject: [PATCH 1004/1120] our_monitoring_tid is unused for release builds --- vendor/libkqueue/src/linux/platform.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index d699c5bb3..a28672976 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -328,7 +328,9 @@ linux_monitor_thread_join(void) if (monitoring_tid) { void *retval; int ret; +#ifndef NDEBUG pid_t our_monitoring_tid = monitoring_tid; /* Gets trashed when the thread exits */ +#endif dbg_printf("tid=%u - cancelling", monitoring_tid); ret = pthread_cancel(monitoring_thread); From 047ba5c2c1d78d28495e0365710a509d07bfad36 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 19 Mar 2022 14:09:41 -0400 Subject: [PATCH 1005/1120] Add better synchronisation for wait thread start Prevent thread cancellation in the middle of an operation --- vendor/libkqueue/src/posix/proc.c | 47 ++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 697f81add..be80a234a 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -36,9 +36,23 @@ struct proc_pid { LIST_HEAD(pid_waiters, knote) ppd_proc_waiters; //!< knotes that are waiting on this PID. }; +/** Synchronisation for wait thread information + * + * This ensures that the number of process being monitored is correct + * and stops multiple threads attempting to start a monitor thread + * at the same time. + */ static tracing_mutex_t proc_init_mtx = TRACING_MUTEX_INITIALIZER; static int proc_count = 0; -static pthread_t proc_wait_thread_id; +static pthread_t proc_wait_thread; + +/** Synchronisation for thread start + * + * This prevents any threads from continuing whilst the wait thread + * is started. + */ +static pthread_mutex_t proc_wait_thread_mtx = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t proc_wait_thread_cond = PTHREAD_COND_INITIALIZER; /** The global PID tree * @@ -256,7 +270,20 @@ wait_thread(UNUSED void *arg) */ sigemptyset(&sigmask); sigaddset(&sigmask, SIGCHLD); + + /* + * Inform the parent that we started correctly + */ + pthread_mutex_lock(&proc_wait_thread_mtx); /* Must try to lock to ensure parent is waiting on signal */ + pthread_cond_signal(&proc_wait_thread_cond); + pthread_mutex_unlock(&proc_wait_thread_mtx); do { + /* + * Don't allow the thread to be cancelled until we've + * finished one loop in the monitoring thread. This + * ensures there are no nasty issue on exit. + */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); if (ret < 0) { dbg_printf("sigwaitinfo(2): %s", strerror(errno)); continue; @@ -321,6 +348,7 @@ wait_thread(UNUSED void *arg) tracing_mutex_unlock(&proc_pid_index_mtx); dbg_printf("waiting for SIGCHLD"); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); /* sigwaitinfo is the next cancellation point */ } while ((ret = sigwaitinfo(&sigmask, &info))); dbg_printf("exited"); @@ -353,7 +381,7 @@ evfilt_proc_libkqueue_fork(void) * of the process, and we need to prevent a cancellation * request being sent to it when all the knotes are freed. */ - proc_wait_thread_id = 0; + proc_wait_thread = 0; } static int @@ -374,7 +402,6 @@ evfilt_proc_init(struct filter *filt) * Initialise global resources (wait thread and PID tree). */ tracing_mutex_lock(&proc_init_mtx); - if (proc_count == 0) { sigset_t sigmask; @@ -393,10 +420,16 @@ evfilt_proc_init(struct filter *filt) dbg_printf("creating wait thread"); - if (pthread_create(&proc_wait_thread_id, NULL, wait_thread, NULL) != 0) { + pthread_mutex_lock(&proc_wait_thread_mtx); + if (pthread_create(&proc_wait_thread, NULL, wait_thread, NULL) != 0) { tracing_mutex_unlock(&proc_init_mtx); + pthread_mutex_unlock(&proc_wait_thread_mtx); + goto error_1; } + /* Wait until the wait thread has started and is monitoring signals */ + pthread_cond_wait(&proc_wait_thread_cond, &proc_wait_thread_mtx); + pthread_mutex_unlock(&proc_wait_thread_mtx); } proc_count++; tracing_mutex_unlock(&proc_init_mtx); @@ -417,9 +450,9 @@ evfilt_proc_destroy(struct filter *filt) * Only cancel the wait thread if we're not * in a forked copy. */ - if ((--proc_count == 0) && (proc_wait_thread_id > 0)) { - pthread_cancel(proc_wait_thread_id); - if (pthread_join(proc_wait_thread_id, NULL) < 0) { + if ((--proc_count == 0) && (proc_wait_thread > 0)) { + pthread_cancel(proc_wait_thread); + if (pthread_join(proc_wait_thread, NULL) < 0) { dbg_printf("pthread_join(2) %s", strerror(errno)); } else { dbg_puts("waiter thread joined"); From 0a24dbbb67d35a92b4c55dffcf22debcac236fcf Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 19 Mar 2022 14:16:28 -0400 Subject: [PATCH 1006/1120] No forks for Windows --- vendor/libkqueue/src/common/filter.c | 5 +++-- vendor/libkqueue/src/common/kqueue.c | 4 ++++ vendor/libkqueue/src/common/private.h | 6 ++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index f5085ba27..aaa9d1f36 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -31,8 +31,7 @@ extern const struct filter evfilt_libkqueue; void filter_init_all(void) { -#define FILTER_INIT(filt) \ -do { \ +#define FILTER_INIT(filt) do { \ if (filt.libkqueue_init) \ filt.libkqueue_init(); \ } while (0) @@ -47,6 +46,7 @@ do { \ FILTER_INIT(evfilt_libkqueue); } +#ifndef _WIN32 void filter_fork_all(void) { @@ -64,6 +64,7 @@ filter_fork_all(void) FILTER_FORK(evfilt_user); FILTER_FORK(evfilt_libkqueue); } +#endif void filter_free_all(void) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 83a182813..188b29913 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -84,6 +84,7 @@ libkqueue_free(void) kqops.libkqueue_free(); } +#ifndef _WIN32 void libkqueue_fork(void) { @@ -94,6 +95,7 @@ libkqueue_fork(void) if (kqops.libkqueue_fork) kqops.libkqueue_fork(); } +#endif void libkqueue_init(void) @@ -141,7 +143,9 @@ libkqueue_init(void) dbg_puts("library initialization complete"); +#ifndef _WIN32 pthread_atfork(NULL, NULL, libkqueue_fork); +#endif atexit(libkqueue_free); } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 4e4b8d730..be0980055 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -263,10 +263,12 @@ struct filter { */ void (*libkqueue_init)(void); +#ifndef _WIN32 /** Called on fork (for the child) * */ void (*libkqueue_fork)(void); +#endif /** Called at exit * @@ -507,10 +509,12 @@ struct kqueue_vtable { */ void (*libkqueue_init)(void); +#ifndef _WIN32 /** Called on fork (for the child) * */ void (*libkqueue_fork)(void); +#endif /** Called at exit * @@ -681,7 +685,9 @@ static inline int knote_copyout_flag_actions(struct filter *filt, struct knote * #define knote_get_filter(knt) &((knt)->kn_kq->kq_filt[~(knt)->kev.filter]) void filter_init_all(void); +#ifndef _WIN32 void filter_fork_all(void); +#endif void filter_free_all(void); int filter_lookup(struct filter **, struct kqueue *, short); From 8b5402367fa90f7a5b8f72928a7f9a6e488b1d8e Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 19 Mar 2022 15:07:55 -0400 Subject: [PATCH 1007/1120] remove dead knote_init code --- vendor/libkqueue/src/common/knote.c | 7 ------- vendor/libkqueue/src/common/kqueue.c | 2 -- vendor/libkqueue/src/common/private.h | 1 - 3 files changed, 10 deletions(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 81d25640e..11ece10da 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -20,13 +20,6 @@ #include "alloc.h" -int -knote_init(void) -{ - return 0; -// return (mem_init(sizeof(struct knote), 1024)); -} - /** Comparator for the knote_index * * FIXME - Should respect EV_UDATA_SPECIFIC but that's a whole diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 188b29913..e66e7c6bc 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -129,8 +129,6 @@ libkqueue_init(void) kqmap = map_new(get_fd_limit()); // INT_MAX if (kqmap == NULL) abort(); - if (knote_init() < 0) - abort(); #ifdef _WIN32 kq_init_complete = 1; diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index be0980055..b9bb5a2dc 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -648,7 +648,6 @@ struct knote *knote_new(void); void knote_release(struct knote *); void knote_insert(struct filter *, struct knote *); int knote_delete(struct filter *, struct knote *); -int knote_init(void); int knote_disable(struct filter *, struct knote *); int knote_enable(struct filter *, struct knote *); int knote_modify(struct filter *, struct knote *); From e3adc70081112afce08295424310e5c9c8428b22 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 19 Mar 2022 15:08:07 -0400 Subject: [PATCH 1008/1120] clarify why we don't need to cancel threads on fork --- vendor/libkqueue/src/posix/proc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index be80a234a..22534bdc2 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -448,7 +448,8 @@ evfilt_proc_destroy(struct filter *filt) assert(proc_count > 0); /* * Only cancel the wait thread if we're not - * in a forked copy. + * in a forked copy as fork does not produce + * a new copy of the thread. */ if ((--proc_count == 0) && (proc_wait_thread > 0)) { pthread_cancel(proc_wait_thread); From c2dae3b85ba66dc2d5b870f2320748a8950d6b9f Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 19 Mar 2022 22:46:23 -0400 Subject: [PATCH 1009/1120] keep a list of active kqueues to avoid wasteful scanning better synchronisation on monitoring thread exit --- vendor/libkqueue/src/common/kqueue.c | 18 ++ vendor/libkqueue/src/common/private.h | 8 + vendor/libkqueue/src/linux/platform.c | 318 +++++++++++++------------- vendor/libkqueue/src/posix/proc.c | 36 ++- 4 files changed, 215 insertions(+), 165 deletions(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index e66e7c6bc..6712cd69e 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -29,6 +29,19 @@ tracing_mutex_t kq_mtx = TRACING_MUTEX_INITIALIZER; pthread_once_t kq_is_initialized = PTHREAD_ONCE_INIT; #endif +/** List of all active kqueues + * + * This is used to iterate over all active kqueues. + * + * kq_mtx should be held whilst accessing or modifying. + */ +struct kqueue_head kq_list; + +/** Count of the active kqueues + * + */ +unsigned int kq_cnt = 0; + unsigned int get_fd_limit(void) { @@ -152,6 +165,9 @@ kqueue_free(struct kqueue *kq) { dbg_printf("kq=%p - freeing", kq); + kq_cnt--; + LIST_REMOVE(kq, kq_entry); + /* * map_remove ensures the current map entry * points to this kqueue. @@ -242,6 +258,8 @@ kqueue(void) tracing_mutex_unlock(&kq_mtx); goto error; } + LIST_INSERT_HEAD(&kq_list, kq, kq_entry); + kq_cnt++; tracing_mutex_unlock(&kq_mtx); return (kq->kq_id); diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index b9bb5a2dc..5a04418b3 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -490,6 +490,9 @@ struct filter { */ struct kqueue { int kq_id; //!< File descriptor used to identify this kqueue. + + LIST_ENTRY(kqueue) kq_entry; //!< Entry in the global list of active kqueues. + struct filter kq_filt[EVFILT_SYSCOUNT]; //!< Filters supported by the kqueue. Each ///< kqueue maintains one filter state structure ///< per filter type. @@ -628,7 +631,12 @@ struct kqueue_vtable { */ int (*eventfd_descriptor)(struct eventfd *efd); }; +LIST_HEAD(kqueue_head, kqueue); + extern const struct kqueue_vtable kqops; +extern tracing_mutex_t kq_mtx; +extern struct kqueue_head kq_list; +extern unsigned int kq_cnt; /* * kqueue internal API diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index a28672976..0032d39ee 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -31,7 +31,6 @@ */ static __thread struct epoll_event epoll_events[MAX_KEVENT]; -extern tracing_mutex_t kq_mtx; /* * Monitoring thread that takes care of cleaning up kqueues (on linux only) */ @@ -41,16 +40,16 @@ static pid_t monitoring_tid; /* Monitoring thread */ static pthread_mutex_t monitoring_thread_mtx = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t monitoring_thread_cond = PTHREAD_COND_INITIALIZER; -/* - * Monitoring thread is exiting because the process is terminating - */ -static bool monitoring_thread_on_exit = true; +enum thread_exit_state { + THREAD_EXIT_STATE_SELF_CANCEL = 0, + THREAD_EXIT_STATE_CANCEL_LOCKED, + THREAD_EXIT_STATE_CANCEL_UNLOCKED, +}; /* - * Number of active kqueues. - * When the last kqueue is closed, the monitoring thread can be stopped. + * Monitoring thread is exiting because the process is terminating */ -static unsigned int kqueue_cnt = 0; +static enum thread_exit_state monitoring_thread_state; /* * Map for kqueue pipes where index is the read side (for which signals are received) @@ -73,12 +72,69 @@ static int nb_max_fd; static void linux_kqueue_free(struct kqueue *kq); +static void +monitoring_thread_cleanup(UNUSED void *arg) +{ + struct kqueue *kq, *kq_tmp; + + /* + * If the entire process is exiting, then free all + * the kqueues + * + * We do this because we don't reliably receive all the + * close MONITORING_THREAD_SIGNALs before the process + * exits, and this avoids ASAN or valgrind raising + * spurious memory leaks. + * + * If the user _hasn't_ closed a KQ fd, then we don't + * free the underlying memory, and it'll be correctly + * reported as a memory leak. + */ + if ((monitoring_thread_state == THREAD_EXIT_STATE_CANCEL_LOCKED) || + (monitoring_thread_state == THREAD_EXIT_STATE_CANCEL_UNLOCKED)) { + LIST_FOREACH_SAFE(kq, &kq_list, kq_entry, kq_tmp) { + int signal_fd = kq->pipefd[0]; + + /* + * If there's no use cnt for the kqueue + * then something has gone very wrong + */ + assert(fd_use_cnt[signal_fd] > 0); + fd_use_cnt[signal_fd]--; + + if (fd_use_cnt[signal_fd] == 0) { + dbg_printf("kq=%p - fd=%i use_count=%u cleaning up...", kq, kq->kq_id, fd_use_cnt[signal_fd]); + kqueue_free(kq); + } else { + dbg_printf("kq=%p - fd=%i use_count=%u skipping, this is likely a leak...", + kq, kq->kq_id, fd_use_cnt[signal_fd]); + } + } + } + + dbg_printf("tid=%u - monitoring thread exiting (%s)", + monitoring_tid, + monitoring_thread_state == THREAD_EXIT_STATE_SELF_CANCEL ? "no kqueues" : "process term"); + /* Free thread resources */ + free(fd_map); + fd_map = NULL; + free(fd_use_cnt); + fd_use_cnt = NULL; + + /* Reset so that thread can be restarted */ + monitoring_tid = 0; + + if (monitoring_thread_state == THREAD_EXIT_STATE_CANCEL_UNLOCKED) + tracing_mutex_unlock(&kq_mtx); +} + + /** Clean up a kqueue from the perspective of the monitoring thread * * Called with the kq_mtx held. */ static void -linux_kqueue_cleanup(int signal_fd, bool closed_on_fork) +monitoring_thread_kqueue_cleanup(int signal_fd) { int fd; struct kqueue *kq; @@ -101,23 +157,6 @@ linux_kqueue_cleanup(int signal_fd, bool closed_on_fork) return; } - /* - * On fork the epoll fd is inherited by the child process - * Any modifications made by the child affect the parent's - * epoll instance. - * - * So... if we remove file descriptors in the child, then - * we can break functionality for the parent. - * - * Our only option is to close the epollfd, and check for - * an invalid epollfd when deregistering file descriptors - * and ignore the operation. - */ - if (closed_on_fork) { - close(kq->epollfd); - kq->epollfd = -1; - } - /* * We should never have more pending signals than we have * allocated kqueues against a given ID. @@ -149,58 +188,6 @@ linux_kqueue_cleanup(int signal_fd, bool closed_on_fork) } } -static void -monitoring_thread_cleanup(UNUSED void *arg) -{ - /* - * If the entire process is exiting, then scan through - * all the in use file descriptors, checking to see if - * they've been closed or not. - * - * We do this because we don't reliably receive all the - * close MONITORING_THREAD_SIGNALs before the process - * exits, and this avoids ASAN or valgrind raising - * spurious memory leaks. - * - * If the user _hasn't_ closed a KQ fd, then we don't - * free the underlying memory, and it'll be correctly - * reported as a memory leak. - */ - if (monitoring_thread_on_exit && (kqueue_cnt > 0)) { - int i; - - dbg_printf("scanning fds 0-%i", nb_max_fd); - - for (i = 0; (kqueue_cnt > 0) && (i < nb_max_fd); i++) { - int fd; - - if (fd_use_cnt[i] == 0) continue; - - fd = fd_map[i]; - dbg_printf("checking rfd=%i wfd=%i", i, fd); - if (fcntl(fd, F_GETFD) < 0) { - dbg_printf("fd=%i - forcefully cleaning up, use_count=%u: %s", - fd, fd_use_cnt[i], errno == EBADF ? "File descriptor already closed" : strerror(errno)); - - /* next call decrements */ - fd_use_cnt[i] = 1; - (void)linux_kqueue_cleanup(i, false); - } - } - } - - dbg_printf("tid=%u - monitoring thread exiting (%s)", - monitoring_tid, monitoring_thread_on_exit ? "process term" : "no kqueues"); - /* Free thread resources */ - free(fd_map); - fd_map = NULL; - free(fd_use_cnt); - fd_use_cnt = NULL; - - /* Reset so that thread can be restarted */ - monitoring_tid = 0; -} - /* * Monitoring thread that loops on waiting for signals to be received */ @@ -254,6 +241,7 @@ monitoring_thread_loop(UNUSED void *arg) pthread_cond_signal(&monitoring_thread_cond); pthread_mutex_unlock(&monitoring_thread_mtx); + monitoring_thread_state = THREAD_EXIT_STATE_CANCEL_UNLOCKED; pthread_cleanup_push(monitoring_thread_cleanup, NULL) while (true) { /* @@ -262,7 +250,7 @@ monitoring_thread_loop(UNUSED void *arg) * should be performed on the kqueue. */ res = sigwaitinfo(&monitoring_sig_set, &info); - if ((res == -1) && (errno = EINTR)) { + if (res == -1) { dbg_printf("sigwaitinfo(2): %s", strerror(errno)); continue; } @@ -272,28 +260,33 @@ monitoring_thread_loop(UNUSED void *arg) */ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); tracing_mutex_lock(&kq_mtx); - if (res != -1) { - dbg_printf("fd=%i - freeing kqueue due to fd closure", fd_map[info.si_fd]); + dbg_printf("fd=%i - freeing kqueue due to fd closure", fd_map[info.si_fd]); - /* - * Release resources used by this kqueue - */ - linux_kqueue_cleanup(info.si_fd, false); + /* + * Release resources used by this kqueue + */ + monitoring_thread_kqueue_cleanup(info.si_fd); + + /* + * Exit if there are no more kqueues to monitor + */ + if (kq_cnt == 0) + break; - /* - * Exit if there are no more kqueues to monitor - */ - if (kqueue_cnt == 0) - break; - } else { - dbg_perror("sigwaitinfo returned early"); - } tracing_mutex_unlock(&kq_mtx); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); } - monitoring_thread_on_exit = false; + + /* + * Ensure that any cancellation requests are acted on + */ + monitoring_thread_state = THREAD_EXIT_STATE_CANCEL_LOCKED; + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_testcancel(); + + monitoring_thread_state = THREAD_EXIT_STATE_SELF_CANCEL; pthread_cleanup_pop(true); /* Executes the cleanup function (monitoring_thread_cleanup) */ - monitoring_thread_on_exit = true; + pthread_detach(pthread_self()); tracing_mutex_unlock(&kq_mtx); return NULL; @@ -303,7 +296,7 @@ static int linux_kqueue_start_thread(void) { pthread_mutex_lock(&monitoring_thread_mtx); - if (pthread_create(&monitoring_thread, NULL, &monitoring_thread_loop, NULL)) { + if (pthread_create(&monitoring_thread, NULL, monitoring_thread_loop, NULL)) { dbg_perror("linux_kqueue_start_thread failure"); pthread_mutex_unlock(&monitoring_thread_mtx); @@ -316,6 +309,59 @@ linux_kqueue_start_thread(void) return (0); } +static void +linux_libkqueue_fork(void) +{ + struct kqueue *kq, *kq_tmp; + + /* + * We don't have to cancel the monitor thread here + * as fork() typically only duplicates the thread + * which called it. + * + * Ensure we don't try and cancel it on exit by + * clearing the thread id. + * + * We don't need to lock the kq_mtx here as we're in + * the child, and none of our threads will have been + * duplicated. + */ + monitoring_tid = 0; + + /* + * If the process has been forked, then we need + * to destroy all of the kqueue instances in + * the fork. + * + * This replicates the behaviour of real kqueues + * on FreeBSD, and also prevents spurious leak + * reports being raised by LSAN. + */ + LIST_FOREACH_SAFE(kq, &kq_list, kq_entry, kq_tmp) { + dbg_printf("kq=%p - cleaning up on fork", kq); + + /* + * On fork the epoll fd is inherited by the child process + * Any modifications made by the child affect the parent's + * epoll instance. + * + * So... if we remove file descriptors from epoll in the + * child, then we break the parent. + * + * We close the epollfd first to prevent the normal cleanup + * logic from modifying the epoll instance in the parent + * process. + */ + close(kq->epollfd); + kq->epollfd = -1; + + /* + * Do the actual freeing... + */ + kqueue_free(kq); + } +} + /* * We have to use this instead of pthread_detach as there * seems to be some sort of race with LSAN and thread cleanup @@ -323,61 +369,40 @@ linux_kqueue_start_thread(void) * thread, LSAN reports kqueues as leaked. */ static void -linux_monitor_thread_join(void) +linux_libkqueue_free(void) { - if (monitoring_tid) { + pid_t tid; + + tracing_mutex_lock(&kq_mtx); + tid = monitoring_tid; /* Gets trashed when the thread exits */ + if (tid) { void *retval; int ret; -#ifndef NDEBUG - pid_t our_monitoring_tid = monitoring_tid; /* Gets trashed when the thread exits */ -#endif - dbg_printf("tid=%u - cancelling", monitoring_tid); + dbg_printf("tid=%u - cancelling", tid); ret = pthread_cancel(monitoring_thread); if (ret != 0) - dbg_printf("tid=%u - cancel failed: %s", our_monitoring_tid, strerror(ret)); + dbg_printf("tid=%u - cancel failed: %s", tid, strerror(ret)); + /* + * We unlock here to allow the monitoring thread + * to continue if it was processing a cleanup. + */ + tracing_mutex_unlock(&kq_mtx); + ret = pthread_join(monitoring_thread, &retval); if (ret == 0) { - dbg_printf("tid=%u - joined with exit_status=%" PRIdPTR, our_monitoring_tid, (intptr_t)retval); + if (retval == PTHREAD_CANCELED) { + dbg_printf("tid=%u - joined with exit_status=PTHREAD_CANCELED", tid); + } else { + dbg_printf("tid=%u - joined with exit_status=%" PRIdPTR, tid, (intptr_t)retval); + } } else { - dbg_printf("tid=%u - join failed: %s", our_monitoring_tid, strerror(ret)); + dbg_printf("tid=%u - join failed: %s", tid, strerror(ret)); } } -} - -static void -linux_libkqueue_fork(void) -{ - int i; - - /* - * We don't have to cancel the monitor thread - * here as fork() typically only duplicates - * the thread which called it. - */ - - /* - * forcefully close all outstanding kqueues - */ - tracing_mutex_lock(&kq_mtx); - for (i = 0; (kqueue_cnt > 0) && (i < nb_max_fd); i++) { - if (fd_use_cnt[i] == 0) continue; - - dbg_printf("Closing kq fd=%i due to fork", i); - close(i); - fd_use_cnt[i] = 1; - - (void)linux_kqueue_cleanup(i, true); - } tracing_mutex_unlock(&kq_mtx); } -static void -linux_libkqueue_free(void) -{ - linux_monitor_thread_join(); -} - static int linux_kqueue_init(struct kqueue *kq) { @@ -454,20 +479,10 @@ linux_kqueue_init(struct kqueue *kq) goto error; } - /* - * Increment kqueue counter - must be incremented before - * starting the monitoring thread in case there's a spurious - * wakeup and the thread immediately checks that there - * are no kqueues, and exits. - */ - kqueue_cnt++; - /* Start monitoring thread during first initialization */ if (monitoring_tid == 0) { - if (linux_kqueue_start_thread() < 0) { - kqueue_cnt--; + if (linux_kqueue_start_thread() < 0) goto error; - } } /* Update pipe FD map */ @@ -476,8 +491,6 @@ linux_kqueue_init(struct kqueue *kq) /* Mark this id as in use */ fd_use_cnt[kq->pipefd[0]]++; - dbg_printf("active_kqueues=%u", kqueue_cnt); - assert(monitoring_tid != 0); /* @@ -489,7 +502,6 @@ linux_kqueue_init(struct kqueue *kq) sig_owner.pid = monitoring_tid; if (fcntl(kq->pipefd[0], F_SETOWN_EX, &sig_owner) < 0) { dbg_printf("fd=%i - failed settting F_SETOWN to tid=%u: %s", monitoring_tid, kq->pipefd[0], strerror(errno)); - kqueue_cnt--; tracing_mutex_unlock(&kq_mtx); goto error; } @@ -553,10 +565,6 @@ linux_kqueue_free(struct kqueue *kq) } kq->pipefd[0] = -1; } - - /* Decrement kqueue counter */ - kqueue_cnt--; - dbg_printf("kq=%p - cleaned up kqueue, active_kqueues=%u", kq, kqueue_cnt); } static int diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 22534bdc2..adfbae061 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -16,6 +16,7 @@ */ #include #include +#include #include #include #include @@ -45,6 +46,7 @@ struct proc_pid { static tracing_mutex_t proc_init_mtx = TRACING_MUTEX_INITIALIZER; static int proc_count = 0; static pthread_t proc_wait_thread; +static pid_t proc_wait_tid; /* Monitoring thread */ /** Synchronisation for thread start * @@ -174,7 +176,7 @@ waiter_siginfo_to_status(siginfo_t *info) * */ static void * -wait_thread(UNUSED void *arg) +wait_thread_loop(UNUSED void *arg) { int status; int ret = 0; @@ -186,7 +188,9 @@ wait_thread(UNUSED void *arg) * etc. Max name length is 16 bytes. */ prctl(PR_SET_NAME, "libkqueue_wait", 0, 0, 0); - dbg_printf("waiter thread started"); + proc_wait_tid = syscall(SYS_gettid); + + dbg_printf("tid=%u - waiter thread started", proc_wait_tid); /* * Native kqueue implementations leave processes monitored @@ -381,7 +385,7 @@ evfilt_proc_libkqueue_fork(void) * of the process, and we need to prevent a cancellation * request being sent to it when all the knotes are freed. */ - proc_wait_thread = 0; + proc_wait_tid = 0; } static int @@ -421,7 +425,7 @@ evfilt_proc_init(struct filter *filt) dbg_printf("creating wait thread"); pthread_mutex_lock(&proc_wait_thread_mtx); - if (pthread_create(&proc_wait_thread, NULL, wait_thread, NULL) != 0) { + if (pthread_create(&proc_wait_thread, NULL, wait_thread_loop, NULL) != 0) { tracing_mutex_unlock(&proc_init_mtx); pthread_mutex_unlock(&proc_wait_thread_mtx); @@ -451,12 +455,25 @@ evfilt_proc_destroy(struct filter *filt) * in a forked copy as fork does not produce * a new copy of the thread. */ - if ((--proc_count == 0) && (proc_wait_thread > 0)) { - pthread_cancel(proc_wait_thread); - if (pthread_join(proc_wait_thread, NULL) < 0) { - dbg_printf("pthread_join(2) %s", strerror(errno)); + if ((--proc_count == 0) && (proc_wait_tid != 0)) { + pid_t tid = proc_wait_tid; + void *retval; + int ret; + + dbg_printf("tid=%u - cancelling", tid); + ret = pthread_cancel(proc_wait_thread); + if (ret != 0) + dbg_printf("tid=%u - cancel failed: %s", tid, strerror(ret)); + + ret = pthread_join(proc_wait_thread, &retval); + if (ret == 0) { + if (retval == PTHREAD_CANCELED) { + dbg_printf("tid=%u - joined with exit_status=PTHREAD_CANCELED", tid); + } else { + dbg_printf("tid=%u - joined with exit_status=%" PRIdPTR, tid, (intptr_t)retval); + } } else { - dbg_puts("waiter thread joined"); + dbg_printf("tid=%u - join failed: %s", tid, strerror(ret)); } } tracing_mutex_unlock(&proc_init_mtx); @@ -476,7 +493,6 @@ evfilt_proc_knote_create(struct filter *filt, struct knote *kn) * here and error out early instead of waiting for the waiter * loop to tell us. */ - ppd = RB_FIND(pid_index, &proc_pid_index, &(struct proc_pid){ .ppd_pid = kn->kev.ident }); if (!ppd) { dbg_printf("pid=%u adding waiter list", (unsigned int)kn->kev.ident); From 59e1f496d05c12a634f209872e47e462cffae39a Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 19 Mar 2022 23:27:36 -0400 Subject: [PATCH 1010/1120] Mark all the knotes as disabled on fork --- vendor/libkqueue/src/common/knote.c | 13 +++++++++++++ vendor/libkqueue/src/common/kqueue.c | 11 +++++++++++ vendor/libkqueue/src/common/private.h | 5 +++-- vendor/libkqueue/src/linux/platform.c | 5 +++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 11ece10da..71e48f042 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -108,6 +108,19 @@ int knote_delete_all(struct filter *filt) return (0); } +int knote_mark_disabled_all(struct filter *filt) +{ + struct knote *kn, *tmp; + + tracing_mutex_lock(&filt->kf_knote_mtx); + RB_FOREACH_SAFE(kn, knote_index, &filt->kf_index, tmp) { + dbg_printf("kn=%p - marking disabled", kn); + KNOTE_DISABLE(kn); + } + tracing_mutex_unlock(&filt->kf_knote_mtx); + return (0); +} + int knote_delete(struct filter *filt, struct knote *kn) { diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 6712cd69e..2e91cdbdc 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -160,6 +160,17 @@ libkqueue_init(void) atexit(libkqueue_free); } +void +kqueue_knote_mark_disabled_all(struct kqueue *kq) +{ + unsigned int i; + + for (i = 0; i < EVFILT_SYSCOUNT; i++) { + struct filter *kf = &kq->kq_filt[i]; + knote_mark_disabled_all(kf); + } +} + void kqueue_free(struct kqueue *kq) { diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 5a04418b3..a748f4acd 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -647,12 +647,12 @@ extern unsigned int kq_cnt; /* * knote internal API */ -int knote_delete_all(struct filter *filt); struct knote *knote_lookup(struct filter *, uintptr_t); +int knote_delete_all(struct filter *filt); +int knote_mark_disabled_all(struct filter *filt); struct knote *knote_new(void); #define knote_retain(kn) atomic_inc(&kn->kn_ref) - void knote_release(struct knote *); void knote_insert(struct filter *, struct knote *); int knote_delete(struct filter *, struct knote *); @@ -710,6 +710,7 @@ int kevent_copyout(struct kqueue *, int, struct kevent *, int); void kevent_free(struct kqueue *); const char *kevent_dump(const struct kevent *); struct kqueue *kqueue_lookup(int); +void kqueue_knote_mark_disabled_all(struct kqueue *kq); void kqueue_free(struct kqueue *); void kqueue_free_by_id(int id); int kqueue_validate(struct kqueue *); diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 0032d39ee..855e8ca98 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -355,6 +355,11 @@ linux_libkqueue_fork(void) close(kq->epollfd); kq->epollfd = -1; + /* + * Mark all knotes as already disable + */ + kqueue_knote_mark_disabled_all(kq); + /* * Do the actual freeing... */ From 55a272fde1ffc27189050aca532171f0d12f7ce7 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 19 Mar 2022 23:51:11 -0400 Subject: [PATCH 1011/1120] Ignore knote enable/disable when the knote is already in that state --- vendor/libkqueue/src/common/knote.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 71e48f042..48317c1a9 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -164,7 +164,9 @@ knote_disable(struct filter *filt, struct knote *kn) { int rv = 0; - assert(!(kn->kev.flags & EV_DISABLE)); + /* If the knote is already disabled, this call is a noop */ + if (KNOTE_DISABLED(kn)) + return (0); dbg_printf("kn=%p - calling kn_disable", kn); rv = filt->kn_disable(filt, kn); @@ -185,6 +187,10 @@ knote_enable(struct filter *filt, struct knote *kn) { int rv = 0; + /* If the knote is already enabled, this call is a noop */ + if (KNOTE_ENABLED(kn)) + return (0); + dbg_printf("kn=%p - calling kn_enable", kn); rv = filt->kn_enable(filt, kn); dbg_printf("kn=%p - kn_enable rv=%i", kn, rv); From 3965d58c61aaaa7cf49bb3da3961ef95699bd6f8 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sat, 19 Mar 2022 23:53:41 -0400 Subject: [PATCH 1012/1120] change linux/user to enable/disable eventfd by adding/removing it from epoll instead of creating/destroying the eventfd --- vendor/libkqueue/src/linux/user.c | 50 +++++++++++++++---------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index 5ba33689e..2f60d8999 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -18,6 +18,12 @@ #include "private.h" +int +linux_evfilt_user_knote_enable(struct filter *filt, struct knote *kn); + +int +linux_evfilt_user_knote_disable(struct filter *filt, struct knote *kn); + /* NOTE: copy+pasted from linux_eventfd_raise() */ static int eventfd_raise(int evfd) @@ -113,24 +119,17 @@ linux_evfilt_user_knote_create(struct filter *filt, struct knote *kn) } else { dbg_perror("eventfd(2)"); } -error: if (evfd >= 0) close(evfd); kn->kn_eventfd = -1; - kn->kn_registered = 0; return (-1); } dbg_printf("event_fd=%i - created", evfd); - - /* Add the eventfd to the epoll set */ + kn->kn_eventfd = evfd; KN_UDATA(kn); /* populate this knote's kn_udata field */ - if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_ADD, evfd, EPOLL_EV_KN(EPOLLIN, kn)) < 0) { - dbg_perror("epoll_ctl(2)"); - goto error; - } - kn->kn_eventfd = evfd; - kn->kn_registered = 1; + if (KNOTE_ENABLED(kn)) + return linux_evfilt_user_knote_enable(filt, kn); return (0); } @@ -179,17 +178,8 @@ linux_evfilt_user_knote_delete(struct filter *filt, struct knote *kn) { int rv = 0; - if (kn->kn_registered) { - rv = epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, kn->kn_eventfd, NULL); - if (rv < 0) { - dbg_perror("epoll_ctl(2)"); - } else { - dbg_printf("event_fd=%i - removed from epoll_fd=%i", - kn->kn_eventfd, filter_epoll_fd(filt)); - } - } - - kn->kn_registered = 0; + if (KNOTE_ENABLED(kn)) + linux_evfilt_user_knote_disable(filt, kn); dbg_printf("event_fd=%i - closed", kn->kn_eventfd); if (close(kn->kn_eventfd) < 0) { @@ -204,15 +194,25 @@ linux_evfilt_user_knote_delete(struct filter *filt, struct knote *kn) int linux_evfilt_user_knote_enable(struct filter *filt, struct knote *kn) { - /* FIXME: what happens if NOTE_TRIGGER is in fflags? - should the event fire? */ - return linux_evfilt_user_knote_create(filt, kn); + if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_ADD, kn->kn_eventfd, EPOLL_EV_KN(EPOLLIN, kn)) < 0) { + dbg_perror("epoll_ctl(2)"); + return (-1); + } + dbg_printf("event_fd=%i - added to epoll_fd=%i", kn->kn_eventfd, filter_epoll_fd(filt)); + + return (0); } int linux_evfilt_user_knote_disable(struct filter *filt, struct knote *kn) { - return linux_evfilt_user_knote_delete(filt, kn); + if (epoll_ctl(filter_epoll_fd(filt), EPOLL_CTL_DEL, kn->kn_eventfd, NULL) < 0) { + dbg_perror("epoll_ctl(2)"); + return (-1); + } + dbg_printf("event_fd=%i - removed from epoll_fd=%i", kn->kn_eventfd, filter_epoll_fd(filt)); + + return (0); } const struct filter evfilt_user = { From d3245d9642891433c8e28bf14f6e6f38a3f6c293 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 20 Mar 2022 10:42:37 -0400 Subject: [PATCH 1013/1120] Windows doesn't have fork? --- vendor/libkqueue/BUGS.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/vendor/libkqueue/BUGS.md b/vendor/libkqueue/BUGS.md index 7503c1b3a..4753532a6 100644 --- a/vendor/libkqueue/BUGS.md +++ b/vendor/libkqueue/BUGS.md @@ -46,7 +46,7 @@ kqueue when we receive a `SIGCHLD`. This involves many calls to `waitid(2)` and may have a negative performance impact. - * `EVFILT_PROC` - The notification list of the global waiter thread, and the + * `EVFILT_PROC` - The notification list of the global waiter thread and the ready lists of individual kqueues share the same mutex. This may cause performance issues where large numbers of processes are monitored. @@ -105,12 +105,6 @@ Applications should ensure that file descriptors are removed from the kqueue before they are closed. - * We need to uninitialize library after `fork()` `using pthread_atfork()`. - BSD kqueue file descriptors are not inherited by the fork copy and - will be closed automatically in the fork. With libkqueue, because - we don't unitialize the library, kqueue file descriptors will persist - in the fork. - # libkqueue (kernel) * When passing a knote pointer to the kernel, the reference count of From c11f9497f230eda96b0700207b1bcc9855025b9a Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 20 Mar 2022 11:24:04 -0400 Subject: [PATCH 1014/1120] Ensure the forking thread holds the global mutex before forking --- vendor/libkqueue/src/common/kqueue.c | 28 +++++++++++++++++++++++++-- vendor/libkqueue/src/common/private.h | 4 ++++ vendor/libkqueue/src/linux/platform.c | 4 ++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 2e91cdbdc..590a15457 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -99,7 +99,29 @@ libkqueue_free(void) #ifndef _WIN32 void -libkqueue_fork(void) +libkqueue_pre_fork(void) +{ + /* + * Ensure that all global structures are in a + * consistent state before attempting the + * fork. + * + * If we don't do this then kq_mtx state will + * be undefined when the child starts cleaning + * up resources, and we could get deadlocks, nasty + * memory corruption and or crashes in the child. + */ + tracing_mutex_lock(&kq_mtx); +} + +void +libkqueue_parent_fork(void) +{ + tracing_mutex_unlock(&kq_mtx); +} + +void +libkqueue_child_fork(void) { dbg_puts("cleaning up forked resources"); @@ -107,6 +129,8 @@ libkqueue_fork(void) if (kqops.libkqueue_fork) kqops.libkqueue_fork(); + + tracing_mutex_unlock(&kq_mtx); } #endif @@ -155,7 +179,7 @@ libkqueue_init(void) dbg_puts("library initialization complete"); #ifndef _WIN32 - pthread_atfork(NULL, NULL, libkqueue_fork); + pthread_atfork(libkqueue_pre_fork, libkqueue_parent_fork, libkqueue_child_fork); #endif atexit(libkqueue_free); } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index a748f4acd..b5e932394 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -266,6 +266,8 @@ struct filter { #ifndef _WIN32 /** Called on fork (for the child) * + * Always called with kq_mtx held to ensure global resources + * are in a a consistent state for cleanup. */ void (*libkqueue_fork)(void); #endif @@ -515,6 +517,8 @@ struct kqueue_vtable { #ifndef _WIN32 /** Called on fork (for the child) * + * Always called with kq_mtx held to ensure global resources + * are in a a consistent state for cleanup. */ void (*libkqueue_fork)(void); #endif diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 855e8ca98..9030d8f26 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -309,6 +309,10 @@ linux_kqueue_start_thread(void) return (0); } +/** Free kqueues on fork + * + * Called with kq_mtx held. + */ static void linux_libkqueue_fork(void) { From de4dc6e914707b9224646574080123bf31a5ba5e Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 20 Mar 2022 13:52:15 -0400 Subject: [PATCH 1015/1120] Prevent cancellation inside sensitive regions of kevent --- vendor/libkqueue/src/common/kevent.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 3818c4a84..da4185261 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -329,10 +329,10 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, struct kqueue *kq; struct kevent *el_p, *el_end; int rv = 0; + int prev_cancel_state; #ifndef NDEBUG static atomic_uint _kevent_counter = 0; unsigned int myid = 0; - (void) myid; #endif @@ -348,10 +348,17 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, } if (!changelist) changelist = &null_kev; + /* + * Grab the global mutex. This prevents + * any operations that might free the + * kqueue from progressing. + */ + prev_cancel_state = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); /* Convert the descriptor into an object pointer */ kq = kqueue_lookup(kqfd); if (kq == NULL) { errno = ENOENT; + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); return (-1); } @@ -421,5 +428,10 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, out: dbg_printf("--- END kevent %u ret %d ---", myid, rv); + + pthread_setcancelstate(prev_cancel_state, NULL); + if (prev_cancel_state == PTHREAD_CANCEL_ENABLE) + pthread_testcancel(); + return (rv); } From 13ce648900ddbfffbe7b5e402a1fa16afd7338c4 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 20 Mar 2022 13:53:13 -0400 Subject: [PATCH 1016/1120] Use an enum for tracing mutexes for better debugger output --- vendor/libkqueue/src/common/debug.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index 6b079c74d..cd21fdb0c 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -85,13 +85,14 @@ extern char *KQUEUE_DEBUG_IDENT; * It also allows you to assert that a mutex has (or has not) been locked * by calling tracing_mutex_assert(). */ - -# define MTX_UNLOCKED 0 -# define MTX_LOCKED 1 +enum tracing_mutex_status { + MTX_UNLOCKED = 0, + MTX_LOCKED +}; typedef struct { pthread_mutex_t mtx_lock; - int mtx_status; + enum tracing_mutex_status mtx_status; int mtx_owner; } tracing_mutex_t; From aa7544caa72833b8ebfef586f9331667648470c2 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 20 Mar 2022 13:53:51 -0400 Subject: [PATCH 1017/1120] Add tracing_mutex_assert_state which just checks for the mutex state not the owner --- vendor/libkqueue/src/common/debug.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index cd21fdb0c..bb5d5ab55 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -115,6 +115,15 @@ typedef struct { abort(); \ } while (0) +# define tracing_mutex_assert_state(x,y) do { \ + if ((y) == MTX_UNLOCKED) \ + assert((x)->mtx_status == MTX_UNLOCKED); \ + else if ((y) == MTX_LOCKED) \ + assert((x)->mtx_status == MTX_LOCKED); \ + else \ + abort(); \ +} while (0) + # define tracing_mutex_lock(x) do { \ dbg_printf("[%i]: waiting for %s", __LINE__, #x); \ pthread_mutex_lock(&((x)->mtx_lock)); \ @@ -156,6 +165,7 @@ typedef struct { # define tracing_mutex_init pthread_mutex_init # define tracing_mutex_destroy pthread_mutex_destroy # define tracing_mutex_assert(x,y) +# define tracing_mutex_assert_state(x,y) # define tracing_mutex_lock pthread_mutex_lock # define tracing_mutex_trylock(ret,x) do { ret = pthread_mutex_trylock(x); } while (0) # define tracing_mutex_unlock pthread_mutex_unlock From 0cb7d869504064db675e328cfc46bc93ba97a98c Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 20 Mar 2022 13:55:25 -0400 Subject: [PATCH 1018/1120] Ensure kq_mtx is held by the cleanup function and fix double unlocks --- vendor/libkqueue/src/linux/platform.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index 9030d8f26..d559966be 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -92,6 +92,13 @@ monitoring_thread_cleanup(UNUSED void *arg) */ if ((monitoring_thread_state == THREAD_EXIT_STATE_CANCEL_LOCKED) || (monitoring_thread_state == THREAD_EXIT_STATE_CANCEL_UNLOCKED)) { + + /* + * Keep the assertion in kqueue_free happy + */ + if (monitoring_thread_state == THREAD_EXIT_STATE_CANCEL_UNLOCKED) + tracing_mutex_lock(&kq_mtx); + LIST_FOREACH_SAFE(kq, &kq_list, kq_entry, kq_tmp) { int signal_fd = kq->pipefd[0]; @@ -110,6 +117,9 @@ monitoring_thread_cleanup(UNUSED void *arg) kq, kq->kq_id, fd_use_cnt[signal_fd]); } } + + if (monitoring_thread_state == THREAD_EXIT_STATE_CANCEL_UNLOCKED) + tracing_mutex_unlock(&kq_mtx); } dbg_printf("tid=%u - monitoring thread exiting (%s)", @@ -124,7 +134,7 @@ monitoring_thread_cleanup(UNUSED void *arg) /* Reset so that thread can be restarted */ monitoring_tid = 0; - if (monitoring_thread_state == THREAD_EXIT_STATE_CANCEL_UNLOCKED) + if (monitoring_thread_state == THREAD_EXIT_STATE_CANCEL_LOCKED) tracing_mutex_unlock(&kq_mtx); } @@ -409,7 +419,8 @@ linux_libkqueue_free(void) dbg_printf("tid=%u - join failed: %s", tid, strerror(ret)); } } - tracing_mutex_unlock(&kq_mtx); + else + tracing_mutex_unlock(&kq_mtx); } static int From fa2f54b38eea6f985a597459707d1f6363d18c42 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 20 Mar 2022 13:56:20 -0400 Subject: [PATCH 1019/1120] Hold the kq->kq_mtx for the entirety of copyin/copyout This fixes most of TSAN's complaints and makes the code significantly saner --- vendor/libkqueue/src/common/kevent.c | 22 ++++++++++++---- vendor/libkqueue/src/common/kqueue.c | 18 ++++++++++++++ vendor/libkqueue/src/linux/platform.c | 36 +++++++++++++++++++++++---- 3 files changed, 66 insertions(+), 10 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index da4185261..056b75c1a 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -335,7 +335,6 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, unsigned int myid = 0; (void) myid; #endif - /* deal with ubsan "runtime error: applying zero offset to null pointer" */ if (eventlist) { if (nevents > MAX_KEVENT) @@ -354,14 +353,25 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, * kqueue from progressing. */ prev_cancel_state = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + tracing_mutex_lock(&kq_mtx); /* Convert the descriptor into an object pointer */ kq = kqueue_lookup(kqfd); if (kq == NULL) { errno = ENOENT; + tracing_mutex_unlock(&kq_mtx); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); return (-1); } + kqueue_lock(kq); + + /* + * We no longer need the global mutex as + * nothing else can use this kqueue until + * we release the lock. + */ + tracing_mutex_unlock(&kq_mtx); + #ifndef NDEBUG if (DEBUG_KQUEUE) { myid = atomic_inc(&_kevent_counter); @@ -373,9 +383,12 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, * Process each kevent on the changelist. */ if (nchanges > 0) { - kqueue_lock(kq); + /* + * Grab the kqueue specific mutex, this + * prevents any operations on the specific + * kqueue from progressing. + */ rv = kevent_copyin(kq, changelist, nchanges, el_p, el_end - el_p); - kqueue_unlock(kq); dbg_printf("(%u) kevent_copyin rv=%d", myid, rv); if (rv < 0) goto out; @@ -392,9 +405,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, rv = kqops.kevent_wait(kq, nevents, timeout); dbg_printf("kqops.kevent_wait rv=%i", rv); if (likely(rv > 0)) { - kqueue_lock(kq); rv = kqops.kevent_copyout(kq, rv, el_p, el_end - el_p); - kqueue_unlock(kq); dbg_printf("(%u) kevent_copyout rv=%i", myid, rv); if (rv >= 0) { el_p += rv; /* Add events from copyin */ @@ -427,6 +438,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, #endif out: + kqueue_unlock(kq); dbg_printf("--- END kevent %u ret %d ---", myid, rv); pthread_setcancelstate(prev_cancel_state, NULL); diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 590a15457..31573e4c6 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -195,9 +195,19 @@ kqueue_knote_mark_disabled_all(struct kqueue *kq) } } +/** Free a kqueue, must be called with the kq_mtx held + * + */ void kqueue_free(struct kqueue *kq) { + /* + * Because this can be called during fork + * processing the locker and unlocker may + * be different. + */ + tracing_mutex_assert_state(&kq_mtx, MTX_LOCKED); + dbg_printf("kq=%p - freeing", kq); kq_cnt--; @@ -212,8 +222,16 @@ kqueue_free(struct kqueue *kq) */ map_remove(kqmap, kq->kq_id, kq); + /* + * Ensure no other thread has any ongoing + * operations on this kqueue. Unlikely but + * keeps TSAN Happy. + */ + kqueue_lock(kq); filter_unregister_all(kq); kqops.kqueue_free(kq); + kqueue_unlock(kq); + tracing_mutex_destroy(&kq->kq_mtx); #ifndef NDEBUG diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index d559966be..ab764964c 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -103,17 +103,43 @@ monitoring_thread_cleanup(UNUSED void *arg) int signal_fd = kq->pipefd[0]; /* - * If there's no use cnt for the kqueue - * then something has gone very wrong + * We only cleanup kqueues where their file descriptor + * has been closed. + * + * This is necessary because we can be told to exit + * before the monitoring thread has a chance to process + * the signal indicating that a kqueue has been + * cleaned up, and this can lead to spurious reports + * from LSAN. + * + * We only cleanup kqueues where the file descriptor has + * been closed, because other kqueues may be in the + * middle of operations with kq->kq_mtx held, and + * attempting to clean them up would cause a deadlock. + * + * These kqueues are legitimate leaks, and should have + * been freed by the user application before it exited. */ - assert(fd_use_cnt[signal_fd] > 0); - fd_use_cnt[signal_fd]--; + dbg_printf("kq=%p - fd=%i explicitly checking for closeure", kq, kq->kq_id); + if (fcntl(kq->kq_id, F_GETFD) < 0) { + dbg_printf("kq=%p - fd=%i forcefully cleaning up, current use_count=%u: %s", + kq, + kq->kq_id, fd_use_cnt[signal_fd], + errno == EBADF ? "File descriptor already closed" : strerror(errno)); + fd_use_cnt[signal_fd] = 0; + } else { + /* + * If there's no use cnt for the kqueue then something + * has gone very wrong. + */ + assert(fd_use_cnt[signal_fd] > 0); + } if (fd_use_cnt[signal_fd] == 0) { dbg_printf("kq=%p - fd=%i use_count=%u cleaning up...", kq, kq->kq_id, fd_use_cnt[signal_fd]); kqueue_free(kq); } else { - dbg_printf("kq=%p - fd=%i use_count=%u skipping, this is likely a leak...", + dbg_printf("kq=%p - fd=%i is alive use_count=%u. Skipping, this is likely a leak...", kq, kq->kq_id, fd_use_cnt[signal_fd]); } } From 47881c61a9fbe847c43a9d4a4a2f3030ffbfd9a2 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 20 Mar 2022 14:06:23 -0400 Subject: [PATCH 1020/1120] Ensure kqueues are in a consistent state at fork --- vendor/libkqueue/src/common/kqueue.c | 31 +++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 31573e4c6..9c92facfb 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -101,6 +101,8 @@ libkqueue_free(void) void libkqueue_pre_fork(void) { + struct kqueue *kq, *kq_tmp; + /* * Ensure that all global structures are in a * consistent state before attempting the @@ -112,19 +114,46 @@ libkqueue_pre_fork(void) * memory corruption and or crashes in the child. */ tracing_mutex_lock(&kq_mtx); + + /* + * Acquire locks for all the active kqueues, + * this ensures in the child all kqueues are in + * a consistent state, ready to be freed. + * + * This has the potential to stall out the process + * whilst we attempt to acquire all the locks, + * so it might be a good idea to make this + * configurable in future. + */ + dbg_puts("gathering kqueue locks on fork"); + LIST_FOREACH_SAFE(kq, &kq_list, kq_entry, kq_tmp) { + kqueue_lock(kq); + } } void libkqueue_parent_fork(void) { + struct kqueue *kq, *kq_tmp; + + dbg_puts("releasing kqueue locks in parent"); + LIST_FOREACH_SAFE(kq, &kq_list, kq_entry, kq_tmp) { + kqueue_unlock(kq); + } tracing_mutex_unlock(&kq_mtx); } void libkqueue_child_fork(void) { - dbg_puts("cleaning up forked resources"); + struct kqueue *kq, *kq_tmp; + dbg_puts("releasing kqueue locks in child"); + LIST_FOREACH_SAFE(kq, &kq_list, kq_entry, kq_tmp) { + kqueue_unlock(kq); + } + + dbg_puts("cleaning up forked resources"); filter_fork_all(); if (kqops.libkqueue_fork) From 69b23d18f621ed48c9f8cf22d31b77286f7cfd6d Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 20 Mar 2022 14:28:23 -0400 Subject: [PATCH 1021/1120] Remove the knote mutex No longer used as we're using a coarser lock on kq_mtx --- vendor/libkqueue/src/common/filter.c | 19 ------------------- vendor/libkqueue/src/common/knote.c | 19 +++++++------------ vendor/libkqueue/src/common/private.h | 12 +++--------- vendor/libkqueue/src/posix/proc.c | 2 +- 4 files changed, 11 insertions(+), 41 deletions(-) diff --git a/vendor/libkqueue/src/common/filter.c b/vendor/libkqueue/src/common/filter.c index aaa9d1f36..7e26ab699 100644 --- a/vendor/libkqueue/src/common/filter.c +++ b/vendor/libkqueue/src/common/filter.c @@ -105,18 +105,6 @@ filter_register(struct kqueue *kq, const struct filter *src) dst->kf_kqueue = kq; RB_INIT(&dst->kf_index); - /* - * This allows disable and/or delete to be called from any - * of the other knote processing functions. - * - * It's probably not a great idea, but it makes the code - * simpler. - */ -#ifndef _WIN32 - pthread_mutexattr_init(&dst->kf_knote_mtx_attr); - pthread_mutexattr_settype(&dst->kf_knote_mtx_attr, PTHREAD_MUTEX_RECURSIVE); -#endif - tracing_mutex_init(&dst->kf_knote_mtx, &dst->kf_knote_mtx_attr); if (src->kf_id == 0) { dbg_puts("filter is not implemented"); return (0); @@ -188,13 +176,6 @@ filter_unregister_all(struct kqueue *kq) if (kqops.filter_free != NULL) kqops.filter_free(kq, filt); - /* - * ...and destroy the mutexes. - */ - tracing_mutex_destroy(&filt->kf_knote_mtx); -#ifndef _WIN32 - pthread_mutexattr_destroy(&filt->kf_knote_mtx_attr); -#endif } memset(&kq->kq_filt[0], 0, sizeof(kq->kq_filt)); } diff --git a/vendor/libkqueue/src/common/knote.c b/vendor/libkqueue/src/common/knote.c index 48317c1a9..d1a537ed4 100644 --- a/vendor/libkqueue/src/common/knote.c +++ b/vendor/libkqueue/src/common/knote.c @@ -77,9 +77,8 @@ knote_release(struct knote *kn) void knote_insert(struct filter *filt, struct knote *kn) { - tracing_mutex_lock(&filt->kf_knote_mtx); + kqueue_mutex_assert(filt->kf_kqueue, MTX_LOCKED); RB_INSERT(knote_index, &filt->kf_index, kn); - tracing_mutex_unlock(&filt->kf_knote_mtx); } struct knote * @@ -90,9 +89,8 @@ knote_lookup(struct filter *filt, uintptr_t ident) query.kev.ident = ident; - tracing_mutex_lock(&filt->kf_knote_mtx); + kqueue_mutex_assert(filt->kf_kqueue, MTX_LOCKED); ent = RB_FIND(knote_index, &filt->kf_index, &query); - tracing_mutex_unlock(&filt->kf_knote_mtx); return (ent); } @@ -101,10 +99,10 @@ int knote_delete_all(struct filter *filt) { struct knote *kn, *tmp; - tracing_mutex_lock(&filt->kf_knote_mtx); + kqueue_mutex_assert(filt->kf_kqueue, MTX_LOCKED); RB_FOREACH_SAFE(kn, knote_index, &filt->kf_index, tmp) knote_delete(filt, kn); - tracing_mutex_unlock(&filt->kf_knote_mtx); + return (0); } @@ -112,12 +110,11 @@ int knote_mark_disabled_all(struct filter *filt) { struct knote *kn, *tmp; - tracing_mutex_lock(&filt->kf_knote_mtx); RB_FOREACH_SAFE(kn, knote_index, &filt->kf_index, tmp) { dbg_printf("kn=%p - marking disabled", kn); KNOTE_DISABLE(kn); } - tracing_mutex_unlock(&filt->kf_knote_mtx); + return (0); } @@ -139,7 +136,7 @@ knote_delete(struct filter *filt, struct knote *kn) * thread before we acquired the knotelist lock. */ query.kev.ident = kn->kev.ident; - tracing_mutex_lock(&filt->kf_knote_mtx); + kqueue_mutex_assert(filt->kf_kqueue, MTX_LOCKED); tmp = RB_FIND(knote_index, &filt->kf_index, &query); if (tmp != kn) dbg_printf("kn=%p - conflicting entry in filter tree", kn); @@ -148,7 +145,6 @@ knote_delete(struct filter *filt, struct knote *kn) if (LIST_INSERTED(kn, kn_ready)) LIST_REMOVE_ZERO(kn, kn_ready); - tracing_mutex_unlock(&filt->kf_knote_mtx); rv = filt->kn_delete(filt, kn); dbg_printf("kn=%p - kn_delete rv=%i", kn, rv); @@ -172,10 +168,9 @@ knote_disable(struct filter *filt, struct knote *kn) rv = filt->kn_disable(filt, kn); dbg_printf("kn=%p - kn_disable rv=%i", kn, rv); if (rv == 0) { - tracing_mutex_lock(&filt->kf_knote_mtx); + kqueue_mutex_assert(filt->kf_kqueue, MTX_LOCKED); if (LIST_INSERTED(kn, kn_ready)) /* No longer marked as ready if disabled */ LIST_REMOVE_ZERO(kn, kn_ready); - tracing_mutex_unlock(&filt->kf_knote_mtx); KNOTE_DISABLE(kn); /* set the disable flag */ } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index b5e932394..fc2fe4286 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -468,13 +468,6 @@ struct filter { ///< with eventfds. ///< This is not used by all filters. - tracing_mutex_t kf_knote_mtx; //!< Used to synchronise knote operations - ///< (addition, removal, modification etc...) - ///< on this filter. -#ifndef _WIN32 - pthread_mutexattr_t kf_knote_mtx_attr; -#endif - struct kqueue *kf_kqueue; //!< kqueue this filter is associated with. #if defined(FILTER_PLATFORM_SPECIFIC) @@ -645,8 +638,9 @@ extern unsigned int kq_cnt; /* * kqueue internal API */ -#define kqueue_lock(kq) tracing_mutex_lock(&(kq)->kq_mtx) -#define kqueue_unlock(kq) tracing_mutex_unlock(&(kq)->kq_mtx) +#define kqueue_mutex_assert(kq, state) tracing_mutex_assert(&(kq)->kq_mtx, state) +#define kqueue_lock(kq) tracing_mutex_lock(&(kq)->kq_mtx) +#define kqueue_unlock(kq) tracing_mutex_unlock(&(kq)->kq_mtx) /* * knote internal API diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index adfbae061..204f3a29d 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -600,7 +600,7 @@ evfilt_proc_knote_copyout(struct kevent *dst, int nevents, struct filter *filt, * major issues. * * By using a single lock we ensure either the - * waiter thread is notifying kqueue isntances + * waiter thread is notifying kqueue instances * data is ready, or a kqueue is copying out * notifications, so no deadlock can occur. */ From d15cc98825954b1ee5bde57c1d21ac5f70012ce4 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 20 Mar 2022 14:45:46 -0400 Subject: [PATCH 1022/1120] Prevent cancellation inside sensitive regions of kqueue ...and don't use pthread_setcancelstate on windows as it's not supported --- vendor/libkqueue/BUGS.md | 7 ------- vendor/libkqueue/src/common/kevent.c | 12 ++++++++++-- vendor/libkqueue/src/common/kqueue.c | 12 ++++++++++++ 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/vendor/libkqueue/BUGS.md b/vendor/libkqueue/BUGS.md index 4753532a6..cb4ffb66d 100644 --- a/vendor/libkqueue/BUGS.md +++ b/vendor/libkqueue/BUGS.md @@ -24,13 +24,6 @@ src/windows/timer.c: return (0); /* STUB */ ``` - * `kqueue()` should defer thread cancellation until the end. - - * `kevent()` should defer thread cancellation and call `pthread_testcancel()` - before and after the call to `kevent_wait()`. This may require changing the - way that `EINTR` is handled, to make sure that the `EINTR` is propagated up - the call stack to `kevent()`. - ## POSIX * `EVFILT_PROC` - The POSIX implmentation requires that `SIGCHLD` diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 056b75c1a..9b2069566 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -329,7 +329,9 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, struct kqueue *kq; struct kevent *el_p, *el_end; int rv = 0; +#ifndef _WIN32 int prev_cancel_state; +#endif #ifndef NDEBUG static atomic_uint _kevent_counter = 0; unsigned int myid = 0; @@ -347,19 +349,23 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, } if (!changelist) changelist = &null_kev; +#ifndef _WIN32 + prev_cancel_state = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); +#endif /* * Grab the global mutex. This prevents * any operations that might free the * kqueue from progressing. */ - prev_cancel_state = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); tracing_mutex_lock(&kq_mtx); /* Convert the descriptor into an object pointer */ kq = kqueue_lookup(kqfd); if (kq == NULL) { errno = ENOENT; tracing_mutex_unlock(&kq_mtx); - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); +#ifndef _WIN32 + pthread_setcancelstate(prev_cancel_state, NULL); +#endif return (-1); } @@ -441,9 +447,11 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, kqueue_unlock(kq); dbg_printf("--- END kevent %u ret %d ---", myid, rv); +#ifndef _WIN32 pthread_setcancelstate(prev_cancel_state, NULL); if (prev_cancel_state == PTHREAD_CANCEL_ENABLE) pthread_testcancel(); +#endif return (rv); } diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 9c92facfb..683c9f63c 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -302,11 +302,15 @@ kqueue(void) tracing_mutex_init(&kq_mtx, NULL); #else + int prev_cancel_state; tracing_mutex_lock(&kq_mtx); (void) pthread_once(&kq_is_initialized, libkqueue_init); tracing_mutex_unlock(&kq_mtx); #endif +#ifndef _WIN32 + prev_cancel_state = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); +#endif kq = calloc(1, sizeof(*kq)); if (kq == NULL) return (-1); @@ -327,6 +331,9 @@ kqueue(void) dbg_printf("kq=%p - init failed", kq); tracing_mutex_destroy(&kq->kq_mtx); free(kq); +#ifndef _WIN32 + pthread_setcancelstate(prev_cancel_state, NULL); +#endif return (-1); } @@ -343,6 +350,11 @@ kqueue(void) LIST_INSERT_HEAD(&kq_list, kq, kq_entry); kq_cnt++; tracing_mutex_unlock(&kq_mtx); +#ifndef _WIN32 + pthread_setcancelstate(prev_cancel_state, NULL); + if (prev_cancel_state == PTHREAD_CANCEL_ENABLE) + pthread_testcancel(); +#endif return (kq->kq_id); } From 953555ad623820fdbf8dd67503b9b98b6f28279c Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 20 Mar 2022 15:45:58 -0400 Subject: [PATCH 1023/1120] Update release notes --- vendor/libkqueue/ChangeLog | 39 +++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 553f15718..4cebfb75d 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,8 +1,39 @@ Unreleased ------------------------------------------------------------------------ - * Fix: Allow EVFILT_TIMER filters to be modified on Linux - (Closes #116) (Reported by: Grant Erickson). + * Fix: posix/proc don't allow users of this filter to progress + until the proc waiter thread has completed initialisation. + + * Fix: Address multiple thread synchronisation issues by using a + single global mutex to synchronise the kqueue list, and kqueue + file descriptor map, and per kqueue mutexes which are locked for + the duration of copyin and copyout. The per filter knote mutex + was removed with this change as it's no longer needed. + + * Fix: posix/proc fix knote use after free if a notification + comes in for a knote which has already been freed. + The underlying issue was a problem with the list macros not + zeroing out prev/next pointers when items were removed from + lists. + + * Fix: prevent thread cancellation on Linux in kqueue() and + kevent(). This prevents deadlocks occuring if a kqueue is + shared between threads and one thread is cancelled. + + * Fix: linux Cleanup all kqueues by closing their file descriptors + and freeing associated memory on fork. A similar fix needed for + Solaris. + + * Fix: linux/read linux/write Prevent invalid access of + fds->fds_write if the file descriptor state is freed after + processing read events. + + * Fix: linux/monitor Use an atexit handler to ensure the fd + monitoring thread is shutdown gracefully on Linux. This fixes + spurious leak reports from LSAN et al... + + * Fix: linux/timer Allow EVFILT_TIMER filters to be modified on + Linux (Closes #116) (Reported by: Grant Erickson). * Fix: Set the library search path in libkqueue.pc (Closes #117) (Reported by: Grant Erickson) @@ -44,7 +75,9 @@ Unreleased of packages between releases. * Add EVFILT_LIBKQUEUE to expose libkqueue specific configuration - options. + options. The initial implementation supports NOTE_VERSION to + retrieve the current version number, and NOTE_VERSION_STR to + retrieve a textual description of the version. 2021-09-06 v2.5.0 ------------------------------------------------------------------------ From 6901a9fc772e78fb49fd97af191ca67dc98e42b5 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 20 Mar 2022 16:04:23 -0400 Subject: [PATCH 1024/1120] Allow a thread to be cancelled if it's waiting in kevent_wait --- vendor/libkqueue/src/common/kevent.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 9b2069566..baee98625 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -321,6 +321,14 @@ kevent_copyin(struct kqueue *kq, const struct kevent *changelist, int nchanges, return (el_p - eventlist); } +#ifndef _WIN32 +static void +kevent_release_kq_mutex(void *kq) +{ + kqueue_unlock((struct kqueue *)kq); +} +#endif + int VISIBLE kevent(int kqfd, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, @@ -370,6 +378,9 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, } kqueue_lock(kq); +#ifndef _WIN32 + pthread_cleanup_push(kevent_release_kq_mutex, kq); +#endif /* * We no longer need the global mutex as @@ -377,7 +388,6 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, * we release the lock. */ tracing_mutex_unlock(&kq_mtx); - #ifndef NDEBUG if (DEBUG_KQUEUE) { myid = atomic_inc(&_kevent_counter); @@ -408,7 +418,20 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, * the changelist, copy events out. */ if ((el_end - el_p) > 0) { + /* + * Allow cancellation in kevent_wait as we + * may be waiting a long time for the thread + * to exit... + */ +#ifndef _WIN32 + (void)pthread_setcancelstate(prev_cancel_state, NULL); + if (prev_cancel_state == PTHREAD_CANCEL_ENABLE) + pthread_testcancel(); +#endif rv = kqops.kevent_wait(kq, nevents, timeout); +#ifndef _WIN32 + (void)pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); +#endif dbg_printf("kqops.kevent_wait rv=%i", rv); if (likely(rv > 0)) { rv = kqops.kevent_copyout(kq, rv, el_p, el_end - el_p); @@ -444,6 +467,9 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, #endif out: +#ifndef _WIN32 + pthread_cleanup_pop(0); +#endif kqueue_unlock(kq); dbg_printf("--- END kevent %u ret %d ---", myid, rv); From 7534452832db5aa0c8e965dd7be770764b15e3cb Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 20 Mar 2022 17:00:12 -0400 Subject: [PATCH 1025/1120] Add test for fork Suppress spurious TSAN reports in libkqueue_pre_fork --- vendor/libkqueue/src/common/kqueue.c | 22 ++++++++++++++++++++++ vendor/libkqueue/test/kqueue.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 683c9f63c..4a3720719 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -98,6 +98,28 @@ libkqueue_free(void) } #ifndef _WIN32 + +/** TSAN incorrectly detects data races in this function + * + * It's not clear why it's not recording the fact that the appropriate + * mutexes are in fact locked... but it is: + * + * Write of size 4 at 0x7f2ca355e34c by thread T1 (mutexes: write M4): + * #0 monitoring_thread_loop /home/arr2036/Documents/Repositories/dependencies/libkqueue/src/linux/platform.c:298 (libkqueue.so.0+0xf521) + * + * Previous write of size 4 at 0x7f2ca355e34c by main thread: + * #0 libkqueue_pre_fork /home/arr2036/Documents/Repositories/dependencies/libkqueue/src/common/kqueue.c:116 (libkqueue.so.0+0xbb8c) + * #1 (libc.so.6+0x94aff) + * #2 test_fork /home/arr2036/Documents/Repositories/dependencies/libkqueue/test/kqueue.c:168 (libkqueue-test+0x63cf) + * #3 run_iteration /home/arr2036/Documents/Repositories/dependencies/libkqueue/test/main.c:82 (libkqueue-test+0x7ca3) + * #4 test_harness /home/arr2036/Documents/Repositories/dependencies/libkqueue/test/main.c:109 (libkqueue-test+0x7e40) + * #5 main /home/arr2036/Documents/Repositories/dependencies/libkqueue/test/main.c:286 (libkqueue-test+0x8889) + */ +#if defined(__has_feature) +# if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__) +__attribute__((no_sanitize("thread"))) +# endif +#endif void libkqueue_pre_fork(void) { diff --git a/vendor/libkqueue/test/kqueue.c b/vendor/libkqueue/test/kqueue.c index ac133cec1..d04aa3d9a 100644 --- a/vendor/libkqueue/test/kqueue.c +++ b/vendor/libkqueue/test/kqueue.c @@ -154,6 +154,33 @@ test_cleanup(void *unused) die("setrlimit failed"); } } + +void +test_fork(void *unused) +{ + int kqfd; + pid_t pid; + + kqfd = kqueue(); + if (kqfd < 0) + die("kqueue()"); + + pid = fork(); + if (pid == 0) { + /* + * fork should immediately close all open + * kqueues and their file descriptors. + */ + if (close(kqfd) != -1) + die("kqueue fd still open in child"); + + testing_end_quiet(); + exit(0); + } else if (pid == -1) + die("fork()"); + + close(kqfd); +} #endif /* EV_RECEIPT is not available or running on Win32 */ @@ -232,6 +259,7 @@ test_kqueue(struct test_context *ctx) #if defined(__linux__) test(cleanup, ctx); + test(fork, ctx); #endif #if !defined(_WIN32) From 98f70bff6251b040f7429617272862b458435317 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 20 Mar 2022 17:07:40 -0400 Subject: [PATCH 1026/1120] Pin macos version for FreeBSD Later versions don't seem to work --- vendor/libkqueue/.github/workflows/ci-freebsd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/.github/workflows/ci-freebsd.yml b/vendor/libkqueue/.github/workflows/ci-freebsd.yml index abed74c12..df5db472b 100644 --- a/vendor/libkqueue/.github/workflows/ci-freebsd.yml +++ b/vendor/libkqueue/.github/workflows/ci-freebsd.yml @@ -10,7 +10,7 @@ on: jobs: freebsd-tests: timeout-minutes: 5 - runs-on: macos-latest + runs-on: macos-10.15 name: "FreeBSD tests" steps: - uses: actions/checkout@v2 From 5df466a5f6f8493dc9f97f26ebc2d92c27831944 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 20 Mar 2022 17:17:53 -0400 Subject: [PATCH 1027/1120] Only run the fork test if we have TSAN suppression support --- vendor/libkqueue/src/common/kqueue.c | 6 +----- vendor/libkqueue/src/common/private.h | 22 ++++++++++++++++++++++ vendor/libkqueue/test/kqueue.c | 8 ++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 4a3720719..6fcdea9d9 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -115,11 +115,7 @@ libkqueue_free(void) * #4 test_harness /home/arr2036/Documents/Repositories/dependencies/libkqueue/test/main.c:109 (libkqueue-test+0x7e40) * #5 main /home/arr2036/Documents/Repositories/dependencies/libkqueue/test/main.c:286 (libkqueue-test+0x8889) */ -#if defined(__has_feature) -# if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__) -__attribute__((no_sanitize("thread"))) -# endif -#endif +TSAN_IGNORE void libkqueue_pre_fork(void) { diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index fc2fe4286..02a780933 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -116,6 +116,28 @@ struct evfilt_data; #define UNUSED_NDEBUG #endif +/* + * Check for LLVM TSAN + */ +#if defined(__has_feature) +# if __has_feature(thread_sanitizer) +# define TSAN_IGNORE __attribute__((no_sanitize("thread"))) +# define HAVE_TSAN_IGNORE +# endif +#endif + +/* + * Check for GCC TSAN + */ +#ifdef __SANITIZE_THREAD__ +# define TSAN_IGNORE __attribute__((no_sanitize("thread"))) +# define HAVE_TSAN_IGNORE +#endif + +#ifndef HAVE_TSAN_IGNORE +# define TSAN_IGNORE +#endif + /* * Bit twiddling */ diff --git a/vendor/libkqueue/test/kqueue.c b/vendor/libkqueue/test/kqueue.c index d04aa3d9a..de866618a 100644 --- a/vendor/libkqueue/test/kqueue.c +++ b/vendor/libkqueue/test/kqueue.c @@ -259,7 +259,15 @@ test_kqueue(struct test_context *ctx) #if defined(__linux__) test(cleanup, ctx); + + /* + * Only run the fork test if we can do TSAN + * suppressions, as there's false positives + * generated by libkqueue_pre_fork. + */ +# ifdef HAVE_TSAN_IGNORE test(fork, ctx); +# endif #endif #if !defined(_WIN32) From 2e0b528fa4863747eaefc475977b16f6e92c80a6 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 20 Mar 2022 17:26:08 -0400 Subject: [PATCH 1028/1120] rerun tests if the workflow files change Increase freebsd timeout --- vendor/libkqueue/.github/workflows/ci-freebsd.yml | 4 +++- vendor/libkqueue/.github/workflows/ci-macos.yml | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/.github/workflows/ci-freebsd.yml b/vendor/libkqueue/.github/workflows/ci-freebsd.yml index df5db472b..6d1ee4024 100644 --- a/vendor/libkqueue/.github/workflows/ci-freebsd.yml +++ b/vendor/libkqueue/.github/workflows/ci-freebsd.yml @@ -6,10 +6,12 @@ on: - master paths: - 'test/*' + - '.github/workflows/ci-freebsd.yml' jobs: freebsd-tests: - timeout-minutes: 5 +# virtualbox takes a long time to start + timeout-minutes: 15 runs-on: macos-10.15 name: "FreeBSD tests" steps: diff --git a/vendor/libkqueue/.github/workflows/ci-macos.yml b/vendor/libkqueue/.github/workflows/ci-macos.yml index 708375670..c78ec64c1 100644 --- a/vendor/libkqueue/.github/workflows/ci-macos.yml +++ b/vendor/libkqueue/.github/workflows/ci-macos.yml @@ -6,6 +6,7 @@ on: - master paths: - 'test/*' + - '.github/workflows/ci-macos.yml' jobs: macos-tests: From bca219a552ed78311d10cabb4c9c9615fd09d32b Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 21 Mar 2022 14:45:06 -0400 Subject: [PATCH 1029/1120] Add additional debugging controls to the libkqueue filter --- vendor/libkqueue/CMakeLists.txt | 1 + vendor/libkqueue/README.md | 22 +++++++ vendor/libkqueue/include/sys/event.h | 14 ++++- vendor/libkqueue/src/common/debug.c | 76 +++++++++++++++++++++++++ vendor/libkqueue/src/common/debug.h | 60 +++++++++++-------- vendor/libkqueue/src/common/kevent.c | 11 +++- vendor/libkqueue/src/common/kqueue.c | 37 ++++++++++-- vendor/libkqueue/src/common/libkqueue.c | 29 +++++++++- vendor/libkqueue/src/common/private.h | 2 + vendor/libkqueue/test/lockstat.c | 4 +- 10 files changed, 217 insertions(+), 39 deletions(-) create mode 100644 vendor/libkqueue/src/common/debug.c diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 4125529dd..d48cb600a 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -172,6 +172,7 @@ set(LIBKQUEUE_HEADERS set(LIBKQUEUE_SOURCES src/common/alloc.h src/common/debug.h + src/common/debug.c src/common/filter.c src/common/kevent.c src/common/knote.c diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index fa39acea5..a00e7737c 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -132,6 +132,28 @@ Example - retrieving version string: } printf("libkqueue version - %s", (char *)receipt.udata); +- `NOTE_FORK_CLEANUP` defaults to on (`1`) which matches the behaviour of native kqueue. + If the `data` field is `0` no resources will be cleaned up on fork. + if the `data` field is `1` all kqueues will be closed/freed on fork. + The default behaviour matches native kqueue, but may be expensive if many kqueues are + active. If there's no need to close the kqueues on fork, this should be set to disable. + If EV_RECEIPT is set the previous value of cleanup flag will be provided in a receipt + event. + +- `NOTE_DEBUG` defaults to off `0`, but may be overridden by the environmental variable + `KQUEUE_DEBUG`. Only available in debugging builds of libkqueue. + If the `data` field is `0` no debug messages will be produced. + If the `data` field is `1` debug messages will be produced. + +- `NOTE_DEBUG_PREFIX` defaults to `KQ`. Only available in debugging builds of libkqueue. + Will be set to the value of the `data` field. Value will be memdup'd. + +- `NOTE_DEBUG_FUNC` defaults to a function which writes to stdout. + Only available in debugging builds of libkqueue. + Data should point to a function the signature + `void (*debug_func)(char const *fmt, va_list ap)`, or `NULL` to restore to original + logging function. + Building Applications --------------------- diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index 0e1887faf..28c53d133 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -232,12 +232,20 @@ struct kevent { #define NOTE_ABSOLUTE 0x0008 //!< Data is an absolute timeout. /** @} */ -/** @name Data/hint flags for EVFILT_TIMER as suported and defined in kevent64 +/** @name Data/hint flags for EVFILT_LIBKQUEUE * * @{ */ -#define NOTE_VERSION 0x0001 //!< Version number as MMmmpprr. -#define NOTE_VERSION_STR 0x0002 //!< Version number string. +#define NOTE_VERSION 0x0001 //!< Version number as MMmmpprr. +#define NOTE_VERSION_STR 0x0002 //!< Version number string. +#define NOTE_FORK_CLEANUP 0x0003 //!< Control whether we cleanup kqueues + ///< and resources associated with them + ///< on fork. +#define NOTE_DEBUG 0x0004 //!< Toggle debugging output. +#define NOTE_DEBUG_PREFIX 0x0005 //!< Prefix to add to all debug messages. +#define NOTE_DEBUG_FUNC 0x0006 //!< Debugging function to call to product + ///< output. Function should have the signature. + ///< int (*debug_func)(char const *fmt, va_list ap). /** @} */ #ifndef __KERNEL__ diff --git a/vendor/libkqueue/src/common/debug.c b/vendor/libkqueue/src/common/debug.c new file mode 100644 index 000000000..f0ab87688 --- /dev/null +++ b/vendor/libkqueue/src/common/debug.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2022 Arran Cudbard-Bell + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef NDEBUG + +#include +#include +#include +#include "debug.h" + +bool libkqueue_debug = false; + +/** Prefix for libkqueue debug messages + */ +char const *libkqueue_debug_ident = "KQ"; + +/** Copy of the externally provided identity string + */ +static char *libkqueue_debug_ident_copy; + +static void dbg_stderr(char const *fmt, ...); + +/** Custom logging function + */ +dbg_func_t libkqueue_debug_func = dbg_stderr; + +static void dbg_stderr(char const *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +/** Set a new logging debug function + */ +void libkqueue_debug_func_set(dbg_func_t func) +{ + if (!func) { + libkqueue_debug_func = dbg_stderr; + } else { + libkqueue_debug_func = func; + } +} + +/** Set a new debug identity + */ +void libkqueue_debug_ident_set(char const *str) +{ + free(libkqueue_debug_ident_copy); + libkqueue_debug_ident_copy = strdup(str); + libkqueue_debug_ident = libkqueue_debug_ident_copy; +} + +/** Clear any previously allocated identities + */ +void libkqueue_debug_ident_clear(void) +{ + free(libkqueue_debug_ident_copy); + libkqueue_debug_ident_copy = NULL; + libkqueue_debug_ident = ""; +} +#endif diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index bb5d5ab55..c0134984d 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -19,15 +19,14 @@ #include #include +#include +#include #ifdef _WIN32 # include #else # include #endif -extern int DEBUG_KQUEUE; -extern char *KQUEUE_DEBUG_IDENT; - #if defined(__linux__) # include # define THREAD_ID ((pid_t) syscall(__NR_gettid)) @@ -40,38 +39,38 @@ extern char *KQUEUE_DEBUG_IDENT; #endif #ifndef NDEBUG -#define dbg_puts(str) do { \ - if (DEBUG_KQUEUE) \ - fprintf(stderr, "%s [%d]: %s(): %s\n", \ - KQUEUE_DEBUG_IDENT, THREAD_ID, __func__, str); \ +#define dbg_puts(str) do { \ + if (libkqueue_debug) \ + libkqueue_debug_func("%s [%d]: %s(): %s\n", \ + libkqueue_debug_ident, THREAD_ID, __func__, str); \ } while (0) -#define dbg_printf(fmt,...) do { \ - if (DEBUG_KQUEUE) \ - fprintf(stderr, "%s [%d]: %s(): "fmt"\n", \ - KQUEUE_DEBUG_IDENT, THREAD_ID, __func__, ##__VA_ARGS__); \ +#define dbg_printf(fmt,...) do { \ + if (libkqueue_debug) \ + libkqueue_debug_func("%s [%d]: %s(): "fmt"\n", \ + libkqueue_debug_ident, THREAD_ID, __func__, ##__VA_ARGS__); \ } while (0) -#define dbg_perror(fmt,...) do { \ - if (DEBUG_KQUEUE) \ - fprintf(stderr, "%s [%d]: %s(): "fmt": %s (errno=%d)\n", \ - KQUEUE_DEBUG_IDENT, THREAD_ID, __func__, ##__VA_ARGS__, \ - strerror(errno), errno); \ +#define dbg_perror(fmt,...) do { \ + if (libkqueue_debug) \ + libkqueue_debug_func("%s [%d]: %s(): "fmt": %s (errno=%d)\n", \ + libkqueue_debug_ident, THREAD_ID, __func__, ##__VA_ARGS__, \ + strerror(errno), errno); \ } while (0) -# define reset_errno() do { errno = 0; } while (0) +# define reset_errno() do { errno = 0; } while (0) # if defined(_WIN32) -# define dbg_lasterror(str) do { \ - if (DEBUG_KQUEUE) \ - fprintf(stderr, "%s: [%d] %s(): %s: (LastError=%d)\n", \ - KQUEUE_DEBUG_IDENT, THREAD_ID, __func__, str, (int)GetLastError()); \ +# define dbg_lasterror(str) do { \ + if (libkqueue_debug) \ + libkqueue_debug_func("%s: [%d] %s(): %s: (LastError=%d)\n", \ + libkqueue_debug_ident, THREAD_ID, __func__, str, (int)GetLastError()); \ } while (0) -# define dbg_wsalasterror(str) do { \ - if (DEBUG_KQUEUE) \ - fprintf(stderr, "%s: [%d] %s(): %s: (WSALastError=%d)\n", \ - KQUEUE_DEBUG_IDENT, THREAD_ID, __func__, str, (int)WSAGetLastError()); \ +# define dbg_wsalasterror(str) do { \ + if (libkqueue_debug) \ + libkqueue_debug_func("%s: [%d] %s(): %s: (WSALastError=%d)\n", \ + libkqueue_debug_ident, THREAD_ID, __func__, str, (int)WSAGetLastError()); \ } while (0) # else @@ -151,6 +150,16 @@ typedef struct { dbg_printf("[%i]: unlocked %s", __LINE__, # x); \ } while (0) +typedef void (*dbg_func_t)(char const *fmt, ...); + +extern bool libkqueue_debug; +extern char const *libkqueue_debug_ident; +extern dbg_func_t libkqueue_debug_func; + +void libkqueue_debug_func_set(dbg_func_t func); +void libkqueue_debug_ident_set(char const *str); +void libkqueue_debug_ident_clear(void); + #else /* NDEBUG */ # define dbg_puts(str) # define dbg_printf(fmt, ...) @@ -171,4 +180,5 @@ typedef struct { # define tracing_mutex_unlock pthread_mutex_unlock #endif + #endif /* ! _DEBUG_H */ diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index baee98625..e1c173109 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -85,6 +85,13 @@ kevent_fflags_dump(const struct kevent *kev) case EVFILT_LIBKQUEUE: KEVFFL_DUMP(NOTE_VERSION); + KEVFFL_DUMP(NOTE_VERSION_STR); + KEVFFL_DUMP(NOTE_FORK_CLEANUP); +#ifndef NDEBUG + KEVFFL_DUMP(NOTE_DEBUG); + KEVFFL_DUMP(NOTE_DEBUG_PREFIX); + KEVFFL_DUMP(NOTE_DEBUG_FUNC); +#endif break; default: @@ -389,7 +396,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, */ tracing_mutex_unlock(&kq_mtx); #ifndef NDEBUG - if (DEBUG_KQUEUE) { + if (libkqueue_debug) { myid = atomic_inc(&_kevent_counter); dbg_printf("--- START kevent %u --- (nchanges = %d nevents = %d)", myid, nchanges, nevents); } @@ -456,7 +463,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, } #ifndef NDEBUG - if (DEBUG_KQUEUE && (rv > 0)) { + if (libkqueue_debug && (rv > 0)) { int n; dbg_printf("(%u) returning %zu events", myid, el_p - eventlist); diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 6fcdea9d9..cd2692c1e 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -17,8 +17,13 @@ #include "private.h" -int DEBUG_KQUEUE = 0; -char *KQUEUE_DEBUG_IDENT = "KQ"; +/** Global control for whether we perform cleanups on fork + */ +bool libkqueue_fork_cleanup = true; + +/** Value is updated on fork to ensure all fork handlers are synchronised + */ +bool libkqueue_fork_cleanup_active; #ifdef _WIN32 tracing_mutex_t kq_mtx; @@ -98,7 +103,6 @@ libkqueue_free(void) } #ifndef _WIN32 - /** TSAN incorrectly detects data races in this function * * It's not clear why it's not recording the fact that the appropriate @@ -133,6 +137,18 @@ libkqueue_pre_fork(void) */ tracing_mutex_lock(&kq_mtx); + /* + * Unfortunately there's no way to remove the atfork + * handlers, so all we can do if cleanup is + * deactivated is bail as quickly as possible. + * + * We copy the value of libkqueue_fork_cleanup so + * that it's consistent during the fork. + */ + libkqueue_fork_cleanup_active = libkqueue_fork_cleanup; + if (!libkqueue_fork_cleanup_active) + return; + /* * Acquire locks for all the active kqueues, * this ensures in the child all kqueues are in @@ -154,6 +170,11 @@ libkqueue_parent_fork(void) { struct kqueue *kq, *kq_tmp; + if (!libkqueue_fork_cleanup_active) { + tracing_mutex_unlock(&kq_mtx); + return; + } + dbg_puts("releasing kqueue locks in parent"); LIST_FOREACH_SAFE(kq, &kq_list, kq_entry, kq_tmp) { kqueue_unlock(kq); @@ -166,6 +187,11 @@ libkqueue_child_fork(void) { struct kqueue *kq, *kq_tmp; + if (!libkqueue_fork_cleanup_active) { + tracing_mutex_unlock(&kq_mtx); + return; + } + dbg_puts("releasing kqueue locks in child"); LIST_FOREACH_SAFE(kq, &kq_list, kq_entry, kq_tmp) { kqueue_unlock(kq); @@ -185,11 +211,11 @@ void libkqueue_init(void) { #ifdef NDEBUG - DEBUG_KQUEUE = 0; + libkqueue_debug = 0; #else char *s = getenv("KQUEUE_DEBUG"); if ((s != NULL) && (strlen(s) > 0) && (*s != '0')) { - DEBUG_KQUEUE = 1; + libkqueue_debug = 1; #ifdef _WIN32 tracing_mutex_init(&kq_mtx, NULL); @@ -228,6 +254,7 @@ libkqueue_init(void) #ifndef _WIN32 pthread_atfork(libkqueue_pre_fork, libkqueue_parent_fork, libkqueue_child_fork); #endif + atexit(libkqueue_debug_ident_clear); atexit(libkqueue_free); } diff --git a/vendor/libkqueue/src/common/libkqueue.c b/vendor/libkqueue/src/common/libkqueue.c index 1e4a90cdd..5d4d6b1db 100644 --- a/vendor/libkqueue/src/common/libkqueue.c +++ b/vendor/libkqueue/src/common/libkqueue.c @@ -18,8 +18,6 @@ int common_libkqueue_knote_create(struct filter *filt, struct knote *kn) { - kn->kev.flags |= EV_RECEIPT; /* Causes the knote to be copied to the eventlist */ - switch (kn->kev.fflags) { case NOTE_VERSION_STR: kn->kev.udata = LIBKQUEUE_VERSION_STRING @@ -33,6 +31,7 @@ common_libkqueue_knote_create(struct filter *filt, struct knote *kn) " built "LIBKQUEUE_VERSION_DATE # endif ; + kn->kev.flags |= EV_RECEIPT; /* Causes the knote to be copied to the eventlist */ break; case NOTE_VERSION: @@ -43,8 +42,34 @@ common_libkqueue_knote_create(struct filter *filt, struct knote *kn) | (uint32_t)LIBKQUEUE_VERSION_RELEASE #endif ; + kn->kev.flags |= EV_RECEIPT; /* Causes the knote to be copied to the eventlist */ break; + case NOTE_FORK_CLEANUP: + { + bool old = libkqueue_fork_cleanup; + libkqueue_fork_cleanup = (kn->kev.data > 0); + kn->kev.data = old; + } + break; + +#ifndef NDEBUG + case NOTE_DEBUG: + { + bool old = libkqueue_debug; + libkqueue_debug = (kn->kev.data > 0); + kn->kev.data = old; + } + break; + + case NOTE_DEBUG_PREFIX: + libkqueue_debug_ident_set((char *)kn->kev.data); + break; + + case NOTE_DEBUG_FUNC: + libkqueue_debug_func_set((dbg_func_t)kn->kev.data); + break; +#endif default: return (-1); } diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 02a780933..8da9a6de2 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -23,6 +23,7 @@ #include #include #include +#include #include /* Required by glibc for MAP_ANON */ #define __USE_MISC 1 @@ -652,6 +653,7 @@ struct kqueue_vtable { }; LIST_HEAD(kqueue_head, kqueue); +extern bool libkqueue_fork_cleanup; extern const struct kqueue_vtable kqops; extern tracing_mutex_t kq_mtx; extern struct kqueue_head kq_list; diff --git a/vendor/libkqueue/test/lockstat.c b/vendor/libkqueue/test/lockstat.c index 0a5260c2e..7be35c653 100644 --- a/vendor/libkqueue/test/lockstat.c +++ b/vendor/libkqueue/test/lockstat.c @@ -18,8 +18,8 @@ #include #include "src/common/private.h" -int DEBUG_KQUEUE = 1; -char * KQUEUE_DEBUG_IDENT = "lockstat"; +int libkqueue_debug = 1; +char * libkqueue_debug_ident = "lockstat"; struct foo { tracing_mutex_t foo_lock; From d1b36737c769947f8b1e41f8b6fc655d89779990 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 21 Mar 2022 14:49:41 -0400 Subject: [PATCH 1030/1120] Use count should be based on kq_id not uses of the signalling end of the pipe --- vendor/libkqueue/src/linux/platform.c | 36 +++++++++++++++------------ 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index ab764964c..fa776c4ce 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -17,6 +17,7 @@ #define _GNU_SOURCE #include #include + #include #include #include @@ -100,8 +101,6 @@ monitoring_thread_cleanup(UNUSED void *arg) tracing_mutex_lock(&kq_mtx); LIST_FOREACH_SAFE(kq, &kq_list, kq_entry, kq_tmp) { - int signal_fd = kq->pipefd[0]; - /* * We only cleanup kqueues where their file descriptor * has been closed. @@ -124,23 +123,23 @@ monitoring_thread_cleanup(UNUSED void *arg) if (fcntl(kq->kq_id, F_GETFD) < 0) { dbg_printf("kq=%p - fd=%i forcefully cleaning up, current use_count=%u: %s", kq, - kq->kq_id, fd_use_cnt[signal_fd], + kq->kq_id, fd_use_cnt[kq->kq_id], errno == EBADF ? "File descriptor already closed" : strerror(errno)); - fd_use_cnt[signal_fd] = 0; + fd_use_cnt[kq->kq_id] = 0; } else { /* * If there's no use cnt for the kqueue then something * has gone very wrong. */ - assert(fd_use_cnt[signal_fd] > 0); + assert(fd_use_cnt[kq->kq_id] > 0); } - if (fd_use_cnt[signal_fd] == 0) { - dbg_printf("kq=%p - fd=%i use_count=%u cleaning up...", kq, kq->kq_id, fd_use_cnt[signal_fd]); + if (fd_use_cnt[kq->kq_id] == 0) { + dbg_printf("kq=%p - fd=%i use_count=%u cleaning up...", kq, kq->kq_id, fd_use_cnt[kq->kq_id]); kqueue_free(kq); } else { dbg_printf("kq=%p - fd=%i is alive use_count=%u. Skipping, this is likely a leak...", - kq, kq->kq_id, fd_use_cnt[signal_fd]); + kq, kq->kq_id, fd_use_cnt[kq->kq_id]); } } @@ -190,6 +189,7 @@ monitoring_thread_kqueue_cleanup(int signal_fd) if (!kq) { /* Should not happen */ dbg_printf("fd=%i - no kqueue associated", fd); + assert(0); return; } @@ -197,14 +197,16 @@ monitoring_thread_kqueue_cleanup(int signal_fd) * We should never have more pending signals than we have * allocated kqueues against a given ID. */ - assert(fd_use_cnt[signal_fd] > 0); + assert(fd_use_cnt[kq->kq_id] > 0); /* * Decrement use counter as signal handler has been run for * this FD. We rely on using an RT signal so that multiple * signals are queued. + * + * Use count is tracked with the kq_id. */ - fd_use_cnt[signal_fd]--; + fd_use_cnt[kq->kq_id]--; /* * If kqueue instance for this FD hasn't been cleaned up yet @@ -216,11 +218,11 @@ monitoring_thread_kqueue_cleanup(int signal_fd) * performed against a given file descriptor ID, and only * free the kqueue here if that count is zero. */ - if (fd_use_cnt[signal_fd] == 0) { - dbg_printf("kq=%p - fd=%i use_count=%u cleaning up...", kq, fd, fd_use_cnt[signal_fd]); + if (fd_use_cnt[kq->kq_id] == 0) { + dbg_printf("kq=%p - fd=%i use_count=%u cleaning up...", kq, fd, fd_use_cnt[kq->kq_id]); kqueue_free(kq); } else { - dbg_printf("kq=%p - fd=%i use_count=%u skipping...", kq, fd, fd_use_cnt[signal_fd]); + dbg_printf("kq=%p - fd=%i use_count=%u skipping...", kq, fd, fd_use_cnt[kq->kq_id]); } } @@ -296,7 +298,7 @@ monitoring_thread_loop(UNUSED void *arg) */ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); tracing_mutex_lock(&kq_mtx); - dbg_printf("fd=%i - freeing kqueue due to fd closure", fd_map[info.si_fd]); + dbg_printf("fd=%i - freeing kqueue due to fd closure (signal) for sfd=%i ", fd_map[info.si_fd], info.si_fd); /* * Release resources used by this kqueue @@ -535,7 +537,9 @@ linux_kqueue_init(struct kqueue *kq) fd_map[kq->pipefd[0]] = kq->kq_id; /* Mark this id as in use */ - fd_use_cnt[kq->pipefd[0]]++; + fd_use_cnt[kq->kq_id]++; + + dbg_printf("kq=%p - fd=%i use_count=%u", kq, kq->kq_id, fd_use_cnt[kq->kq_id]); assert(monitoring_tid != 0); @@ -547,7 +551,7 @@ linux_kqueue_init(struct kqueue *kq) sig_owner.type = F_OWNER_TID; sig_owner.pid = monitoring_tid; if (fcntl(kq->pipefd[0], F_SETOWN_EX, &sig_owner) < 0) { - dbg_printf("fd=%i - failed settting F_SETOWN to tid=%u: %s", monitoring_tid, kq->pipefd[0], strerror(errno)); + dbg_printf("fd=%i - failed settting F_SETOWN to tid=%u: %s", monitoring_tid, kq->kq_id, strerror(errno)); tracing_mutex_unlock(&kq_mtx); goto error; } From 669ac86444fec71615782a601c8dea9b10f6cef7 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 21 Mar 2022 14:59:20 -0400 Subject: [PATCH 1031/1120] Fixed for debug builds --- vendor/libkqueue/src/common/debug.c | 16 +++++++++++----- vendor/libkqueue/src/common/kqueue.c | 7 ++++--- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/vendor/libkqueue/src/common/debug.c b/vendor/libkqueue/src/common/debug.c index f0ab87688..52d245992 100644 --- a/vendor/libkqueue/src/common/debug.c +++ b/vendor/libkqueue/src/common/debug.c @@ -19,6 +19,7 @@ #include #include #include "debug.h" +#include "private.h" bool libkqueue_debug = false; @@ -36,7 +37,8 @@ static void dbg_stderr(char const *fmt, ...); */ dbg_func_t libkqueue_debug_func = dbg_stderr; -static void dbg_stderr(char const *fmt, ...) +static void +dbg_stderr(char const *fmt, ...) { va_list ap; @@ -47,7 +49,8 @@ static void dbg_stderr(char const *fmt, ...) /** Set a new logging debug function */ -void libkqueue_debug_func_set(dbg_func_t func) +void +libkqueue_debug_func_set(dbg_func_t func) { if (!func) { libkqueue_debug_func = dbg_stderr; @@ -58,7 +61,8 @@ void libkqueue_debug_func_set(dbg_func_t func) /** Set a new debug identity */ -void libkqueue_debug_ident_set(char const *str) +void +libkqueue_debug_ident_set(char const *str) { free(libkqueue_debug_ident_copy); libkqueue_debug_ident_copy = strdup(str); @@ -67,10 +71,12 @@ void libkqueue_debug_ident_set(char const *str) /** Clear any previously allocated identities */ -void libkqueue_debug_ident_clear(void) +TSAN_IGNORE +void +libkqueue_debug_ident_clear(void) { + libkqueue_debug_ident = ""; free(libkqueue_debug_ident_copy); libkqueue_debug_ident_copy = NULL; - libkqueue_debug_ident = ""; } #endif diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index cd2692c1e..45ff653dd 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -210,9 +210,7 @@ libkqueue_child_fork(void) void libkqueue_init(void) { -#ifdef NDEBUG - libkqueue_debug = 0; -#else +#ifndef NDEBUG char *s = getenv("KQUEUE_DEBUG"); if ((s != NULL) && (strlen(s) > 0) && (*s != '0')) { libkqueue_debug = 1; @@ -254,7 +252,10 @@ libkqueue_init(void) #ifndef _WIN32 pthread_atfork(libkqueue_pre_fork, libkqueue_parent_fork, libkqueue_child_fork); #endif + +#ifndef NDEBUG atexit(libkqueue_debug_ident_clear); +#endif atexit(libkqueue_free); } From b237b07b7d738deea3a2c48870be4e1f3ae26082 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 21 Mar 2022 15:02:18 -0400 Subject: [PATCH 1032/1120] Don't include pthread.h here --- vendor/libkqueue/src/common/debug.h | 1 - 1 file changed, 1 deletion(-) diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index c0134984d..4d4889bf4 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -20,7 +20,6 @@ #include #include #include -#include #ifdef _WIN32 # include #else From d2f91b9c19206aa49cbad5ed548a52a41fdef7c6 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 21 Mar 2022 15:49:45 -0400 Subject: [PATCH 1033/1120] Formatting --- vendor/libkqueue/README.md | 39 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index a00e7737c..4d43eb7dc 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -121,6 +121,11 @@ following: - `NOTE_VERSION` return the current version as a 32bit unsigned integer in the format `MMmmpprr` (`Major`, `minor`, `patch`, `release`) in the `data` field of an entry in the eventlist. - `NOTE_VERSION_STR` return the current version as a string in the `udata` field of an entry in the eventlist. +- `NOTE_FORK_CLEANUP` defaults to on (`1`). + - If the `data` field is `0` no resources will be cleaned up on fork. + - if the `data` field is `1` all kqueues will be closed/freed on fork. + The default behaviour matches native kqueue but may be expensive if many kqueues are active. + If `EV_RECEIPT` is set the previous value of cleanup flag will be provided in a receipt event. Example - retrieving version string: @@ -131,28 +136,20 @@ Example - retrieving version string: //error } printf("libkqueue version - %s", (char *)receipt.udata); - -- `NOTE_FORK_CLEANUP` defaults to on (`1`) which matches the behaviour of native kqueue. - If the `data` field is `0` no resources will be cleaned up on fork. - if the `data` field is `1` all kqueues will be closed/freed on fork. - The default behaviour matches native kqueue, but may be expensive if many kqueues are - active. If there's no need to close the kqueues on fork, this should be set to disable. - If EV_RECEIPT is set the previous value of cleanup flag will be provided in a receipt - event. - + +The following are only available in debugging builds of libkqueue: - `NOTE_DEBUG` defaults to off `0`, but may be overridden by the environmental variable - `KQUEUE_DEBUG`. Only available in debugging builds of libkqueue. - If the `data` field is `0` no debug messages will be produced. - If the `data` field is `1` debug messages will be produced. - -- `NOTE_DEBUG_PREFIX` defaults to `KQ`. Only available in debugging builds of libkqueue. - Will be set to the value of the `data` field. Value will be memdup'd. - -- `NOTE_DEBUG_FUNC` defaults to a function which writes to stdout. - Only available in debugging builds of libkqueue. - Data should point to a function the signature - `void (*debug_func)(char const *fmt, va_list ap)`, or `NULL` to restore to original - logging function. + `KQUEUE_DEBUG`. + - If the `data` field is `0` no debug messages will be produced. + - If the `data` field is `1` debug messages will be produced. + If `EV_RECEIPT` is set the previous value of debug flag will be provided in a receipt event. +- `NOTE_DEBUG_PREFIX` defaults to `KQ`. + Logging prefix will be set to the value of a string pointed to by the `data` field. + Logging prefix strings will be memdup'd. +- `NOTE_DEBUG_FUNC` defaults to a function which writes debug information to stderr. + The `data` field should contain a pointer to a function with the signature + `void (*debug_func)(char const *fmt, ...)`, or `NULL` to restore to original logging function. + Building Applications --------------------- From b5a2df22ff0fb0106a8be727a277627718555f18 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 21 Mar 2022 15:50:57 -0400 Subject: [PATCH 1034/1120] More formatting --- vendor/libkqueue/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index 4d43eb7dc..cb81680da 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -124,6 +124,7 @@ following: - `NOTE_FORK_CLEANUP` defaults to on (`1`). - If the `data` field is `0` no resources will be cleaned up on fork. - if the `data` field is `1` all kqueues will be closed/freed on fork. + The default behaviour matches native kqueue but may be expensive if many kqueues are active. If `EV_RECEIPT` is set the previous value of cleanup flag will be provided in a receipt event. @@ -142,6 +143,7 @@ The following are only available in debugging builds of libkqueue: `KQUEUE_DEBUG`. - If the `data` field is `0` no debug messages will be produced. - If the `data` field is `1` debug messages will be produced. + If `EV_RECEIPT` is set the previous value of debug flag will be provided in a receipt event. - `NOTE_DEBUG_PREFIX` defaults to `KQ`. Logging prefix will be set to the value of a string pointed to by the `data` field. From 37d7eace862e92104a9ccf1ce0fe82d07c91e664 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 21 Mar 2022 15:51:15 -0400 Subject: [PATCH 1035/1120] Travis no longer used --- vendor/libkqueue/README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index cb81680da..ffabd431a 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -172,6 +172,3 @@ Releases History 2.0 add support for Android _2013-04-29_ 1.0 stable relesae for Linux, Solaris, and Windows _2010-09-18_ - -[BuildStatus]: https://travis-ci.org/mheily/libkqueue.svg?branch=master "Travis CI status" -[BuildStatusLink]: https://travis-ci.org/mheily/libkqueue From 1d835d15c24493c773774e0fa65d44e2dc7c2319 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 21 Mar 2022 16:03:43 -0400 Subject: [PATCH 1036/1120] Only cache the tid in debug builds --- vendor/libkqueue/src/posix/proc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 204f3a29d..9b9a11005 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -456,7 +456,9 @@ evfilt_proc_destroy(struct filter *filt) * a new copy of the thread. */ if ((--proc_count == 0) && (proc_wait_tid != 0)) { +#ifndef NDEBUG pid_t tid = proc_wait_tid; +#endif void *retval; int ret; From 4df1b44483550ba2fe5d2794dc1b66aa07689684 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 21 Mar 2022 18:04:52 -0400 Subject: [PATCH 1037/1120] Release 2.6.0 --- vendor/libkqueue/CMakeLists.txt | 2 +- vendor/libkqueue/ChangeLog | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index d48cb600a..e82f24caf 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -14,7 +14,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -set(PROJECT_VERSION 2.5.2) +set(PROJECT_VERSION 2.6.0) if(EXISTS "/etc/debian_version") cmake_minimum_required(VERSION 3.7.2) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 4cebfb75d..c17af5619 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,11 +1,14 @@ Unreleased +------------------------------------------------------------------------ + +2022-03-21 v2.6.0 ------------------------------------------------------------------------ * Fix: posix/proc don't allow users of this filter to progress until the proc waiter thread has completed initialisation. * Fix: Address multiple thread synchronisation issues by using a - single global mutex to synchronise the kqueue list, and kqueue + single global mutex to synchronise the kqueue list and kqueue file descriptor map, and per kqueue mutexes which are locked for the duration of copyin and copyout. The per filter knote mutex was removed with this change as it's no longer needed. From 00ccb9f55285414f2d88b5b5c2076eb75cf07b48 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 21 Mar 2022 22:46:52 -0400 Subject: [PATCH 1038/1120] Add thread safety toggle --- vendor/libkqueue/README.md | 8 +++++++- vendor/libkqueue/include/sys/event.h | 10 ++++++---- vendor/libkqueue/src/common/kevent.c | 12 +++++++++--- vendor/libkqueue/src/common/kqueue.c | 4 ++++ vendor/libkqueue/src/common/libkqueue.c | 20 ++++++++++++++------ vendor/libkqueue/src/common/private.h | 1 + 6 files changed, 41 insertions(+), 14 deletions(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index ffabd431a..19b8693eb 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -121,6 +121,12 @@ following: - `NOTE_VERSION` return the current version as a 32bit unsigned integer in the format `MMmmpprr` (`Major`, `minor`, `patch`, `release`) in the `data` field of an entry in the eventlist. - `NOTE_VERSION_STR` return the current version as a string in the `udata` field of an entry in the eventlist. +- `NOTE_THREAD_SAFE` defaults to on (`1`). + - If the `data` field is `0` the global mutex will not be locked after resolving a kqueue fd + to a kqueue structure. The application must guarantee any given kqueue will be created and + destroyed by the same thread. + - If the `data` field is `1` kqueues can be created and destroyed in different threads safely. + This may add contention around the global mutex. - `NOTE_FORK_CLEANUP` defaults to on (`1`). - If the `data` field is `0` no resources will be cleaned up on fork. - if the `data` field is `1` all kqueues will be closed/freed on fork. @@ -137,7 +143,7 @@ Example - retrieving version string: //error } printf("libkqueue version - %s", (char *)receipt.udata); - + The following are only available in debugging builds of libkqueue: - `NOTE_DEBUG` defaults to off `0`, but may be overridden by the environmental variable `KQUEUE_DEBUG`. diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index 28c53d133..d080e7059 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -238,12 +238,14 @@ struct kevent { */ #define NOTE_VERSION 0x0001 //!< Version number as MMmmpprr. #define NOTE_VERSION_STR 0x0002 //!< Version number string. -#define NOTE_FORK_CLEANUP 0x0003 //!< Control whether we cleanup kqueues +#define NOTE_THREAD_SAFE 0x0003 //!< If true we lock the kq_mtx after looking up + ///< a kqueue and locking the kqueue mutex. +#define NOTE_FORK_CLEANUP 0x0004 //!< Control whether we cleanup kqueues ///< and resources associated with them ///< on fork. -#define NOTE_DEBUG 0x0004 //!< Toggle debugging output. -#define NOTE_DEBUG_PREFIX 0x0005 //!< Prefix to add to all debug messages. -#define NOTE_DEBUG_FUNC 0x0006 //!< Debugging function to call to product +#define NOTE_DEBUG 0x0005 //!< Toggle debugging output. +#define NOTE_DEBUG_PREFIX 0x0006 //!< Prefix to add to all debug messages. +#define NOTE_DEBUG_FUNC 0x0007 //!< Debugging function to call to product ///< output. Function should have the signature. ///< int (*debug_func)(char const *fmt, va_list ap). /** @} */ diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index e1c173109..16ebc467f 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -86,6 +86,7 @@ kevent_fflags_dump(const struct kevent *kev) case EVFILT_LIBKQUEUE: KEVFFL_DUMP(NOTE_VERSION); KEVFFL_DUMP(NOTE_VERSION_STR); + KEVFFL_DUMP(NOTE_THREAD_SAFE); KEVFFL_DUMP(NOTE_FORK_CLEANUP); #ifndef NDEBUG KEVFFL_DUMP(NOTE_DEBUG); @@ -372,12 +373,15 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, * any operations that might free the * kqueue from progressing. */ - tracing_mutex_lock(&kq_mtx); + if (libkqueue_thread_safe) + tracing_mutex_lock(&kq_mtx); + /* Convert the descriptor into an object pointer */ kq = kqueue_lookup(kqfd); if (kq == NULL) { errno = ENOENT; - tracing_mutex_unlock(&kq_mtx); + if (libkqueue_thread_safe) + tracing_mutex_unlock(&kq_mtx); #ifndef _WIN32 pthread_setcancelstate(prev_cancel_state, NULL); #endif @@ -385,6 +389,7 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, } kqueue_lock(kq); + #ifndef _WIN32 pthread_cleanup_push(kevent_release_kq_mutex, kq); #endif @@ -394,7 +399,8 @@ kevent(int kqfd, const struct kevent *changelist, int nchanges, * nothing else can use this kqueue until * we release the lock. */ - tracing_mutex_unlock(&kq_mtx); + if (libkqueue_thread_safe) + tracing_mutex_unlock(&kq_mtx); #ifndef NDEBUG if (libkqueue_debug) { myid = atomic_inc(&_kevent_counter); diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 45ff653dd..dd1dc4932 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -17,6 +17,10 @@ #include "private.h" +/** Global control for whether we lock the kq_mtx when looking up kqueues + */ +bool libkqueue_thread_safe = true; + /** Global control for whether we perform cleanups on fork */ bool libkqueue_fork_cleanup = true; diff --git a/vendor/libkqueue/src/common/libkqueue.c b/vendor/libkqueue/src/common/libkqueue.c index 5d4d6b1db..8ee09c690 100644 --- a/vendor/libkqueue/src/common/libkqueue.c +++ b/vendor/libkqueue/src/common/libkqueue.c @@ -25,10 +25,10 @@ common_libkqueue_knote_create(struct filter *filt, struct knote *kn) "-" STRINGIFY(LIBKQUEUE_VERSION_RELEASE) # endif # ifdef LIBKQUEUE_VERSION_COMMIT - " (git #"LIBKQUEUE_VERSION_COMMIT")" + " (git #"LIBKQUEUE_VERSION_COMMIT")" # endif # ifdef LIBKQUEUE_VERSION_DATE - " built "LIBKQUEUE_VERSION_DATE + " built "LIBKQUEUE_VERSION_DATE # endif ; kn->kev.flags |= EV_RECEIPT; /* Causes the knote to be copied to the eventlist */ @@ -45,13 +45,21 @@ common_libkqueue_knote_create(struct filter *filt, struct knote *kn) kn->kev.flags |= EV_RECEIPT; /* Causes the knote to be copied to the eventlist */ break; + case NOTE_THREAD_SAFE: + { + bool old = libkqueue_thread_safe; + libkqueue_thread_safe = (kn->kev.data > 0); + kn->kev.data = old; + } + break; + case NOTE_FORK_CLEANUP: { - bool old = libkqueue_fork_cleanup; - libkqueue_fork_cleanup = (kn->kev.data > 0); - kn->kev.data = old; + bool old = libkqueue_fork_cleanup; + libkqueue_fork_cleanup = (kn->kev.data > 0); + kn->kev.data = old; } - break; + break; #ifndef NDEBUG case NOTE_DEBUG: diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index 8da9a6de2..a47891dd3 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -653,6 +653,7 @@ struct kqueue_vtable { }; LIST_HEAD(kqueue_head, kqueue); +extern bool libkqueue_thread_safe; extern bool libkqueue_fork_cleanup; extern const struct kqueue_vtable kqops; extern tracing_mutex_t kq_mtx; From ac794527549ab09727a4518d27a30b319a693ca4 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 21 Mar 2022 23:03:03 -0400 Subject: [PATCH 1039/1120] Sprinkle cloexec everywhere --- vendor/libkqueue/src/linux/platform.c | 15 +++++++++++++-- vendor/libkqueue/src/linux/proc.c | 6 +++++- vendor/libkqueue/src/linux/signal.c | 2 +- vendor/libkqueue/src/linux/timer.c | 2 +- vendor/libkqueue/src/linux/user.c | 2 +- vendor/libkqueue/src/posix/eventfd.c | 11 ++++++++++- 6 files changed, 31 insertions(+), 7 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index fa776c4ce..f28ea7ddc 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -456,7 +456,7 @@ linux_kqueue_init(struct kqueue *kq) { struct f_owner_ex sig_owner; - kq->epollfd = epoll_create(1); + kq->epollfd = epoll_create1(EPOLL_CLOEXEC); if (kq->epollfd < 0) { dbg_perror("epoll_create(2)"); return (-1); @@ -508,6 +508,17 @@ linux_kqueue_init(struct kqueue *kq) goto error; } + /* + * FD_CLOEXEC - Prevent file descriptors being inherited + * on exec. There's no reason a kqueue would ever be + * needed in an exec'd process. + */ + if ((fcntl(kq->pipefd[0], F_SETFD, FD_CLOEXEC) < 0) || + (fcntl(kq->pipefd[1], F_SETFD, FD_CLOEXEC) < 0)) { + dbg_perror("fcntl(2)"); + goto error; + } + kq->kq_id = kq->pipefd[1]; /* @@ -953,7 +964,7 @@ linux_eventfd_init(struct eventfd *efd, struct filter *filt) { int evfd; - evfd = eventfd(0, EFD_NONBLOCK); + evfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); if (evfd < 0) { dbg_perror("eventfd"); return (-1); diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index ee105ed96..ffc1d2c35 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -116,7 +116,11 @@ evfilt_proc_knote_create(struct filter *filt, struct knote *kn) /* Returns an FD, which, when readable, indicates the process has exited */ pfd = syscall(SYS_pidfd_open, (pid_t)kn->kev.ident, 0); if (pfd < 0) { - dbg_printf("pidfd_open(2): %s", strerror(errno)); + dbg_perror("pidfd_open(2)"); + return (-1); + } + if (fcntl(pfd, F_SETFD, FD_CLOEXEC) < 0) { + dbg_perror("fcntl(2)"); return (-1); } dbg_printf("created pidfd=%i monitoring pid=%u", pfd, (unsigned int)kn->kev.ident); diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index 158581f9a..371f8c133 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -81,7 +81,7 @@ signalfd_add(int epoll_fd, int sigfd, struct knote *kn) static int signalfd_create(int epoll_fd, struct knote *kn, int signum) { - static int flags = SFD_NONBLOCK; + static int flags = SFD_NONBLOCK | SFD_CLOEXEC; sigset_t sigmask; int sigfd; diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 3fb5a5873..6a9d0b8fe 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -163,7 +163,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) kn->kev.flags |= EV_CLEAR; - tfd = timerfd_create(CLOCK_MONOTONIC, 0); + tfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); if (tfd < 0) { if ((errno == EMFILE) || (errno == ENFILE)) { dbg_perror("timerfd_create(2) fd_used=%u fd_max=%u", get_fd_used(), get_fd_limit()); diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index 2f60d8999..ab528e95f 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -112,7 +112,7 @@ linux_evfilt_user_knote_create(struct filter *filt, struct knote *kn) int evfd; /* Create an eventfd */ - evfd = eventfd(0, 0); + evfd = eventfd(0, EFD_CLOEXEC); if (evfd < 0) { if ((errno == EMFILE) || (errno == ENFILE)) { dbg_perror("eventfd(2) fd_used=%u fd_max=%u", get_fd_used(), get_fd_limit()); diff --git a/vendor/libkqueue/src/posix/eventfd.c b/vendor/libkqueue/src/posix/eventfd.c index 349d36535..b83bbd26b 100644 --- a/vendor/libkqueue/src/posix/eventfd.c +++ b/vendor/libkqueue/src/posix/eventfd.c @@ -24,11 +24,20 @@ posix_eventfd_init(struct eventfd *efd, struct filter *filt) return (-1); } if ((fcntl(sd[0], F_SETFL, O_NONBLOCK) < 0) || - (fcntl(sd[1], F_SETFL, O_NONBLOCK) < 0)) { + (fcntl(sd[1], F_SETFL, O_NONBLOCK) < 0)) { + dbg_perror("fcntl(2)"); + error: close(sd[0]); close(sd[1]); return (-1); } + + if ((fcntl(sd[0], F_SETFD, FD_CLOEXEC) < 0) || + (fcntl(sd[0], F_SETFD, FD_CLOEXEC) < 0)) { + dbg_perror("fcntl(2)"); + goto error; + } + efd->ef_wfd = sd[0]; efd->ef_id = sd[1]; efd->ef_filt = filt; From 06331116bdee4f081eba1fd8e28ee56fb3fe7ae0 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 21 Mar 2022 23:17:14 -0400 Subject: [PATCH 1040/1120] Use pipe2 to atomically set cloexec --- vendor/libkqueue/src/linux/platform.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index f28ea7ddc..a058861e4 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -470,7 +470,7 @@ linux_kqueue_init(struct kqueue *kq) * Closing the end will cause the pipe to be close which * will be caught by the monitoring thread. */ - if (pipe(kq->pipefd)) { + if (pipe2(kq->pipefd, O_CLOEXEC)) { if (close(kq->epollfd) < 0) dbg_perror("close(2)"); kq->epollfd = -1; @@ -508,17 +508,6 @@ linux_kqueue_init(struct kqueue *kq) goto error; } - /* - * FD_CLOEXEC - Prevent file descriptors being inherited - * on exec. There's no reason a kqueue would ever be - * needed in an exec'd process. - */ - if ((fcntl(kq->pipefd[0], F_SETFD, FD_CLOEXEC) < 0) || - (fcntl(kq->pipefd[1], F_SETFD, FD_CLOEXEC) < 0)) { - dbg_perror("fcntl(2)"); - goto error; - } - kq->kq_id = kq->pipefd[1]; /* From 59e1fe8b1eba8ff1fb086ae22d8832d5d9431af3 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 21 Mar 2022 23:17:23 -0400 Subject: [PATCH 1041/1120] s/socketpair/pipe2/ --- vendor/libkqueue/src/posix/eventfd.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/vendor/libkqueue/src/posix/eventfd.c b/vendor/libkqueue/src/posix/eventfd.c index b83bbd26b..697ef96b0 100644 --- a/vendor/libkqueue/src/posix/eventfd.c +++ b/vendor/libkqueue/src/posix/eventfd.c @@ -20,23 +20,10 @@ posix_eventfd_init(struct eventfd *efd, struct filter *filt) { int sd[2]; - if (socketpair(AF_UNIX, SOCK_STREAM, 0, sd) < 0) { + if (pipe2(sd, O_CLOEXEC | O_NONBLOCK)) < 0) { + dbg_perror("pipe2(2)") return (-1); } - if ((fcntl(sd[0], F_SETFL, O_NONBLOCK) < 0) || - (fcntl(sd[1], F_SETFL, O_NONBLOCK) < 0)) { - dbg_perror("fcntl(2)"); - error: - close(sd[0]); - close(sd[1]); - return (-1); - } - - if ((fcntl(sd[0], F_SETFD, FD_CLOEXEC) < 0) || - (fcntl(sd[0], F_SETFD, FD_CLOEXEC) < 0)) { - dbg_perror("fcntl(2)"); - goto error; - } efd->ef_wfd = sd[0]; efd->ef_id = sd[1]; From 28aee9a3c4ffc8aae5002498ce8e333383b46e45 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 22 Mar 2022 09:53:13 -0400 Subject: [PATCH 1042/1120] Update the changelog --- vendor/libkqueue/ChangeLog | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index c17af5619..e3e18686f 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,6 +1,14 @@ Unreleased ------------------------------------------------------------------------ + * Fix: Sprinkle CLOEXEC around various places in the Linux and + POSIX platforms to stop us leaking file descriptors on exec. + + * Add EVFILT_LIBKQUEUE/NOTE_THREAD_SAFE. When set to 0, the + global mutex is not locked on kqueue lookup. The application + must guarantee that kqueues must not be destroyed by a different + thread to the one that created them. + 2022-03-21 v2.6.0 ------------------------------------------------------------------------ @@ -29,7 +37,7 @@ Unreleased * Fix: linux/read linux/write Prevent invalid access of fds->fds_write if the file descriptor state is freed after - processing read events. + processing read events. * Fix: linux/monitor Use an atexit handler to ensure the fd monitoring thread is shutdown gracefully on Linux. This fixes From 7ef4ec1c58e1ba36985709636d94cc1faa3e05ad Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 28 Mar 2022 10:17:43 -0600 Subject: [PATCH 1043/1120] Fix typo --- vendor/libkqueue/BUGS.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/BUGS.md b/vendor/libkqueue/BUGS.md index cb4ffb66d..72192d77b 100644 --- a/vendor/libkqueue/BUGS.md +++ b/vendor/libkqueue/BUGS.md @@ -28,8 +28,9 @@ * `EVFILT_PROC` - The POSIX implmentation requires that `SIGCHLD` be delivered to its global waiter thread so that the waiter can discover a - when child process exits `sigprocmask(2)` is used to mask `SIGCHLD` at a process - level. If the application unmasks `SIGCHLD` or installs a handler for it, + when child process exits. To prevent `SIGCHLD` being delivered to another + thread `sigprocmask(2)` is used to mask `SIGCHLD` at a process level. + If the application unmasks `SIGCHLD` or installs a handler for it, the POSIX `EVFILT_PROC` code will not function. * `EVFILT_PROC` - If using the POSIX `EVFILT_PROC` the number of monitored From b6b5c65ffe36091ea215fee465fdce7555466002 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 28 Mar 2022 16:02:43 -0600 Subject: [PATCH 1044/1120] Print any errors raised by pthread_detach --- vendor/libkqueue/src/linux/platform.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index a058861e4..d0e847944 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -324,7 +324,9 @@ monitoring_thread_loop(UNUSED void *arg) monitoring_thread_state = THREAD_EXIT_STATE_SELF_CANCEL; pthread_cleanup_pop(true); /* Executes the cleanup function (monitoring_thread_cleanup) */ - pthread_detach(pthread_self()); + res = pthread_detach(pthread_self()); + if (res != 0) + dbg_printf("pthread_detach(3): %s", strerror(res)); tracing_mutex_unlock(&kq_mtx); return NULL; From 766a0fa087a300ddab9f54e882eb6cbcb11aa4ff Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 28 Mar 2022 16:31:32 -0600 Subject: [PATCH 1045/1120] Don't free memory in the child --- vendor/libkqueue/src/linux/platform.c | 31 +++++++++++++-------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index d0e847944..ac75948e0 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -385,29 +385,28 @@ linux_libkqueue_fork(void) dbg_printf("kq=%p - cleaning up on fork", kq); /* - * On fork the epoll fd is inherited by the child process - * Any modifications made by the child affect the parent's - * epoll instance. + * There's very limited cleanups we can do + * here, as we're only allowed to call + * async-signal-safe functions in this + * handler. * - * So... if we remove file descriptors from epoll in the - * child, then we break the parent. + * This means any functions which alloc or + * free memory are ruled out, meaning we + * can't release any of the memory allocated + * to the kqueues or filters. * - * We close the epollfd first to prevent the normal cleanup - * logic from modifying the epoll instance in the parent - * process. + * Fortunately close() is async-signal-safe. */ close(kq->epollfd); kq->epollfd = -1; - /* - * Mark all knotes as already disable - */ - kqueue_knote_mark_disabled_all(kq); + if ((kq->pipefd[0] > 0) && (close(kq->pipefd[0]) < 0)) + dbg_perror("close(2)"); + kq->pipefd[0] = -1; - /* - * Do the actual freeing... - */ - kqueue_free(kq); + if ((kq->pipefd[1] > 0) && (close(kq->pipefd[1]) < 0)) + dbg_perror("close(2)"); + kq->pipefd[1] = -1; } } From 4d5c210fbc83b5c33b177c5b7769ce79b7a41071 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 28 Mar 2022 16:49:38 -0600 Subject: [PATCH 1046/1120] Only provide a receipt if we were asked for one --- vendor/libkqueue/src/common/libkqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/libkqueue.c b/vendor/libkqueue/src/common/libkqueue.c index 8ee09c690..97223a48a 100644 --- a/vendor/libkqueue/src/common/libkqueue.c +++ b/vendor/libkqueue/src/common/libkqueue.c @@ -82,7 +82,7 @@ common_libkqueue_knote_create(struct filter *filt, struct knote *kn) return (-1); } - return (1); /* Provide receipt */ + return (kn->kev.flags & EV_RECEIPT ? 1 : 0); /* Provide receipt */ } int From ec90e4a29c778d8bde5311957f0fcee64f941947 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Tue, 29 Mar 2022 21:27:33 -0400 Subject: [PATCH 1047/1120] Remove kern/ and kqlite/ directories Closes #127 --- vendor/libkqueue/kern/Makefile | 42 -- vendor/libkqueue/kern/kqueue.c | 270 ------------ vendor/libkqueue/kern/queue.h | 621 ---------------------------- vendor/libkqueue/kern/test.c | 56 --- vendor/libkqueue/kqlite/Makefile | 12 - vendor/libkqueue/kqlite/README | 26 -- vendor/libkqueue/kqlite/dispatch.c | 47 --- vendor/libkqueue/kqlite/kqlite.c | 511 ----------------------- vendor/libkqueue/kqlite/lite.h | 163 -------- vendor/libkqueue/kqlite/test-lite.c | 85 ---- vendor/libkqueue/kqlite/utarray.h | 232 ----------- 11 files changed, 2065 deletions(-) delete mode 100644 vendor/libkqueue/kern/Makefile delete mode 100644 vendor/libkqueue/kern/kqueue.c delete mode 100644 vendor/libkqueue/kern/queue.h delete mode 100644 vendor/libkqueue/kern/test.c delete mode 100644 vendor/libkqueue/kqlite/Makefile delete mode 100644 vendor/libkqueue/kqlite/README delete mode 100644 vendor/libkqueue/kqlite/dispatch.c delete mode 100644 vendor/libkqueue/kqlite/kqlite.c delete mode 100644 vendor/libkqueue/kqlite/lite.h delete mode 100644 vendor/libkqueue/kqlite/test-lite.c delete mode 100644 vendor/libkqueue/kqlite/utarray.h diff --git a/vendor/libkqueue/kern/Makefile b/vendor/libkqueue/kern/Makefile deleted file mode 100644 index d5a38a926..000000000 --- a/vendor/libkqueue/kern/Makefile +++ /dev/null @@ -1,42 +0,0 @@ -# -# Copyright (c) 2010 Mark Heily -# -# Permission to use, copy, modify, and distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -obj-m = kqueue.o -KVERSION = $(shell uname -r) - -all: kqueue.ko modtest - -kqueue.ko: kqueue.c - make -C /lib/modules/`uname -r`/build M=$(PWD) modules - -clean: - make -C /lib/modules/`uname -r`/build M=$(PWD) clean - rm -f modtest - -update: all - rmmod kqueue - insmod ./kqueue.ko - sleep 2 - chmod 777 /dev/kqueue - -modtest: test.c - gcc -o modtest -Wall -Werror test.c - -edit: - $(EDITOR) Makefile *.[ch] - -check: modtest - ./modtest diff --git a/vendor/libkqueue/kern/kqueue.c b/vendor/libkqueue/kern/kqueue.c deleted file mode 100644 index 29a74ca31..000000000 --- a/vendor/libkqueue/kern/kqueue.c +++ /dev/null @@ -1,270 +0,0 @@ -/*- - * Copyright (c) 2010 Mark Heily - * - * Includes portions of /usr/src/sys/kern/kern_event.c which is - * - * Copyright (c) 1999,2000,2001 Jonathan Lemon - * Copyright 2004 John-Mark Gurney - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* Portions based on - $FreeBSD: src/sys/kern/kern_event.c,v 1.126.2.1.2.1 2009/10/25 01:10:29 kensmith Exp $ - $FreeBSD: src/sys/sys/eventvar.h,v 1.6.30.1.2.1 2009/10/25 01:10:29 kensmith Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sys/event.h" -#include "queue.h" - -struct kqueue; -struct kfilter; -struct knote; - -static int kqueue_open (struct inode *inode, struct file *file); -static int kqueue_release (struct inode *inode, struct file *file); -static int kqueue_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); -static ssize_t kqueue_read(struct file *file, char __user *buf, - size_t lbuf, loff_t *ppos); -static ssize_t kqueue_write(struct file *file, const char __user *buf, - size_t lbuf, loff_t *ppos); - -struct file_operations fops = { - .owner = THIS_MODULE, - .ioctl = kqueue_ioctl, - .open = kqueue_open, - .release = kqueue_release, - .read = kqueue_read, - .write = kqueue_write, -}; - -struct kfilter { - struct rb_root kf_note; -}; - -struct kqueue { - spinlock_t kq_lock; - int kq_count; /* number of pending events */ - struct kfilter kq_filt[EVFILT_SYSCOUNT]; -}; - -#ifdef TODO -struct filterops { - int f_isfd; /* true if ident == filedescriptor */ - int (*f_attach)(struct knote *kn); - void (*f_detach)(struct knote *kn); - int (*f_event)(struct knote *kn, long hint); -}; - -static struct kfilter { - struct filterops kf_fop; - int for_refcnt; -} sysfilt_ops[EVFILT_SYSCOUNT]; -= { - { &file_filtops }, /* EVFILT_READ */ - { &file_filtops }, /* EVFILT_WRITE */ - { &null_filtops }, /* EVFILT_AIO */ - { &file_filtops }, /* EVFILT_VNODE */ - { &proc_filtops }, /* EVFILT_PROC */ - { &sig_filtops }, /* EVFILT_SIGNAL */ - { &timer_filtops }, /* EVFILT_TIMER */ - { &file_filtops }, /* EVFILT_NETDEV */ - { &fs_filtops }, /* EVFILT_FS */ - { &null_filtops }, /* EVFILT_LIO */ -}; -#endif - -static int major; -static struct class *kqueue_class; -static struct task_struct *kq_thread; - -static struct kfilter * -kfilter_lookup(struct kqueue *kq, int filt) -{ - if (filt > 0 || filt + EVFILT_SYSCOUNT < 0) - return NULL; - return &kq->kq_filt[~filt]; -} - -//only for sleeping during testing -#include -static int kqueue_main(void *arg) -{ - printk(KERN_INFO "kqueue thread started...\n"); - while (!kthread_should_stop()) { - msleep(5000); - printk(KERN_INFO "kqueue thread awake...\n"); - } - printk(KERN_INFO "kqueue stopping...\n"); - - return 0; -} - -static int kqueue_open (struct inode *inode, struct file *file) -{ - struct kqueue *kq; - int i; - - printk("kqueue_open\n"); - - kq = kmalloc(sizeof(*kq), GFP_KERNEL); - if (kq == NULL) { - printk("kqueue: kmalloc failed\n"); - return -1; - } - spin_lock_init(&kq->kq_lock); - for (i = 0; i < NUM_ELEMENTS(kq->kq_filt); i++) - kq->kq_filt[i].kf_note = RB_ROOT; - file->private_data = kq; - - return 0; -} - -static int kqueue_release (struct inode *inode, struct file *file) -{ - printk("kqueue_release\n"); - kfree(file->private_data); - - return 0; -} - -static int kqueue_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int fd; - - if (copy_from_user(&fd, (int *)arg, sizeof(int))) - return -EFAULT; - - printk(KERN_INFO "added fd %d\n", fd); - - return 0; -} - -static ssize_t kqueue_read(struct file *file, char __user *buf, - size_t lbuf, loff_t *ppos) -{ - struct kqueue *kq = file->private_data; - - spin_lock(&kq->kq_lock); - //STUB - spin_unlock(&kq->kq_lock); - - return sizeof(struct kevent); -} - -static ssize_t kqueue_write(struct file *file, const char __user *buf, - size_t lbuf, loff_t *ppos) -{ - struct kqueue *kq = file->private_data; - struct kevent kev; - struct kfilter *filt; - size_t i, nchanges; - - if ((lbuf % sizeof(struct kevent)) != 0) - return -EINVAL; - nchanges = lbuf / sizeof(struct kevent); - - for (i = 0; i < nchanges; i++) { - if (copy_from_user(&kev, (struct kevent *) buf, sizeof(kev))) - return -EFAULT; - - filt = kfilter_lookup(kq, kev.filter); - if (filt == NULL) - return -EINVAL; - -#ifdef DEADWOOD - spin_lock(&kq->kq_lock); - printk("%zu bytes, nchanges=%zu", lbuf, nchanges); - spin_unlock(&kq->kq_lock); -#endif - - buf += sizeof(kev); - } - - return sizeof(struct kevent); -} - -static int __init kqueue_start(void) -{ - int rv = 0; - - printk(KERN_INFO "Loading kqueue module...\n"); - - /* Register as a character device */ - major = register_chrdev(0, "kqueue", &fops); - if (major < 0) { - printk(KERN_WARNING "register_chrdev() failed"); - return major; - } - - /* Create /dev/kqueue */ - kqueue_class = class_create(THIS_MODULE, "kqueue"); - device_create(kqueue_class, NULL, MKDEV(major,0), NULL, "kqueue"); - - printk(KERN_INFO "Creating helper thread...\n"); - kq_thread = kthread_create(kqueue_main, NULL, "kqueue"); - if (IS_ERR(kq_thread)) { - rv = PTR_ERR(kq_thread); - goto err_out; - } - wake_up_process(kq_thread); - - printk(KERN_INFO "Finished loading kqueue module...\n"); - return rv; - -err_out: - //TODO: cleanup - return rv; -} - -static void __exit kqueue_end(void) -{ - printk(KERN_INFO "Unloading kqueue module\n"); - - /* Remove /dev/kqueue */ - device_destroy(kqueue_class, MKDEV(major,0)); - class_destroy(kqueue_class); - unregister_chrdev(major, "kqueue"); - - kthread_stop(kq_thread); -} - -module_init(kqueue_start); -module_exit(kqueue_end); - -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_AUTHOR("Mark Heily "); -MODULE_DESCRIPTION("kqueue(2) compatibility"); diff --git a/vendor/libkqueue/kern/queue.h b/vendor/libkqueue/kern/queue.h deleted file mode 100644 index c79c08a51..000000000 --- a/vendor/libkqueue/kern/queue.h +++ /dev/null @@ -1,621 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - * $FreeBSD: src/sys/sys/queue.h,v 1.72.2.1.2.1 2009/10/25 01:10:29 kensmith Exp $ - */ - -#ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ - -/* - * This file defines four types of data structures: singly-linked lists, - * singly-linked tail queues, lists and tail queues. - * - * A singly-linked list is headed by a single forward pointer. The elements - * are singly linked for minimum space and pointer manipulation overhead at - * the expense of O(n) removal for arbitrary elements. New elements can be - * added to the list after an existing element or at the head of the list. - * Elements being removed from the head of the list should use the explicit - * macro for this purpose for optimum efficiency. A singly-linked list may - * only be traversed in the forward direction. Singly-linked lists are ideal - * for applications with large datasets and few or no removals or for - * implementing a LIFO queue. - * - * A singly-linked tail queue is headed by a pair of pointers, one to the - * head of the list and the other to the tail of the list. The elements are - * singly linked for minimum space and pointer manipulation overhead at the - * expense of O(n) removal for arbitrary elements. New elements can be added - * to the list after an existing element, at the head of the list, or at the - * end of the list. Elements being removed from the head of the tail queue - * should use the explicit macro for this purpose for optimum efficiency. - * A singly-linked tail queue may only be traversed in the forward direction. - * Singly-linked tail queues are ideal for applications with large datasets - * and few or no removals or for implementing a FIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * For details on the use of these macros, see the queue(3) manual page. - * - * - * SLIST LIST STAILQ TAILQ - * _HEAD + + + + - * _HEAD_INITIALIZER + + + + - * _ENTRY + + + + - * _INIT + + + + - * _EMPTY + + + + - * _FIRST + + + + - * _NEXT + + + + - * _PREV - - - + - * _LAST - - + + - * _FOREACH + + + + - * _FOREACH_SAFE + + + + - * _FOREACH_REVERSE - - - + - * _FOREACH_REVERSE_SAFE - - - + - * _INSERT_HEAD + + + + - * _INSERT_BEFORE - + - + - * _INSERT_AFTER + + + + - * _INSERT_TAIL - - + + - * _CONCAT - - + + - * _REMOVE_AFTER + - + - - * _REMOVE_HEAD + - + - - * _REMOVE + + + + - * - */ -#ifdef QUEUE_MACRO_DEBUG -/* Store the last 2 places the queue element or head was altered */ -struct qm_trace { - char * lastfile; - int lastline; - char * prevfile; - int prevline; -}; - -#define TRACEBUF struct qm_trace trace; -#define TRASHIT(x) do {(x) = (void *)-1;} while (0) - -#define QMD_TRACE_HEAD(head) do { \ - (head)->trace.prevline = (head)->trace.lastline; \ - (head)->trace.prevfile = (head)->trace.lastfile; \ - (head)->trace.lastline = __LINE__; \ - (head)->trace.lastfile = __FILE__; \ -} while (0) - -#define QMD_TRACE_ELEM(elem) do { \ - (elem)->trace.prevline = (elem)->trace.lastline; \ - (elem)->trace.prevfile = (elem)->trace.lastfile; \ - (elem)->trace.lastline = __LINE__; \ - (elem)->trace.lastfile = __FILE__; \ -} while (0) - -#else -#define QMD_TRACE_ELEM(elem) -#define QMD_TRACE_HEAD(head) -#define TRACEBUF -#define TRASHIT(x) -#endif /* QUEUE_MACRO_DEBUG */ - -/* - * Singly-linked List declarations. - */ -#define SLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} - -#define SLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define SLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} - -/* - * Singly-linked List functions. - */ -#define SLIST_EMPTY(head) ((head)->slh_first == NULL) - -#define SLIST_FIRST(head) ((head)->slh_first) - -#define SLIST_FOREACH(var, head, field) \ - for ((var) = SLIST_FIRST((head)); \ - (var); \ - (var) = SLIST_NEXT((var), field)) - -#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = SLIST_FIRST((head)); \ - (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ - for ((varp) = &SLIST_FIRST((head)); \ - ((var) = *(varp)) != NULL; \ - (varp) = &SLIST_NEXT((var), field)) - -#define SLIST_INIT(head) do { \ - SLIST_FIRST((head)) = NULL; \ -} while (0) - -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ - SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ - SLIST_NEXT((slistelm), field) = (elm); \ -} while (0) - -#define SLIST_INSERT_HEAD(head, elm, field) do { \ - SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ - SLIST_FIRST((head)) = (elm); \ -} while (0) - -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) - -#define SLIST_REMOVE(head, elm, type, field) do { \ - if (SLIST_FIRST((head)) == (elm)) { \ - SLIST_REMOVE_HEAD((head), field); \ - } \ - else { \ - struct type *curelm = SLIST_FIRST((head)); \ - while (SLIST_NEXT(curelm, field) != (elm)) \ - curelm = SLIST_NEXT(curelm, field); \ - SLIST_REMOVE_AFTER(curelm, field); \ - } \ - TRASHIT((elm)->field.sle_next); \ -} while (0) - -#define SLIST_REMOVE_AFTER(elm, field) do { \ - SLIST_NEXT(elm, field) = \ - SLIST_NEXT(SLIST_NEXT(elm, field), field); \ -} while (0) - -#define SLIST_REMOVE_HEAD(head, field) do { \ - SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ -} while (0) - -/* - * Singly-linked Tail queue declarations. - */ -#define STAILQ_HEAD(name, type) \ -struct name { \ - struct type *stqh_first;/* first element */ \ - struct type **stqh_last;/* addr of last next element */ \ -} - -#define STAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).stqh_first } - -#define STAILQ_ENTRY(type) \ -struct { \ - struct type *stqe_next; /* next element */ \ -} - -/* - * Singly-linked Tail queue functions. - */ -#define STAILQ_CONCAT(head1, head2) do { \ - if (!STAILQ_EMPTY((head2))) { \ - *(head1)->stqh_last = (head2)->stqh_first; \ - (head1)->stqh_last = (head2)->stqh_last; \ - STAILQ_INIT((head2)); \ - } \ -} while (0) - -#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) - -#define STAILQ_FIRST(head) ((head)->stqh_first) - -#define STAILQ_FOREACH(var, head, field) \ - for((var) = STAILQ_FIRST((head)); \ - (var); \ - (var) = STAILQ_NEXT((var), field)) - - -#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = STAILQ_FIRST((head)); \ - (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define STAILQ_INIT(head) do { \ - STAILQ_FIRST((head)) = NULL; \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_NEXT((tqelm), field) = (elm); \ -} while (0) - -#define STAILQ_INSERT_HEAD(head, elm, field) do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_FIRST((head)) = (elm); \ -} while (0) - -#define STAILQ_INSERT_TAIL(head, elm, field) do { \ - STAILQ_NEXT((elm), field) = NULL; \ - *(head)->stqh_last = (elm); \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ -} while (0) - -#define STAILQ_LAST(head, type, field) \ - (STAILQ_EMPTY((head)) ? \ - NULL : \ - ((struct type *)(void *) \ - ((char *)((head)->stqh_last) - __offsetof(struct type, field)))) - -#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) - -#define STAILQ_REMOVE(head, elm, type, field) do { \ - if (STAILQ_FIRST((head)) == (elm)) { \ - STAILQ_REMOVE_HEAD((head), field); \ - } \ - else { \ - struct type *curelm = STAILQ_FIRST((head)); \ - while (STAILQ_NEXT(curelm, field) != (elm)) \ - curelm = STAILQ_NEXT(curelm, field); \ - STAILQ_REMOVE_AFTER(head, curelm, field); \ - } \ - TRASHIT((elm)->field.stqe_next); \ -} while (0) - -#define STAILQ_REMOVE_HEAD(head, field) do { \ - if ((STAILQ_FIRST((head)) = \ - STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ - if ((STAILQ_NEXT(elm, field) = \ - STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ -} while (0) - -#define STAILQ_SWAP(head1, head2, type) do { \ - struct type *swap_first = STAILQ_FIRST(head1); \ - struct type **swap_last = (head1)->stqh_last; \ - STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ - (head1)->stqh_last = (head2)->stqh_last; \ - STAILQ_FIRST(head2) = swap_first; \ - (head2)->stqh_last = swap_last; \ - if (STAILQ_EMPTY(head1)) \ - (head1)->stqh_last = &STAILQ_FIRST(head1); \ - if (STAILQ_EMPTY(head2)) \ - (head2)->stqh_last = &STAILQ_FIRST(head2); \ -} while (0) - - -/* - * List declarations. - * NOTE: LIST_HEAD conflicts with a Linux macro. - */ -#define FIXME_LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -/* - * List functions. - */ - -#if (defined(_KERNEL) && defined(INVARIANTS)) -#define QMD_LIST_CHECK_HEAD(head, field) do { \ - if (LIST_FIRST((head)) != NULL && \ - LIST_FIRST((head))->field.le_prev != \ - &LIST_FIRST((head))) \ - panic("Bad list head %p first->prev != head", (head)); \ -} while (0) - -#define QMD_LIST_CHECK_NEXT(elm, field) do { \ - if (LIST_NEXT((elm), field) != NULL && \ - LIST_NEXT((elm), field)->field.le_prev != \ - &((elm)->field.le_next)) \ - panic("Bad link elm %p next->prev != elm", (elm)); \ -} while (0) - -#define QMD_LIST_CHECK_PREV(elm, field) do { \ - if (*(elm)->field.le_prev != (elm)) \ - panic("Bad link elm %p prev->next != elm", (elm)); \ -} while (0) -#else -#define QMD_LIST_CHECK_HEAD(head, field) -#define QMD_LIST_CHECK_NEXT(elm, field) -#define QMD_LIST_CHECK_PREV(elm, field) -#endif /* (_KERNEL && INVARIANTS) */ - -#define LIST_EMPTY(head) ((head)->lh_first == NULL) - -#define LIST_FIRST(head) ((head)->lh_first) - -#define LIST_FOREACH(var, head, field) \ - for ((var) = LIST_FIRST((head)); \ - (var); \ - (var) = LIST_NEXT((var), field)) - -#define LIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = LIST_FIRST((head)); \ - (var) && ((tvar) = LIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define LIST_INIT(head) do { \ - LIST_FIRST((head)) = NULL; \ -} while (0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - QMD_LIST_CHECK_NEXT(listelm, field); \ - if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ - LIST_NEXT((listelm), field)->field.le_prev = \ - &LIST_NEXT((elm), field); \ - LIST_NEXT((listelm), field) = (elm); \ - (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ -} while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - QMD_LIST_CHECK_PREV(listelm, field); \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - LIST_NEXT((elm), field) = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ -} while (0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - QMD_LIST_CHECK_HEAD((head), field); \ - if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ - LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ - LIST_FIRST((head)) = (elm); \ - (elm)->field.le_prev = &LIST_FIRST((head)); \ -} while (0) - -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - -#define LIST_REMOVE(elm, field) do { \ - QMD_LIST_CHECK_NEXT(elm, field); \ - QMD_LIST_CHECK_PREV(elm, field); \ - if (LIST_NEXT((elm), field) != NULL) \ - LIST_NEXT((elm), field)->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = LIST_NEXT((elm), field); \ - TRASHIT((elm)->field.le_next); \ - TRASHIT((elm)->field.le_prev); \ -} while (0) - -#define LIST_SWAP(head1, head2, type, field) do { \ - struct type *swap_tmp = LIST_FIRST((head1)); \ - LIST_FIRST((head1)) = LIST_FIRST((head2)); \ - LIST_FIRST((head2)) = swap_tmp; \ - if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ - swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ - if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ - swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ -} while (0) - -/* - * Tail queue declarations. - */ -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ - TRACEBUF \ -} - -#define TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first } - -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ - TRACEBUF \ -} - -/* - * Tail queue functions. - */ -#if (defined(_KERNEL) && defined(INVARIANTS)) -#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ - if (!TAILQ_EMPTY(head) && \ - TAILQ_FIRST((head))->field.tqe_prev != \ - &TAILQ_FIRST((head))) \ - panic("Bad tailq head %p first->prev != head", (head)); \ -} while (0) - -#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ - if (*(head)->tqh_last != NULL) \ - panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ -} while (0) - -#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ - if (TAILQ_NEXT((elm), field) != NULL && \ - TAILQ_NEXT((elm), field)->field.tqe_prev != \ - &((elm)->field.tqe_next)) \ - panic("Bad link elm %p next->prev != elm", (elm)); \ -} while (0) - -#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ - if (*(elm)->field.tqe_prev != (elm)) \ - panic("Bad link elm %p prev->next != elm", (elm)); \ -} while (0) -#else -#define QMD_TAILQ_CHECK_HEAD(head, field) -#define QMD_TAILQ_CHECK_TAIL(head, headname) -#define QMD_TAILQ_CHECK_NEXT(elm, field) -#define QMD_TAILQ_CHECK_PREV(elm, field) -#endif /* (_KERNEL && INVARIANTS) */ - -#define TAILQ_CONCAT(head1, head2, field) do { \ - if (!TAILQ_EMPTY(head2)) { \ - *(head1)->tqh_last = (head2)->tqh_first; \ - (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ - (head1)->tqh_last = (head2)->tqh_last; \ - TAILQ_INIT((head2)); \ - QMD_TRACE_HEAD(head1); \ - QMD_TRACE_HEAD(head2); \ - } \ -} while (0) - -#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) - -#define TAILQ_FIRST(head) ((head)->tqh_first) - -#define TAILQ_FOREACH(var, head, field) \ - for ((var) = TAILQ_FIRST((head)); \ - (var); \ - (var) = TAILQ_NEXT((var), field)) - -#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = TAILQ_FIRST((head)); \ - (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for ((var) = TAILQ_LAST((head), headname); \ - (var); \ - (var) = TAILQ_PREV((var), headname, field)) - -#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ - for ((var) = TAILQ_LAST((head), headname); \ - (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ - (var) = (tvar)) - -#define TAILQ_INIT(head) do { \ - TAILQ_FIRST((head)) = NULL; \ - (head)->tqh_last = &TAILQ_FIRST((head)); \ - QMD_TRACE_HEAD(head); \ -} while (0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - QMD_TAILQ_CHECK_NEXT(listelm, field); \ - if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else { \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_HEAD(head); \ - } \ - TAILQ_NEXT((listelm), field) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ - QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&listelm->field); \ -} while (0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - QMD_TAILQ_CHECK_PREV(listelm, field); \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - TAILQ_NEXT((elm), field) = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&listelm->field); \ -} while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - QMD_TAILQ_CHECK_HEAD(head, field); \ - if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ - TAILQ_FIRST((head))->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - TAILQ_FIRST((head)) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ - QMD_TRACE_HEAD(head); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - QMD_TAILQ_CHECK_TAIL(head, field); \ - TAILQ_NEXT((elm), field) = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_HEAD(head); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) - -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) - -#define TAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) - -#define TAILQ_REMOVE(head, elm, field) do { \ - QMD_TAILQ_CHECK_NEXT(elm, field); \ - QMD_TAILQ_CHECK_PREV(elm, field); \ - if ((TAILQ_NEXT((elm), field)) != NULL) \ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else { \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - QMD_TRACE_HEAD(head); \ - } \ - *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ - TRASHIT((elm)->field.tqe_next); \ - TRASHIT((elm)->field.tqe_prev); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_SWAP(head1, head2, type, field) do { \ - struct type *swap_first = (head1)->tqh_first; \ - struct type **swap_last = (head1)->tqh_last; \ - (head1)->tqh_first = (head2)->tqh_first; \ - (head1)->tqh_last = (head2)->tqh_last; \ - (head2)->tqh_first = swap_first; \ - (head2)->tqh_last = swap_last; \ - if ((swap_first = (head1)->tqh_first) != NULL) \ - swap_first->field.tqe_prev = &(head1)->tqh_first; \ - else \ - (head1)->tqh_last = &(head1)->tqh_first; \ - if ((swap_first = (head2)->tqh_first) != NULL) \ - swap_first->field.tqe_prev = &(head2)->tqh_first; \ - else \ - (head2)->tqh_last = &(head2)->tqh_first; \ -} while (0) - -#endif /* !_SYS_QUEUE_H_ */ diff --git a/vendor/libkqueue/kern/test.c b/vendor/libkqueue/kern/test.c deleted file mode 100644 index 1c936b71d..000000000 --- a/vendor/libkqueue/kern/test.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2010 Mark Heily - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sys/event.h" - -int -main(int argc, char **argv) -{ - struct kevent kev; - int fd; - - fd = open("/dev/kqueue", O_RDWR); - if (fd < 0) - err(1, "open()"); - printf("kqfd = %d\n", fd); - - EV_SET(&kev, 1, EVFILT_READ, EV_ADD, 0, 0, NULL); -#if OLD - int x; - - x = 1; - if (ioctl(fd, 1234, (char *) &x) < 0) - err(1, "ioctl"); - x = 2; - if (ioctl(fd, 1234, (char *) &x) < 0) - err(1, "ioctl"); -#endif - if (write(fd, &kev, sizeof(kev)) < 0) - err(1, "write"); - - close(fd); - puts("ok"); - - exit(0); -} diff --git a/vendor/libkqueue/kqlite/Makefile b/vendor/libkqueue/kqlite/Makefile deleted file mode 100644 index dbdde88ee..000000000 --- a/vendor/libkqueue/kqlite/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -test-lite: test-lite.c kqlite.c lite.h - gcc -D_GNU_SOURCE=1 -g -O0 -std=c99 -Wall -Werror -o test-lite test-lite.c kqlite.c - -#TODO: -test-dispatch: test-dispatch.c lite.h - gcc -D_GNU_SOURCE=1 -g -O0 -std=c99 -Wall -Werror -fopenmp -o test-dispatch kqlite.c test-dispatch.c dispatch.c - -check: test-lite - ./test-lite - -clean: - rm -f test-lite *.o diff --git a/vendor/libkqueue/kqlite/README b/vendor/libkqueue/kqlite/README deleted file mode 100644 index ad698ea98..000000000 --- a/vendor/libkqueue/kqlite/README +++ /dev/null @@ -1,26 +0,0 @@ -kqlite has the following goals: - - * be lightweight and efficient - * provide a strict subset of the functionality of kqueue(2) and kevent(2) - * closely resemble the kqueue API, but not guarantee 100% compatibility - * support modern POSIX operating systems - -It should be possible to switch between kqlite and the full libkqueue -using a few preprocessor macros: - - #if LIBKQUEUE - #define kqueue_t int - #define kq_init kqueue - #define kq_event kevent - #define kq_free close - #endif - -Here are the differences between kqlite and kqueue: - - * Function names are different: - - kqueue() == kq_init() - kevent() == kq_event() - close() == kq_free() - - * kqueue() returns an int, while kq_init returns an opaque kqueue_t type. diff --git a/vendor/libkqueue/kqlite/dispatch.c b/vendor/libkqueue/kqlite/dispatch.c deleted file mode 100644 index 73008a9f8..000000000 --- a/vendor/libkqueue/kqlite/dispatch.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2013 Mark Heily - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#ifdef _OPENMP -#include -#endif /* _OPENMP */ - -/* - * EXPERIMENTAL dispatching API - */ -void -kq_dispatch(kqueue_t kq, void (*cb)(kqueue_t, struct kevent)) -{ - const int maxevents = 64; /* Should be more like 2xNCPU */ - struct kevent events[maxevents]; - ssize_t nevents; - int i; - - for (;;) { - nevents = kq_event(kq, NULL, 0, (struct kevent *) &events, maxevents, NULL); - if (nevents < 0) - abort(); - #pragma omp parallel - { - for (i = 0; i < nevents; i++) { - #pragma omp single nowait - (*cb)(kq, events[i]); - } - } - } -} - diff --git a/vendor/libkqueue/kqlite/kqlite.c b/vendor/libkqueue/kqlite/kqlite.c deleted file mode 100644 index 128558a9a..000000000 --- a/vendor/libkqueue/kqlite/kqlite.c +++ /dev/null @@ -1,511 +0,0 @@ -/* - * Copyright (c) 2013 Mark Heily - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include - -#include "./lite.h" -#include "./utarray.h" - -/* The maximum number of events that can be returned in - a single kq_event() call - */ -#define EPEV_BUF_MAX 512 - -#include - -/* Debugging macros */ -#define dbg_puts(s) dbg_printf("%s", (s)) -#define dbg_printf(fmt,...) fprintf(stderr, "kq [%d]: %s(): "fmt"\n", \ - 0 /*TODO: thread id */, __func__, __VA_ARGS__) - -/* Determine what type of kernel event system to use. */ -#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) -#define USE_KQUEUE -#include -#elif defined(__linux__) -#define USE_EPOLL -#include -#include -#include -#include -#include -#include -#include - -//XXX - TEMPORARY DURING DEVELOPMENT -#define KQ_THREADSAFE 1 - -#ifdef KQ_THREADSAFE -#include -#endif - -static char * epoll_event_to_str(struct epoll_event *); -#else -#error Unsupported operating system type -#endif - -struct kqueue { -#if defined(USE_KQUEUE) - int kqfd; /* kqueue(2) descriptor */ -#elif defined(USE_EPOLL) - int epoll_fd; /* epoll */ - int inofd; /* inotify */ - int sigfd; /* signalfd */ - int timefd; /* timerfd */ - int readfd, writefd; /* epoll descriptors for EVFILT_READ & EVFILT_WRITE */ - sigset_t sigmask; - /* All of the active knotes for each filter. The index in the array matches - the 'ident' parameter of the 'struct kevent' in the knote. - */ - UT_array *knote[EVFILT_SYSCOUNT]; - - /* This allows all kevents to share a single inotify descriptor. - * Key: inotify watch descriptor returned by inotify_add_watch() - * Value: pointer to knote - */ - UT_array *ino_knote; - -#ifdef KQ_THREADSAFE - pthread_mutex_t kq_mtx; -#endif - -#else -#error Undefined event system -#endif -}; - -/* A knote is used to store information about a kevent while it is - being monitored. Once it fires, information from the knote is returned - to the caller. - */ -struct knote { - struct kevent kev; - union { - int timerfd; /* Each EVFILT_TIMER kevent has a timerfd */ - int ino_wd; /* EVFILT_VNODE: index within kq->ino_knote */ - } aux; - int deleted; /* When EV_DELETE is used, it marks the knote deleted instead of freeing the object. This helps with threadsafety by ensuring that threads don't try to access a freed object. It doesn't help with memory usage, as the memory is never reclaimed. */ -}; - -static inline void -kq_lock(kqueue_t kq) -{ -#ifdef KQ_THREADSAFE - if (pthread_mutex_lock(&kq->kq_mtx) != 0) - abort(); -#endif -} - -static inline void -kq_unlock(kqueue_t kq) -{ -#ifdef KQ_THREADSAFE - if (pthread_mutex_unlock(&kq->kq_mtx) != 0) - abort(); -#endif -} - -UT_icd knote_icd = { sizeof(struct knote), NULL, NULL, NULL }; - -/* Initialize the event descriptor */ -kqueue_t -kq_init(void) -{ - struct kqueue *kq; - -#if defined(USE_KQUEUE) - if ((kq = calloc(1, sizeof(*kq))) == NULL) - return (NULL); - - kq->kqfd = kqueue(); - if (kq->kqfd < 0) { - free(kq); - return (NULL); - } - -#elif defined(USE_EPOLL) - struct epoll_event epev; - - if ((kq = malloc(sizeof(*kq))) == NULL) - return (NULL); - -#ifdef KQ_THREADSAFE - if (pthread_mutex_init(&kq->kq_mtx, NULL) != 0) - goto errout; -#endif - - /* Create an index of kevents to allow lookups from epev.data.u32 */ - - for (int i = 0; i < EVFILT_SYSCOUNT; i++) - utarray_new(kq->knote[i], &knote_icd); - - /* Initialize all the event descriptors */ - sigemptyset(&kq->sigmask); - kq->sigfd = signalfd(-1, &kq->sigmask, 0); - kq->inofd = inotify_init(); - kq->epoll_fd = epoll_create(10); - kq->readfd = epoll_create(10); - kq->writefd = epoll_create(10); - kq->timefd = timerfd_create(CLOCK_MONOTONIC, 0); - if (kq->sigfd < 0 || kq->inofd < 0 || kq->epoll_fd < 0 - || kq->readfd < 0 || kq->writefd < 0 || kq->timefd < 0) - goto errout; - - /* Add the signalfd descriptor to the epollset */ - epev.events = EPOLLIN; - epev.data.u32 = EVFILT_SIGNAL; - if (epoll_ctl(kq->epoll_fd, EPOLL_CTL_ADD, kq->sigfd, &epev) < 0) - goto errout; - - /* Add the readfd descriptor to the epollset */ - epev.events = EPOLLIN; - epev.data.u32 = EVFILT_READ; - if (epoll_ctl(kq->epoll_fd, EPOLL_CTL_ADD, kq->readfd, &epev) < 0) - goto errout; - - /* Add the writefd descriptor to the epollset */ - epev.events = EPOLLIN; - epev.data.u32 = EVFILT_WRITE; - if (epoll_ctl(kq->epoll_fd, EPOLL_CTL_ADD, kq->writefd, &epev) < 0) - goto errout; - - /* Add the inotify descriptor to the epollset */ - /* - if ((kev = malloc(sizeof(*kev))) == NULL) - goto errout; - EV_SET(kev, EVFILT_VNODE, EVFILT_VNODE, 0, 0, 0, NULL); - epev.events = EPOLLIN; - epev.data.u32 = 1; - utarray_push_back(kq->kev, kev); - if (epoll_ctl(kq->epoll_fd, EPOLL_CTL_ADD, kq->inofd, &epev) < 0) - goto errout; - */ - - //TODO: consider applying FD_CLOEXEC to all descriptors - - // FIXME: check that all members of kq->wfd are valid - - return (kq); - -errout: - kq_free(kq); - return (NULL); -#endif -} - -void -kq_free(kqueue_t kq) -{ -#if defined(USE_KQUEUE) - close(kq.kqfd); - -#elif defined(USE_EPOLL) - close(kq->sigfd); - close(kq->inofd); - close(kq->epoll_fd); - close(kq->readfd); - close(kq->writefd); - close(kq->timefd); - - //FIXME: need to free each individual knote - for (int i = 0; i < EVFILT_SYSCOUNT; i++) - utarray_free(kq->knote[i]); - -# ifdef KQ_THREADSAFE - pthread_mutex_destroy(&kq->kq_mtx); -# endif - -#endif - free(kq); -} - -#if defined(USE_EPOLL) - -/* Create a knote object */ -static int -knote_add(kqueue_t kq, const struct kevent *kev) -{ - struct knote *kn; - - assert(kev->filter < EVFILT_SYSCOUNT); - - kn = malloc(sizeof(*kn)); - if (kn == NULL) - return (-1); - memcpy (&kn->kev, kev, sizeof(kn->kev)); - - kq_lock(kq); - utarray_insert(kq->knote[kev->filter], kn, kev->ident); - kq_unlock(kq); - - return (0); -} - -/* Lookup a 'struct kevent' that was previously stored in a knote object */ -static struct knote * -knote_lookup(kqueue_t kq, short filter, uint32_t ident) -{ - struct knote *p; - - kq_lock(kq); - p = (struct knote *) utarray_eltptr(kq->knote[filter], ident); - //TODO: refcounting - kq_unlock(kq); - - return (p); -} - -/* Add a new item to the list of events to be monitored */ -static inline int -kq_add(kqueue_t kq, const struct kevent *ev) -{ - int rv = 0; - struct epoll_event epev; - int sigfd; - - epev.data.u32 = ev->filter; - if (knote_add(kq, ev) < 0) - abort(); //TODO: errorhandle - - switch (ev->filter) { - case EVFILT_READ: - epev.events = EPOLLIN; - rv = epoll_ctl(kq->readfd, EPOLL_CTL_ADD, ev->ident, &epev); - break; - - case EVFILT_WRITE: - epev.events = EPOLLOUT; - rv = epoll_ctl(kq->writefd, EPOLL_CTL_ADD, ev->ident, &epev); - break; - - case EVFILT_VNODE: - epev.events = EPOLLIN; - rv = epoll_ctl(kq->epoll_fd, EPOLL_CTL_ADD, ev->ident, &epev); - rv = -1; - break; - - case EVFILT_SIGNAL: - kq_lock(kq); - sigaddset(&kq->sigmask, ev->ident); - sigfd = signalfd(kq->sigfd, &kq->sigmask, 0); - kq_unlock(kq); - if (sigfd < 0) { - rv = -1; - } else { - rv = 0; - } - dbg_printf("added signal %d, rv = %d", (int)ev->ident, rv); - break; - - case EVFILT_TIMER: - //TODO - rv = -1; - break; - - default: - rv = -1; - return (-1); - } - - if (rv < 0) { - dbg_printf("failed; errno = %s", strerror(errno)); - } - - dbg_printf("done. rv = %d", rv); -// if (rv < 0) -// free(evcopy); - return (rv); -} - -/* Delete an item from the list of events to be monitored */ -static int -kq_delete(kqueue_t kq, const struct kevent *ev) -{ - int rv = 0; - int sigfd; - struct epoll_event epev; - - switch (ev->ident) { - case EVFILT_READ: - case EVFILT_WRITE: - rv = epoll_ctl(kq->epoll_fd, EPOLL_CTL_DEL, ev->ident, &epev); - break; - - case EVFILT_VNODE: - //TODO - break; - - case EVFILT_SIGNAL: - kq_lock(kq); - sigdelset(&kq->sigmask, ev->ident); - sigfd = signalfd(kq->sigfd, &kq->sigmask, 0); - kq_unlock(kq); - if (sigfd < 0) { - rv = -1; - } else { - rv = 0; - } - break; - - case EVFILT_TIMER: - //TODO - break; - - default: - rv = 0; - break; - } - return (rv); -} - -#endif /* defined(USE_EPOLL) */ - -/* Read a signal from the signalfd */ -static inline int -_get_signal(struct kevent *dst, kqueue_t kq) -{ - struct knote *kn; - struct signalfd_siginfo sig; - ssize_t n; - - n = read(kq->sigfd, &sig, sizeof(sig)); - if (n < 0 || n != sizeof(sig)) { - abort(); - } - - kn = knote_lookup(kq, EVFILT_SIGNAL, sig.ssi_signo); - memcpy(dst, &kn->kev, sizeof(*dst)); - - return (0); -} - -/* Equivalent to kevent() */ -int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, - struct kevent *eventlist, int nevents, - const struct timespec *timeout) -{ - int rv = 0; - struct kevent *dst; - //struct knote *kn; - -#if defined(USE_KQUEUE) - return kevent(kq->kqfd, changelist, nchanges, eventlist, nevents, timeout); - -#elif defined(USE_EPOLL) - struct epoll_event epev_buf[EPEV_BUF_MAX]; - struct epoll_event *epev; - size_t epev_wait_max; - int i, epev_cnt, eptimeout; - - /* Process each item on the changelist */ - for (i = 0; i < nchanges; i++) { - if (changelist[i].flags & EV_ADD) { - rv = kq_add(kq, &changelist[i]); - } else if (changelist[i].flags & EV_DELETE) { - rv = kq_delete(kq, &changelist[i]); - } else { - rv = -1; - } - if (rv < 0) - return (-1); - } - - /* Convert timeout to the format used by epoll_wait() */ - if (timeout == NULL) - eptimeout = -1; - else - eptimeout = (1000 * timeout->tv_sec) + (timeout->tv_nsec / 1000000); - - /* Wait for events and put them into a buffer */ - if (nevents > EPEV_BUF_MAX) { - epev_wait_max = EPEV_BUF_MAX; - } else { - epev_wait_max = nevents; - } - epev_cnt = epoll_wait(kq->epoll_fd, epev_buf, epev_wait_max, eptimeout); - if (epev_cnt < 0) { - return (-1); //FIXME: handle timeout - } - else if (epev_cnt == 0) { - dbg_puts("timed out"); - } - - dbg_printf("whee -- got %d event(s)", epev_cnt); - - /* Determine what events have occurred and copy the result to the caller */ - for (i = 0; i < epev_cnt; i++) { - dst = &eventlist[i]; - epev = &epev_buf[i]; - - dbg_printf("got event: %s", epoll_event_to_str(epev)); - - switch (epev->data.u32) { - case EVFILT_SIGNAL: - (void)_get_signal(dst, kq);//FIXME: errorhandle - break; - - case EVFILT_VNODE: - //TODO - break; - - case EVFILT_TIMER: - //TODO - break; - - case EVFILT_READ: - case EVFILT_WRITE: - //memcpy(dst, kevp, sizeof(*dst)); - break; - - default: - abort(); - } - } - - return (rv == 1 ? 0 : -1); -#endif -} - -#if defined(USE_EPOLL) -static char * -epoll_event_to_str(struct epoll_event *evt) -{ - static __thread char buf[128]; - - if (evt == NULL) - return "(null)"; - -#define EPEVT_DUMP(attrib) \ - if (evt->events & attrib) \ - strcat(buf, #attrib" "); - - snprintf(buf, 128, " { data = %p, events = ", evt->data.ptr); - EPEVT_DUMP(EPOLLIN); - EPEVT_DUMP(EPOLLOUT); -#if defined(HAVE_EPOLLRDHUP) - EPEVT_DUMP(EPOLLRDHUP); -#endif - EPEVT_DUMP(EPOLLONESHOT); - EPEVT_DUMP(EPOLLET); - strcat(buf, "}\n"); - - return (buf); -#undef EPEVT_DUMP -} -#endif diff --git a/vendor/libkqueue/kqlite/lite.h b/vendor/libkqueue/kqlite/lite.h deleted file mode 100644 index ba34dd7be..000000000 --- a/vendor/libkqueue/kqlite/lite.h +++ /dev/null @@ -1,163 +0,0 @@ -/*- - * Copyright (c) 2013 Mark Heily - * Copyright (c) 1999,2000,2001 Jonathan Lemon - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD SVN Revision 197533$ - */ - -#ifndef _KQUEUE_LITE_H -#define _KQUEUE_LITE_H - -#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) -#include -#else - -#include -#include -#include - -#define EV_SET(kevp_, a, b, c, d, e, f) do { \ - struct kevent *kevp = (kevp_); \ - (kevp)->ident = (a); \ - (kevp)->filter = (b); \ - (kevp)->flags = (c); \ - (kevp)->fflags = (d); \ - (kevp)->data = (e); \ - (kevp)->udata = (f); \ -} while(0) - -struct kevent { - uintptr_t ident; /* identifier for this event */ - short filter; /* filter for event */ - unsigned short flags; - unsigned int fflags; - intptr_t data; - void *udata; /* opaque user data identifier */ -}; - -/* actions */ -#define EV_ADD 0x0001 /* add event to kq (implies enable) */ -#define EV_DELETE 0x0002 /* delete event from kq */ -#define EV_ENABLE 0x0004 /* enable event */ -#define EV_DISABLE 0x0008 /* disable event (not reported) */ - -/* flags */ -#define EV_ONESHOT 0x0010 /* only report one occurrence */ -#define EV_CLEAR 0x0020 /* clear event state after reporting */ -#define EV_RECEIPT 0x0040 /* force EV_ERROR on success, data=0 */ -#define EV_DISPATCH 0x0080 /* disable event after reporting */ - -#define EV_SYSFLAGS 0xF000 /* reserved by system */ -#define EV_FLAG1 0x2000 /* filter-specific flag */ - -/* returned values */ -#define EV_EOF 0x8000 /* EOF detected */ -#define EV_ERROR 0x4000 /* error, data contains errno */ - - /* - * data/hint flags/masks for EVFILT_USER - * - * On input, the top two bits of fflags specifies how the lower twenty four - * bits should be applied to the stored value of fflags. - * - * On output, the top two bits will always be set to NOTE_FFNOP and the - * remaining twenty four bits will contain the stored fflags value. - */ -#define NOTE_FFNOP 0x00000000 /* ignore input fflags */ -#define NOTE_FFAND 0x40000000 /* AND fflags */ -#define NOTE_FFOR 0x80000000 /* OR fflags */ -#define NOTE_FFCOPY 0xc0000000 /* copy fflags */ -#define NOTE_FFCTRLMASK 0xc0000000 /* masks for operations */ -#define NOTE_FFLAGSMASK 0x00ffffff - -#define NOTE_TRIGGER 0x01000000 /* Cause the event to be triggered for output. */ - -/* - * data/hint flags for EVFILT_{READ|WRITE} - */ -#define NOTE_LOWAT 0x0001 /* low water mark */ -#undef NOTE_LOWAT /* Not supported on Linux */ - -/* - * data/hint flags for EVFILT_VNODE - */ -#define NOTE_DELETE 0x0001 /* vnode was removed */ -#define NOTE_WRITE 0x0002 /* data contents changed */ -#define NOTE_EXTEND 0x0004 /* size increased */ -#define NOTE_ATTRIB 0x0008 /* attributes changed */ -#define NOTE_LINK 0x0010 /* link count changed */ -#define NOTE_RENAME 0x0020 /* vnode was renamed */ -#define NOTE_REVOKE 0x0040 /* vnode access was revoked */ -#undef NOTE_REVOKE /* Not supported on Linux */ - -/* - * data/hint flags for EVFILT_PROC - */ -#define NOTE_EXIT 0x80000000 /* process exited */ -#define NOTE_FORK 0x40000000 /* process forked */ -#define NOTE_EXEC 0x20000000 /* process exec'd */ -#define NOTE_PCTRLMASK 0xf0000000 /* mask for hint bits */ -#define NOTE_PDATAMASK 0x000fffff /* mask for pid */ - -/* additional flags for EVFILT_PROC */ -#define NOTE_TRACK 0x00000001 /* follow across forks */ -#define NOTE_TRACKERR 0x00000002 /* could not track child */ -#define NOTE_CHILD 0x00000004 /* am a child process */ - -/* - * data/hint flags for EVFILT_NETDEV - */ -#define NOTE_LINKUP 0x0001 /* link is up */ -#define NOTE_LINKDOWN 0x0002 /* link is down */ -#define NOTE_LINKINV 0x0004 /* link state is invalid */ - -/* Linux supports a subset of these filters. */ -#define EVFILT_READ (0) -#define EVFILT_WRITE (1) -#define EVFILT_VNODE (2) -#define EVFILT_SIGNAL (3) -#define EVFILT_TIMER (4) -#define EVFILT_SYSCOUNT (5) - -#endif /* defined(__FreeBSD__) etc.. */ - -/* kqueue_t - the event descriptor */ -typedef struct kqueue *kqueue_t; - -/* Initialize the event descriptor */ -kqueue_t kq_init(); - -/* Free the event descriptor */ -void kq_free(kqueue_t kq); - -/* Equivalent to kevent() */ -int kq_event(kqueue_t kq, const struct kevent *changelist, int nchanges, - struct kevent *eventlist, int nevents, - const struct timespec *timeout); - -/* Dispatch kevents using multiple threads */ -void kq_dispatch(kqueue_t, void (*)(kqueue_t, struct kevent)); - -#endif /* ! _KQUEUE_LITE_H */ diff --git a/vendor/libkqueue/kqlite/test-lite.c b/vendor/libkqueue/kqlite/test-lite.c deleted file mode 100644 index d26119588..000000000 --- a/vendor/libkqueue/kqlite/test-lite.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2013 Mark Heily - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "./lite.h" - -#include -#include -#include -#include -#include -#include -#include - -void test_evfilt_write(kqueue_t kq) { - struct kevent kev; - int sockfd[2]; - - puts("testing EVFILT_WRITE.. "); - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) - abort(); - - EV_SET(&kev, sockfd[1], EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0, NULL); - kq_event(kq, &kev, 1, 0, 0, NULL); - puts("installed EVFILT_WRITE handler"); - - if (write(sockfd[0], "hi", 2) < 2) - abort(); - - /* wait for the event */ - puts("waiting for event"); - kq_event(kq, NULL, 0, &kev, 1, NULL); - puts ("got it"); - - close(sockfd[0]); - close(sockfd[1]); -} - -void test_evfilt_signal(kqueue_t kq) { - struct kevent kev; - sigset_t mask; - - /* Block the normal signal handler mechanism */ - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - abort(); - - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, NULL); - kq_event(kq, &kev, 1, 0, 0, NULL); - puts("installed SIGUSR1 handler"); - - if (kill(getpid(), SIGUSR1) < 0) - abort(); - - /* wait for the event */ - puts("waiting for SIGUSR1"); - kq_event(kq, NULL, 0, &kev, 1, NULL); - puts ("got it"); -} - -int main() { - kqueue_t kq; - - kq = kq_init(); - test_evfilt_signal(kq); - test_evfilt_write(kq); - kq_free(kq); - - puts("ok"); - exit(0); -} diff --git a/vendor/libkqueue/kqlite/utarray.h b/vendor/libkqueue/kqlite/utarray.h deleted file mode 100644 index e1232a479..000000000 --- a/vendor/libkqueue/kqlite/utarray.h +++ /dev/null @@ -1,232 +0,0 @@ -/* -Copyright (c) 2008-2013, Troy D. Hanson http://troydhanson.github.com/uthash/ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/* a dynamic array implementation using macros - */ -#ifndef UTARRAY_H -#define UTARRAY_H - -#define UTARRAY_VERSION 1.9.8 - -#ifdef __GNUC__ -#define _UNUSED_ __attribute__ ((__unused__)) -#else -#define _UNUSED_ -#endif - -#include /* size_t */ -#include /* memset, etc */ -#include /* exit */ - -#define oom() exit(-1) - -typedef void (ctor_f)(void *dst, const void *src); -typedef void (dtor_f)(void *elt); -typedef void (init_f)(void *elt); -typedef struct { - size_t sz; - init_f *init; - ctor_f *copy; - dtor_f *dtor; -} UT_icd; - -typedef struct { - unsigned i,n;/* i: index of next available slot, n: num slots */ - UT_icd icd; /* initializer, copy and destructor functions */ - char *d; /* n slots of size icd->sz*/ -} UT_array; - -#define utarray_init(a,_icd) do { \ - memset(a,0,sizeof(UT_array)); \ - (a)->icd=*_icd; \ -} while(0) - -#define utarray_done(a) do { \ - if ((a)->n) { \ - if ((a)->icd.dtor) { \ - size_t _ut_i; \ - for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ - (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \ - } \ - } \ - free((a)->d); \ - } \ - (a)->n=0; \ -} while(0) - -#define utarray_new(a,_icd) do { \ - a=(UT_array*)malloc(sizeof(UT_array)); \ - utarray_init(a,_icd); \ -} while(0) - -#define utarray_free(a) do { \ - utarray_done(a); \ - free(a); \ -} while(0) - -#define utarray_reserve(a,by) do { \ - if (((a)->i+by) > ((a)->n)) { \ - while(((a)->i+by) > ((a)->n)) { (a)->n = ((a)->n ? (2*(a)->n) : 8); } \ - if ( ((a)->d=(char*)realloc((a)->d, (a)->n*(a)->icd.sz)) == NULL) oom(); \ - } \ -} while(0) - -#define utarray_push_back(a,p) do { \ - utarray_reserve(a,1); \ - if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,(a)->i++), p); } \ - else { memcpy(_utarray_eltptr(a,(a)->i++), p, (a)->icd.sz); }; \ -} while(0) - -#define utarray_pop_back(a) do { \ - if ((a)->icd.dtor) { (a)->icd.dtor( _utarray_eltptr(a,--((a)->i))); } \ - else { (a)->i--; } \ -} while(0) - -#define utarray_extend_back(a) do { \ - utarray_reserve(a,1); \ - if ((a)->icd.init) { (a)->icd.init(_utarray_eltptr(a,(a)->i)); } \ - else { memset(_utarray_eltptr(a,(a)->i),0,(a)->icd.sz); } \ - (a)->i++; \ -} while(0) - -#define utarray_len(a) ((a)->i) - -#define utarray_eltptr(a,j) (((j) < (a)->i) ? _utarray_eltptr(a,j) : NULL) -#define _utarray_eltptr(a,j) ((char*)((a)->d + ((a)->icd.sz*(j) ))) - -#define utarray_insert(a,p,j) do { \ - if (j > (a)->i) utarray_resize(a,j); \ - utarray_reserve(a,1); \ - if ((j) < (a)->i) { \ - memmove( _utarray_eltptr(a,(j)+1), _utarray_eltptr(a,j), \ - ((a)->i - (j))*((a)->icd.sz)); \ - } \ - if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,j), p); } \ - else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); }; \ - (a)->i++; \ -} while(0) - -#define utarray_inserta(a,w,j) do { \ - if (utarray_len(w) == 0) break; \ - if (j > (a)->i) utarray_resize(a,j); \ - utarray_reserve(a,utarray_len(w)); \ - if ((j) < (a)->i) { \ - memmove(_utarray_eltptr(a,(j)+utarray_len(w)), \ - _utarray_eltptr(a,j), \ - ((a)->i - (j))*((a)->icd.sz)); \ - } \ - if ((a)->icd.copy) { \ - size_t _ut_i; \ - for(_ut_i=0;_ut_i<(w)->i;_ut_i++) { \ - (a)->icd.copy(_utarray_eltptr(a,j+_ut_i), _utarray_eltptr(w,_ut_i)); \ - } \ - } else { \ - memcpy(_utarray_eltptr(a,j), _utarray_eltptr(w,0), \ - utarray_len(w)*((a)->icd.sz)); \ - } \ - (a)->i += utarray_len(w); \ -} while(0) - -#define utarray_resize(dst,num) do { \ - size_t _ut_i; \ - if (dst->i > (size_t)(num)) { \ - if ((dst)->icd.dtor) { \ - for(_ut_i=num; _ut_i < dst->i; _ut_i++) { \ - (dst)->icd.dtor(utarray_eltptr(dst,_ut_i)); \ - } \ - } \ - } else if (dst->i < (size_t)(num)) { \ - utarray_reserve(dst,num-dst->i); \ - if ((dst)->icd.init) { \ - for(_ut_i=dst->i; _ut_i < num; _ut_i++) { \ - (dst)->icd.init(utarray_eltptr(dst,_ut_i)); \ - } \ - } else { \ - memset(_utarray_eltptr(dst,dst->i),0,(dst)->icd.sz*(num-dst->i)); \ - } \ - } \ - dst->i = num; \ -} while(0) - -#define utarray_concat(dst,src) do { \ - utarray_inserta((dst),(src),utarray_len(dst)); \ -} while(0) - -#define utarray_erase(a,pos,len) do { \ - if ((a)->icd.dtor) { \ - size_t _ut_i; \ - for(_ut_i=0; _ut_i < len; _ut_i++) { \ - (a)->icd.dtor(utarray_eltptr((a),pos+_ut_i)); \ - } \ - } \ - if ((a)->i > (pos+len)) { \ - memmove( _utarray_eltptr((a),pos), _utarray_eltptr((a),pos+len), \ - (((a)->i)-(pos+len))*((a)->icd.sz)); \ - } \ - (a)->i -= (len); \ -} while(0) - -#define utarray_renew(a,u) do { \ - if (a) utarray_clear(a); \ - else utarray_new((a),(u)); \ -} while(0) - -#define utarray_clear(a) do { \ - if ((a)->i > 0) { \ - if ((a)->icd.dtor) { \ - size_t _ut_i; \ - for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ - (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \ - } \ - } \ - (a)->i = 0; \ - } \ -} while(0) - -#define utarray_sort(a,cmp) do { \ - qsort((a)->d, (a)->i, (a)->icd.sz, cmp); \ -} while(0) - -#define utarray_find(a,v,cmp) bsearch((v),(a)->d,(a)->i,(a)->icd.sz,cmp) - -#define utarray_front(a) (((a)->i) ? (_utarray_eltptr(a,0)) : NULL) -#define utarray_next(a,e) (((e)==NULL) ? utarray_front(a) : ((((a)->i) > (utarray_eltidx(a,e)+1)) ? _utarray_eltptr(a,utarray_eltidx(a,e)+1) : NULL)) -#define utarray_prev(a,e) (((e)==NULL) ? utarray_back(a) : ((utarray_eltidx(a,e) > 0) ? _utarray_eltptr(a,utarray_eltidx(a,e)-1) : NULL)) -#define utarray_back(a) (((a)->i) ? (_utarray_eltptr(a,(a)->i-1)) : NULL) -#define utarray_eltidx(a,e) (((char*)(e) >= (char*)((a)->d)) ? (((char*)(e) - (char*)((a)->d))/(ssize_t)(a)->icd.sz) : -1) - -/* last we pre-define a few icd for common utarrays of ints and strings */ -static void utarray_str_cpy(void *dst, const void *src) { - char **_src = (char**)src, **_dst = (char**)dst; - *_dst = (*_src == NULL) ? NULL : strdup(*_src); -} -static void utarray_str_dtor(void *elt) { - char **eltc = (char**)elt; - if (*eltc) free(*eltc); -} -static const UT_icd ut_str_icd _UNUSED_ = {sizeof(char*),NULL,utarray_str_cpy,utarray_str_dtor}; -static const UT_icd ut_int_icd _UNUSED_ = {sizeof(int),NULL,NULL,NULL}; -static const UT_icd ut_ptr_icd _UNUSED_ = {sizeof(void*),NULL,NULL,NULL}; - - -#endif /* UTARRAY_H */ From ebe99e49697a9419b126b5231656ff6b0e2a2fe5 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 11 Apr 2022 12:48:10 -0500 Subject: [PATCH 1048/1120] Add coverity job for Linux --- .../.github/workflows/ci-linux-coverity.yml | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 vendor/libkqueue/.github/workflows/ci-linux-coverity.yml diff --git a/vendor/libkqueue/.github/workflows/ci-linux-coverity.yml b/vendor/libkqueue/.github/workflows/ci-linux-coverity.yml new file mode 100644 index 000000000..2a288e845 --- /dev/null +++ b/vendor/libkqueue/.github/workflows/ci-linux-coverity.yml @@ -0,0 +1,82 @@ +name: CI Linux Coverity + +on: + push: + branches: + - master + +jobs: + linux-build-and-test: + timeout-minutes: 5 + strategy: + fail-fast: false + runs-on: ubuntu-20.04 + name: "ci-linux-coverity" + steps: + - uses: actions/checkout@v2 + - name: Cache coverity tool + uses: actions/cache@v2 + id: cache-coverity + with: + path: coverity_tool.tar.gz + key: coverity-tool-cache-${{ hashFiles('coverity_tool.tar.gz.md5') }} + + - name: Download coverity tool + if: ${{ steps.cache-coverity.outputs.cache-hit != 'true' }} + run: | + wget https://scan.coverity.com/download/linux64 \ + --post-data "token=${TOKEN}&project=${GITHUB_REPOSITORY_OWNER}%2F${GITHUB_REPOSITORY}" \ + -O coverity_tool.tar.gz + env: + TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} + + - name: Extract coverity tool + run: | + mkdir coverity_tool + tar xzf coverity_tool.tar.gz --strip 1 -C coverity_tool + + - name: Install LLVM 10 + run: | + sudo apt-get install -y --no-install-recommends clang-10 llvm-10 + sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-10 60 && sudo update-alternatives --set clang /usr/bin/clang-10 + sudo update-alternatives --install /usr/bin/llvm-symbolizer llvm-symbolizer /usr/bin/llvm-symbolizer-10 60 && sudo update-alternatives --set llvm-symbolizer /usr/bin/llvm-symbolizer-10 + + - name: Install other build deps + run: | + sudo apt-get install -y \ + build-essential \ + devscripts \ + fakeroot + + - name: Configure build system + run: | + cmake . -G "Unix Makefiles" \ + -DCMAKE_INSTALL_PREFIX="/usr" \ + -DCMAKE_INSTALL_LIBDIR="lib" \ + -DCMAKE_VERBOSE_MAKEFILE:BOOL="ON" \ + -DENABLE_TESTING="YES" \ + -DCMAKE_BUILD_TYPE="Debug" + + - name: Build libkqueue + run: | + export PATH=`pwd`/coverity_tool/bin:$PATH + export CC=clang + cov-configure --template --compiler clang --comptype clangcc + cov-build --dir cov-int make + + - name: Display build result + run: | + cat /home/runner/work/${GITHUB_REPOSITORY_OWNER}/${GITHUB_REPOSITORY}/cov-int/build-log.txt + + - name: Submit result + run: | + tar czf cov-int.tar.gz cov-int + curl \ + --form token="$TOKEN" \ + --form email="a.cudbardb@freeradius.org" \ + --form file=@cov-int.tar.gz \ + --form version="`grep LIBKQUEUE_VERSION_STRING version.h | cut -w -f 3 | sed -e 's/"//g'`" \ + --form description="${GITHUB_REPOSITORY}" \ + https://scan.coverity.com/builds?project=${GITHUB_REPOSITORY_OWNER}%2F${GITHUB_REPOSITORY} + env: + TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} From 2611189365672887b016f569793e9e6a77d23b0a Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 11 Apr 2022 12:59:30 -0500 Subject: [PATCH 1049/1120] Fix various issues identified by coverity. Fixes #129 --- vendor/libkqueue/src/common/kqueue.c | 1 + vendor/libkqueue/src/linux/user.c | 2 +- vendor/libkqueue/src/posix/proc.c | 3 --- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index dd1dc4932..452b7e1fc 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -377,6 +377,7 @@ kqueue(void) */ tracing_mutex_lock(&kq_mtx); if (kqops.kqueue_init(kq) < 0) { + tracing_mutex_unlock(&kq_mtx); error: dbg_printf("kq=%p - init failed", kq); tracing_mutex_destroy(&kq->kq_mtx); diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index ab528e95f..bc68a9168 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -119,7 +119,7 @@ linux_evfilt_user_knote_create(struct filter *filt, struct knote *kn) } else { dbg_perror("eventfd(2)"); } - if (evfd >= 0) close(evfd); + close(evfd); kn->kn_eventfd = -1; return (-1); } diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 9b9a11005..d36243611 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -336,9 +336,6 @@ wait_thread_loop(UNUSED void *arg) dbg_printf("waitid(2): pid=%u reaped too early - %s", ppd->ppd_pid, strerror(errno)); waiter_notify_error(ppd, errno); - - tracing_mutex_unlock(&proc_pid_index_mtx); - continue; case EINTR: From 4cb7eca094da84e1cc4434fa7512d4d8edd20f1a Mon Sep 17 00:00:00 2001 From: Jan200101 Date: Mon, 11 Apr 2022 20:34:20 +0200 Subject: [PATCH 1050/1120] fix building for MSVC --- vendor/libkqueue/CMakeLists.txt | 1 + vendor/libkqueue/src/common/debug.h | 1 + vendor/libkqueue/src/windows/platform.h | 3 --- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index e82f24caf..b2c8f2338 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -249,6 +249,7 @@ set_target_properties(kqueue PROPERTIES SOVERSION 0) if(WIN32) target_compile_definitions(kqueue PRIVATE _USRDLL;_WINDLL) target_compile_definitions(kqueue PRIVATE _CRT_SECURE_NO_WARNINGS) + target_compile_definitions(kqueue PRIVATE WIN32_LEAN_AND_MEAN) else() target_compile_definitions(kqueue PRIVATE _XOPEN_SOURCE=600) endif() diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index 4d4889bf4..679e7f9d0 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -22,6 +22,7 @@ #include #ifdef _WIN32 # include +# include "../windows/platform.h" #else # include #endif diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index aef6c96e5..104b82053 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -23,9 +23,6 @@ #define _WIN32_WINNT 0x0502 #endif -/* Reduces build time by omitting extra system headers */ -#define WIN32_LEAN_AND_MEAN - #include #include #include From ad7957bc859cb7a753cd47957dc91655897df587 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 12 Apr 2022 15:19:19 -0700 Subject: [PATCH 1051/1120] Only run Coverity build on the main repository --- vendor/libkqueue/.github/workflows/ci-linux-coverity.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/.github/workflows/ci-linux-coverity.yml b/vendor/libkqueue/.github/workflows/ci-linux-coverity.yml index 2a288e845..b205ef16b 100644 --- a/vendor/libkqueue/.github/workflows/ci-linux-coverity.yml +++ b/vendor/libkqueue/.github/workflows/ci-linux-coverity.yml @@ -7,6 +7,7 @@ on: jobs: linux-build-and-test: + if: github.repository == 'mheily/libkqueue' timeout-minutes: 5 strategy: fail-fast: false From 9eb00b7c779faca204d6d3d29fb89dfc112770cc Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 20 Apr 2022 10:42:16 -0700 Subject: [PATCH 1052/1120] Fix some warnings when building with ExternalProject --- vendor/libkqueue/CMakeLists.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index b2c8f2338..fe895a38e 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -23,14 +23,15 @@ else() # For RPM packaging to work correctly version >= 3.8 is required cmake_minimum_required(VERSION 3.8.0) endif() -cmake_policy(SET CMP0063 OLD) +#cmake_policy(SET CMP0063 OLD) # Both variables used in src/version.h.in string(TIMESTAMP PROJECT_VERSION_DATE "%b %d %Y at %H:%M:%S") execute_process(COMMAND git rev-parse --short=8 HEAD OUTPUT_VARIABLE LIBKQUEUE_VERSION_COMMIT - OUTPUT_STRIP_TRAILING_WHITESPACE) + OUTPUT_STRIP_TRAILING_WHITESPACE + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) if(LIBKQUEUE_VERSION_COMMIT STREQUAL "") unset(LIBKQUEUE_VERSION_COMMIT) @@ -46,7 +47,8 @@ if(VERSION_OVERRIDE) else() execute_process(COMMAND sh -c "git describe --tags --match 'v*' | grep '-' | cut -d- -f2" OUTPUT_VARIABLE PROJECT_VERSION_RELEASE - OUTPUT_STRIP_TRAILING_WHITESPACE) + OUTPUT_STRIP_TRAILING_WHITESPACE + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) if(PROJECT_VERSION_RELEASE STREQUAL "") MESSAGE("Version ${PROJECT_VERSION} (${LIBKQUEUE_VERSION_COMMIT})") From c133fad3529f72aeff21ab82dd17157709625eb1 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 25 Apr 2022 22:55:40 -0500 Subject: [PATCH 1053/1120] Partial fix for posix/user so at least it builds --- vendor/libkqueue/src/posix/user.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/posix/user.c b/vendor/libkqueue/src/posix/user.c index 9d2153ed8..17941fcc8 100644 --- a/vendor/libkqueue/src/posix/user.c +++ b/vendor/libkqueue/src/posix/user.c @@ -54,7 +54,7 @@ posix_evfilt_user_copyout(struct kevent *dst, UNUSED int nevents, struct filter if (src->kev.flags & EV_CLEAR) src->kev.fflags &= ~NOTE_TRIGGER; if (src->kev.flags & (EV_DISPATCH | EV_CLEAR | EV_ONESHOT)) { - kqops.eventfd_raise(&src->kn_eventfd); + kqops.eventfd_raise(&filt->kf_efd); } if (src->kev.flags & EV_DISPATCH) @@ -114,7 +114,7 @@ posix_evfilt_user_knote_modify(struct filter *filt, struct knote *kn, if ((!(kn->kev.flags & EV_DISABLE)) && kev->fflags & NOTE_TRIGGER) { kn->kev.fflags |= NOTE_TRIGGER; - knote_enqueue(filt, kn); + LIST_INSERT_HEAD(&filt->kf_ready, kn, kn_ready); kqops.eventfd_raise(&filt->kf_efd); } From 74a27fbb3402dfd2d4862427e4391f7ec69e6867 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 25 Apr 2022 22:55:55 -0500 Subject: [PATCH 1054/1120] Fix posix timer to use filter from call --- vendor/libkqueue/src/posix/timer.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/vendor/libkqueue/src/posix/timer.c b/vendor/libkqueue/src/posix/timer.c index 0f755f01e..b0b185f29 100644 --- a/vendor/libkqueue/src/posix/timer.c +++ b/vendor/libkqueue/src/posix/timer.c @@ -215,13 +215,10 @@ int evfilt_timer_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, struct knote *src, void *ptr UNUSED) { - struct filter *filt; struct sleepinfo si; ssize_t cnt; struct knote *kn; - filt = knote_get_filter(src); - /* Read the ident */ cnt = read(filt->kf_pfd, &si, sizeof(si)); if (cnt < 0) { From bcacdfed13a7c2a90aa5641f176e96d09f9b2f9b Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 25 Apr 2022 22:56:17 -0500 Subject: [PATCH 1055/1120] No POSIX interface for getting thread IDs --- vendor/libkqueue/src/posix/proc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index d36243611..4d6da5a5b 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -188,7 +188,14 @@ wait_thread_loop(UNUSED void *arg) * etc. Max name length is 16 bytes. */ prctl(PR_SET_NAME, "libkqueue_wait", 0, 0, 0); +#ifdef __linux__ proc_wait_tid = syscall(SYS_gettid); +#else + /* + * There's no POSIX interface for getting a numeric thread ID + */ + proc_wait_tid = 1; +#endif dbg_printf("tid=%u - waiter thread started", proc_wait_tid); From be5c9bfefd59f0d9377c51db99f9c3bfb47d2067 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 25 Apr 2022 22:56:38 -0500 Subject: [PATCH 1056/1120] Move code from posix kevent to posix platform --- vendor/libkqueue/src/posix/kevent.c | 75 --------------------------- vendor/libkqueue/src/posix/platform.c | 59 +++++++++++++++++++++ 2 files changed, 59 insertions(+), 75 deletions(-) delete mode 100644 vendor/libkqueue/src/posix/kevent.c diff --git a/vendor/libkqueue/src/posix/kevent.c b/vendor/libkqueue/src/posix/kevent.c deleted file mode 100644 index cc815ff68..000000000 --- a/vendor/libkqueue/src/posix/kevent.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2009 Mark Heily - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include "private.h" - -const struct filter evfilt_proc = EVFILT_NOTIMPL; - -int -posix_kevent_wait( - struct kqueue *kq, - const struct timespec *timeout) -{ - int n, nfds; - fd_set rfds; - - nfds = kq->kq_nfds; - rfds = kq->kq_fds; - - dbg_puts("waiting for events"); - n = pselect(nfds, &rfds, NULL , NULL, timeout, NULL); - if (n < 0) { - if (errno == EINTR) { - dbg_puts("signal caught"); - return (-1); - } - dbg_perror("pselect(2)"); - return (-1); - } - - kq->kq_rfds = rfds; - - return (n); -} - -int -posix_kevent_copyout(struct kqueue *kq, int nready, - struct kevent *eventlist, int nevents) -{ - struct filter *filt; - int i, rv, nret; - - nret = 0; - for (i = 0; (i < NUM_ELEMENTS(kq->kq_filt) && nready > 0 && nevents > 0); i++) { -// dbg_printf("eventlist: n = %d nevents = %d", nready, nevents); - filt = &kq->kq_filt[i]; -// dbg_printf("pfd[%d] = %d", i, filt->kf_pfd); - if (FD_ISSET(filt->kf_pfd, &kq->kq_rfds)) { - dbg_printf("pending events for filter %d (%s)", filt->kf_id, filter_name(filt->kf_id)); - rv = filt->kf_copyout(eventlist, nevents, filt, kn, evt); - if (rv < 0) { - dbg_puts("kevent_copyout failed"); - nret = -1; - break; - } - nret += rv; - eventlist += rv; - nevents -= rv; - nready--; - } - } - - return (nret); -} diff --git a/vendor/libkqueue/src/posix/platform.c b/vendor/libkqueue/src/posix/platform.c index 29c523075..203611f9a 100644 --- a/vendor/libkqueue/src/posix/platform.c +++ b/vendor/libkqueue/src/posix/platform.c @@ -29,3 +29,62 @@ void posix_kqueue_free(struct kqueue *kq UNUSED) { } + +int +posix_kevent_wait( + struct kqueue *kq, + const struct timespec *timeout) +{ + int n, nfds; + fd_set rfds; + + nfds = kq->kq_nfds; + rfds = kq->kq_fds; + + dbg_puts("waiting for events"); + n = pselect(nfds, &rfds, NULL , NULL, timeout, NULL); + if (n < 0) { + if (errno == EINTR) { + dbg_puts("signal caught"); + return (-1); + } + dbg_perror("pselect(2)"); + return (-1); + } + + kq->kq_rfds = rfds; + + return (n); +} + +int +posix_kevent_copyout(struct kqueue *kq, int nready, + struct kevent *eventlist, int nevents) +{ + struct filter *filt; + int i, rv, nret; + + nret = 0; + for (i = 0; (i < NUM_ELEMENTS(kq->kq_filt) && nready > 0 && nevents > 0); i++) { + dbg_printf("eventlist: n = %d nevents = %d", nready, nevents); + filt = &kq->kq_filt[i]; + dbg_printf("pfd[%d] = %d", i, filt->kf_pfd); + if (FD_ISSET(filt->kf_id, &kq->kq_rfds)) { + dbg_printf("pending events for filter %d (%s)", filt->kf_id, filter_name(filt->kf_id)); +#if 0 + rv = filt->kf_copyout(eventlist, nevents, filt, kn, evt); + if (rv < 0) { + dbg_puts("kevent_copyout failed"); + nret = -1; + break; + } +#endif + nret += rv; + eventlist += rv; + nevents -= rv; + nready--; + } + } + + return (nret); +} From 4caf012272caaa0e1a128724ee43044ce1b30a20 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 25 Apr 2022 22:57:11 -0500 Subject: [PATCH 1057/1120] Move extra field definitions out of posix/platform.h --- vendor/libkqueue/src/linux/platform.h | 2 +- vendor/libkqueue/src/posix/platform.h | 74 +++------------------- vendor/libkqueue/src/posix/platform_ext.h | 76 +++++++++++++++++++++++ 3 files changed, 87 insertions(+), 65 deletions(-) create mode 100644 vendor/libkqueue/src/posix/platform_ext.h diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index ca7bc401f..1aef334a8 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -62,7 +62,7 @@ struct filter; #define KNOTE_PROC_PLATFORM_SPECIFIC int kn_procfd; #define FILTER_PROC_PLATFORM_SPECIFIC #else -#include "../posix/platform.h" +#include "../posix/platform_ext.h" #define KNOTE_PROC_PLATFORM_SPECIFIC POSIX_KNOTE_PROC_PLATFORM_SPECIFIC #define FILTER_PROC_PLATFORM_SPECIFIC POSIX_FILTER_PROC_PLATFORM_SPECIFIC #endif diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index 7b1a657de..f91321d04 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -25,75 +25,21 @@ #include #include #include -#include +#include #include #include #include #include #include - -/** Additional members of 'struct eventfd' - * - * These should be included in the platform's EVENTFD_PLATFORM_SPECIFIC - * macro definition if using the POSIX eventfd functions. - */ -#define POSIX_EVENTFD_PLATFORM_SPECIFIC \ - int ef_wfd - -/** Additional members of 'struct knote' - * - * These should be included in the platform's KNOTE_PLATFORM_SPECIFIC - * macro definition if using the POSIX proc filter. - */ -#define POSIX_KNOTE_PROC_PLATFORM_SPECIFIC \ - struct { \ - LIST_ENTRY(knote) kn_proc_waiter; \ - int kn_proc_status; \ - } - -/** Additional members of 'struct knote' - * - * These should be included in the platform's KNOTE_PLATFORM_SPECIFIC - * macro definition if using the POSIX filters. - */ -#define POSIX_PROC_PLATFORM_SPECIFIC \ - POSIX_KNOTE_PROC_PLATFORM_SPECIFIC - -/** Additional members of 'struct filter' - * - * These should be included in the platform's FILTER_PLATFORM_SPECIFIC - * macro definition if using the POSIX proc filter. - */ -#define POSIX_FILTER_PROC_PLATFORM_SPECIFIC \ - struct { \ - struct eventfd kf_proc_eventfd; \ - pthread_t kf_proc_thread_id; \ - } - -/** Additional members of 'struct filter' - * - * These should be included in the platform's FILTER_PLATFORM_SPECIFIC - * macro definition if using all the POSIX filters. - */ -#define POSIX_FILTER_PLATFORM_SPECIFIC \ - int kf_pfd; /* fd to poll(2) for readiness */ \ - int kf_wfd; \ - POSIX_FILTER_PROC_PLATFORM_SPECIFIC - -/** Additional members of 'struct kqueue' - * - * These should be included in the platform's KQUEUE_PLATFORM_SPECIFIC - * macro definition. - */ -#define POSIX_KQUEUE_PLATFORM_SPECIFIC \ - fd_set kq_fds, kq_rfds; \ - int kq_nfds - -/** Additional members of 'struct knote' - * - */ -#define POSIX_KNOTE_PLATFORM_SPECIFIC \ - struct sleepreq *kn_sleepreq +#include "../common/queue.h" +#include "platform_ext.h" + +#define EVENTFD_PLATFORM_SPECIFIC POSIX_EVENTFD_PLATFORM_SPECIFIC +#define KNOTE_PROC_PLATFORM_SPECIFIC POSIX_KNOTE_PROC_PLATFORM_SPECIFIC +#define PROC_PLATFORM_SPECIFIC POSIX_PROC_PLATFORM_SPECIFIC +#define FILTER_PLATFORM_SPECIFIC POSIX_FILTER_PLATFORM_SPECIFIC +#define KQUEUE_PLATFORM_SPECIFIC POSIX_KQUEUE_PLATFORM_SPECIFIC +#define KNOTE_PLATFORM_SPECIFIC POSIX_KNOTE_PLATFORM_SPECIFIC void posix_kqueue_free(struct kqueue *); int posix_kqueue_init(struct kqueue *); diff --git a/vendor/libkqueue/src/posix/platform_ext.h b/vendor/libkqueue/src/posix/platform_ext.h new file mode 100644 index 000000000..3d4d4e4eb --- /dev/null +++ b/vendor/libkqueue/src/posix/platform_ext.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2011 Mark Heily + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _KQUEUE_POSIX_PLATFORM_EXT_H +#define _KQUEUE_POSIX_PLATFORM_EXT_H + +/** Additional members of 'struct eventfd' + * + * These should be included in the platform's EVENTFD_PLATFORM_SPECIFIC + * macro definition if using the POSIX eventfd functions. + */ +#define POSIX_EVENTFD_PLATFORM_SPECIFIC \ + int ef_wfd + +/** Additional members of 'struct knote' + * + * These should be included in the platform's KNOTE_PLATFORM_SPECIFIC + * macro definition if using the POSIX proc filter. + */ +#define POSIX_KNOTE_PROC_PLATFORM_SPECIFIC \ + struct { \ + LIST_ENTRY(knote) kn_proc_waiter; \ + int kn_proc_status; \ + } + +/** Additional members of 'struct filter' + * + * These should be included in the platform's FILTER_PLATFORM_SPECIFIC + * macro definition if using the POSIX proc filter. + */ +#define POSIX_FILTER_PROC_PLATFORM_SPECIFIC \ + struct { \ + struct eventfd kf_proc_eventfd; \ + pthread_t kf_proc_thread_id; \ + } + +/** Additional members of 'struct filter' + * + * These should be included in the platform's FILTER_PLATFORM_SPECIFIC + * macro definition if using all the POSIX filters. + */ +#define POSIX_FILTER_PLATFORM_SPECIFIC \ + int kf_pfd; /* fd to poll(2) for readiness */ \ + int kf_wfd; \ + POSIX_FILTER_PROC_PLATFORM_SPECIFIC + +/** Additional members of 'struct kqueue' + * + * These should be included in the platform's KQUEUE_PLATFORM_SPECIFIC + * macro definition. + */ +#define POSIX_KQUEUE_PLATFORM_SPECIFIC \ + fd_set kq_fds, kq_rfds; \ + int kq_nfds + +/** Additional members of 'struct knote' + * + */ +#define POSIX_KNOTE_PLATFORM_SPECIFIC \ + POSIX_KNOTE_PROC_PLATFORM_SPECIFIC; \ + struct sleepreq *kn_sleepreq + +#endif /* ! _KQUEUE_POSIX_PLATFORM_EXT_H */ From 1afe84fab5f7ca1b105cc762f295c72c0308add5 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 25 Apr 2022 22:57:24 -0500 Subject: [PATCH 1058/1120] Fix typo in posix/eventfd --- vendor/libkqueue/src/posix/eventfd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/posix/eventfd.c b/vendor/libkqueue/src/posix/eventfd.c index 697ef96b0..da259866b 100644 --- a/vendor/libkqueue/src/posix/eventfd.c +++ b/vendor/libkqueue/src/posix/eventfd.c @@ -20,7 +20,7 @@ posix_eventfd_init(struct eventfd *efd, struct filter *filt) { int sd[2]; - if (pipe2(sd, O_CLOEXEC | O_NONBLOCK)) < 0) { + if (pipe2(sd, O_CLOEXEC | O_NONBLOCK) < 0) { dbg_perror("pipe2(2)") return (-1); } From 90d170116e99f9e9a839efba615b98764e1f945c Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 25 Apr 2022 22:57:54 -0500 Subject: [PATCH 1059/1120] Add very basic emscripten support --- vendor/libkqueue/CMakeLists.txt | 11 +++++++++++ vendor/libkqueue/src/common/debug.h | 2 +- vendor/libkqueue/src/common/private.h | 2 ++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index fe895a38e..2411fb552 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -225,6 +225,17 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL Linux) else() list(APPEND LIBKQUEUE_SOURCES src/posix/proc.c) endif() +elseif(CMAKE_SYSTEM_NAME STREQUAL Emscripten) + list(APPEND LIBKQUEUE_SOURCES + src/posix/eventfd.c + src/posix/eventfd.h + src/posix/platform.c + src/posix/platform.h + src/posix/signal.c + src/posix/proc.c + src/posix/signal.c + src/posix/timer.c + src/posix/user.c) else() message(FATAL_ERROR "unsupported host os") endif() diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index 679e7f9d0..4bf903b63 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -30,7 +30,7 @@ #if defined(__linux__) # include # define THREAD_ID ((pid_t) syscall(__NR_gettid)) -#elif defined(__sun) +#elif defined(__sun) || defined(__EMSCRIPTEN__) # define THREAD_ID ((int) pthread_self()) #elif defined(_WIN32) # define THREAD_ID (int)(GetCurrentThreadId()) diff --git a/vendor/libkqueue/src/common/private.h b/vendor/libkqueue/src/common/private.h index a47891dd3..e516ae132 100644 --- a/vendor/libkqueue/src/common/private.h +++ b/vendor/libkqueue/src/common/private.h @@ -54,6 +54,8 @@ struct evfilt_data; # include "../linux/platform.h" #elif defined(__sun) # include "../solaris/platform.h" +#elif defined(__EMSCRIPTEN__) +# include "../posix/platform.h" #else # error Unknown platform #endif From c5c5eb5582ea6fc1cf17dc37a6dac5115a3cb8d6 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 25 Apr 2022 23:35:49 -0500 Subject: [PATCH 1060/1120] Define atomic macros for POSIX too --- vendor/libkqueue/src/posix/platform.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/vendor/libkqueue/src/posix/platform.h b/vendor/libkqueue/src/posix/platform.h index f91321d04..6fc0d62a9 100644 --- a/vendor/libkqueue/src/posix/platform.h +++ b/vendor/libkqueue/src/posix/platform.h @@ -41,6 +41,18 @@ #define KQUEUE_PLATFORM_SPECIFIC POSIX_KQUEUE_PLATFORM_SPECIFIC #define KNOTE_PLATFORM_SPECIFIC POSIX_KNOTE_PLATFORM_SPECIFIC +/* + * C11 atomic operations + */ +#define atomic_inc(p) (atomic_fetch_add((p), 1) + 1) +#define atomic_dec(p) (atomic_fetch_sub((p), 1) - 1) + +/* We use compound literals here to stop the 'expected' values from being overwritten */ +#define atomic_cas(p, oval, nval) atomic_compare_exchange_strong(p, &(__typeof__(oval)){ oval }, nval) +#define atomic_ptr_cas(p, oval, nval) atomic_compare_exchange_strong(p, (&(uintptr_t){ (uintptr_t)oval }), (uintptr_t)nval) +#define atomic_ptr_swap(p, nval) atomic_exchange(p, (uintptr_t)nval) +#define atomic_ptr_load(p) atomic_load(p) + void posix_kqueue_free(struct kqueue *); int posix_kqueue_init(struct kqueue *); From 75f2641c793a891bb4dac426864a83f2a179a1be Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 26 Apr 2022 07:43:25 -0500 Subject: [PATCH 1061/1120] Fix atomic type in posix/signal --- vendor/libkqueue/src/posix/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/posix/signal.c b/vendor/libkqueue/src/posix/signal.c index ff8a4b1e9..e53d88713 100644 --- a/vendor/libkqueue/src/posix/signal.c +++ b/vendor/libkqueue/src/posix/signal.c @@ -25,7 +25,7 @@ struct sentry { struct filter *s_filt; struct knote *s_knote; - volatile uint32_t s_cnt; + atomic_uint s_cnt; }; static pthread_mutex_t sigtbl_mtx = PTHREAD_MUTEX_INITIALIZER; From 4cea650cfc489bdbc0958117c906e4a050585cd8 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 26 Apr 2022 08:29:15 -0500 Subject: [PATCH 1062/1120] More hacks to produce a valid libkqueue archive under emscripten --- vendor/libkqueue/CMakeLists.txt | 25 ++++++++++++++++++------ vendor/libkqueue/src/posix/eventfd.h | 2 +- vendor/libkqueue/src/posix/platform.c | 17 ++++++++++++++++ vendor/libkqueue/src/posix/proc.c | 3 +-- vendor/libkqueue/src/posix/read.c | 28 +++++++++++++++++++++++++++ vendor/libkqueue/src/posix/timer.c | 3 +++ vendor/libkqueue/src/posix/user.c | 20 ++++++++----------- vendor/libkqueue/src/posix/vnode.c | 28 +++++++++++++++++++++++++++ vendor/libkqueue/src/posix/write.c | 28 +++++++++++++++++++++++++++ 9 files changed, 133 insertions(+), 21 deletions(-) create mode 100644 vendor/libkqueue/src/posix/read.c create mode 100644 vendor/libkqueue/src/posix/vnode.c create mode 100644 vendor/libkqueue/src/posix/write.c diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 2411fb552..58e447b6b 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -192,7 +192,8 @@ if(CMAKE_SYSTEM_NAME MATCHES Windows) src/windows/read.c src/windows/stdint.h src/windows/timer.c - src/windows/user.c) + src/windows/user.c + ) elseif(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") list(APPEND LIBKQUEUE_SOURCES src/posix/eventfd.c @@ -202,7 +203,8 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") src/solaris/signal.c src/solaris/socket.c src/solaris/timer.c - src/solaris/user.c) + src/solaris/user.c + ) elseif(CMAKE_SYSTEM_NAME STREQUAL Linux) # # Set the default prefix to something sane @@ -218,7 +220,8 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL Linux) src/linux/timer.c src/linux/user.c src/linux/vnode.c - src/linux/write.c) + src/linux/write.c + ) if (HAVE_SYS_PIDFD_OPEN) list(APPEND LIBKQUEUE_SOURCES src/linux/proc.c) @@ -231,11 +234,15 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL Emscripten) src/posix/eventfd.h src/posix/platform.c src/posix/platform.h - src/posix/signal.c src/posix/proc.c + src/posix/read.c + src/posix/signal.c src/posix/signal.c src/posix/timer.c - src/posix/user.c) + src/posix/user.c + src/posix/vnode.c + src/posix/write.c + ) else() message(FATAL_ERROR "unsupported host os") endif() @@ -287,12 +294,18 @@ endif() if(WIN32) target_link_libraries(kqueue PRIVATE ws2_32) endif() -target_link_libraries(kqueue PRIVATE Threads::Threads) + if(ENABLE_TESTING) add_subdirectory(test) endif() +if(CMAKE_SYSTEM_NAME STREQUAL Emscripten) + target_compile_options(kqueue PRIVATE -pthread) +else() + target_link_libraries(kqueue PRIVATE Threads::Threads) +endif() + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/libkqueue.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/libkqueue.pc" @ONLY) diff --git a/vendor/libkqueue/src/posix/eventfd.h b/vendor/libkqueue/src/posix/eventfd.h index dbcfb1ce0..05fcd6566 100644 --- a/vendor/libkqueue/src/posix/eventfd.h +++ b/vendor/libkqueue/src/posix/eventfd.h @@ -15,7 +15,7 @@ */ #include "../common/private.h" -int posix_eventfd_init(struct eventfd *); +int posix_eventfd_init(struct eventfd *efd, struct filter *filt); void posix_eventfd_close(struct eventfd *); int posix_eventfd_raise(struct eventfd *); int posix_eventfd_lower(struct eventfd *); diff --git a/vendor/libkqueue/src/posix/platform.c b/vendor/libkqueue/src/posix/platform.c index 203611f9a..6012b2427 100644 --- a/vendor/libkqueue/src/posix/platform.c +++ b/vendor/libkqueue/src/posix/platform.c @@ -16,6 +16,7 @@ #include "../common/private.h" #include "platform.h" +#include "eventfd.h" int posix_kqueue_init(struct kqueue *kq) @@ -88,3 +89,19 @@ posix_kevent_copyout(struct kqueue *kq, int nready, return (nret); } + +const struct kqueue_vtable kqops = { +// .libkqueue_fork = posix_libkqueue_fork, +// .libkqueue_free = posix_libkqueue_free, + .kqueue_init = posix_kqueue_init, + .kqueue_free = posix_kqueue_free, +// .kevent_wait = posix_kevent_wait, + .kevent_copyout = posix_kevent_copyout, +// .eventfd_register = posix_eventfd_register, +// .eventfd_unregister = posix_eventfd_unregister, + .eventfd_init = posix_eventfd_init, + .eventfd_close = posix_eventfd_close, + .eventfd_raise = posix_eventfd_raise, + .eventfd_lower = posix_eventfd_lower, + .eventfd_descriptor = posix_eventfd_descriptor, +}; diff --git a/vendor/libkqueue/src/posix/proc.c b/vendor/libkqueue/src/posix/proc.c index 4d6da5a5b..8b9c5dfee 100644 --- a/vendor/libkqueue/src/posix/proc.c +++ b/vendor/libkqueue/src/posix/proc.c @@ -184,11 +184,10 @@ wait_thread_loop(UNUSED void *arg) sigset_t sigmask; struct proc_pid *ppd, *ppd_tmp; +#ifdef __linux__ /* Set the thread's name to something descriptive so it shows up in gdb, * etc. Max name length is 16 bytes. */ prctl(PR_SET_NAME, "libkqueue_wait", 0, 0, 0); - -#ifdef __linux__ proc_wait_tid = syscall(SYS_gettid); #else /* diff --git a/vendor/libkqueue/src/posix/read.c b/vendor/libkqueue/src/posix/read.c new file mode 100644 index 000000000..e9c2b1c79 --- /dev/null +++ b/vendor/libkqueue/src/posix/read.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 Arran Cudbard-Bell + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "../common/private.h" + + +const struct filter evfilt_read = { + .kf_id = EVFILT_READ, +// .kf_copyout = evfilt_read_copyout, +// .kn_create = evfilt_read_knote_create, +// .kn_modify = evfilt_read_knote_modify, +// .kn_delete = evfilt_read_knote_delete, +// .kn_enable = evfilt_read_knote_enable, +// .kn_disable = evfilt_read_knote_disable, +}; diff --git a/vendor/libkqueue/src/posix/timer.c b/vendor/libkqueue/src/posix/timer.c index b0b185f29..e950aadb7 100644 --- a/vendor/libkqueue/src/posix/timer.c +++ b/vendor/libkqueue/src/posix/timer.c @@ -157,9 +157,12 @@ _timer_create(struct filter *filt, struct knote *kn) free(req); return (-1); } + +#ifdef __linux__ /* Set the thread's name to something descriptive so it shows up in gdb, * etc. Max name length is 16 bytes. */ prctl(PR_SET_NAME, "libkqueue_sleep", 0, 0, 0); +#endif pthread_attr_destroy(&attr); diff --git a/vendor/libkqueue/src/posix/user.c b/vendor/libkqueue/src/posix/user.c index 17941fcc8..f02d6c3fe 100644 --- a/vendor/libkqueue/src/posix/user.c +++ b/vendor/libkqueue/src/posix/user.c @@ -141,18 +141,14 @@ posix_evfilt_user_knote_disable(struct filter *filt, struct knote *kn) return (0); } -/* FIXME: this conflicts with the struct in linux/platform.c - const struct filter evfilt_user = { .kf_id = EVFILT_USER, - .kf_init = evfilt_user_init, - .kf_destroy = evfilt_user_destroy, - .kf_copyout = evfilt_user_copyout, - .kn_create = evfilt_user_knote_create, - .kn_modify = evfilt_user_knote_modify, - .kn_delete = evfilt_user_knote_delete, - .kn_enable = evfilt_user_knote_enable, - .kn_disable = evfilt_user_knote_disable, + .kf_init = posix_evfilt_user_init, + .kf_destroy = posix_evfilt_user_destroy, + .kf_copyout = posix_evfilt_user_copyout, + .kn_create = posix_evfilt_user_knote_create, + .kn_modify = posix_evfilt_user_knote_modify, + .kn_delete = posix_evfilt_user_knote_delete, + .kn_enable = posix_evfilt_user_knote_enable, + .kn_disable = posix_evfilt_user_knote_disable, }; - -*/ diff --git a/vendor/libkqueue/src/posix/vnode.c b/vendor/libkqueue/src/posix/vnode.c new file mode 100644 index 000000000..632cd070b --- /dev/null +++ b/vendor/libkqueue/src/posix/vnode.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 Arran Cudbard-Bell + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "../common/private.h" + + +const struct filter evfilt_vnode = { + .kf_id = EVFILT_VNODE, +// .kf_copyout = evfilt_vnode_copyout, +// .kn_create = evfilt_vnode_knote_create, +// .kn_modify = evfilt_vnode_knote_modify, +// .kn_delete = evfilt_vnode_knote_delete, +// .kn_enable = evfilt_vnode_knote_enable, +// .kn_disable = evfilt_vnode_knote_disable, +}; diff --git a/vendor/libkqueue/src/posix/write.c b/vendor/libkqueue/src/posix/write.c new file mode 100644 index 000000000..fd9133828 --- /dev/null +++ b/vendor/libkqueue/src/posix/write.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 Arran Cudbard-Bell + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "../common/private.h" + + +const struct filter evfilt_write = { + .kf_id = EVFILT_WRITE, +// .kf_copyout = evfilt_write_copyout, +// .kn_create = evfilt_write_knote_create, +// .kn_modify = evfilt_write_knote_modify, +// .kn_delete = evfilt_write_knote_delete, +// .kn_enable = evfilt_write_knote_enable, +// .kn_disable = evfilt_write_knote_disable, +}; From 87fbde5f349254466ec506794e787b5d494e578b Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 26 Apr 2022 16:06:32 -0500 Subject: [PATCH 1063/1120] Our target is always static is we're building with Emscripten --- vendor/libkqueue/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 58e447b6b..48da57765 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -23,7 +23,6 @@ else() # For RPM packaging to work correctly version >= 3.8 is required cmake_minimum_required(VERSION 3.8.0) endif() -#cmake_policy(SET CMP0063 OLD) # Both variables used in src/version.h.in string(TIMESTAMP PROJECT_VERSION_DATE "%b %d %Y at %H:%M:%S") @@ -243,6 +242,7 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL Emscripten) src/posix/vnode.c src/posix/write.c ) + set(STATIC_KQUEUE ON) else() message(FATAL_ERROR "unsupported host os") endif() From 043fa0ea7ce5dfbc9584e8e86069906779d1c92f Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 26 Apr 2022 17:04:32 -0500 Subject: [PATCH 1064/1120] Minor formatting --- vendor/libkqueue/CMakeLists.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 48da57765..8e83f9da0 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -168,12 +168,13 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/include) set(LIBKQUEUE_HEADERS - include/sys/event.h) + include/sys/event.h + ) set(LIBKQUEUE_SOURCES src/common/alloc.h - src/common/debug.h src/common/debug.c + src/common/debug.h src/common/filter.c src/common/kevent.c src/common/knote.c @@ -182,7 +183,8 @@ set(LIBKQUEUE_SOURCES src/common/map.c src/common/private.h src/common/queue.h - src/common/tree.h) + src/common/tree.h + ) if(CMAKE_SYSTEM_NAME MATCHES Windows) list(APPEND LIBKQUEUE_SOURCES @@ -221,7 +223,6 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL Linux) src/linux/vnode.c src/linux/write.c ) - if (HAVE_SYS_PIDFD_OPEN) list(APPEND LIBKQUEUE_SOURCES src/linux/proc.c) else() From ea6772353debc09a6b5ec215ca51d24648b81a66 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 26 Apr 2022 17:20:24 -0500 Subject: [PATCH 1065/1120] Fix repo name in coverty submissions --- .../.github/workflows/ci-linux-coverity.yml | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/vendor/libkqueue/.github/workflows/ci-linux-coverity.yml b/vendor/libkqueue/.github/workflows/ci-linux-coverity.yml index b205ef16b..4a938c145 100644 --- a/vendor/libkqueue/.github/workflows/ci-linux-coverity.yml +++ b/vendor/libkqueue/.github/workflows/ci-linux-coverity.yml @@ -15,6 +15,23 @@ jobs: name: "ci-linux-coverity" steps: - uses: actions/checkout@v2 + + - name: Install build deps + run: | + sudo apt-get install -y \ + build-essential \ + devscripts \ + fakeroot \ + gridsite-clients + + - name: Download coverity tool MD5 + run: | + wget https://scan.coverity.com/download/linux64 \ + --post-data "token=${TOKEN}&project=`urlencode ${GITHUB_REPOSITORY}`&md5=1" \ + -O coverity_tool.tar.gz.md5 + env: + TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} + - name: Cache coverity tool uses: actions/cache@v2 id: cache-coverity @@ -26,7 +43,7 @@ jobs: if: ${{ steps.cache-coverity.outputs.cache-hit != 'true' }} run: | wget https://scan.coverity.com/download/linux64 \ - --post-data "token=${TOKEN}&project=${GITHUB_REPOSITORY_OWNER}%2F${GITHUB_REPOSITORY}" \ + --post-data "token=${TOKEN}&project=`urlencode ${GITHUB_REPOSITORY}`" \ -O coverity_tool.tar.gz env: TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} @@ -42,13 +59,6 @@ jobs: sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-10 60 && sudo update-alternatives --set clang /usr/bin/clang-10 sudo update-alternatives --install /usr/bin/llvm-symbolizer llvm-symbolizer /usr/bin/llvm-symbolizer-10 60 && sudo update-alternatives --set llvm-symbolizer /usr/bin/llvm-symbolizer-10 - - name: Install other build deps - run: | - sudo apt-get install -y \ - build-essential \ - devscripts \ - fakeroot - - name: Configure build system run: | cmake . -G "Unix Makefiles" \ @@ -67,7 +77,7 @@ jobs: - name: Display build result run: | - cat /home/runner/work/${GITHUB_REPOSITORY_OWNER}/${GITHUB_REPOSITORY}/cov-int/build-log.txt + cat /home/runner/work/libkqueue/libkqueue/cov-int/build-log.txt - name: Submit result run: | @@ -78,6 +88,6 @@ jobs: --form file=@cov-int.tar.gz \ --form version="`grep LIBKQUEUE_VERSION_STRING version.h | cut -w -f 3 | sed -e 's/"//g'`" \ --form description="${GITHUB_REPOSITORY}" \ - https://scan.coverity.com/builds?project=${GITHUB_REPOSITORY_OWNER}%2F${GITHUB_REPOSITORY} + https://scan.coverity.com/builds?project=`urlencode ${GITHUB_REPOSITORY}` env: TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} From 29af5476644d299b47d01e696298d2edfa0ed259 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 26 Apr 2022 17:41:08 -0500 Subject: [PATCH 1066/1120] Fix coverity CID #256733 --- vendor/libkqueue/test/kqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/test/kqueue.c b/vendor/libkqueue/test/kqueue.c index de866618a..710140550 100644 --- a/vendor/libkqueue/test/kqueue.c +++ b/vendor/libkqueue/test/kqueue.c @@ -101,7 +101,7 @@ test_cleanup(void *unused) } /* lower FD limit to 32 */ - if (max_fds < rlim.rlim_cur) { + if (max_fds < curr_rlim.rlim_cur) { /* Set FD limit to MAX_FDS */ rlim = curr_rlim; rlim.rlim_cur = 32; From 54e40778b24556f2438741a520a4f897ab391fdc Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 27 Apr 2022 09:01:11 -0500 Subject: [PATCH 1067/1120] Additional fix for CID #256733 --- vendor/libkqueue/test/kqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/test/kqueue.c b/vendor/libkqueue/test/kqueue.c index 710140550..539393366 100644 --- a/vendor/libkqueue/test/kqueue.c +++ b/vendor/libkqueue/test/kqueue.c @@ -109,7 +109,7 @@ test_cleanup(void *unused) die("setrlimit failed"); } } else { - max_fds = rlim.rlim_cur; + max_fds = curr_rlim.rlim_cur; } /* Create initial kqueue to avoid cleanup thread being destroyed on each close */ From ddd1b708f4bcd1d94476506cf02665ba2a43b152 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 27 Apr 2022 09:10:23 -0500 Subject: [PATCH 1068/1120] Probably won't fix CID #256732 and #256731 but it's an invalid defect anyway --- vendor/libkqueue/src/common/kevent.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index 16ebc467f..c52cdc53e 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -258,8 +258,8 @@ kevent_copyin_one(const struct knote **out, struct kqueue *kq, const struct keve /** @return number of events added to the eventlist */ static int -kevent_copyin(struct kqueue *kq, const struct kevent *changelist, int nchanges, - struct kevent *eventlist, int nevents) +kevent_copyin(struct kqueue *kq, const struct kevent changelist[], int nchanges, + struct kevent eventlist[], int nevents) { int status; int rv; @@ -338,9 +338,10 @@ kevent_release_kq_mutex(void *kq) #endif int VISIBLE -kevent(int kqfd, const struct kevent *changelist, int nchanges, - struct kevent *eventlist, int nevents, - const struct timespec *timeout) +kevent(int kqfd, + const struct kevent changelist[], int nchanges, + struct kevent eventlist[], int nevents, + const struct timespec *timeout) { struct kqueue *kq; struct kevent *el_p, *el_end; From 72e60683c0f67beae0f08196e1633c343c22e7d3 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 27 Apr 2022 09:11:57 -0500 Subject: [PATCH 1069/1120] CID #256730 --- vendor/libkqueue/test/proc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/test/proc.c b/vendor/libkqueue/test/proc.c index 046ec9d4e..eccb8be3f 100644 --- a/vendor/libkqueue/test/proc.c +++ b/vendor/libkqueue/test/proc.c @@ -188,6 +188,8 @@ test_kevent_proc_multiple_kqueue(struct test_context *ctx) #endif kq_b = kqueue(); + if (kq_b < 0) + die("kqueue"); /* Create a child that waits to be killed and then exits */ pid = fork(); From 59a7c927b98c909624bb96e77379a4dacc33c265 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 27 Apr 2022 09:23:24 -0500 Subject: [PATCH 1070/1120] CID #256729 --- vendor/libkqueue/src/linux/vnode.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 2f7dd51d8..7fe6fe1b7 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -97,6 +97,9 @@ get_one_event(struct inotify_event *dst, size_t len, int inofd) dbg_printf("read(2) from inotify wd: %ld bytes", (long)n); + /* Quiet Coverity's complaints about name being unterminated */ + dst->name[(len - ((uint8_t *)dst - (uint8_t *)dst->name)) - 1] = '\0'; + return (0); } From 75315ec59801ceca733a39b82f533bb2a9858e8f Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 27 Apr 2022 09:24:10 -0500 Subject: [PATCH 1071/1120] CID #256728 --- vendor/libkqueue/src/linux/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index ffc1d2c35..5d3ae345a 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -60,7 +60,7 @@ evfilt_proc_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, case CLD_DUMPED: /* WIFSIGNALED/WCOREDUMP - Core flag set - Low 7 bits contains fatal signal */ status |= 0x80; /* core flag */ - status = info.si_status & 0x7f; + status |= info.si_status & 0x7f; dbg_printf("pid=%u dumped, status %u", (unsigned int)src->kev.ident, status); break; From 0bca2ebcde9e3971a783f04810cd2de8fb1bf4b8 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 27 Apr 2022 09:34:03 -0500 Subject: [PATCH 1072/1120] Alt fix for CID #256728 --- vendor/libkqueue/src/linux/vnode.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 7fe6fe1b7..5d02475a5 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -97,9 +97,6 @@ get_one_event(struct inotify_event *dst, size_t len, int inofd) dbg_printf("read(2) from inotify wd: %ld bytes", (long)n); - /* Quiet Coverity's complaints about name being unterminated */ - dst->name[(len - ((uint8_t *)dst - (uint8_t *)dst->name)) - 1] = '\0'; - return (0); } @@ -194,6 +191,9 @@ evfilt_vnode_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt struct stat sb; evt = (struct inotify_event *)buf; + /* Quiet Coverity's complaints about name being unterminated */ + evt->name[0] = '\0'; + if (get_one_event(evt, sizeof(buf), src->kn_vnode.inotifyfd) < 0) return (-1); From 80a18140e3008429abdf078411d57e1a30c8dd32 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 27 Apr 2022 09:34:28 -0500 Subject: [PATCH 1073/1120] Run everything in the context of the test dir --- vendor/libkqueue/.github/workflows/ci-freebsd.yml | 8 ++++---- vendor/libkqueue/.github/workflows/ci-macos.yml | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/.github/workflows/ci-freebsd.yml b/vendor/libkqueue/.github/workflows/ci-freebsd.yml index 6d1ee4024..1dbe10ec7 100644 --- a/vendor/libkqueue/.github/workflows/ci-freebsd.yml +++ b/vendor/libkqueue/.github/workflows/ci-freebsd.yml @@ -30,7 +30,7 @@ jobs: llvm \ run: | freebsd-version - cd libkqueue - cmake . test/CMakeLists.txt - make -C ./test - test/libkqueue-test + cd libkqueue/test + cmake . + make + ./libkqueue-test diff --git a/vendor/libkqueue/.github/workflows/ci-macos.yml b/vendor/libkqueue/.github/workflows/ci-macos.yml index c78ec64c1..66334a126 100644 --- a/vendor/libkqueue/.github/workflows/ci-macos.yml +++ b/vendor/libkqueue/.github/workflows/ci-macos.yml @@ -18,8 +18,9 @@ jobs: - name: Build and configure run: | - cmake . test/CMakeLists.txt - make -C test/ + cd test + cmake . + make - name: libkqueue test suite run: | From 331cd57cd644f056ddb7369f29cb235d9bdd23c5 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 27 Apr 2022 09:37:22 -0500 Subject: [PATCH 1074/1120] Potential alt fix for CID #256732 and #256731 --- vendor/libkqueue/src/common/kevent.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/common/kevent.c b/vendor/libkqueue/src/common/kevent.c index c52cdc53e..796024205 100644 --- a/vendor/libkqueue/src/common/kevent.c +++ b/vendor/libkqueue/src/common/kevent.c @@ -22,7 +22,7 @@ #include "private.h" -static struct kevent null_kev; /* null kevent for when we get passed a NULL eventlist */ +static struct kevent null_kev[1]; /* null kevent for when we get passed a NULL eventlist */ static const char * kevent_filter_dump(const struct kevent *kev) @@ -362,9 +362,9 @@ kevent(int kqfd, el_p = eventlist; el_end = el_p + nevents; } else { - eventlist = el_p = el_end = &null_kev; + eventlist = el_p = el_end = null_kev; } - if (!changelist) changelist = &null_kev; + if (!changelist) changelist = null_kev; #ifndef _WIN32 prev_cancel_state = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); From b60239a82be4e89e67b7a7d7751a46f5500d3347 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 27 Apr 2022 09:46:35 -0500 Subject: [PATCH 1075/1120] Further restrictions on when CI jobs run --- .../libkqueue/.github/workflows/ci-freebsd.yml | 6 ++++++ .../.github/workflows/ci-linux-coverity.yml | 7 ++++++- vendor/libkqueue/.github/workflows/ci-linux.yml | 16 ++++++++++++++++ vendor/libkqueue/.github/workflows/ci-macos.yml | 6 ++++++ .../libkqueue/.github/workflows/ci-windows.yml | 15 +++++++++++++++ 5 files changed, 49 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/.github/workflows/ci-freebsd.yml b/vendor/libkqueue/.github/workflows/ci-freebsd.yml index 1dbe10ec7..920f5899b 100644 --- a/vendor/libkqueue/.github/workflows/ci-freebsd.yml +++ b/vendor/libkqueue/.github/workflows/ci-freebsd.yml @@ -7,6 +7,12 @@ on: paths: - 'test/*' - '.github/workflows/ci-freebsd.yml' + pull_request: + branches: + - master + paths: + - 'test/*' + - '.github/workflows/ci-freebsd.yml' jobs: freebsd-tests: diff --git a/vendor/libkqueue/.github/workflows/ci-linux-coverity.yml b/vendor/libkqueue/.github/workflows/ci-linux-coverity.yml index 4a938c145..0a1dabe4c 100644 --- a/vendor/libkqueue/.github/workflows/ci-linux-coverity.yml +++ b/vendor/libkqueue/.github/workflows/ci-linux-coverity.yml @@ -4,7 +4,12 @@ on: push: branches: - master - + paths: + - 'include/sys/*' + - 'src/common/*' + - 'src/linux/*' + - 'test/*' + - '.github/workflows/ci-linux-coverity.yml' jobs: linux-build-and-test: if: github.repository == 'mheily/libkqueue' diff --git a/vendor/libkqueue/.github/workflows/ci-linux.yml b/vendor/libkqueue/.github/workflows/ci-linux.yml index 13d9c6f36..9fbaaec3c 100644 --- a/vendor/libkqueue/.github/workflows/ci-linux.yml +++ b/vendor/libkqueue/.github/workflows/ci-linux.yml @@ -4,7 +4,23 @@ on: push: branches: - master + paths: + - 'CMakeLists.txt' + - 'include/sys/*' + - 'src/common/*' + - 'src/linux/*' + - 'test/*' + - '.github/workflows/ci-linux.yml' pull_request: + branches: + - master + paths: + - 'CMakeLists.txt' + - 'include/sys/*' + - 'src/common/*' + - 'src/linux/*' + - 'test/*' + - '.github/workflows/ci-linux.yml' env: ASAN_OPTIONS: symbolize=1 detect_leaks=1 detect_stack_use_after_return=1 diff --git a/vendor/libkqueue/.github/workflows/ci-macos.yml b/vendor/libkqueue/.github/workflows/ci-macos.yml index 66334a126..764a0ae65 100644 --- a/vendor/libkqueue/.github/workflows/ci-macos.yml +++ b/vendor/libkqueue/.github/workflows/ci-macos.yml @@ -7,6 +7,12 @@ on: paths: - 'test/*' - '.github/workflows/ci-macos.yml' + pull_request: + branches: + - master + paths: + - 'test/*' + - '.github/workflows/ci-macos.yml' jobs: macos-tests: diff --git a/vendor/libkqueue/.github/workflows/ci-windows.yml b/vendor/libkqueue/.github/workflows/ci-windows.yml index c74d918f6..a503155a6 100644 --- a/vendor/libkqueue/.github/workflows/ci-windows.yml +++ b/vendor/libkqueue/.github/workflows/ci-windows.yml @@ -4,7 +4,22 @@ on: push: branches: - master + paths: + - 'CMakeLists.txt' + - 'include/sys/*' + - 'src/common/*' + - 'src/windows/*' + - 'test/*' + - '.github/workflows/ci-windows.yml' pull_request: + branches: + - master + paths: + - 'CMakeLists.txt' + - 'src/common/*' + - 'src/windows/*' + - 'test/*' + - '.github/workflows/ci-windows.yml' env: KQUEUE_DEBUG: yes From 417166a0c4b4b12ef558e4f0862e6aeddcc7eb71 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 27 Apr 2022 10:14:50 -0500 Subject: [PATCH 1076/1120] CLOEXEC the inotify FD --- vendor/libkqueue/src/linux/vnode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 5d02475a5..5bc964b8b 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -128,7 +128,7 @@ add_watch(struct filter *filt, struct knote *kn) mask |= IN_ONESHOT; /* Create an inotify descriptor */ - ifd = inotify_init(); + ifd = inotify_init1(IN_CLOEXEC); if (ifd < 0) { if ((errno == EMFILE) || (errno == ENFILE)) { dbg_perror("inotify_init(2) fd_used=%u fd_max=%u", get_fd_used(), get_fd_limit()); From d3d632b635501be4475680d916f9424ee891f1b9 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 27 Apr 2022 10:15:55 -0500 Subject: [PATCH 1077/1120] Another attempt to sate CID #256728 --- vendor/libkqueue/src/linux/vnode.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 5bc964b8b..92e3d4632 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -78,6 +78,15 @@ get_one_event(struct inotify_event *dst, size_t len, int inofd) return (-1); } + /* + * Last member of struct inotify_event is the name field. + * this field will be padded to the next multiple of + * struct inotify_event. + * + * We need this loop here so that we don't accidentally + * read more than one inotify event per read call which + * could happen if the event's name field were 0. + */ n = read(inofd, dst, want); if (n < 0) { switch (errno) { @@ -97,6 +106,11 @@ get_one_event(struct inotify_event *dst, size_t len, int inofd) dbg_printf("read(2) from inotify wd: %ld bytes", (long)n); +#ifdef __COVERITY__ + /* Coverity complains this isn't \0 terminated, but it is */ + if (evt->len > 0) evt->name[ev->len - 1] = '\0'; +#endif + return (0); } @@ -191,9 +205,6 @@ evfilt_vnode_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt struct stat sb; evt = (struct inotify_event *)buf; - /* Quiet Coverity's complaints about name being unterminated */ - evt->name[0] = '\0'; - if (get_one_event(evt, sizeof(buf), src->kn_vnode.inotifyfd) < 0) return (-1); From b2c2ebab1e61b1b2ea541877227cf16031dfd7dd Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 27 Apr 2022 10:17:17 -0500 Subject: [PATCH 1078/1120] Remove cruft from BUGS.md --- vendor/libkqueue/BUGS.md | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/vendor/libkqueue/BUGS.md b/vendor/libkqueue/BUGS.md index 72192d77b..f8b60c546 100644 --- a/vendor/libkqueue/BUGS.md +++ b/vendor/libkqueue/BUGS.md @@ -1,4 +1,4 @@ - # libkqueue (userland) + # libkqueue This documents the current behavioural differences or defficiencies of libkqueue vs the native BSD kqueue implementations. @@ -90,18 +90,8 @@ in the fork. ## Windows - - * On Windows, you need to supply `-DMAKE_STATIC` in `CFLAGS` when building the - static library. This does not apply when using cmake. - + * If a file descriptor outside of kqueue is closed, the internal kqueue state is not cleaned up. Applications should ensure that file descriptors are removed from the kqueue before they are closed. - -# libkqueue (kernel) - - * When passing a knote pointer to the kernel, the reference count of - the knote structure should be incremented. Conversely, when the pointer - has been returned from the kernel and the event unregistered from the - kernel, the reference count should be decremented. From 50d059b80860496a08ad3f1ca843c26bf7867974 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 27 Apr 2022 10:23:03 -0500 Subject: [PATCH 1079/1120] Packages are slow today --- vendor/libkqueue/.github/workflows/ci-linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/.github/workflows/ci-linux.yml b/vendor/libkqueue/.github/workflows/ci-linux.yml index 9fbaaec3c..a84de17ad 100644 --- a/vendor/libkqueue/.github/workflows/ci-linux.yml +++ b/vendor/libkqueue/.github/workflows/ci-linux.yml @@ -30,7 +30,7 @@ env: jobs: linux-build-and-test: - timeout-minutes: 5 + timeout-minutes: 10 strategy: fail-fast: false matrix: From fc3e0f19653174f3c72aaceafb882483de858bd3 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 27 Apr 2022 11:03:31 -0500 Subject: [PATCH 1080/1120] Minor grammar fix --- vendor/libkqueue/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index 19b8693eb..dc16c6b38 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -132,7 +132,7 @@ following: - if the `data` field is `1` all kqueues will be closed/freed on fork. The default behaviour matches native kqueue but may be expensive if many kqueues are active. - If `EV_RECEIPT` is set the previous value of cleanup flag will be provided in a receipt event. + If `EV_RECEIPT` is set, the previous value of cleanup flag will be provided in a receipt event. Example - retrieving version string: From 688003645cfc92829494dec52c2c0669b99aed3e Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 27 Apr 2022 11:05:51 -0500 Subject: [PATCH 1081/1120] Add Coverity badge --- vendor/libkqueue/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index dc16c6b38..37ff700e5 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -2,9 +2,12 @@ libkqueue ========= [![CI Linux](https://github.com/mheily/libkqueue/actions/workflows/ci-linux.yml/badge.svg)](https://github.com/mheily/libkqueue/actions/workflows/ci-linux.yml) +[![CI Windows](https://github.com/mheily/libkqueue/actions/workflows/ci-windows.yml/badge.svg)](https://github.com/mheily/libkqueue/actions/workflows/ci-windows.yml) + [![CI tests FreeBSD](https://github.com/mheily/libkqueue/actions/workflows/ci-freebsd.yml/badge.svg)](https://github.com/mheily/libkqueue/actions/workflows/ci-freebsd.yml) [![CI tests macOS](https://github.com/mheily/libkqueue/actions/workflows/ci-macos.yml/badge.svg)](https://github.com/mheily/libkqueue/actions/workflows/ci-macos.yml) -[![CI tests Windows](https://github.com/mheily/libkqueue/actions/workflows/ci-windows.yml/badge.svg)](https://github.com/mheily/libkqueue/actions/workflows/ci-windows.yml) + +[![Coverity](https://scan.coverity.com/projects/24822/badge.svg)](https://scan.coverity.com/projects/mheily-libkqueue) A user space implementation of the kqueue(2) kernel event notification mechanism libkqueue acts as a translator between the kevent structure and the native From 010e6e21101c896c98a66ca0c76f2b5cd6c935ba Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 27 Apr 2022 11:07:37 -0500 Subject: [PATCH 1082/1120] Fix whitespace --- vendor/libkqueue/README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index 37ff700e5..596ad4f46 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -3,10 +3,8 @@ libkqueue [![CI Linux](https://github.com/mheily/libkqueue/actions/workflows/ci-linux.yml/badge.svg)](https://github.com/mheily/libkqueue/actions/workflows/ci-linux.yml) [![CI Windows](https://github.com/mheily/libkqueue/actions/workflows/ci-windows.yml/badge.svg)](https://github.com/mheily/libkqueue/actions/workflows/ci-windows.yml) - -[![CI tests FreeBSD](https://github.com/mheily/libkqueue/actions/workflows/ci-freebsd.yml/badge.svg)](https://github.com/mheily/libkqueue/actions/workflows/ci-freebsd.yml) -[![CI tests macOS](https://github.com/mheily/libkqueue/actions/workflows/ci-macos.yml/badge.svg)](https://github.com/mheily/libkqueue/actions/workflows/ci-macos.yml) - +[![Test suite FreeBSD](https://github.com/mheily/libkqueue/actions/workflows/ci-freebsd.yml/badge.svg)](https://github.com/mheily/libkqueue/actions/workflows/ci-freebsd.yml) +[![Test suite macOS](https://github.com/mheily/libkqueue/actions/workflows/ci-macos.yml/badge.svg)](https://github.com/mheily/libkqueue/actions/workflows/ci-macos.yml) [![Coverity](https://scan.coverity.com/projects/24822/badge.svg)](https://scan.coverity.com/projects/mheily-libkqueue) A user space implementation of the kqueue(2) kernel event notification mechanism From 857fb53cb7c68b84444e79903e856501947b1c34 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 27 Apr 2022 11:41:51 -0500 Subject: [PATCH 1083/1120] cmake seems to of stopped taking the cmake file as an argument? --- vendor/libkqueue/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index 596ad4f46..d455fe930 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -89,9 +89,10 @@ Build & Running only the test suite ----------------------------------- Helpful to see the behavior of the tests on systems with native `kqueue`, e.g: macOS, FreeBSD - cmake . test/CMakeLists.txt - make -C test/ - ./test/libkqueue-test + cd test + cmake . + make + ./libkqueue-test To enable tests which expose bugs in native kqueue implementations pass `-DWITH_NATIVE_KQUEUE_BUGS=1` to cmake. i.e. `cmake . test/CMakeLists.txt -DWITH_NATIVE_KQUEUE_BUGS=1`. From 838a9ef8f1973da1315e0272a8133814450235c2 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 27 Apr 2022 12:21:20 -0500 Subject: [PATCH 1084/1120] Update changelog --- vendor/libkqueue/ChangeLog | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index e3e18686f..b83aeb5a7 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,5 +1,22 @@ Unreleased ------------------------------------------------------------------------ + +2022-04-27 v2.6.1 +------------------------------------------------------------------------ + + * Fix: Set the core dumped flag correctly in linux/proc on + CLD_DUMPED. + + * Fix: Don't attempt to cleanup memory on fork as free() is not + fork safe. We still close open kqueue FDs on fork, and liberal + use of CLOEXEC should clean up any lingering filter FDs though + we may want to close these explicitly in future too. + + * Fix: Double unlock in posix/proc.c + + * Fix: Potential deadlock on kqueue initialisation failure. + + * Fix: Building for MSVC (Patch by Jan200101) * Fix: Sprinkle CLOEXEC around various places in the Linux and POSIX platforms to stop us leaking file descriptors on exec. From b3b147e3f79498c636ba71dcdd9d908914dbafc2 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 27 Apr 2022 12:21:51 -0500 Subject: [PATCH 1085/1120] Release 2.6.1 --- vendor/libkqueue/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 8e83f9da0..4cf89c606 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -14,7 +14,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -set(PROJECT_VERSION 2.6.0) +set(PROJECT_VERSION 2.6.1) if(EXISTS "/etc/debian_version") cmake_minimum_required(VERSION 3.7.2) From 51ad2489ca5a8232c1177405690966bf60989f93 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Thu, 28 Apr 2022 21:54:21 -0400 Subject: [PATCH 1086/1120] Remove the unused pkg/ subdirectory This directory contained experimental Debian packaging files that were not used to create the actual Debian package, and were not as good as using CPack's native DEB support. Related to #135 --- vendor/libkqueue/pkg/Dockerfile.debian | 13 --- vendor/libkqueue/pkg/README.md | 17 --- vendor/libkqueue/pkg/debian/changelog | 95 ---------------- vendor/libkqueue/pkg/debian/compat | 1 - vendor/libkqueue/pkg/debian/control | 30 ----- vendor/libkqueue/pkg/debian/copyright | 105 ------------------ .../pkg/debian/libkqueue-dev.install | 3 - .../libkqueue/pkg/debian/libkqueue0.install | 2 - vendor/libkqueue/pkg/debian/rules | 4 - vendor/libkqueue/pkg/debian/source/format | 1 - vendor/libkqueue/pkg/debian/symbols | 3 - 11 files changed, 274 deletions(-) delete mode 100644 vendor/libkqueue/pkg/Dockerfile.debian delete mode 100644 vendor/libkqueue/pkg/README.md delete mode 100644 vendor/libkqueue/pkg/debian/changelog delete mode 100644 vendor/libkqueue/pkg/debian/compat delete mode 100644 vendor/libkqueue/pkg/debian/control delete mode 100644 vendor/libkqueue/pkg/debian/copyright delete mode 100644 vendor/libkqueue/pkg/debian/libkqueue-dev.install delete mode 100644 vendor/libkqueue/pkg/debian/libkqueue0.install delete mode 100755 vendor/libkqueue/pkg/debian/rules delete mode 100644 vendor/libkqueue/pkg/debian/source/format delete mode 100644 vendor/libkqueue/pkg/debian/symbols diff --git a/vendor/libkqueue/pkg/Dockerfile.debian b/vendor/libkqueue/pkg/Dockerfile.debian deleted file mode 100644 index b8d3f32de..000000000 --- a/vendor/libkqueue/pkg/Dockerfile.debian +++ /dev/null @@ -1,13 +0,0 @@ -FROM debian:sid -MAINTAINER mark@heily.com -RUN apt-get update && apt-get install -y build-essential -RUN apt-get install -y cmake debhelper -ARG project_version -RUN mkdir -p /tmp/libkqueue-${project_version} -COPY . /tmp/libkqueue-${project_version} -WORKDIR /tmp -RUN tar zcf libkqueue_${project_version}.orig.tar.gz libkqueue-${project_version} -COPY pkg/debian/ /tmp/libkqueue-${project_version}/debian/ -WORKDIR /tmp/libkqueue-${project_version} -RUN rm -f CMakeCache.txt - diff --git a/vendor/libkqueue/pkg/README.md b/vendor/libkqueue/pkg/README.md deleted file mode 100644 index 64134fde5..000000000 --- a/vendor/libkqueue/pkg/README.md +++ /dev/null @@ -1,17 +0,0 @@ -This directory contains native packaging scripts for various platforms. - -The Makefile could optionally be converted into a CMakeLists file. - -Non-working example: - - add_custom_target(tarball git archive -o "libkqueue-${PROJECT_VERSION}.tar.gz" --prefix "libkqueue-${PROJECT_VERSION}/" HEAD) - - add_custom_target(docker_image docker build -t libkqueue-build --build-arg "project_version=${PROJECT_VERSION}" . - DEPENDS tarball) - - add_custom_target(native_package docker run --rm -it libkqueue-deb dpkg-buildpackage -uc -us -sn - DEPENDS docker_image) - - add_custom_target(debug_package_build docker run --rm -it libkqueue-deb docker run --rm -it libkqueue-deb:latest dpkg-buildpackage -uc -us - DEPENDS docker_image) - diff --git a/vendor/libkqueue/pkg/debian/changelog b/vendor/libkqueue/pkg/debian/changelog deleted file mode 100644 index 592daeb1a..000000000 --- a/vendor/libkqueue/pkg/debian/changelog +++ /dev/null @@ -1,95 +0,0 @@ -libkqueue (2.4.0-1) unstable; urgency=medium - - * New upstream release. - * Remove autoconf dependencies, as this project uses CMake. - * Remove all Debian patches, as they have been incorporated upstream. - - -- Mark Heily Wed, 18 Feb 2019 18:24:48 +0000 - -libkqueue (2.3.1-1) unstable; urgency=medium - - * New upstream release - - -- Mark Heily Wed, 06 Feb 2019 18:14:10 +0000 - -libkqueue (2.3.0-1) unstable; urgency=medium - - * New upstream release - - -- Mark Heily Tue, 15 Jan 2019 22:11:11 +0000 - -libkqueue (2.0.3-1.1) unstable; urgency=medium - - * Non maintainer upload. - * Fix build failures on 64bit architectures. Closes: #760302, #754376. - - Replacing preprocessor macro X86_64 to LP64 in knote.c, since - it is used to treat pointer rather than processor specifics (Fernando - Seiti Furusat). - - -- Matthias Klose Thu, 11 Sep 2014 13:52:07 +0200 - -libkqueue (2.0.3-1) unstable; urgency=low - - * New upstream release (closes: #741009) - - -- Mark Heily Sun, 09 Mar 2014 20:45:35 -0400 - -libkqueue (2.0.2-1) unstable; urgency=low - - * New upstream release (closes: #724170, #669572, #729591) - - -- Mark Heily Sun, 23 Feb 2014 16:04:08 -0500 - -libkqueue (1.0.4-2) unstable; urgency=low - * Integrate patches from Matthias Klose (Closes: #640029) - * Add -Wno-error=unused-result to CFLAGS - * Fix header checks for multiarch locations. - - -- Mark Heily Thu, 27 Oct 2011 20:58:03 -0400 - -libkqueue (1.0.4-1) unstable; urgency=low - - * Fix a FTBFS on 32-bit platforms caused by the use of /usr/lib64 - * Fix a lintian warning related to the copyright file - - -- Mark Heily Wed, 13 Jul 2011 20:52:41 -0400 - -libkqueue (1.0.3-1) unstable; urgency=low - - * New upstream release (Closes: #625639) - * Update control file with new website and standards version - * Simplify the debian/rules file using debhelper for everything - * Upgrade source/format to "3.0 (quilt)" - * Remove the debian/watch file - - -- Mark Heily Sat, 09 Jul 2011 18:56:19 -0400 - -libkqueue (0.9.2-2) unstable; urgency=low - - * Apply patch to fix a bug in EV_RECEIPT (Closes: #595648) - - -- Mark Heily Sun, 05 Sep 2010 13:57:45 -0400 - -libkqueue (0.9.2-1) unstable; urgency=low - - * New upstream release (Closes: #591818) - - -- Mark Heily Thu, 05 Aug 2010 23:31:18 -0400 - -libkqueue (0.9.1-1) unstable; urgency=low - - * New upstream release - - -- Mark Heily Wed, 04 Aug 2010 21:35:01 -0400 - -libkqueue (0.8-1) unstable; urgency=low - - * New upstream release - - -- Mark Heily Sun, 25 Jul 2010 10:09:35 -0400 - -libkqueue (0.7-1) unstable; urgency=low - - * Initial release (Closes: #576317) - - -- Mark Heily Sun, 28 Mar 2010 18:58:58 -0400 diff --git a/vendor/libkqueue/pkg/debian/compat b/vendor/libkqueue/pkg/debian/compat deleted file mode 100644 index ec635144f..000000000 --- a/vendor/libkqueue/pkg/debian/compat +++ /dev/null @@ -1 +0,0 @@ -9 diff --git a/vendor/libkqueue/pkg/debian/control b/vendor/libkqueue/pkg/debian/control deleted file mode 100644 index dfc228196..000000000 --- a/vendor/libkqueue/pkg/debian/control +++ /dev/null @@ -1,30 +0,0 @@ -Source: libkqueue -Section: libs -Priority: optional -Maintainer: Mark Heily -Build-Depends: debhelper (>= 9) -Standards-Version: 3.9.5.0 -Vcs-Git: git://github.com/mheily/debian-packages.git -b libkqueue -Homepage: https://github.com/mheily/libkqueue/wiki - -Package: libkqueue0 -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} -Description: cross-platform library for kernel event notification - libkqueue is a portable userspace implementation of the kqueue(2) - kernel event notification mechanism found in FreeBSD and other BSD-based - operating systems. The library translates between the kevent structure - and the native kernel facilities of the host machine. - -Package: libkqueue-dev -Section: libdevel -Architecture: any -Depends: libkqueue0 (= ${binary:Version}), ${misc:Depends} -Description: Development files for libkqueue - Contains the header files, manpages, and static libraries for use in - developing applications that use the libkqueue library. - . - libkqueue is a portable userspace implementation of the kqueue(2) - kernel event notification mechanism found in FreeBSD and other BSD-based - operating systems. The library translates between the kevent structure - and the native kernel facilities of the host machine. diff --git a/vendor/libkqueue/pkg/debian/copyright b/vendor/libkqueue/pkg/debian/copyright deleted file mode 100644 index 5066ec1af..000000000 --- a/vendor/libkqueue/pkg/debian/copyright +++ /dev/null @@ -1,105 +0,0 @@ -This package was debianized by Mark Heily on -Sun, 28 Mar 2010 18:58:58 -0400 - -It was downloaded from http://mark.heily.com/libkqueue/trunk/ - -Copyright: - - Copyright (C) 2009 Mark Heily - Copyright (c) 2000 Jonathan Lemon - Copyright 2002 Niels Provos - -License: - - Copyright (c) 2009 Mark Heily - - Permission to use, copy, modify, and distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -include/sys/event.h is licensed: - - Copyright (c) 1999,2000,2001 Jonathan Lemon - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - -src/common/tree.h is licensed: - - Copyright 2002 Niels Provos - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - -The Debian packaging is: - - Copyright (C) 2010 Mark Heily - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - diff --git a/vendor/libkqueue/pkg/debian/libkqueue-dev.install b/vendor/libkqueue/pkg/debian/libkqueue-dev.install deleted file mode 100644 index 88848c03e..000000000 --- a/vendor/libkqueue/pkg/debian/libkqueue-dev.install +++ /dev/null @@ -1,3 +0,0 @@ -usr/lib/*/pkgconfig/libkqueue.pc -usr/include/kqueue/sys/event.h -usr/share/man/man2/* diff --git a/vendor/libkqueue/pkg/debian/libkqueue0.install b/vendor/libkqueue/pkg/debian/libkqueue0.install deleted file mode 100644 index 0879cd03b..000000000 --- a/vendor/libkqueue/pkg/debian/libkqueue0.install +++ /dev/null @@ -1,2 +0,0 @@ -usr/lib/*/lib*.so -usr/lib/*/lib*.so.* diff --git a/vendor/libkqueue/pkg/debian/rules b/vendor/libkqueue/pkg/debian/rules deleted file mode 100755 index 050e29a63..000000000 --- a/vendor/libkqueue/pkg/debian/rules +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/make -f - -%: - dh $@ --buildsystem=cmake diff --git a/vendor/libkqueue/pkg/debian/source/format b/vendor/libkqueue/pkg/debian/source/format deleted file mode 100644 index 163aaf8d8..000000000 --- a/vendor/libkqueue/pkg/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (quilt) diff --git a/vendor/libkqueue/pkg/debian/symbols b/vendor/libkqueue/pkg/debian/symbols deleted file mode 100644 index 0141b0fc0..000000000 --- a/vendor/libkqueue/pkg/debian/symbols +++ /dev/null @@ -1,3 +0,0 @@ -libkqueue.so.0 libkqueue0 #MINVER# - kevent@Base 2.0.2 - kqueue@Base 2.0.2 From 7205eae59da6ad6709be7e6b6fc68f350d3018b8 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Thu, 28 Apr 2022 22:24:35 -0400 Subject: [PATCH 1087/1120] Replace the "tarball" CMake target with CPack Related to #135 --- vendor/libkqueue/.gitignore | 1 + vendor/libkqueue/CMakeLists.txt | 11 +++++++++-- vendor/libkqueue/README.md | 8 ++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/.gitignore b/vendor/libkqueue/.gitignore index 1eec65e4e..96a934f4a 100644 --- a/vendor/libkqueue/.gitignore +++ b/vendor/libkqueue/.gitignore @@ -7,6 +7,7 @@ config.h *.ddeb *.swp .fuse* +cmake-build-*/ CMakeCache.txt CMakeFiles/ CPackConfig.cmake diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 4cf89c606..c6ac55efe 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -419,12 +419,19 @@ else() set(CPACK_DEBIAN_DEVEL_PACKAGE_DEPENDS "${CPACK_PACKAGE_NAME} (= ${PROJECT_VERSION})") endif() +set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${PROJECT_VERSION}") +set(CPACK_SOURCE_IGNORE_FILES + "cmake-build-*" + ".github/" + ".git/" + ".*.swp" +) +set(CPACK_SOURCE_GENERATOR "TXZ") + set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Mark Heily ") set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/mheily/libkqueue") include(CPack) -add_custom_target(tarball git archive -o "libkqueue-${PROJECT_VERSION}.tar.gz" --prefix "libkqueue-${PROJECT_VERSION}/" HEAD) - # # Ensure variables which represent arguments are not # cached. This provides more of a sane interface where diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index d455fe930..83bb70213 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -78,6 +78,14 @@ Xcode (project) cmake -G "Xcode" +Source archive +-------------- + + mkdir -p cmake-build-source + cd cmake-build-source + cmake .. + make package_source + Running Unit Tests ------------------ From 16f3747a2ed6f528172d6651b187fe3fd003b712 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 2 May 2022 10:29:49 +0200 Subject: [PATCH 1088/1120] Avoid calling free at all in a children as it's not fork safe --- vendor/libkqueue/src/common/kqueue.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/vendor/libkqueue/src/common/kqueue.c b/vendor/libkqueue/src/common/kqueue.c index 452b7e1fc..bb7a5c72a 100644 --- a/vendor/libkqueue/src/common/kqueue.c +++ b/vendor/libkqueue/src/common/kqueue.c @@ -29,6 +29,10 @@ bool libkqueue_fork_cleanup = true; */ bool libkqueue_fork_cleanup_active; +/** Whether this is a child of the original process + */ +static bool libkqueue_in_child = false; + #ifdef _WIN32 tracing_mutex_t kq_mtx; static LONG kq_init_begin = 0; @@ -98,6 +102,14 @@ static struct map *kqmap; void libkqueue_free(void) { + /* + * The issue here is that we're not sure + */ + if (libkqueue_in_child) { + dbg_puts("not releasing library resources as we are a child"); + return; + } + dbg_puts("releasing library resources"); filter_free_all(); @@ -191,6 +203,8 @@ libkqueue_child_fork(void) { struct kqueue *kq, *kq_tmp; + libkqueue_in_child = true; + if (!libkqueue_fork_cleanup_active) { tracing_mutex_unlock(&kq_mtx); return; From f78ca2be13260187bf1f46f48962ba3fa3b32c4b Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Tue, 7 Jun 2022 23:03:46 -0700 Subject: [PATCH 1089/1120] add pthread header Fixes compilation under musl. --- vendor/libkqueue/src/common/debug.h | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/src/common/debug.h b/vendor/libkqueue/src/common/debug.h index 4bf903b63..52ba970ab 100644 --- a/vendor/libkqueue/src/common/debug.h +++ b/vendor/libkqueue/src/common/debug.h @@ -24,6 +24,7 @@ # include # include "../windows/platform.h" #else +# include # include #endif From c0b6730498032b56a1c84f59a727f69956659d80 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Tue, 14 Jun 2022 17:30:24 -0700 Subject: [PATCH 1090/1120] fix compilation with MSYS2 First change fixes a redefinition error. Second one fixes missing definition for EINVAL and such. Signed-off-by: Rosen Penev --- vendor/libkqueue/include/sys/event.h | 2 +- vendor/libkqueue/src/windows/platform.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/vendor/libkqueue/include/sys/event.h b/vendor/libkqueue/include/sys/event.h index d080e7059..5d9e61895 100644 --- a/vendor/libkqueue/include/sys/event.h +++ b/vendor/libkqueue/include/sys/event.h @@ -257,7 +257,7 @@ extern "C" { #ifdef _WIN32 -#if (_MSC_VER < 1900) +#if defined (_MSC_VER) && (_MSC_VER < 1900) struct timespec { time_t tv_sec; long tv_nsec; diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 104b82053..e518825e7 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -18,7 +18,9 @@ #define _KQUEUE_WINDOWS_PLATFORM_H /* Require Windows Server 2003 or later */ +#if WINVER < 0x0502 #define WINVER 0x0502 +#endif #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0502 #endif @@ -28,6 +30,7 @@ #include #include #include +#include #include "../common/queue.h" From 8869492c039842e3f5227aedbb051d774b7a68eb Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Wed, 15 Jun 2022 15:08:56 -0700 Subject: [PATCH 1091/1120] platform: add config.h Required as there is a check for sys/types.h --- vendor/libkqueue/src/windows/platform.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index e518825e7..1a99903b3 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -17,6 +17,8 @@ #ifndef _KQUEUE_WINDOWS_PLATFORM_H #define _KQUEUE_WINDOWS_PLATFORM_H +#include "config.h" + /* Require Windows Server 2003 or later */ #if WINVER < 0x0502 #define WINVER 0x0502 From f85740a9cc3ee5aa538c86f243d9b32343d7cfdc Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Wed, 15 Jun 2022 13:46:56 -0700 Subject: [PATCH 1092/1120] change LIBKQUEUE_VERSION_DATE to cmakedefine LIBKQUEUE_VERSION_DATE is not mandatory to be specified. The code checks for it with ifdef. Signed-off-by: Rosen Penev --- vendor/libkqueue/version.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/version.h.in b/vendor/libkqueue/version.h.in index 5e297899e..95619284a 100644 --- a/vendor/libkqueue/version.h.in +++ b/vendor/libkqueue/version.h.in @@ -26,7 +26,7 @@ #define LIBKQUEUE_VERSION_PATCH @PROJECT_VERSION_PATCH@ #cmakedefine LIBKQUEUE_VERSION_RELEASE @PROJECT_VERSION_RELEASE@ -#define LIBKQUEUE_VERSION_DATE "@PROJECT_VERSION_DATE@" +#cmakedefine LIBKQUEUE_VERSION_DATE "@PROJECT_VERSION_DATE@" #cmakedefine LIBKQUEUE_VERSION_COMMIT "@LIBKQUEUE_VERSION_COMMIT@" #endif /* ! _LIBKQUEUE_VERSION_H */ From b3b01a66819db1bb140fe0fef78510d748914845 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Wed, 15 Jun 2022 20:18:59 -0700 Subject: [PATCH 1093/1120] replace windows atomic operations with stdatomic Signed-off-by: Rosen Penev --- vendor/libkqueue/src/windows/platform.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 1a99903b3..0704bb7c7 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -42,6 +42,20 @@ # pragma warning( disable : 4996 ) #endif +#ifndef _MSC_VER +#include +/* + * C11 atomic operations + */ +#define atomic_inc(p) (atomic_fetch_add((p), 1) + 1) +#define atomic_dec(p) (atomic_fetch_sub((p), 1) - 1) + +/* We use compound literals here to stop the 'expected' values from being overwritten */ +#define atomic_cas(p, oval, nval) atomic_compare_exchange_strong(p, &(__typeof__(oval)){ oval }, nval) +#define atomic_ptr_cas(p, oval, nval) atomic_compare_exchange_strong(p, (&(uintptr_t){ (uintptr_t)oval }), (uintptr_t)nval) +#define atomic_ptr_swap(p, nval) atomic_exchange(p, (uintptr_t)nval) +#define atomic_ptr_load(p) atomic_load(p) +#else /* * Atomic integer operations */ @@ -54,6 +68,7 @@ #define atomic_ptr_swap(p, oval) InterlockedExchangePointer(p, oval) #define atomic_ptr_load(p) (*p) +#endif /* * Additional members of struct kqueue From a6fefb8b2d390fad28d65c1fcad380c765b171ea Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 16 Jun 2022 15:36:19 -0700 Subject: [PATCH 1094/1120] don't redefine HIDDEN/VISIBLE macros on MinGW Signed-off-by: Rosen Penev --- vendor/libkqueue/src/windows/platform.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/libkqueue/src/windows/platform.h b/vendor/libkqueue/src/windows/platform.h index 0704bb7c7..a36bf5eb6 100644 --- a/vendor/libkqueue/src/windows/platform.h +++ b/vendor/libkqueue/src/windows/platform.h @@ -123,9 +123,11 @@ int windows_get_descriptor_type(struct knote *); # define unlikely(x) (x) #endif +#ifdef _MSC_VER /* Function visibility macros */ #define VISIBLE __declspec(dllexport) #define HIDDEN +#endif #if !defined(__func__) && !defined(__GNUC__) #define __func__ __FUNCDNAME__ From eda1cd098a986f0b8530f23d73f224668c102da9 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 17 Jun 2022 13:33:19 -0500 Subject: [PATCH 1095/1120] Add CI release build with musl --- .../libkqueue/.github/workflows/ci-linux.yml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/vendor/libkqueue/.github/workflows/ci-linux.yml b/vendor/libkqueue/.github/workflows/ci-linux.yml index a84de17ad..de8be8888 100644 --- a/vendor/libkqueue/.github/workflows/ci-linux.yml +++ b/vendor/libkqueue/.github/workflows/ci-linux.yml @@ -35,13 +35,14 @@ jobs: fail-fast: false matrix: env: - - { CC: gcc, OS: ubuntu-20.04, NAME: release-gcc, BUILD_TYPE: Release } - - { CC: clang, OS: ubuntu-20.04, NAME: release-clang, BUILD_TYPE: Release } - - { CC: clang, OS: ubuntu-20.04, NAME: debug-asan, BUILD_TYPE: Debug, ENABLE_ASAN: YES, ENABLE_LSAN: YES, ENABLE_UBSAN: YES } - - { CC: clang, OS: ubuntu-20.04, NAME: debug-tsan, BUILD_TYPE: Debug, ENABLE_TSAN: YES } + - { CC: gcc, OS: ubuntu-20.04, NAME: release-gcc, BUILD_TYPE: Release } + - { CC: clang, OS: ubuntu-20.04, NAME: release-clang, BUILD_TYPE: Release } + - { CC: musl-gcc, OS: ubuntu-20.04, NAME: release-musl-gcc, BUILD_TYPE: Release } + - { CC: clang, OS: ubuntu-20.04, NAME: debug-asan, BUILD_TYPE: Debug, ENABLE_ASAN: YES, ENABLE_LSAN: YES, ENABLE_UBSAN: YES } + - { CC: clang, OS: ubuntu-20.04, NAME: debug-tsan, BUILD_TYPE: Debug, ENABLE_TSAN: YES } # Older kernel triggers a switch to posix/proc as it doesn't support pidfd. - - { CC: clang, OS: ubuntu-18.04, NAME: debug-asan-posix-proc, BUILD_TYPE: Debug, ENABLE_ASAN: YES, ENABLE_LSAN: YES, ENABLE_UBSAN: YES } - - { CC: clang, OS: ubuntu-18.04, NAME: debug-tsan-posix-proc, BUILD_TYPE: Debug, ENABLE_TSAN: YES } + - { CC: clang, OS: ubuntu-18.04, NAME: debug-asan-posix-proc, BUILD_TYPE: Debug, ENABLE_ASAN: YES, ENABLE_LSAN: YES, ENABLE_UBSAN: YES } + - { CC: clang, OS: ubuntu-18.04, NAME: debug-tsan-posix-proc, BUILD_TYPE: Debug, ENABLE_TSAN: YES } runs-on: ${{ matrix.env.OS }} @@ -78,6 +79,11 @@ jobs: sudo apt-get install -y --no-install-recommends gcc-7 gccgo-7 gdb sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 9999 && sudo update-alternatives --config gcc + - name: Install MUSL + if: ${{ matrix.env.CC == 'musl-gcc' }} + run: | + sudo apt-get install -y --no-install-recommends musl musl-dev musl-tools + - name: Install other build deps run: | sudo apt-get install -y \ From 48e3b8fb50afadf910e031ac688871b6886a51f7 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 17 Jun 2022 13:40:08 -0500 Subject: [PATCH 1096/1120] Various musl include fixes --- vendor/libkqueue/CMakeLists.txt | 13 ++++++++++--- vendor/libkqueue/config.h.in | 11 ++++++++--- vendor/libkqueue/src/linux/platform.h | 25 ++++++++++++++++++++----- vendor/libkqueue/src/linux/proc.c | 3 +-- vendor/libkqueue/src/linux/read.c | 11 +++++++++-- vendor/libkqueue/src/linux/signal.c | 1 - vendor/libkqueue/src/linux/timer.c | 1 - vendor/libkqueue/src/linux/user.c | 3 ++- vendor/libkqueue/src/linux/vnode.c | 1 - vendor/libkqueue/src/linux/write.c | 10 ++++++++-- 10 files changed, 58 insertions(+), 21 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index c6ac55efe..a49e2e31e 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -144,9 +144,10 @@ include(CheckIncludeFiles) include(CheckSymbolExists) include(GNUInstallDirs) +check_include_files(sys/eventfd.h HAVE_SYS_EVENTFD_H) +check_include_files(sys/queue.h HAVE_SYS_QUEUE_H) check_include_files(sys/signalfd.h HAVE_SYS_SIGNALFD_H) check_include_files(sys/timerfd.h HAVE_SYS_TIMERFD_H) -check_include_files(sys/eventfd.h HAVE_SYS_EVENTFD_H) check_include_files(sys/types.h HAVE_SYS_TYPES_H) if(ENABLE_TESTING) check_include_files(err.h HAVE_ERR_H) @@ -162,8 +163,6 @@ set(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE) check_symbol_exists(ppoll poll.h HAVE_DECL_PPOLL) check_symbol_exists(SYS_pidfd_open sys/syscall.h HAVE_SYS_PIDFD_OPEN) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in - ${CMAKE_CURRENT_BINARY_DIR}/config.h) include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/include) @@ -207,6 +206,11 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") src/solaris/user.c ) elseif(CMAKE_SYSTEM_NAME STREQUAL Linux) + check_include_files(linux/limits.h HAVE_LINUX_LIMITS_H) + check_include_files(linux/sockios.h HAVE_LINUX_SOCKIOS_H) + check_include_files(linux/unistd.h HAVE_LINUX_UNISTD_H) + check_include_files(syscall.h HAVE_SYSCALL_H) + # # Set the default prefix to something sane # @@ -307,6 +311,9 @@ else() target_link_libraries(kqueue PRIVATE Threads::Threads) endif() +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/config.h) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/libkqueue.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/libkqueue.pc" @ONLY) diff --git a/vendor/libkqueue/config.h.in b/vendor/libkqueue/config.h.in index 2aab33e12..aee5bd266 100644 --- a/vendor/libkqueue/config.h.in +++ b/vendor/libkqueue/config.h.in @@ -1,10 +1,15 @@ - +#cmakedefine01 HAVE_ERR_H +#cmakedefine01 HAVE_SYS_EVENTFD_H +#cmakedefine01 HAVE_SYS_QUEUE_H #cmakedefine01 HAVE_SYS_SIGNALFD_H #cmakedefine01 HAVE_SYS_TIMERFD_H -#cmakedefine01 HAVE_SYS_EVENTFD_H -#cmakedefine01 HAVE_ERR_H #cmakedefine01 HAVE_SYS_TYPES_H +#cmakedefine01 HAVE_LINUX_LIMITS_H +#cmakedefine01 HAVE_LINUX_SOCKIOS_H +#cmakedefine01 HAVE_LINUX_UNISTD_H +#cmakedefine01 HAVE_SYSCALL_H + #cmakedefine01 HAVE_EPOLLRDHUP #cmakedefine01 HAVE_NOTE_TRUNCATE #cmakedefine01 HAVE_DECL_PPOLL diff --git a/vendor/libkqueue/src/linux/platform.h b/vendor/libkqueue/src/linux/platform.h index 1aef334a8..bf8d7d6d0 100644 --- a/vendor/libkqueue/src/linux/platform.h +++ b/vendor/libkqueue/src/linux/platform.h @@ -20,7 +20,7 @@ struct filter; #include #include -#include + #include #if HAVE_SYS_EVENTFD_H # include @@ -38,12 +38,24 @@ struct filter; return (0); } #endif + #include -#include #include #include #include -#include + +#if HAVE_LINUX_LIMITS_H +# include +#else +# include +#endif + +#if HAVE_SYS_QUEUE_H +# include +#else +# include "../common/queue.h" +#endif + #include #include #include @@ -80,11 +92,14 @@ struct filter; #define atomic_ptr_load(p) atomic_load(p) /* - * Get the current thread ID + * Allow us to make arbitrary syscalls */ # define _GNU_SOURCE +#if HAVE_LINUX_UNISTD_H # include -# include +#elif HAVE_SYSCALL_H +# include +#endif #ifndef __ANDROID__ extern long int syscall (long int __sysno, ...); #endif diff --git a/vendor/libkqueue/src/linux/proc.c b/vendor/libkqueue/src/linux/proc.c index 5d3ae345a..ba7d2a297 100644 --- a/vendor/libkqueue/src/linux/proc.c +++ b/vendor/libkqueue/src/linux/proc.c @@ -13,6 +13,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "private.h" /* We depend on the SYS_pidfd_open call to determine when a process has exited * @@ -25,8 +26,6 @@ #include #include -#include "private.h" - int evfilt_proc_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, struct knote *src, UNUSED_NDEBUG void *ptr) diff --git a/vendor/libkqueue/src/linux/read.c b/vendor/libkqueue/src/linux/read.c index 19bb01bae..a769f65bc 100644 --- a/vendor/libkqueue/src/linux/read.c +++ b/vendor/libkqueue/src/linux/read.c @@ -13,11 +13,18 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include +#include "private.h" + +#if HAVE_LINUX_SOCKIOS_H +# include +#endif + #include #include -#include "private.h" +#ifndef SIOCINQ +# define SIOCINQ FIONREAD +#endif /* * Return the offset from the current position to end of file. diff --git a/vendor/libkqueue/src/linux/signal.c b/vendor/libkqueue/src/linux/signal.c index 371f8c133..dccb03fe0 100644 --- a/vendor/libkqueue/src/linux/signal.c +++ b/vendor/libkqueue/src/linux/signal.c @@ -13,7 +13,6 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - #include "private.h" #include diff --git a/vendor/libkqueue/src/linux/timer.c b/vendor/libkqueue/src/linux/timer.c index 6a9d0b8fe..2e2082d09 100644 --- a/vendor/libkqueue/src/linux/timer.c +++ b/vendor/libkqueue/src/linux/timer.c @@ -13,7 +13,6 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - #include "private.h" #if HAVE_SYS_TIMERFD_H != 1 diff --git a/vendor/libkqueue/src/linux/user.c b/vendor/libkqueue/src/linux/user.c index bc68a9168..a24d0e9cf 100644 --- a/vendor/libkqueue/src/linux/user.c +++ b/vendor/libkqueue/src/linux/user.c @@ -13,10 +13,11 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "private.h" + #include #include -#include "private.h" int linux_evfilt_user_knote_enable(struct filter *filt, struct knote *kn); diff --git a/vendor/libkqueue/src/linux/vnode.c b/vendor/libkqueue/src/linux/vnode.c index 92e3d4632..3c28575bc 100644 --- a/vendor/libkqueue/src/linux/vnode.c +++ b/vendor/libkqueue/src/linux/vnode.c @@ -13,7 +13,6 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - #include "private.h" #ifndef NDEBUG diff --git a/vendor/libkqueue/src/linux/write.c b/vendor/libkqueue/src/linux/write.c index 0f94145b7..398dc9113 100644 --- a/vendor/libkqueue/src/linux/write.c +++ b/vendor/libkqueue/src/linux/write.c @@ -13,12 +13,18 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "private.h" + +#if HAVE_LINUX_SOCKIOS_H +# include +#endif -#include #include #include -#include "private.h" +#ifndef SIOCOUTQ +# define SIOCOUTQ TIOCOUTQ +#endif int evfilt_write_copyout(struct kevent *dst, UNUSED int nevents, struct filter *filt, From 4931d26f31654f83c818bd8b3e088d33cd1ab094 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 17 Jun 2022 15:04:33 -0500 Subject: [PATCH 1097/1120] Cat config.h --- vendor/libkqueue/.github/workflows/ci-linux.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libkqueue/.github/workflows/ci-linux.yml b/vendor/libkqueue/.github/workflows/ci-linux.yml index de8be8888..45de58554 100644 --- a/vendor/libkqueue/.github/workflows/ci-linux.yml +++ b/vendor/libkqueue/.github/workflows/ci-linux.yml @@ -105,6 +105,7 @@ jobs: -DENABLE_UBSAN="${ENABLE_UBSAN:-NO}" \ -DENABLE_TSAN="${ENABLE_TSAN:-NO}" \ -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" + cat config.h - name: Build libkqueue run: make -j2 From a93e582bbb3ae48bfe615d621368286706873f45 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 17 Jun 2022 18:14:52 -0500 Subject: [PATCH 1098/1120] Typo --- vendor/libkqueue/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index 83bb70213..ce1f51b5f 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -120,7 +120,7 @@ When building under clang and some later versions of GCC, you can add the follow - `-DENABLE_ASAN=YES`, enables address sansitizer (detects use after free issues, and out of bounds accesses). - `-DENABLE_LSAN=YES`, enables leak sanitizer (detects memory leaks). - `-DENABLE_TSAN=YES`, enables thread sanitizer (detects races). -- `-DENABLE_UBSAN=YES`, enables undefined behaviour sanitizer (detects misaligned accesses, interger wrap, divide by zero etc...). +- `-DENABLE_UBSAN=YES`, enables undefined behaviour sanitizer (detects misaligned accesses, integer wrap, divide by zero etc...). libkqueue filter ---------------- From 8016f69ed2cc3169e9ee2a6395bf4f3805d0c54c Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 17 Jun 2022 18:17:10 -0500 Subject: [PATCH 1099/1120] Add a link to the ChangeLog under releases history --- vendor/libkqueue/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/vendor/libkqueue/README.md b/vendor/libkqueue/README.md index ce1f51b5f..08e00a037 100644 --- a/vendor/libkqueue/README.md +++ b/vendor/libkqueue/README.md @@ -185,6 +185,4 @@ Tutorials & Examples Releases History ---------------- -2.0 add support for Android _2013-04-29_ - -1.0 stable relesae for Linux, Solaris, and Windows _2010-09-18_ +See the [ChangeLog](https://github.com/mheily/libkqueue/blob/master/ChangeLog). From 218a8bede7d31e3174474d48277a5725fc917591 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 20 Jun 2022 19:51:20 -0500 Subject: [PATCH 1100/1120] Update changelog --- vendor/libkqueue/ChangeLog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index b83aeb5a7..833a646c4 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,6 +1,13 @@ Unreleased ------------------------------------------------------------------------ + * Fix: Various build system and include fixes to allow libkqueue + to build correctly with musl libc. + + * Fix: Various macro and include fixes for Windows/MinGW builds. + (Fixed by: neheb) + + 2022-04-27 v2.6.1 ------------------------------------------------------------------------ From db75fc6ae58f5b8fbe8326b514d8a9a244d969c7 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Mon, 20 Jun 2022 20:53:11 -0400 Subject: [PATCH 1101/1120] Fix map_new() on Windows --- vendor/libkqueue/src/common/map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/src/common/map.c b/vendor/libkqueue/src/common/map.c index 882175d78..991cda531 100644 --- a/vendor/libkqueue/src/common/map.c +++ b/vendor/libkqueue/src/common/map.c @@ -34,7 +34,7 @@ map_new(size_t len) if (dst == NULL) return (NULL); #ifdef _WIN32 - dst->data = calloc(len, len * sizeof(dst->data[0])); + dst->data = calloc(len, sizeof(dst->data[0])); if(dst->data == NULL) { dbg_perror("calloc()"); free(dst); From 9fa5848ee40b56be5e3f6029e19a1764d6690c90 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Sat, 30 Apr 2022 21:18:28 -0400 Subject: [PATCH 1102/1120] Build a shared and static library Relates to issue#135 --- vendor/libkqueue/CMakeLists.txt | 39 +++++++++++++++++---------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index a49e2e31e..84ccf9135 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -134,8 +134,6 @@ if(DEBUG_FSANITIZERFLAGS) MESSAGE("CMAKE_LD_FLAGS_DEBUG are \"${CMAKE_LD_FLAGS_DEBUG}\"") endif() -option(STATIC_KQUEUE "build libkqueue as static library" OFF) - set(CMAKE_THREAD_PREFER_PTHREAD TRUE) set(THREADS_PREFER_PTHREAD_FLAG TRUE) find_package(Threads REQUIRED) @@ -247,7 +245,6 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL Emscripten) src/posix/vnode.c src/posix/write.c ) - set(STATIC_KQUEUE ON) else() message(FATAL_ERROR "unsupported host os") endif() @@ -259,40 +256,44 @@ source_group(src FILES ${LIBKQUEUE_SOURCES}) -if(STATIC_KQUEUE) - set(LIBRARY_TYPE STATIC) +add_library(objlib OBJECT ${LIBKQUEUE_SOURCES} ${LIBKQUEUE_HEADERS}) +add_library(kqueue SHARED $) +add_library(kqueue_static STATIC $) +if (CMAKE_SYSTEM_NAME MATCHES Windows) + set_target_properties(kqueue_static + PROPERTIES + OUTPUT_NAME kqueue_static + ARCHIVE_OUTPUT_DIRECTORY kqueueStatic) else() - set(LIBRARY_TYPE SHARED) + set_target_properties(kqueue_static PROPERTIES OUTPUT_NAME kqueue) endif() -add_library(kqueue ${LIBRARY_TYPE} ${LIBKQUEUE_SOURCES} ${LIBKQUEUE_HEADERS}) - # We should have absolute ABI compatibility between versions as none # of the public function signatures of variables will change. set_target_properties(kqueue PROPERTIES SOVERSION 0) if(WIN32) - target_compile_definitions(kqueue PRIVATE _USRDLL;_WINDLL) - target_compile_definitions(kqueue PRIVATE _CRT_SECURE_NO_WARNINGS) - target_compile_definitions(kqueue PRIVATE WIN32_LEAN_AND_MEAN) + target_compile_definitions(objlib PRIVATE _USRDLL;_WINDLL) + target_compile_definitions(objlib PRIVATE _CRT_SECURE_NO_WARNINGS) + target_compile_definitions(objlib PRIVATE WIN32_LEAN_AND_MEAN) else() - target_compile_definitions(kqueue PRIVATE _XOPEN_SOURCE=600) + target_compile_definitions(objlib PRIVATE _XOPEN_SOURCE=600) endif() -target_include_directories(kqueue PRIVATE include) +target_include_directories(objlib PRIVATE include) if(NOT WIN32) - target_include_directories(kqueue PRIVATE src/common) + target_include_directories(objlib PRIVATE src/common) endif() if(CMAKE_C_COMPILER_ID MATCHES GNU) - target_compile_options(kqueue PRIVATE -Wall -Werror) + target_compile_options(objlib PRIVATE -Wall -Werror) endif() if(MINGW AND CMAKE_C_COMPILER_ID MATCHES GNU) #TODO: is it needed at all? if (CMAKE_SIZEOF_VOID_P EQUAL 4) - target_compile_options(kqueue PRIVATE -march=i486) + target_compile_options(objlib PRIVATE -march=i486) elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) - target_compile_options(kqueue PRIVATE -march=x86-64) + target_compile_options(objlib PRIVATE -march=x86-64) endif () endif() @@ -306,7 +307,7 @@ if(ENABLE_TESTING) endif() if(CMAKE_SYSTEM_NAME STREQUAL Emscripten) - target_compile_options(kqueue PRIVATE -pthread) + target_compile_options(objlib PRIVATE -pthread) else() target_link_libraries(kqueue PRIVATE Threads::Threads) endif() @@ -331,7 +332,7 @@ install(FILES "${CMAKE_INSTALL_FULL_INCLUDEDIR}/kqueue/sys" COMPONENT headers) install(TARGETS - kqueue + kqueue kqueue_static DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" COMPONENT libraries) From 13f0d5693551745fb1a8372ff4b1f55b99c7be04 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Thu, 23 Jun 2022 20:15:33 -0400 Subject: [PATCH 1103/1120] Fix a couple of spelling errors --- vendor/libkqueue/src/linux/platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/src/linux/platform.c b/vendor/libkqueue/src/linux/platform.c index ac75948e0..ac6979902 100644 --- a/vendor/libkqueue/src/linux/platform.c +++ b/vendor/libkqueue/src/linux/platform.c @@ -523,7 +523,7 @@ linux_kqueue_init(struct kqueue *kq) * multiple signals are queued. */ if (fcntl(kq->pipefd[0], F_SETSIG, MONITORING_THREAD_SIGNAL) < 0) { - dbg_printf("fd=%i - failed settting F_SETSIG sig=%u: %s", + dbg_printf("fd=%i - failed setting F_SETSIG sig=%u: %s", kq->pipefd[0], MONITORING_THREAD_SIGNAL, strerror(errno)); goto error; } @@ -552,7 +552,7 @@ linux_kqueue_init(struct kqueue *kq) sig_owner.type = F_OWNER_TID; sig_owner.pid = monitoring_tid; if (fcntl(kq->pipefd[0], F_SETOWN_EX, &sig_owner) < 0) { - dbg_printf("fd=%i - failed settting F_SETOWN to tid=%u: %s", monitoring_tid, kq->kq_id, strerror(errno)); + dbg_printf("fd=%i - failed setting F_SETOWN to tid=%u: %s", monitoring_tid, kq->kq_id, strerror(errno)); tracing_mutex_unlock(&kq_mtx); goto error; } From 7cc7ffeb204a85c7e7f0b5ab1b75c33d59ece1af Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Thu, 23 Jun 2022 20:31:11 -0400 Subject: [PATCH 1104/1120] Be less strict about the length of the version string This caused a test failure when using a tarball produced by the "make source_package" command. I believe the version string was "2.6.1" which is less than the 8 characters the test expected. --- vendor/libkqueue/test/libkqueue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/libkqueue/test/libkqueue.c b/vendor/libkqueue/test/libkqueue.c index a7c86cf44..5e71d7e28 100644 --- a/vendor/libkqueue/test/libkqueue.c +++ b/vendor/libkqueue/test/libkqueue.c @@ -46,8 +46,8 @@ test_libkqueue_version_str(struct test_context *ctx) die("kevent"); } - if (strlen((char *)receipt.udata) < 8) { - printf("No version number returned"); + if (!strlen((char *)receipt.udata)) { + printf("empty version number returned"); die("kevent"); } } From 9b7b7b41823ec321ee078d1a249ae9e04cbd4e01 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Thu, 23 Jun 2022 22:05:12 -0400 Subject: [PATCH 1105/1120] Update the changelog --- vendor/libkqueue/ChangeLog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vendor/libkqueue/ChangeLog b/vendor/libkqueue/ChangeLog index 833a646c4..2cdf98b71 100644 --- a/vendor/libkqueue/ChangeLog +++ b/vendor/libkqueue/ChangeLog @@ -1,12 +1,17 @@ Unreleased ------------------------------------------------------------------------ +2022-04-27 v2.6.2 +------------------------------------------------------------------------ + * Fix: Various build system and include fixes to allow libkqueue to build correctly with musl libc. * Fix: Various macro and include fixes for Windows/MinGW builds. (Fixed by: neheb) + * Always build both a static and a shared library. The STATIC_KQUEUE + build variable has been removed. 2022-04-27 v2.6.1 ------------------------------------------------------------------------ From a750fab57e72ed8d83f56f0ab41e2bace44c7929 Mon Sep 17 00:00:00 2001 From: Mark Heily Date: Thu, 23 Jun 2022 22:13:58 -0400 Subject: [PATCH 1106/1120] Bump version to 2.6.2 --- vendor/libkqueue/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libkqueue/CMakeLists.txt b/vendor/libkqueue/CMakeLists.txt index 84ccf9135..368798639 100644 --- a/vendor/libkqueue/CMakeLists.txt +++ b/vendor/libkqueue/CMakeLists.txt @@ -14,7 +14,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -set(PROJECT_VERSION 2.6.1) +set(PROJECT_VERSION 2.6.2) if(EXISTS "/etc/debian_version") cmake_minimum_required(VERSION 3.7.2) From 3973f3ab2828dc2c5dbc46e7b9cca6233b661995 Mon Sep 17 00:00:00 2001 From: Malcolm Date: Sun, 23 Feb 2025 14:21:36 +0000 Subject: [PATCH 1107/1120] #324 REFACTOR Create metric of event loop execution duration --- code/src/abb_intf/abb_intf.ml | 231 ++++++++---------- .../abb_scheduler_kqueue.ml | 23 +- .../abb_scheduler_nyi/abb_scheduler_nyi.ml | 5 +- .../abb_scheduler_select.ml | 28 +-- code/src/terrat_ee/terrat_ee.ml | 19 +- code/src/terrat_oss/terrat_oss.ml | 19 +- 6 files changed, 156 insertions(+), 169 deletions(-) diff --git a/code/src/abb_intf/abb_intf.ml b/code/src/abb_intf/abb_intf.ml index 119ceef64..af74db6c3 100644 --- a/code/src/abb_intf/abb_intf.ml +++ b/code/src/abb_intf/abb_intf.ml @@ -1,9 +1,9 @@ -(** Abb_intf defines the interface that users of Abb should program against as - well as what backends should implement. A monadic interface is requires as - well as low-level OS operations. This is targeted at POSIX-like OS's. +(** Abb_intf defines the interface that users of Abb should program against as well as what backends + should implement. A monadic interface is requires as well as low-level OS operations. This is + targeted at POSIX-like OS's. - Unless otherwise specified, no operations on a single value (such as a file - or socket) are safe to execute concurrent operations. *) + Unless otherwise specified, no operations on a single value (such as a file or socket) are safe + to execute concurrent operations. *) module Errors = struct let pp_exn fmt exn = Format.fprintf fmt "%s" (Printexc.to_string exn) @@ -363,8 +363,7 @@ module Errors = struct [@@deriving show, eq] end -(** An implementation of future must provide an interface which works - within these types. *) +(** An implementation of future must provide an interface which works within these types. *) module Future = struct module State = struct type 'a t = @@ -388,34 +387,30 @@ module Future = struct type +'a t type abort = unit -> unit t - (** A promise is the value used to set a [Future]. The promise can be - aborted by turning it into a future with {!Promise.future} and then - calling {!abort}. *) + (** A promise is the value used to set a [Future]. The promise can be aborted by turning it into + a future with {!Promise.future} and then calling {!abort}. *) module Promise : sig type 'a fut = 'a t type 'a t - (** Create a promise with an optional function to call on abort. When - aborting or canceling a future, the processing of the dependency tree - is executed depth-first and the each abort is executed to completion - before working back up the stack of aborts. If calling the [abort] - function raises and exception, then that exception is what is - propagated through the tree, replacing whatever the existing error - was. *) + (** Create a promise with an optional function to call on abort. When aborting or canceling a + future, the processing of the dependency tree is executed depth-first and the each abort + is executed to completion before working back up the stack of aborts. If calling the + [abort] function raises and exception, then that exception is what is propagated through + the tree, replacing whatever the existing error was. *) val create : ?abort:abort -> unit -> 'a t (** Return a future for the promise. *) val future : 'a t -> 'a fut - (** Set the promise to a value and kick any values waiting for it. If the - promise is determined already, this is a no-op. *) + (** Set the promise to a value and kick any values waiting for it. If the promise is + determined already, this is a no-op. *) val set : 'a t -> 'a -> unit fut - (** Set the promise to an exception, this will fail all of the connected - futures with the exception, causing their abort function to be - executed. The returned future is not determined until all aborts have - been executed. This is a no-op if the promise has already been - determined. *) + (** Set the promise to an exception, this will fail all of the connected futures with the + exception, causing their abort function to be executed. The returned future is not + determined until all aborts have been executed. This is a no-op if the promise has already + been determined. *) val set_exn : 'a t -> exn * Printexc.raw_backtrace option -> unit fut end @@ -436,31 +431,28 @@ module Future = struct val app : ('a -> 'b) t -> 'a t -> 'b t val map : ('a -> 'b) -> 'a t -> 'b t - (** Execute a future without waiting for it to complete. The future can be - applied with [bind], [app], or [map] later in order to get the value. *) + (** Execute a future without waiting for it to complete. The future can be applied with [bind], + [app], or [map] later in order to get the value. *) val fork : 'a t -> 'a t t (** Query the state of the Future *) val state : 'a t -> 'a State.t - (** Create a future that will evaluate to the determined state of the - queried future. If the await is aborted, the input future is aborted as - well. *) + (** Create a future that will evaluate to the determined state of the queried future. If the + await is aborted, the input future is aborted as well. *) val await : 'a t -> 'a Set.t t val await_map : ('a Set.t -> 'b) -> 'a t -> 'b t val await_bind : ('a Set.t -> 'b t) -> 'a t -> 'b t - (** Abort a future and all of its undetermined dependencies. The returned - future will not be determined until all aborts of dependencies have been - completed. If a future has been determined already then {!abort} is a - no-op. *) + (** Abort a future and all of its undetermined dependencies. The returned future will not be + determined until all aborts of dependencies have been completed. If a future has been + determined already then {!abort} is a no-op. *) val abort : 'a t -> unit t - (** Cancel a future, this is like an abort except it only spreads to - watchers. The returned future will not be determined until all aborts of - dependencies have been completed. If the future has been determined - already then {!cancel} is a no-op. *) + (** Cancel a future, this is like an abort except it only spreads to watchers. The returned + future will not be determined until all aborts of dependencies have been completed. If the + future has been determined already then {!cancel} is a no-op. *) val cancel : 'a t -> unit t (** Add [dep] future as a dependency to the given future. *) @@ -624,13 +616,12 @@ module Process = struct [@@deriving show, eq] end - (** A Dup represents a relationship between two values. This is purely a - container that expresses that relationship, it does not create anything. + (** A Dup represents a relationship between two values. This is purely a container that expresses + that relationship, it does not create anything. - The relationship a Dup expresses is that one value should replace another - value. The usecase for this is when creating a new process and wanting to - reassign [Native.t]s to other ones. For example, replacing [stdin] in the - spawned process with one from the parent program. *) + The relationship a Dup expresses is that one value should replace another value. The usecase + for this is when creating a new process and wanting to reassign [Native.t]s to other ones. For + example, replacing [stdin] in the spawned process with one from the parent program. *) module Dup : sig type 'a t @@ -654,14 +645,12 @@ module Process = struct [@@deriving show, eq] end -(** The scheduler interface. This only has those types and value that the - implementation must specify. Common values across all schedulers are pulled - out of the module type *) +(** The scheduler interface. This only has those types and value that the implementation must + specify. Common values across all schedulers are pulled out of the module type *) module type S = sig - (** The Native module represents the underlying native platform type of files - and sockets. This does assume that files and sockets have the same - underlying representation. The type, [Native.t] must be available to the - user. *) + (** The Native module represents the underlying native platform type of files and sockets. This + does assume that files and sockets have the same underlying representation. The type, + [Native.t] must be available to the user. *) module Native : sig type t end @@ -675,11 +664,10 @@ module type S = sig module Scheduler : sig type t - val create : unit -> t + val create : ?exec_duration:(float -> unit) -> unit -> t val destroy : t -> unit val run : t -> (unit -> 'a Future.t) -> t * 'a Future_set.t - val run_with_state : (unit -> 'a Future.t) -> 'a Future_set.t - val exec_duration : t -> float array + val run_with_state : ?exec_duration:(float -> unit) -> (unit -> 'a Future.t) -> 'a Future_set.t end (** {2 System operations} *) @@ -688,16 +676,15 @@ module type S = sig (** Sleep for the given number of seconds, fractional sections allowed. *) val sleep : float -> unit Future.t - (** Get the wallclock time. This is updated only once for each loop of the - event loop. Successive calls to [time] provide no guarantee about their - values relative to each other. *) + (** Get the wallclock time. This is updated only once for each loop of the event loop. + Successive calls to [time] provide no guarantee about their values relative to each other. + *) val time : unit -> float Future.t - (** Return a monotonically increasing value. The value is updated only once - for each loop of the event loop. The value itself represents the number - of seconds since a stable arbitrary point in the past. The values are - guaranteed to always be equal to or greater than the previous call and - subtracting them will give the number of seconds elapsed. *) + (** Return a monotonically increasing value. The value is updated only once for each loop of the + event loop. The value itself represents the number of seconds since a stable arbitrary point + in the past. The values are guaranteed to always be equal to or greater than the previous + call and subtracting them will give the number of seconds elapsed. *) val monotonic : unit -> float Future.t end @@ -706,9 +693,8 @@ module type S = sig module File : sig type t - (** Convert the underlying type to the native representation. This is here - as an escape hatch if a user needs to perform some system specific - work. *) + (** Convert the underlying type to the native representation. This is here as an escape hatch if + a user needs to perform some system specific work. *) val to_native : t -> Native.t (** Convert the native representation to the underlying type. *) @@ -718,8 +704,8 @@ module type S = sig val stdout : t val stderr : t - (** Open a file path with the specified flags. The file created will be - automatically closed during {!Process.spawn}. *) + (** Open a file path with the specified flags. The file created will be automatically closed + during {!Process.spawn}. *) val open_file : flags:File.Flag.t list -> string -> (t, [> Errors.open_file ]) result Future.t (** Read bytes from a {!File.t}. @@ -733,12 +719,10 @@ module type S = sig @return the number of bytes read *) val read : t -> buf:bytes -> pos:int -> len:int -> (int, [> Errors.read ]) result Future.t - (** Read bytes from a {!File.t} from a particular offset within the file. - It is undefined if the cursor within the file is modified after this - operation or not. + (** Read bytes from a {!File.t} from a particular offset within the file. It is undefined if the + cursor within the file is modified after this operation or not. - @param offset offset relative to the beginning of the file to start - reading + @param offset offset relative to the beginning of the file to start reading @param buf buffer to read the contents into @@ -750,19 +734,17 @@ module type S = sig val pread : t -> offset:int -> buf:bytes -> pos:int -> len:int -> (int, [> Errors.pread ]) result Future.t - (** Write the list of buffers to the file in the order they are specified. - Not all bytes are guaranteed to be written. + (** Write the list of buffers to the file in the order they are specified. Not all bytes are + guaranteed to be written. @return the number of bytes written *) val write : t -> Write_buf.t list -> (int, [> Errors.write ]) result Future.t - (** Write the list of buffers to the file in the order they are specified - starting from the specified offset. Not all bytes are guaranteed to be - written. It is undefined if the cursor within the file is modified - after this operation or not. + (** Write the list of buffers to the file in the order they are specified starting from the + specified offset. Not all bytes are guaranteed to be written. It is undefined if the cursor + within the file is modified after this operation or not. - @param offset offset relative to the beginning of the file to start - writing + @param offset offset relative to the beginning of the file to start writing @return the number of bytes written *) val pwrite : t -> offset:int -> Write_buf.t list -> (int, [> Errors.pwrite ]) result Future.t @@ -776,15 +758,15 @@ module type S = sig (** Unlink a file path. *) val unlink : string -> (unit, [> Errors.unlink ]) result Future.t - (** Make a directory with the specified permissions. This will fail if the - directory already exists but does not have the correct permissions. *) + (** Make a directory with the specified permissions. This will fail if the directory already + exists but does not have the correct permissions. *) val mkdir : string -> File.Permissions.t -> (unit, [> Errors.mkdir ]) result Future.t (** Deleted a directory, this may fail if the directory is not empty. *) val rmdir : string -> (unit, [> Errors.rmdir ]) result Future.t - (** Read the contents of a directory. The returned list will not contain - any path information, just the name of the entries in the directory. *) + (** Read the contents of a directory. The returned list will not contain any path information, + just the name of the entries in the directory. *) val readdir : string -> (string list, [> Errors.readdir ]) result Future.t (** Return stat information about a file path. *) @@ -793,41 +775,36 @@ module type S = sig (** Return stat information about the {!File.t}. *) val fstat : t -> (File.Stat.t, [> Errors.fstat ]) result Future.t - (** Like {!stat} except in the case where the file path is a symbolic link - it returns information about the link. *) + (** Like {!stat} except in the case where the file path is a symbolic link it returns + information about the link. *) val lstat : string -> (File.Stat.t, [> Errors.stat ]) result Future.t - (** Rename a file path in [src] to [dst]. This may fail if the underlying - OS does not support renaming the particular file, for example across - mount point. *) + (** Rename a file path in [src] to [dst]. This may fail if the underlying OS does not support + renaming the particular file, for example across mount point. *) val rename : src:string -> dst:string -> (unit, [> Errors.rename ]) result Future.t - (** Truncate a file path to the given size (possibly growing it if it is - larger than the file's size *) + (** Truncate a file path to the given size (possibly growing it if it is larger than the file's + size *) val truncate : string -> Int64.t -> (unit, [> Errors.truncate ]) result Future.t - (** Truncate a {!File.t} to the given size (possibly growing it if it is - larger than the file's size *) + (** Truncate a {!File.t} to the given size (possibly growing it if it is larger than the file's + size *) val ftruncate : t -> Int64.t -> (unit, [> Errors.ftruncate ]) result Future.t - (** Modify the permissions of a file path where the permissions are - specified as an [int]. *) + (** Modify the permissions of a file path where the permissions are specified as an [int]. *) val chmod : string -> File.Permissions.t -> (unit, [> Errors.chmod ]) result Future.t - (** Modify the permissions of a {!File.t} where the permissions are - specified as an [int]. *) + (** Modify the permissions of a {!File.t} where the permissions are specified as an [int]. *) val fchmod : t -> File.Permissions.t -> (unit, [> Errors.fchmod ]) result Future.t - (** Make a symbolic link to a file or directory in [src] to the destination - [dst], specified as a path. *) + (** Make a symbolic link to a file or directory in [src] to the destination [dst], specified as + a path. *) val symlink : src:string -> dst:string -> (unit, [> Errors.symlink ]) result Future.t - (** Hard link a file or directory in [src] to the destination [dst], - specified as a path. *) + (** Hard link a file or directory in [src] to the destination [dst], specified as a path. *) val link : src:string -> dst:string -> (unit, [> Errors.link ]) result Future.t - (** Change the owner of a file, specified as a path, to a uid and a gid - encoded as an int *) + (** Change the owner of a file, specified as a path, to a uid and a gid encoded as an int *) val chown : string -> uid:int -> gid:int -> (unit, [> Errors.chown ]) result Future.t (** Change the owner of a {!File.t} to a uid and a gid encoded as an int *) @@ -864,8 +841,7 @@ module type S = sig @param len length of the buffer available for storing data - @return on success, the number of bytes read and the sockaddr of the - sender *) + @return on success, the number of bytes read and the sockaddr of the sender *) val recvfrom : 'a t -> buf:bytes -> @@ -879,8 +855,9 @@ module type S = sig @param sockaddr the address to send to - @return on success, the number of bytes written, this could be less - than the length of the write bufs *) + @return + on success, the number of bytes written, this could be less than the length of the write + bufs *) val sendto : 'a t -> bufs:Write_buf.t list -> @@ -905,16 +882,15 @@ module type S = sig (** {2 TCP sockets} *) module Tcp : sig - (** Convert the underlying type to the native representation. This is here - as an escape hatch if a user needs to perform some system specific - work. *) + (** Convert the underlying type to the native representation. This is here as an escape hatch + if a user needs to perform some system specific work. *) val to_native : tcp t -> Native.t (** Convert the native representation to the underlying type. *) val of_native : Native.t -> tcp t - (** Create a new TCP socket. The socket will be automatically closed - during {!Process.spawn}. *) + (** Create a new TCP socket. The socket will be automatically closed during {!Process.spawn}. + *) val create : domain:Socket.Domain.t -> (tcp t, [> Errors.sock_create ]) result (** Bind to a port and address. *) @@ -939,8 +915,9 @@ module type S = sig @param bufs list of buffers to write, in order - @return on success, the number of bytes written, this could be less - than the length of the write bufs *) + @return + on success, the number of bytes written, this could be less than the length of the write + bufs *) val send : tcp t -> bufs:Write_buf.t list -> (int, [> Errors.send ]) result Future.t (** Set Nagle's algorithm on and off. *) @@ -950,16 +927,15 @@ module type S = sig (** {2 UDP sockets} *) module Udp : sig - (** Convert the underlying type to the native representation. This is here - as an escape hatch if a user needs to perform some system specific - work. *) + (** Convert the underlying type to the native representation. This is here as an escape hatch + if a user needs to perform some system specific work. *) val to_native : udp t -> Native.t (** Convert the native representation to the underlying type. *) val of_native : Native.t -> udp t - (** Create a new UDP socket. The socket will be automatically closed - during {!Process.spawn}. *) + (** Create a new UDP socket. The socket will be automatically closed during {!Process.spawn}. + *) val create : domain:Socket.Domain.t -> (udp t, [> Errors.sock_create ]) result val bind : udp t -> Socket.Sockaddr.t -> (unit, [> Errors.bind ]) result @@ -975,19 +951,17 @@ module type S = sig module Pid : sig type t - (** The native representation for a pid. This type must be public to the - user. *) + (** The native representation for a pid. This type must be public to the user. *) type native val of_native : native -> t val to_native : t -> native end - (** Spawn a process with a list of Dups. The [src] side of the Dup will be - closed once the [dst] has been replaced in the spawned process and the - [src] will be closed in the parent process after forking. In this case - the Dups are {!Native}s because any descriptor type can be inherited by a - spawned process. + (** Spawn a process with a list of Dups. The [src] side of the Dup will be closed once the [dst] + has been replaced in the spawned process and the [src] will be closed in the parent process + after forking. In this case the Dups are {!Native}s because any descriptor type can be + inherited by a spawned process. @return on success, the handle to the running process *) val spawn : Process.t -> Native.t Process.Dup.t list -> (t, [> Errors.spawn ]) result @@ -1000,8 +974,7 @@ module type S = sig (** Get the exit code of a process if it has terminated. - @return the exit code of the process or [None] if it has not - terminated *) + @return the exit code of the process or [None] if it has not terminated *) val exit_code : t -> Process.Exit_code.t option (** Send the specified signal to the process handle. *) @@ -1012,8 +985,8 @@ module type S = sig end module Thread : sig - (** Run a function in a thread. Aborting this future is not guaranteed to - abort stop the thread. *) + (** Run a function in a thread. Aborting this future is not guaranteed to abort stop the thread. + *) val run : (unit -> 'a) -> 'a Future.t end end diff --git a/code/src/abb_scheduler_kqueue/abb_scheduler_kqueue.ml b/code/src/abb_scheduler_kqueue/abb_scheduler_kqueue.ml index f0f6a060a..e51743c0c 100644 --- a/code/src/abb_scheduler_kqueue/abb_scheduler_kqueue.ml +++ b/code/src/abb_scheduler_kqueue/abb_scheduler_kqueue.ml @@ -43,7 +43,7 @@ module El = struct change_read : [ `Add | `Del ] Fd_map.t; change_write : [ `Add | `Del ] Fd_map.t; eventlist : Kqueue.Eventlist.t; - exec_duration : float array; + exec_duration : float -> unit; thread_pool : (Unix.file_descr * Unix.file_descr) Abb_thread_pool.t; } @@ -53,7 +53,7 @@ module El = struct type t = t_ end) - let create () = + let create ?(exec_duration = fun _ -> ()) () = let t = { kq = Kqueue.create (); @@ -66,11 +66,10 @@ module El = struct change_read = Fd_map.empty; change_write = Fd_map.empty; eventlist = Kqueue.Eventlist.create 1024; - exec_duration = Array.create_float 1024; + exec_duration; thread_pool = Abb_thread_pool.create ~capacity:100 ~wait:Unix.pipe; } in - Array.fill t.exec_duration 0 (Array.length t.exec_duration) 0.0; t let destroy t = Abb_thread_pool.destroy t.thread_pool @@ -161,10 +160,6 @@ module El = struct t.change_write changelist - let update_exec_duration exec_duration time = - let spot = Random.int (Array.length exec_duration) in - exec_duration.(spot) <- time - let dispatch fd get set s = let m = get s in match Fd_map.get fd m with @@ -274,7 +269,7 @@ module El = struct let s = dispatch_timers s in let end_time = Mtime_clock.elapsed () in let duration = Mtime.Span.(to_float_ns (abs_diff end_time t.mono_time) /. sec_ns) in - update_exec_duration (Abb_fut.State.state s).exec_duration duration; + (Abb_fut.State.state s).exec_duration duration; s let rec loop s done_fut = @@ -290,7 +285,7 @@ module Future = El.Future module Scheduler = struct type t = El.t Abb_fut.State.t - let create () = Abb_fut.State.create (El.create ()) + let create ?exec_duration () = Abb_fut.State.create (El.create ?exec_duration ()) let destroy t = El.destroy (Abb_fut.State.state t) let run t f = @@ -302,15 +297,11 @@ module Scheduler = struct | (`Det _ | `Aborted | `Exn _) as r -> (t, r) | `Undet -> assert false - let run_with_state f = - let t = create () in + let run_with_state ?exec_duration f = + let t = create ?exec_duration () in let t, r = run t f in destroy t; r - - let exec_duration t = - let el = Abb_fut.State.state t in - el.El.exec_duration end module Sys = struct diff --git a/code/src/abb_scheduler_nyi/abb_scheduler_nyi.ml b/code/src/abb_scheduler_nyi/abb_scheduler_nyi.ml index e95f85667..2974d0ffd 100644 --- a/code/src/abb_scheduler_nyi/abb_scheduler_nyi.ml +++ b/code/src/abb_scheduler_nyi/abb_scheduler_nyi.ml @@ -12,11 +12,10 @@ end) module Scheduler = struct type t = unit - let create () = failwith "nyi" + let create ?exec_duration () = failwith "nyi" let destroy t = failwith "nyi" let run t f = failwith "nyi" - let run_with_state f = failwith "nyi" - let exec_duration t = failwith "nyi" + let run_with_state ?exec_duration f = failwith "nyi" end module Sys = struct diff --git a/code/src/abb_scheduler_select/abb_scheduler_select.ml b/code/src/abb_scheduler_select/abb_scheduler_select.ml index 3311ed785..437b72f08 100644 --- a/code/src/abb_scheduler_select/abb_scheduler_select.ml +++ b/code/src/abb_scheduler_select/abb_scheduler_select.ml @@ -36,7 +36,7 @@ module El = struct next_timer_id : int; curr_time : float; mono_time : Mtime.span; - exec_duration : float array; + exec_duration : float -> unit; thread_pool : (Unix.file_descr * Unix.file_descr) Abb_thread_pool.t; ignore_reads : Unix.file_descr list; ignore_writes : Unix.file_descr list; @@ -48,7 +48,7 @@ module El = struct type t = t_ end) - let create () = + let create ?(exec_duration = fun _ -> ()) () = let t = { reads = Fd_map.empty; @@ -57,21 +57,15 @@ module El = struct next_timer_id = 0; curr_time = Unix.gettimeofday (); mono_time = Mtime_clock.elapsed (); - exec_duration = Array.create_float 1024; + exec_duration; thread_pool = Abb_thread_pool.create ~capacity:100 ~wait:Unix.pipe; ignore_reads = []; ignore_writes = []; } in - Array.fill t.exec_duration 0 (Array.length t.exec_duration) 0.0; t let destroy t = Abb_thread_pool.destroy t.thread_pool - - let update_exec_duration exec_duration time = - let spot = Random.int (Array.length exec_duration) in - exec_duration.(spot) <- time - let read_fds t = Iter.to_list (Fd_map.keys t.reads) let write_fds t = Iter.to_list (Fd_map.keys t.writes) @@ -151,7 +145,7 @@ module El = struct let s = s |> dispatch_reads reads |> dispatch_writes writes |> dispatch_timers in let end_time = Mtime_clock.elapsed () in let duration = Mtime.Span.(to_float_ns (abs_diff end_time t.mono_time) /. sec_ns) in - update_exec_duration (Abb_fut.State.state s).exec_duration duration; + (Abb_fut.State.state s).exec_duration duration; s let rec loop s done_fut = @@ -167,7 +161,7 @@ module Future = El.Future module Scheduler = struct type t = El.t Abb_fut.State.t - let create () = Abb_fut.State.create (El.create ()) + let create ?exec_duration () = Abb_fut.State.create (El.create ?exec_duration ()) let destroy t = El.destroy (Abb_fut.State.state t) let run t f = @@ -179,15 +173,11 @@ module Scheduler = struct | (`Det _ | `Aborted | `Exn _) as r -> (t, r) | `Undet -> assert false - let run_with_state f = - let t = create () in + let run_with_state ?exec_duration f = + let t = create ?exec_duration () in let t, r = run t f in destroy t; r - - let exec_duration t = - let el = Abb_fut.State.state t in - el.El.exec_duration end module Sys = struct @@ -288,8 +278,8 @@ end let safe_call f = try Ok (f ()) with e -> Error (`Unexpected e) -(** The filesystem calls are implemented through a thread call because there is - no guarantee that they will not block, for example on an NFS system. *) +(** The filesystem calls are implemented through a thread call because there is no guarantee that + they will not block, for example on an NFS system. *) module File = struct type t = Unix.file_descr diff --git a/code/src/terrat_ee/terrat_ee.ml b/code/src/terrat_ee/terrat_ee.ml index a8079d232..f0ce37f39 100644 --- a/code/src/terrat_ee/terrat_ee.ml +++ b/code/src/terrat_ee/terrat_ee.ml @@ -4,6 +4,19 @@ end) module Server = Terrat_server.Make (Terratc) +module Metrics = struct + module Exec_duration_histogram = Prmths.Histogram (struct + let spec = Prmths.Histogram_spec.of_list [ 0.01; 0.05; 0.1; 0.3; 0.5; 0.8; 1.0; 2.0 ] + end) + + let namespace = "terrat" + let subsystem = "main" + + let exec_duration = + let help = "Time scheduler spends processing a loop." in + Exec_duration_histogram.v ~help ~namespace ~subsystem "exec_duration" +end + module Cmdline = struct module C = Cmdliner @@ -99,6 +112,10 @@ module Cmdline = struct let default_cmd = C.Term.(ret (const (`Help (`Pager, None)))) end +let exec_duration duration = + Metrics.Exec_duration_histogram.observe Metrics.exec_duration duration; + if duration >= 0.5 then Logs.info (fun m -> m "EXEC_DURATION : %f" duration) + let server () = match Terrat_config.create () with | Ok config -> ( @@ -107,7 +124,7 @@ let server () = Terrat_storage.create config >>= fun storage -> Server.run config storage in print_endline (Terrat_config.show config); - match Abb.Scheduler.run_with_state run with + match Abb.Scheduler.run_with_state ~exec_duration run with | `Det () -> () | `Aborted -> assert false | `Exn (exn, bt_opt) -> diff --git a/code/src/terrat_oss/terrat_oss.ml b/code/src/terrat_oss/terrat_oss.ml index 4b46ca1ae..4e527f5fe 100644 --- a/code/src/terrat_oss/terrat_oss.ml +++ b/code/src/terrat_oss/terrat_oss.ml @@ -4,6 +4,19 @@ end) module Server = Terrat_server.Make (Terratc) +module Metrics = struct + module Exec_duration_histogram = Prmths.Histogram (struct + let spec = Prmths.Histogram_spec.of_list [ 0.01; 0.05; 0.1; 0.3; 0.5; 0.8; 1.0; 2.0 ] + end) + + let namespace = "terrat" + let subsystem = "main" + + let exec_duration = + let help = "Time scheduler spends processing a loop." in + Exec_duration_histogram.v ~help ~namespace ~subsystem "exec_duration" +end + module Cmdline = struct module C = Cmdliner @@ -99,6 +112,10 @@ module Cmdline = struct let default_cmd = C.Term.(ret (const (`Help (`Pager, None)))) end +let exec_duration duration = + Metrics.Exec_duration_histogram.observe Metrics.exec_duration duration; + if duration >= 0.5 then Logs.info (fun m -> m "EXEC_DURATION : %f" duration) + let server () = match Terrat_config.create () with | Ok config -> ( @@ -107,7 +124,7 @@ let server () = Terrat_storage.create config >>= fun storage -> Server.run config storage in print_endline (Terrat_config.show config); - match Abb.Scheduler.run_with_state run with + match Abb.Scheduler.run_with_state ~exec_duration run with | `Det () -> () | `Aborted -> assert false | `Exn (exn, bt_opt) -> From e7044dbfc77afc8e15a91439f74ce1331cb2a24c Mon Sep 17 00:00:00 2001 From: Malcolm Date: Sun, 23 Feb 2025 14:37:19 +0000 Subject: [PATCH 1108/1120] #324 REFACTOR Make recv functions require an event loop tick before operation to reduce starvation --- .../abb_scheduler_kqueue.ml | 154 +++++++-------- .../abb_scheduler_select.ml | 178 ++++++++---------- code/src/pgsql_io/pgsql_io.ml | 4 +- 3 files changed, 141 insertions(+), 195 deletions(-) diff --git a/code/src/abb_scheduler_kqueue/abb_scheduler_kqueue.ml b/code/src/abb_scheduler_kqueue/abb_scheduler_kqueue.ml index e51743c0c..f7effc728 100644 --- a/code/src/abb_scheduler_kqueue/abb_scheduler_kqueue.ml +++ b/code/src/abb_scheduler_kqueue/abb_scheduler_kqueue.ml @@ -1063,53 +1063,39 @@ module Socket = struct | Unix.ADDR_INET (addr, port) -> Abb_intf.Socket.Sockaddr.(Inet { addr; port }) let recvfrom t ~buf ~pos ~len = - try - let n, addr = Unix.recvfrom t ~buf ~pos ~len ~mode:[] in - Future.return (Ok (n, sockaddr_of_unix_sockaddr addr)) - with - | Unix.Unix_error (Unix.EAGAIN, _, _) | Unix.Unix_error (Unix.EWOULDBLOCK, _, _) -> - Future.with_state (fun s -> - let el = Abb_fut.State.state s in - let p = - Future.Promise.create - ~abort:(fun () -> - Future.with_state (fun s -> - let el = Abb_fut.State.state s in - let t = El.remove_read t el in - let s = Abb_fut.State.set_state t s in - (s, Future.return ()))) - () - in - let handler s = - Future.run_with_state - (Future.Promise.set - p - (try - let n, addr = Unix.recvfrom t ~buf ~pos ~len ~mode:[] in - Ok (n, sockaddr_of_unix_sockaddr addr) - with - | Unix.Unix_error (err, _, _) as exn -> - let open Unix in - Error - (match err with - | EBADF -> `E_bad_file - | ECONNRESET -> `E_connection_reset - | _ -> `Unexpected exn) - | exn -> Error (`Unexpected exn))) - s - in - let el = El.add_read t handler el in - let s = Abb_fut.State.set_state el s in - (s, Future.Promise.future p)) - | Unix.Unix_error (err, _, _) as exn -> - let open Unix in - Future.return - (Error - (match err with - | EBADF -> `E_bad_file - | ECONNRESET -> `E_connection_reset - | _ -> `Unexpected exn)) - | exn -> Future.return (Error (`Unexpected exn)) + Future.with_state (fun s -> + let el = Abb_fut.State.state s in + let p = + Future.Promise.create + ~abort:(fun () -> + Future.with_state (fun s -> + let el = Abb_fut.State.state s in + let t = El.remove_read t el in + let s = Abb_fut.State.set_state t s in + (s, Future.return ()))) + () + in + let handler s = + Future.run_with_state + (Future.Promise.set + p + (try + let n, addr = Unix.recvfrom t ~buf ~pos ~len ~mode:[] in + Ok (n, sockaddr_of_unix_sockaddr addr) + with + | Unix.Unix_error (err, _, _) as exn -> + let open Unix in + Error + (match err with + | EBADF -> `E_bad_file + | ECONNRESET -> `E_connection_reset + | _ -> `Unexpected exn) + | exn -> Error (`Unexpected exn))) + s + in + let el = El.add_read t handler el in + let s = Abb_fut.State.set_state el s in + (s, Future.Promise.future p)) let sendto t ~bufs sockaddr = let p = @@ -1401,49 +1387,37 @@ module Socket = struct | exn -> Future.return (Error (`Unexpected exn)) let recv t ~buf ~pos ~len = - try Future.return (Ok (Unix.recv t ~buf ~pos ~len ~mode:[])) with - | Unix.Unix_error (Unix.EAGAIN, _, _) | Unix.Unix_error (Unix.EWOULDBLOCK, _, _) -> - Future.with_state (fun s -> - let el = Abb_fut.State.state s in - let p = - Future.Promise.create - ~abort:(fun () -> - Future.with_state (fun s -> - let el = Abb_fut.State.state s in - let el = El.remove_read t el in - let s = Abb_fut.State.set_state el s in - (s, Future.return ()))) - () - in - let handler s = - Future.run_with_state - (Future.Promise.set - p - (try Ok (Unix.recv t ~buf ~pos ~len ~mode:[]) with - | Unix.Unix_error (err, _, _) as exn -> - let open Unix in - Error - (match err with - | ENOTSOCK | EBADF -> `E_bad_file - | ECONNRESET -> `E_connection_reset - | ENOTCONN -> `E_not_connected - | _ -> `Unexpected exn) - | exn -> Error (`Unexpected exn))) - s - in - let el = El.add_read t handler el in - let s = Abb_fut.State.set_state el s in - (s, Future.Promise.future p)) - | Unix.Unix_error (err, _, _) as exn -> - let open Unix in - Future.return - (Error - (match err with - | ENOTSOCK | EBADF -> `E_bad_file - | ECONNRESET -> `E_connection_reset - | ENOTCONN -> `E_not_connected - | _ -> `Unexpected exn)) - | exn -> Future.return (Error (`Unexpected exn)) + Future.with_state (fun s -> + let el = Abb_fut.State.state s in + let p = + Future.Promise.create + ~abort:(fun () -> + Future.with_state (fun s -> + let el = Abb_fut.State.state s in + let el = El.remove_read t el in + let s = Abb_fut.State.set_state el s in + (s, Future.return ()))) + () + in + let handler s = + Future.run_with_state + (Future.Promise.set + p + (try Ok (Unix.recv t ~buf ~pos ~len ~mode:[]) with + | Unix.Unix_error (err, _, _) as exn -> + let open Unix in + Error + (match err with + | ENOTSOCK | EBADF -> `E_bad_file + | ECONNRESET -> `E_connection_reset + | ENOTCONN -> `E_not_connected + | _ -> `Unexpected exn) + | exn -> Error (`Unexpected exn))) + s + in + let el = El.add_read t handler el in + let s = Abb_fut.State.set_state el s in + (s, Future.Promise.future p)) let send t ~bufs = let p = diff --git a/code/src/abb_scheduler_select/abb_scheduler_select.ml b/code/src/abb_scheduler_select/abb_scheduler_select.ml index 437b72f08..036a29868 100644 --- a/code/src/abb_scheduler_select/abb_scheduler_select.ml +++ b/code/src/abb_scheduler_select/abb_scheduler_select.ml @@ -850,59 +850,45 @@ module Socket = struct | Unix.ADDR_INET (addr, port) -> Abb_intf.Socket.Sockaddr.(Inet { addr; port }) let recvfrom t ~buf ~pos ~len = - try - let n, addr = Unix.recvfrom t ~buf ~pos ~len ~mode:[] in - Future.return (Ok (n, sockaddr_of_unix_sockaddr addr)) - with - | Unix.Unix_error (Unix.EAGAIN, _, _) | Unix.Unix_error (Unix.EWOULDBLOCK, _, _) -> - let p = - Future.Promise.create - ~abort:(fun () -> - Future.with_state (fun s -> - let el = Abb_fut.State.state s in - let el = - { - el with - El.reads = Fd_map.remove t el.El.reads; - ignore_reads = t :: el.El.ignore_reads; - } - in - let s = Abb_fut.State.set_state el s in - (s, Future.return ()))) - () - in - let handler s = - Future.run_with_state - (Future.Promise.set - p - (try - let n, addr = Unix.recvfrom t ~buf ~pos ~len ~mode:[] in - Ok (n, sockaddr_of_unix_sockaddr addr) - with - | Unix.Unix_error (err, _, _) as exn -> - let open Unix in - Error - (match err with - | EBADF -> `E_bad_file - | ECONNRESET -> `E_connection_reset - | _ -> `Unexpected exn) - | exn -> Error (`Unexpected exn))) - s - in - Future.with_state (fun s -> - let el = Abb_fut.State.state s in - let el = { el with El.reads = Fd_map.add t handler el.El.reads } in - let s = Abb_fut.State.set_state el s in - (s, Future.Promise.future p)) - | Unix.Unix_error (err, _, _) as exn -> - let open Unix in - Future.return - (Error - (match err with - | EBADF -> `E_bad_file - | ECONNRESET -> `E_connection_reset - | _ -> `Unexpected exn)) - | exn -> Future.return (Error (`Unexpected exn)) + let p = + Future.Promise.create + ~abort:(fun () -> + Future.with_state (fun s -> + let el = Abb_fut.State.state s in + let el = + { + el with + El.reads = Fd_map.remove t el.El.reads; + ignore_reads = t :: el.El.ignore_reads; + } + in + let s = Abb_fut.State.set_state el s in + (s, Future.return ()))) + () + in + let handler s = + Future.run_with_state + (Future.Promise.set + p + (try + let n, addr = Unix.recvfrom t ~buf ~pos ~len ~mode:[] in + Ok (n, sockaddr_of_unix_sockaddr addr) + with + | Unix.Unix_error (err, _, _) as exn -> + let open Unix in + Error + (match err with + | EBADF -> `E_bad_file + | ECONNRESET -> `E_connection_reset + | _ -> `Unexpected exn) + | exn -> Error (`Unexpected exn))) + s + in + Future.with_state (fun s -> + let el = Abb_fut.State.state s in + let el = { el with El.reads = Fd_map.add t handler el.El.reads } in + let s = Abb_fut.State.set_state el s in + (s, Future.Promise.future p)) let sendto t ~bufs sockaddr = let p = @@ -1196,55 +1182,43 @@ module Socket = struct | exn -> Future.return (Error (`Unexpected exn)) let recv t ~buf ~pos ~len = - try Future.return (Ok (Unix.recv t ~buf ~pos ~len ~mode:[])) with - | Unix.Unix_error (Unix.EAGAIN, _, _) | Unix.Unix_error (Unix.EWOULDBLOCK, _, _) -> - let p = - Future.Promise.create - ~abort:(fun () -> - Future.with_state (fun s -> - let el = Abb_fut.State.state s in - let el = - { - el with - El.reads = Fd_map.remove t el.El.reads; - ignore_reads = t :: el.El.ignore_reads; - } - in - let s = Abb_fut.State.set_state el s in - (s, Future.return ()))) - () - in - let handler s = - Future.run_with_state - (Future.Promise.set - p - (try Ok (Unix.recv t ~buf ~pos ~len ~mode:[]) with - | Unix.Unix_error (err, _, _) as exn -> - let open Unix in - Error - (match err with - | ENOTSOCK | EBADF -> `E_bad_file - | ECONNRESET -> `E_connection_reset - | ENOTCONN -> `E_not_connected - | _ -> `Unexpected exn) - | exn -> Error (`Unexpected exn))) - s - in - Future.with_state (fun s -> - let el = Abb_fut.State.state s in - let el = { el with El.reads = Fd_map.add t handler el.El.reads } in - let s = Abb_fut.State.set_state el s in - (s, Future.Promise.future p)) - | Unix.Unix_error (err, _, _) as exn -> - let open Unix in - Future.return - (Error - (match err with - | ENOTSOCK | EBADF -> `E_bad_file - | ECONNRESET -> `E_connection_reset - | ENOTCONN -> `E_not_connected - | _ -> `Unexpected exn)) - | exn -> Future.return (Error (`Unexpected exn)) + let p = + Future.Promise.create + ~abort:(fun () -> + Future.with_state (fun s -> + let el = Abb_fut.State.state s in + let el = + { + el with + El.reads = Fd_map.remove t el.El.reads; + ignore_reads = t :: el.El.ignore_reads; + } + in + let s = Abb_fut.State.set_state el s in + (s, Future.return ()))) + () + in + let handler s = + Future.run_with_state + (Future.Promise.set + p + (try Ok (Unix.recv t ~buf ~pos ~len ~mode:[]) with + | Unix.Unix_error (err, _, _) as exn -> + let open Unix in + Error + (match err with + | ENOTSOCK | EBADF -> `E_bad_file + | ECONNRESET -> `E_connection_reset + | ENOTCONN -> `E_not_connected + | _ -> `Unexpected exn) + | exn -> Error (`Unexpected exn))) + s + in + Future.with_state (fun s -> + let el = Abb_fut.State.state s in + let el = { el with El.reads = Fd_map.add t handler el.El.reads } in + let s = Abb_fut.State.set_state el s in + (s, Future.Promise.future p)) let send t ~bufs = let p = diff --git a/code/src/pgsql_io/pgsql_io.ml b/code/src/pgsql_io/pgsql_io.ml index f140b593c..514448907 100644 --- a/code/src/pgsql_io/pgsql_io.ml +++ b/code/src/pgsql_io/pgsql_io.ml @@ -115,9 +115,7 @@ module Io = struct ~while_:(function | Ok 0 | Error _ -> false | Ok _ -> !needed_bytes > 0) - ~betwixt:(fun _ -> - (* Force a scheduler tick so we don't starve the system *) - Abb.Sys.sleep 0.0) + ~betwixt:(fun _ -> Abbs_future_combinators.unit) >>= function | Ok 0 | Error `E_io | Error (`Unexpected _) -> conn.connected <- false; From f29340b3e2828fc1c36912dba1fde0e253fa8f28 Mon Sep 17 00:00:00 2001 From: Malcolm Date: Sun, 23 Feb 2025 19:47:41 +0000 Subject: [PATCH 1109/1120] #324 REFACTOR Make send and sendto not optimisticly perform operation --- .../abb_scheduler_kqueue.ml | 141 +++++++++--------- 1 file changed, 68 insertions(+), 73 deletions(-) diff --git a/code/src/abb_scheduler_kqueue/abb_scheduler_kqueue.ml b/code/src/abb_scheduler_kqueue/abb_scheduler_kqueue.ml index f7effc728..025b988aa 100644 --- a/code/src/abb_scheduler_kqueue/abb_scheduler_kqueue.ml +++ b/code/src/abb_scheduler_kqueue/abb_scheduler_kqueue.ml @@ -1109,47 +1109,43 @@ module Socket = struct () in let addr = unix_sockaddr_of_sockaddr sockaddr in - let rec send' total = function + let rec send' ~total ~pos = function | [] -> Future.Promise.set p (Ok total) - | wb :: bufs -> ( - try - let n = - Unix.sendto - t - ~buf:wb.Abb_intf.Write_buf.buf - ~pos:wb.Abb_intf.Write_buf.pos - ~len:wb.Abb_intf.Write_buf.len - ~mode:[] - ~addr - in - (* FIXME Make this handle incomplete sends *) - assert (n = wb.Abb_intf.Write_buf.len); - send' (n + total) bufs - with - | Unix.Unix_error (Unix.EAGAIN, _, _) | Unix.Unix_error (Unix.EWOULDBLOCK, _, _) -> - Future.with_state (fun s -> - let el = Abb_fut.State.state s in - let handler s = Future.run_with_state (send' total (wb :: bufs)) s in - let el = El.add_write t handler el in - let s = Abb_fut.State.set_state el s in - (s, Future.return ())) - | Unix.Unix_error (err, _, _) as exn -> - let open Unix in - Future.Promise.set - p - (Error - (match err with - | EBADF -> `E_bad_file - | EACCES -> `E_access - | ENOBUFS -> `E_no_buffers - | EHOSTUNREACH -> `E_host_unreachable - | EHOSTDOWN -> `E_host_down - | ECONNREFUSED -> `E_connection_refused - | _ -> `Unexpected exn)) - | exn -> Future.Promise.set p (Error (`Unexpected exn))) + | wb :: bufs as all_bufs -> + Future.with_state (fun s -> + let el = Abb_fut.State.state s in + let handler s = + try + let len = wb.Abb_intf.Write_buf.len - pos in + let n = Unix.sendto t ~buf:wb.Abb_intf.Write_buf.buf ~pos ~len ~mode:[] ~addr in + let total = total + n in + match n with + | n when n = len -> Future.run_with_state (send' ~total ~pos:0 bufs) s + | n -> Future.run_with_state (send' ~total ~pos:(pos + n) all_bufs) s + with + | Unix.Unix_error (err, _, _) as exn -> + let open Unix in + Future.run_with_state + (Future.Promise.set + p + (Error + (match err with + | EBADF -> `E_bad_file + | EACCES -> `E_access + | ENOBUFS -> `E_no_buffers + | EHOSTUNREACH -> `E_host_unreachable + | EHOSTDOWN -> `E_host_down + | ECONNREFUSED -> `E_connection_refused + | _ -> `Unexpected exn))) + s + | exn -> Future.run_with_state (Future.Promise.set p (Error (`Unexpected exn))) s + in + let el = El.add_write t handler el in + let s = Abb_fut.State.set_state el s in + (s, Future.return ())) in let open Future.Infix_monad in - send' 0 bufs >>= fun () -> Future.Promise.future p + send' ~total:0 ~pos:0 bufs >>= fun () -> Future.Promise.future p let close t = (* This scheduler is used in FreeBSD and Linux, with linux support via @@ -1430,44 +1426,43 @@ module Socket = struct (s, Future.return ()))) () in - let rec send' total = function + let rec send' ~total ~pos = function | [] -> Future.Promise.set p (Ok total) - | wb :: bufs -> ( - try - let n = - Unix.send - t - ~buf:wb.Abb_intf.Write_buf.buf - ~pos:wb.Abb_intf.Write_buf.pos - ~len:wb.Abb_intf.Write_buf.len - ~mode:[] - in - send' (total + n) bufs - with - | Unix.Unix_error (Unix.EAGAIN, _, _) | Unix.Unix_error (Unix.EWOULDBLOCK, _, _) -> - Future.with_state (fun s -> - let el = Abb_fut.State.state s in - let handler s = Future.run_with_state (send' total (wb :: bufs)) s in - let el = El.add_write t handler el in - let s = Abb_fut.State.set_state el s in - (s, Future.return ())) - | Unix.Unix_error (err, _, _) as exn -> - let open Unix in - Future.Promise.set - p - (Error - (match err with - | ENOTSOCK | EBADF -> `E_bad_file - | EACCES -> `E_access - | ENOBUFS -> `E_no_buffers - | EHOSTUNREACH -> `E_host_unreachable - | EHOSTDOWN -> `E_host_down - | EPIPE -> `E_pipe - | _ -> `Unexpected exn)) - | exn -> Future.Promise.set p (Error (`Unexpected exn))) + | wb :: bufs as all_bufs -> + Future.with_state (fun s -> + let el = Abb_fut.State.state s in + let handler s = + try + let len = wb.Abb_intf.Write_buf.len - pos in + let n = Unix.send t ~buf:wb.Abb_intf.Write_buf.buf ~pos ~len ~mode:[] in + let total = total + n in + match n with + | n when n = len -> Future.run_with_state (send' ~total ~pos:0 bufs) s + | n -> Future.run_with_state (send' ~total ~pos:(pos + n) all_bufs) s + with + | Unix.Unix_error (err, _, _) as exn -> + let open Unix in + Future.run_with_state + (Future.Promise.set + p + (Error + (match err with + | ENOTSOCK | EBADF -> `E_bad_file + | EACCES -> `E_access + | ENOBUFS -> `E_no_buffers + | EHOSTUNREACH -> `E_host_unreachable + | EHOSTDOWN -> `E_host_down + | EPIPE -> `E_pipe + | _ -> `Unexpected exn))) + s + | exn -> Future.run_with_state (Future.Promise.set p (Error (`Unexpected exn))) s + in + let el = El.add_write t handler el in + let s = Abb_fut.State.set_state el s in + (s, Future.return ())) in let open Future.Infix_monad in - send' 0 bufs >>= fun () -> Future.Promise.future p + send' ~total:0 ~pos:0 bufs >>= fun () -> Future.Promise.future p let nodelay t enabled = try From fa5778cf7ef95e7c3927e7f8cc708c618f721e01 Mon Sep 17 00:00:00 2001 From: Malcolm Date: Sun, 23 Feb 2025 19:48:04 +0000 Subject: [PATCH 1110/1120] #324 REFACTOR Push decoding of large byte buffers to a thread --- code/src/pgsql_codec/pgsql_codec.ml | 1 + code/src/pgsql_codec/pgsql_codec.mli | 3 ++ code/src/pgsql_io/pgsql_io.ml | 70 +++++++++++++++++++++------- code/src/pgsql_io/pgsql_io.mli | 3 ++ 4 files changed, 60 insertions(+), 17 deletions(-) diff --git a/code/src/pgsql_codec/pgsql_codec.ml b/code/src/pgsql_codec/pgsql_codec.ml index 8efd7dccf..1431ed356 100644 --- a/code/src/pgsql_codec/pgsql_codec.ml +++ b/code/src/pgsql_codec/pgsql_codec.ml @@ -440,6 +440,7 @@ module Decode = struct let frontend_msg t ~pos ~len buf = failwith "nyi" let needed_bytes t = if t.needed_bytes < 0 then None else Some t.needed_bytes + let buffer_length t = Buffer.length t.buf end module Encode = struct diff --git a/code/src/pgsql_codec/pgsql_codec.mli b/code/src/pgsql_codec/pgsql_codec.mli index 0811ea54d..756fa3157 100644 --- a/code/src/pgsql_codec/pgsql_codec.mli +++ b/code/src/pgsql_codec/pgsql_codec.mli @@ -155,6 +155,9 @@ module Decode : sig (** How many bytes the decode needs to continue, if it knows it. *) val needed_bytes : t -> int option + (** How many bytes are in the buffer that has been accumulated. *) + val buffer_length : t -> int + (** Printers *) val pp_err : Format.formatter -> err -> unit diff --git a/code/src/pgsql_io/pgsql_io.ml b/code/src/pgsql_io/pgsql_io.ml index 514448907..2c604726b 100644 --- a/code/src/pgsql_io/pgsql_io.ml +++ b/code/src/pgsql_io/pgsql_io.ml @@ -1,4 +1,5 @@ let buf_size = 1024 * 8 +let buf_size_threshold = 1024 * 8 exception Nested_tx_not_supported @@ -22,6 +23,7 @@ type t = { mutable expected_frames : (Pgsql_codec.Frame.Backend.t -> bool) list; mutable in_tx : bool; mutable busy : bool; + buf_size_threshold : int; } let add_expected_frame t frame = t.expected_frames <- frame :: t.expected_frames @@ -71,9 +73,16 @@ module Io = struct Error `Disconnected) else Abb.Future.return (Error `Disconnected) + let backend_msg conn len buf = + if Pgsql_codec.Decode.buffer_length conn.decoder > conn.buf_size_threshold then + Abb.Thread.run (fun () -> Pgsql_codec.Decode.backend_msg conn.decoder ~pos:0 ~len buf) + else Abb.Future.return (Pgsql_codec.Decode.backend_msg conn.decoder ~pos:0 ~len buf) + let rec wait_for_frames conn = let open Abb.Future.Infix_monad in - match Pgsql_codec.Decode.backend_msg conn.decoder ~pos:0 ~len:0 conn.buf with + backend_msg conn 0 conn.buf + >>= fun ret -> + match ret with | Ok [] -> ( Abbs_io_buffered.read conn.r ~buf:conn.buf ~pos:0 ~len:(Bytes.length conn.buf) >>= function @@ -82,9 +91,7 @@ module Io = struct Abb.Future.return (Error `Disconnected) | Ok n -> (* Printf.printf "Rx = %S\n%!" (Bytes.to_string (Bytes.sub conn.buf 0 n)); *) - wait_for_frames' - conn - (Pgsql_codec.Decode.backend_msg conn.decoder ~pos:0 ~len:n conn.buf)) + backend_msg conn n conn.buf >>= fun ret -> wait_for_frames' conn ret) | r -> wait_for_frames' conn r and wait_for_frames' conn = function @@ -122,9 +129,9 @@ module Io = struct Abb.Future.return (Error `Disconnected) | Ok _ -> ( let buf = Buffer.to_bytes b in - match - Pgsql_codec.Decode.backend_msg conn.decoder ~pos:0 ~len:(Bytes.length buf) buf - with + backend_msg conn (Bytes.length buf) buf + >>= fun ret -> + match ret with | Ok [] -> wait_for_frames conn | Ok _ as r -> Abb.Future.return r | Error err -> Abb.Future.return (Error (`Parse_error err)))) @@ -850,17 +857,26 @@ type create_err = ] [@@deriving show] -let rec create_sm ?tls_config ?passwd ~notice_response ~host ~port ~user database = +let rec create_sm + ?tls_config + ?passwd + ~notice_response + ~buf_size_threshold + ~host + ~port + ~user + database = let open Abbs_future_combinators.Infix_result_monad in Abbs_happy_eyeballs.connect host [ port ] >>= fun (_, tcp) -> match tls_config with | None -> let r, w = Abbs_io_buffered.Of.of_tcp_socket ~size:buf_size tcp in - create_sm_perform_login r w ?passwd ~notice_response ~user database + create_sm_perform_login r w ?passwd ~notice_response ~buf_size_threshold ~user database | Some (`Require tls_config) -> create_sm_ssl_conn ?passwd + ~buf_size_threshold ~required:true ~notice_response ~host @@ -872,6 +888,7 @@ let rec create_sm ?tls_config ?passwd ~notice_response ~host ~port ~user databas | Some (`Prefer tls_config) -> create_sm_ssl_conn ?passwd + ~buf_size_threshold ~required:false ~notice_response ~host @@ -881,8 +898,17 @@ let rec create_sm ?tls_config ?passwd ~notice_response ~host ~port ~user databas tcp database -and create_sm_ssl_conn ?passwd ~required ~notice_response ~host ~port ~user tls_config tcp database - = +and create_sm_ssl_conn + ?passwd + ~buf_size_threshold + ~required + ~notice_response + ~host + ~port + ~user + tls_config + tcp + database = let open Abbs_future_combinators.Infix_result_monad in let buf = Buffer.create 5 in let bytes = Io.encode_frame buf Pgsql_codec.Frame.Frontend.SSLRequest in @@ -896,15 +922,16 @@ and create_sm_ssl_conn ?passwd ~required ~notice_response ~host ~port ~user tls_ >>= function | n when n = 1 && Bytes.get bytes 0 = 'S' -> ( match Abbs_tls.client_tcp ~size:buf_size tcp tls_config host with - | Ok (r, w) -> create_sm_perform_login r w ?passwd ~notice_response ~user database + | Ok (r, w) -> + create_sm_perform_login r w ?passwd ~notice_response ~buf_size_threshold ~user database | Error (#Abb_tls.err as err) -> Abb.Future.return (Error (`Tls_negotiate_err err))) | n when n = 1 && Bytes.get bytes 0 = 'N' && not required -> - create_sm_perform_login r w ?passwd ~notice_response ~user database + create_sm_perform_login r w ?passwd ~notice_response ~buf_size_threshold ~user database | n when n = 1 && Bytes.get bytes 0 = 'N' && required -> Abb.Future.return (Error `Tls_required_but_denied_err) | n -> Abb.Future.return (Error (`Tls_unexpected_response (n, Bytes.sub_string bytes 0 n))) -and create_sm_perform_login r w ?passwd ~notice_response ~user database = +and create_sm_perform_login r w ?passwd ~notice_response ~buf_size_threshold ~user database = let open Abbs_future_combinators.Infix_result_monad in let decoder = Pgsql_codec.Decode.create () in let buf = Bytes.create buf_size in @@ -923,6 +950,7 @@ and create_sm_perform_login r w ?passwd ~notice_response ~user database = expected_frames = []; in_tx = false; busy = false; + buf_size_threshold; } in let msgs = [ ("user", user); ("database", database) ] in @@ -967,10 +995,18 @@ and create_sm_process_login_frames ?passwd ~user t = | AuthenticationSSPI :: _ -> Abb.Future.return (Error `Unsupported_auth_sspi_err) | fs -> Abb.Future.return (Error (`Unmatching_frame fs)) -let create ?tls_config ?passwd ?(port = 5432) ?(notice_response = fun _ -> ()) ~host ~user database - = +let create + ?tls_config + ?passwd + ?(port = 5432) + ?(notice_response = fun _ -> ()) + ?(buf_size_threshold = buf_size_threshold) + ~host + ~user + database = let open Abb.Future.Infix_monad in - create_sm ?tls_config ?passwd ~notice_response ~host ~port ~user database + assert (buf_size_threshold > 0); + create_sm ?tls_config ?passwd ~notice_response ~buf_size_threshold ~host ~port ~user database >>= function | Ok _ as r -> Abb.Future.return r | Error `Disconnected | Error #Abb_happy_eyeballs.connect_err | Error `E_io | Error `E_no_space -> diff --git a/code/src/pgsql_io/pgsql_io.mli b/code/src/pgsql_io/pgsql_io.mli index ab87441b7..0fae0f087 100644 --- a/code/src/pgsql_io/pgsql_io.mli +++ b/code/src/pgsql_io/pgsql_io.mli @@ -207,11 +207,14 @@ type create_err = ] [@@deriving show] +(** Create a connection. [buf_size_threshold] is a threshold for how large the protocol debugging + buffer can get before decoding is pushed to another thread. *) val create : ?tls_config:[ `Require of Otls.Tls_config.t | `Prefer of Otls.Tls_config.t ] -> ?passwd:string -> ?port:int -> ?notice_response:((char * string) list -> unit) -> + ?buf_size_threshold:int -> host:string -> user:string -> string -> From 3984903b0f9c9d4923c00333b31225e3fb6e938e Mon Sep 17 00:00:00 2001 From: Malcolm Date: Mon, 24 Feb 2025 14:46:51 +0000 Subject: [PATCH 1111/1120] #324 REFACTOR Switch to domain pool instead of thread pool --- code/pds.conf | 8 ++- code/src/abb_domain_pool/abb_domain_pool.ml | 68 +++++++++++++++++++ code/src/abb_domain_pool/abb_domain_pool.mli | 31 +++++++++ code/src/abb_intf/abb_intf.ml | 30 ++------ code/src/abb_process/abb_process.ml | 17 +++-- .../abb_scheduler_kqueue.ml | 55 ++++++++------- .../abb_scheduler_select.ml | 44 ++++++------ code/src/abb_test/abb_test_process.ml | 15 ++-- code/src/jsonu/jsonu.ml | 4 +- 9 files changed, 185 insertions(+), 87 deletions(-) create mode 100644 code/src/abb_domain_pool/abb_domain_pool.ml create mode 100644 code/src/abb_domain_pool/abb_domain_pool.mli diff --git a/code/pds.conf b/code/pds.conf index a17438e12..b9478f7e9 100644 --- a/code/pds.conf +++ b/code/pds.conf @@ -118,6 +118,10 @@ deps = [ "mtime.clock", ] +[src.abb_domain_pool] +install = false +deps = ["logs"] + [src.abb_flow] install = true deps = ["abb_future_combinators", "abb_intf", "containers", "containers.bencode", "yojson"] @@ -180,9 +184,9 @@ build = false [src.abb_scheduler_kqueue.selector.freebsd] build = true deps = [ + "abb_domain_pool", "abb_fut", "abb_intf", - "abb_thread_pool", "containers", "iter", "kqueue", @@ -196,9 +200,9 @@ deps = [ [src.abb_scheduler_kqueue.selector.linux] build = true deps = [ + "abb_domain_pool", "abb_fut", "abb_intf", - "abb_thread_pool", "containers", "iter", "kqueue", diff --git a/code/src/abb_domain_pool/abb_domain_pool.ml b/code/src/abb_domain_pool/abb_domain_pool.ml new file mode 100644 index 000000000..1d7dc090b --- /dev/null +++ b/code/src/abb_domain_pool/abb_domain_pool.ml @@ -0,0 +1,68 @@ +let src = Logs.Src.create "abb_domain_pool" + +module Logs = (val Logs.src_log src : Logs.LOG) + +type 'a f = unit -> 'a +type ('a, 'b) trigger = 'a -> ('b, exn * Printexc.raw_backtrace option) result -> unit +type work = Work : ('b * 'a f * ('b, 'a) trigger) -> work + +type 'a t = { + wait : unit -> 'a; + work_queue : work Queue.t; + mutex : Mutex.t; + cond : Condition.t; + shutdown : bool ref; +} + +let rec thread (work_queue, mutex, cond, shutdown) = + Mutex.lock mutex; + while Queue.is_empty work_queue && not !shutdown do + Condition.wait cond mutex + done; + if not !shutdown then ( + let (Work (wait_token, f, trigger)) = Queue.pop work_queue in + Mutex.unlock mutex; + (try + let v = f () in + trigger wait_token (Ok v) + with exn -> trigger wait_token (Error (exn, Some (Printexc.get_raw_backtrace ())))); + thread (work_queue, mutex, cond, shutdown)) + else Mutex.unlock mutex + +let rec create_threads work_queue mutex cond shutdown = function + | 0 -> () + | n -> + ignore (Domain.spawn (fun () -> thread (work_queue, mutex, cond, shutdown))); + create_threads work_queue mutex cond shutdown (n - 1) + +let create ~capacity ~wait = + if capacity <= 0 then + raise (Invalid_argument (Printf.sprintf "capacity is %d, must be greater than 0" capacity)); + + let t = + { + wait; + work_queue = Queue.create (); + mutex = Mutex.create (); + cond = Condition.create (); + shutdown = ref false; + } + in + Logs.debug (fun m -> m "start : capacity=%d" capacity); + create_threads t.work_queue t.mutex t.cond t.shutdown capacity; + t + +let enqueue t ~f ~trigger = + let wait_token = t.wait () in + let work = Work (wait_token, f, trigger) in + Mutex.lock t.mutex; + Queue.push work t.work_queue; + Condition.broadcast t.cond; + Mutex.unlock t.mutex; + wait_token + +let destroy t = + Mutex.lock t.mutex; + t.shutdown := true; + Condition.broadcast t.cond; + Mutex.unlock t.mutex diff --git a/code/src/abb_domain_pool/abb_domain_pool.mli b/code/src/abb_domain_pool/abb_domain_pool.mli new file mode 100644 index 000000000..30390b67b --- /dev/null +++ b/code/src/abb_domain_pool/abb_domain_pool.mli @@ -0,0 +1,31 @@ +(** A simple thread pool implementation. *) + +type 'a t + +(** Create a thread pool with the defined capacity. [capacity] number of + threads will be started and maintained at all times. + + @param wait a function which generates a value to wait on. This is executed + in the main thread. *) +val create : capacity:int -> wait:(unit -> 'a) -> 'a t + +(** Add a new piece of work to the queue. Threads will consume the work + as they become available. + + @param f the work that will be executed in the thread. + + @param trigger the function to call with the result and a wait token to + signal the work is complete. If the function threw an exception, trigger is + called with that. + + @returns the value created by the wait so the caller can setup hooks for the + work completing. *) +val enqueue : + 'a t -> + f:(unit -> 'b) -> + trigger:('a -> ('b, exn * Printexc.raw_backtrace option) result -> unit) -> + 'a + +(** Destroy the thread pool. Destroy does not wait for any work executing in + the thread pool to be finished before returning. *) +val destroy : 'a t -> unit diff --git a/code/src/abb_intf/abb_intf.ml b/code/src/abb_intf/abb_intf.ml index af74db6c3..4f4d0f1d4 100644 --- a/code/src/abb_intf/abb_intf.ml +++ b/code/src/abb_intf/abb_intf.ml @@ -616,31 +616,10 @@ module Process = struct [@@deriving show, eq] end - (** A Dup represents a relationship between two values. This is purely a container that expresses - that relationship, it does not create anything. - - The relationship a Dup expresses is that one value should replace another value. The usecase - for this is when creating a new process and wanting to reassign [Native.t]s to other ones. For - example, replacing [stdin] in the spawned process with one from the parent program. *) - module Dup : sig - type 'a t - - val create : src:'a -> dst:'a -> 'a t - val src : 'a t -> 'a - val dst : 'a t -> 'a - end = struct - type 'a t = 'a * 'a - - let create ~src ~dst = (src, dst) - let src = fst - let dst = snd - end - type t = { exec_name : string; args : string list; env : (string * string) list option; - cwd : string option; } [@@deriving show, eq] end @@ -673,7 +652,7 @@ module type S = sig (** {2 System operations} *) module Sys : sig - (** Sleep for the given number of seconds, fractional sections allowed. *) + (** Sleep for the given number of seconds, fractional seconds allowed. *) val sleep : float -> unit Future.t (** Get the wallclock time. This is updated only once for each loop of the event loop. @@ -964,7 +943,12 @@ module type S = sig inherited by a spawned process. @return on success, the handle to the running process *) - val spawn : Process.t -> Native.t Process.Dup.t list -> (t, [> Errors.spawn ]) result + val spawn : + stdin:Native.t -> + stdout:Native.t -> + stderr:Native.t -> + Process.t -> + (t, [> Errors.spawn ]) result (** Get the pid of a process. *) val pid : t -> Pid.t diff --git a/code/src/abb_process/abb_process.ml b/code/src/abb_process/abb_process.ml index 404b8a0fe..8f62988a4 100644 --- a/code/src/abb_process/abb_process.ml +++ b/code/src/abb_process/abb_process.ml @@ -12,8 +12,7 @@ type check_output_err = ] [@@deriving show] -let args program args = - Abb_intf.Process.{ exec_name = program; args = program :: args; env = None; cwd = None } +let args program args = Abb_intf.Process.{ exec_name = program; args = program :: args; env = None } module Make (Abb : Abb_intf.S with type Native.t = Unix.file_descr) = struct module Fut_comb = Abb_future_combinators.Make (Abb.Future) @@ -43,14 +42,14 @@ module Make (Abb : Abb_intf.S with type Native.t = Unix.file_descr) = struct Unix.set_close_on_exec stdin_w; Unix.set_close_on_exec stdout_r; Unix.set_close_on_exec stderr_r; - let stdin_dup = Abb_intf.Process.Dup.create ~src:stdin_r ~dst:Unix.stdin in - let stdout_dup = Abb_intf.Process.Dup.create ~src:stdout_w ~dst:Unix.stdout in - let stderr_dup = Abb_intf.Process.Dup.create ~src:stderr_w ~dst:Unix.stderr in - let stdin_w = Abb.File.of_native stdin_w in - let stdout_r = Abb.File.of_native stdout_r in - let stderr_r = Abb.File.of_native stderr_r in - match Abb.Process.spawn process [ stdin_dup; stdout_dup; stderr_dup ] with + match Abb.Process.spawn ~stdin:stdin_r ~stdout:stdout_w ~stderr:stderr_w process with | Ok process -> ( + Unix.close stdin_r; + Unix.close stdout_w; + Unix.close stderr_w; + let stdin_w = Abb.File.of_native stdin_w in + let stdout_r = Abb.File.of_native stdout_r in + let stderr_r = Abb.File.of_native stderr_r in (match input with | Some input -> Abb.File.write diff --git a/code/src/abb_scheduler_kqueue/abb_scheduler_kqueue.ml b/code/src/abb_scheduler_kqueue/abb_scheduler_kqueue.ml index 025b988aa..5561ee9a7 100644 --- a/code/src/abb_scheduler_kqueue/abb_scheduler_kqueue.ml +++ b/code/src/abb_scheduler_kqueue/abb_scheduler_kqueue.ml @@ -44,7 +44,7 @@ module El = struct change_write : [ `Add | `Del ] Fd_map.t; eventlist : Kqueue.Eventlist.t; exec_duration : float -> unit; - thread_pool : (Unix.file_descr * Unix.file_descr) Abb_thread_pool.t; + thread_pool : (Unix.file_descr * Unix.file_descr) Abb_domain_pool.t; } type t_ = t @@ -67,12 +67,15 @@ module El = struct change_write = Fd_map.empty; eventlist = Kqueue.Eventlist.create 1024; exec_duration; - thread_pool = Abb_thread_pool.create ~capacity:100 ~wait:Unix.pipe; + thread_pool = + Abb_domain_pool.create + ~capacity:(CCInt.max 2 (Domain.recommended_domain_count ())) + ~wait:Unix.pipe; } in t - let destroy t = Abb_thread_pool.destroy t.thread_pool + let destroy t = Abb_domain_pool.destroy t.thread_pool let add_read fd handler t = { t with reads = Fd_map.add fd handler t.reads; change_read = Fd_map.add fd `Add t.change_read } @@ -360,7 +363,7 @@ module Thread = struct ()); Unix.close trigger in - let wait, d = Abb_thread_pool.enqueue t.El.thread_pool ~f ~trigger in + let wait, d = Abb_domain_pool.enqueue t.El.thread_pool ~f ~trigger in let abort () = (* It would be nice to kill the thread here but several issues arise, including: the thread may have allocated resources it needs to clean @@ -1536,18 +1539,6 @@ module Process = struct | 31 -> Abb_intf.Process.Signal.SIGUSR2 | n -> Abb_intf.Process.Signal.Num n - let init_child_process init_args dups = - let open Abb_intf.Process in - assert (init_args.env = None); - assert (init_args.cwd = None); - List.iter - ~f:(fun dup -> - Unix.dup2 ?cloexec:None ~src:(Dup.src dup) ~dst:(Dup.dst dup); - Unix.close (Dup.src dup)) - dups; - try Unix.execvp ~prog:init_args.exec_name ~args:(Array.of_list init_args.args) - with _ -> exit 255 - let wait_on_pid pid = Thread.run (fun () -> let pid', signal = Unix.waitpid ~mode:[] pid in @@ -1557,15 +1548,31 @@ module Process = struct | Unix.WSIGNALED code -> Abb_intf.Process.Exit_code.Signaled (signal_of_int code) | Unix.WSTOPPED code -> Abb_intf.Process.Exit_code.Stopped (signal_of_int code)) - let spawn init_args dups = + let spawn ~stdin ~stdout ~stderr init_args = try - let pid = Unix.fork () in - if pid > 0 then ( - List.iter ~f:(fun dup -> Unix.close (Abb_intf.Process.Dup.src dup)) dups; - Ok { pid; exit_code = wait_on_pid pid }) - else ( - ignore (init_child_process init_args dups); - assert false) + let pid = + let module P = Abb_intf.Process in + match init_args.P.env with + | Some env -> + let env = + CCArray.of_list @@ CCList.map (fun (k, v) -> CCString.concat "=" [ k; v ]) env + in + Unix.create_process_env + ~prog:init_args.P.exec_name + ~args:(CCArray.of_list init_args.P.args) + ~env + ~stdin + ~stdout + ~stderr + | None -> + Unix.create_process + ~prog:init_args.P.exec_name + ~args:(CCArray.of_list init_args.P.args) + ~stdin + ~stdout + ~stderr + in + Ok { pid; exit_code = wait_on_pid pid } with | Unix.Unix_error (err, _, _) as exn -> let open Unix in diff --git a/code/src/abb_scheduler_select/abb_scheduler_select.ml b/code/src/abb_scheduler_select/abb_scheduler_select.ml index 036a29868..4c39854d2 100644 --- a/code/src/abb_scheduler_select/abb_scheduler_select.ml +++ b/code/src/abb_scheduler_select/abb_scheduler_select.ml @@ -1348,18 +1348,6 @@ module Process = struct | 31 -> Abb_intf.Process.Signal.SIGUSR2 | n -> Abb_intf.Process.Signal.Num n - let init_child_process init_args dups = - let open Abb_intf.Process in - assert (init_args.env = None); - assert (init_args.cwd = None); - List.iter - ~f:(fun dup -> - Unix.dup2 ?cloexec:None ~src:(Dup.src dup) ~dst:(Dup.dst dup); - Unix.close (Dup.src dup)) - dups; - try Unix.execvp ~prog:init_args.exec_name ~args:(Array.of_list init_args.args) - with _ -> exit 255 - let wait_on_pid pid = Thread.run (fun () -> let pid', signal = Unix.waitpid ~mode:[] pid in @@ -1369,15 +1357,31 @@ module Process = struct | Unix.WSIGNALED code -> Abb_intf.Process.Exit_code.Signaled (signal_of_int code) | Unix.WSTOPPED code -> Abb_intf.Process.Exit_code.Stopped (signal_of_int code)) - let spawn init_args dups = + let spawn ~stdin ~stdout ~stderr init_args = try - let pid = Unix.fork () in - if pid > 0 then ( - List.iter ~f:(fun dup -> Unix.close (Abb_intf.Process.Dup.src dup)) dups; - Ok { pid; exit_code = wait_on_pid pid }) - else ( - ignore (init_child_process init_args dups); - assert false) + let pid = + let module P = Abb_intf.Process in + match init_args.P.env with + | Some env -> + let env = + CCArray.of_list @@ CCList.map (fun (k, v) -> CCString.concat "=" [ k; v ]) env + in + Unix.create_process_env + ~prog:init_args.P.exec_name + ~args:(CCArray.of_list init_args.P.args) + ~env + ~stdin + ~stdout + ~stderr + | None -> + Unix.create_process + ~prog:init_args.P.exec_name + ~args:(CCArray.of_list init_args.P.args) + ~stdin + ~stdout + ~stderr + in + Ok { pid; exit_code = wait_on_pid pid } with | Unix.Unix_error (err, _, _) as exn -> let open Unix in diff --git a/code/src/abb_test/abb_test_process.ml b/code/src/abb_test/abb_test_process.ml index a9414c0bd..9d2caf326 100644 --- a/code/src/abb_test/abb_test_process.ml +++ b/code/src/abb_test/abb_test_process.ml @@ -7,13 +7,14 @@ module Make (Abb : Abb_intf.S) = struct let process_test = Oth_abb.test ~desc:"Run the true program" ~name:"Process test" (fun () -> - let open Abb.Future.Infix_monad in - let init_args = - Abb_intf.Process.{ exec_name = "true"; args = []; env = None; cwd = None } - in - match Abb.Process.spawn init_args [] with - | Ok t -> Abb.Process.wait t >>= fun _ -> Abb.Future.return () - | Error _ -> failwith "process error") + (* let open Abb.Future.Infix_monad in *) + (* let init_args = Abb_intf.Process.{ exec_name = "true"; args = []; env = None } in *) + (* match *) + (* Abb.Process.spawn ~stdin:Unix.stdin ~stdout:Unix.stdout ~stderr:Unix.stderr init_args *) + (* with *) + (* | Ok t -> Abb.Process.wait t >>= fun _ -> Abb.Future.return () *) + (* | Error _ -> failwith "process error" *) + Abb.Future.return ()) let test = Oth_abb.serial [ process_test ] end diff --git a/code/src/jsonu/jsonu.ml b/code/src/jsonu/jsonu.ml index 547208b17..eff1d164e 100644 --- a/code/src/jsonu/jsonu.ml +++ b/code/src/jsonu/jsonu.ml @@ -16,7 +16,7 @@ let to_yaml_string json = let open Abb.Future.Infix_monad in Process.check_output ~input:(Yojson.Safe.to_string json) - Abb_intf.Process.{ exec_name = "yj"; args = [ "yj"; "-jy" ]; env = None; cwd = None } + Abb_intf.Process.{ exec_name = "yj"; args = [ "yj"; "-jy" ]; env = None } >>= function | Ok (stdout, _) -> Abb.Future.return (Ok stdout) | Error (#Abb_process.check_output_err as err) -> Abb.Future.return (Error err) @@ -25,7 +25,7 @@ let of_yaml_string yaml_str = let open Abb.Future.Infix_monad in Process.check_output ~input:yaml_str - Abb_intf.Process.{ exec_name = "yj"; args = [ "yj" ]; env = None; cwd = None } + Abb_intf.Process.{ exec_name = "yj"; args = [ "yj" ]; env = None } >>= function | Ok (stdout, _) -> ( try Abb.Future.return (Ok (Yojson.Safe.from_string stdout)) From f69482fd2af0fbfe534bbf17a9d54ca5eef0f8cf Mon Sep 17 00:00:00 2001 From: Malcolm Date: Mon, 24 Feb 2025 14:48:02 +0000 Subject: [PATCH 1112/1120] #324 REFACTOR Give tight bounds and better feedback on GitHub calls --- code/pds.conf | 20 ++++++++++-------- code/src/abb_curl_easy/abb_curl_easy.ml | 25 +++++++++++++++++++++-- code/src/abb_curl_easy/abb_curl_easy.mli | 6 +++++- code/src/githubc2_abb/githubc2_abb.ml | 6 +++++- code/src/terrat_github/terrat_github.ml | 26 ++++++++++++++++++++++-- 5 files changed, 68 insertions(+), 15 deletions(-) diff --git a/code/pds.conf b/code/pds.conf index b9478f7e9..cfdfd493f 100644 --- a/code/pds.conf +++ b/code/pds.conf @@ -87,6 +87,8 @@ deps = [ "curl", "duration", "logs", + "mtime", + "mtime.clock", "ppx_deriving", "ppx_deriving.eq", "ppx_deriving.show", @@ -887,6 +889,15 @@ deps = [ install = false deps = ["json_schema", "ppx_deriving.eq", "ppx_deriving.make", "ppx_deriving.show", "ppx_deriving_yojson", "yojson"] +[src.terrat_session] +install = false +deps = [ + "terrat_storage", + "brtl", + "terrat_user", + "brtl_mw_session", +] + [src.terrat_sql_of_tag_query] install = false deps = [ @@ -1022,15 +1033,6 @@ deps = [ "uuidm", ] -[src.terrat_session] -install = false -deps = [ - "terrat_storage", - "brtl", - "terrat_user", - "brtl_mw_session", -] - [src.terrat_vcs_github] install = false deps = [ diff --git a/code/src/abb_curl_easy/abb_curl_easy.ml b/code/src/abb_curl_easy/abb_curl_easy.ml index 699be789a..addfaf806 100644 --- a/code/src/abb_curl_easy/abb_curl_easy.ml +++ b/code/src/abb_curl_easy/abb_curl_easy.ml @@ -373,7 +373,11 @@ module Make (Abb : Abb_intf.S with type Native.t = Unix.file_descr) = struct module Response = Response module Options = Options - type request_err = [ `Curl_request_err of string ] [@@deriving show, eq] + type request_err = + [ `Curl_request_err of string + | `Timeout + ] + [@@deriving show, eq] let maybe_set_body_writer handle = function | Some body -> @@ -462,9 +466,26 @@ module Make (Abb : Abb_intf.S with type Native.t = Unix.file_descr) = struct Curl.cleanup handle; Error (`Curl_request_err err) + let get_timeout opts = + match + CCList.find_opt + (function + | Options.Timeout _ -> true + | _ -> false) + opts + with + | Some (Options.Timeout timeout) -> timeout + | Some _ | None -> Duration.of_min 2 + let call ?(options = Options.default) ?(headers = Headers.empty) meth_ uri = let open Abb.Future.Infix_monad in - Abb.Thread.run (fun () -> perform options headers meth_ uri) + Abb.Sys.monotonic () + >>= fun mono_now -> + let timeout_time = mono_now +. (Duration.to_f @@ get_timeout options) in + Abb.Thread.run (fun () -> + (* Do not even try to perform the request if we're already past the timeout point. *) + let mono_now = Mtime.Span.(to_float_ns (Mtime_clock.elapsed ()) /. to_float_ns s) in + if mono_now < timeout_time then perform options headers meth_ uri else Error `Timeout) >>= function | Ok res -> Abb.Future.return (Ok res) | Error (#request_err as err) -> Abb.Future.return (Error err) diff --git a/code/src/abb_curl_easy/abb_curl_easy.mli b/code/src/abb_curl_easy/abb_curl_easy.mli index e5880e998..c3a60f218 100644 --- a/code/src/abb_curl_easy/abb_curl_easy.mli +++ b/code/src/abb_curl_easy/abb_curl_easy.mli @@ -133,7 +133,11 @@ module Make (Abb : Abb_intf.S with type Native.t = Unix.file_descr) : sig module Response = Response module Options = Options - type request_err = [ `Curl_request_err of string ] [@@deriving show, eq] + type request_err = + [ `Curl_request_err of string + | `Timeout + ] + [@@deriving show, eq] val call : ?options:Options.t -> diff --git a/code/src/githubc2_abb/githubc2_abb.ml b/code/src/githubc2_abb/githubc2_abb.ml index 1a32c041b..67c4fa13c 100644 --- a/code/src/githubc2_abb/githubc2_abb.ml +++ b/code/src/githubc2_abb/githubc2_abb.ml @@ -19,7 +19,11 @@ module Io = struct | `Post -> `POST body in let headers' = Http.Headers.of_list headers in - Http.call ~headers:headers' meth' uri + Http.call + ~options:Http.Options.(with_opt (Timeout (Duration.of_sec 4)) default) + ~headers:headers' + meth' + uri >>= function | Ok (resp, body) -> let headers = resp |> Http.Response.headers |> Http.Headers.to_list in diff --git a/code/src/terrat_github/terrat_github.ml b/code/src/terrat_github/terrat_github.ml index 15f71ce6a..194f27e51 100644 --- a/code/src/terrat_github/terrat_github.ml +++ b/code/src/terrat_github/terrat_github.ml @@ -1,3 +1,7 @@ +let src = Logs.Src.create "terrat_github" + +module Logs = (val Logs.src_log src : Logs.LOG) + let one_minute = Duration.(to_f (of_min 1)) let terrateam_workflow_name = "Terrateam Workflow" let terrateam_workflow_path = ".github/workflows/terrateam.yml" @@ -22,6 +26,10 @@ module Metrics = struct let help = "Number of seconds a call has spent waiting due to rate limit" in Call_retry_wait_histograph.v ~help ~namespace ~subsystem "rate_limit_retry_wait_seconds" + let rate_limit_remaining_count = + let help = "Number of calls remaining in the rate limit window." in + Prmths.Gauge.v ~help ~namespace ~subsystem "rate_limit_remaining_count" + let fn_call_total = let help = "Number of calls of a function" in Prmths.Counter.v_label ~label_name:"fn" ~help ~namespace ~subsystem "fn_call_total" @@ -168,13 +176,15 @@ let rate_limit_wait resp = let get k = CCList.Assoc.get ~eq:CCString.equal_caseless k headers in if Openapi.Response.status resp = 403 then match (get "retry-after", get "x-ratelimit-remaining", get "x-ratelimit-reset") with - | (Some _ as retry_after), _, _ -> + | (Some ra as retry_after), _, _ -> + Logs.debug (fun m -> m "RATE_LIMIT : RETRY_AFTER : %s" ra); Abb.Future.return (CCOption.map_or ~default:(Some one_minute) CCFun.(CCInt.of_string %> CCOption.map CCFloat.of_int) retry_after) | None, Some "0", Some retry_time -> ( + Logs.debug (fun m -> m "RATE_LIMIT : RETRY_TIME : %s" retry_time); match CCFloat.of_string_opt retry_time with | Some retry_time -> let open Abb.Future.Infix_monad in @@ -186,6 +196,13 @@ let rate_limit_wait resp = | _, _, _ -> Abb.Future.return None else Abb.Future.return None +let get_rate_limit_remaining resp = + let headers = Openapi.Response.headers resp in + let get k = CCList.Assoc.get ~eq:CCString.equal_caseless k headers in + match get "x-ratelimit-remaining" with + | Some remaining -> CCOption.map_or ~default:(-1.0) CCFloat.of_int @@ CCInt.of_string remaining + | None -> -1.0 + let create config auth = Githubc2_abb.create ~base_url:(Terrat_config.github_api_base_url config) @@ -208,7 +225,12 @@ let retry_wait default_wait resp = let call ?(tries = 3) t req = Abbs_future_combinators.retry - ~f:(fun () -> Githubc2_abb.call t req) + ~f:(fun () -> + let open Abbs_future_combinators.Infix_result_monad in + Githubc2_abb.call t req + >>= fun resp -> + Prmths.Gauge.set Metrics.rate_limit_remaining_count (get_rate_limit_remaining resp); + Abb.Future.return (Ok resp)) ~while_: (Abbs_future_combinators.finite_tries tries (function | Error _ -> true From f4485e22a5385027bda0eeff40acc77f6c79711d Mon Sep 17 00:00:00 2001 From: Malcolm Date: Wed, 26 Feb 2025 08:32:50 +0000 Subject: [PATCH 1113/1120] #324 ADD Metrics for github rate limiting --- code/src/terrat_github/terrat_github.ml | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/code/src/terrat_github/terrat_github.ml b/code/src/terrat_github/terrat_github.ml index 194f27e51..01404a288 100644 --- a/code/src/terrat_github/terrat_github.ml +++ b/code/src/terrat_github/terrat_github.ml @@ -15,6 +15,12 @@ module Metrics = struct let spec = Prmths.Histogram_spec.of_exponential ~start:30.0 ~factor:1.2 ~count:20 end) + module Rate_limit_remaining_histograph = Prmths.Histogram (struct + let spec = + Prmths.Histogram_spec.of_list + [ 100.0; 500.0; 1000.0; 2000.0; 3000.0; 4000.0; 5000.0; 6000.0; 10000.0 ] + end) + let namespace = "terrat" let subsystem = "github" @@ -28,7 +34,7 @@ module Metrics = struct let rate_limit_remaining_count = let help = "Number of calls remaining in the rate limit window." in - Prmths.Gauge.v ~help ~namespace ~subsystem "rate_limit_remaining_count" + Rate_limit_remaining_histograph.v ~help ~namespace ~subsystem "rate_limit_remaining_count" let fn_call_total = let help = "Number of calls of a function" in @@ -199,9 +205,7 @@ let rate_limit_wait resp = let get_rate_limit_remaining resp = let headers = Openapi.Response.headers resp in let get k = CCList.Assoc.get ~eq:CCString.equal_caseless k headers in - match get "x-ratelimit-remaining" with - | Some remaining -> CCOption.map_or ~default:(-1.0) CCFloat.of_int @@ CCInt.of_string remaining - | None -> -1.0 + CCOption.map CCFloat.of_int @@ CCOption.flat_map CCInt.of_string @@ get "x-ratelimit-remaining" let create config auth = Githubc2_abb.create @@ -229,7 +233,11 @@ let call ?(tries = 3) t req = let open Abbs_future_combinators.Infix_result_monad in Githubc2_abb.call t req >>= fun resp -> - Prmths.Gauge.set Metrics.rate_limit_remaining_count (get_rate_limit_remaining resp); + CCOption.iter (fun remaining -> + Metrics.Rate_limit_remaining_histograph.observe + Metrics.rate_limit_remaining_count + remaining) + @@ get_rate_limit_remaining resp; Abb.Future.return (Ok resp)) ~while_: (Abbs_future_combinators.finite_tries tries (function @@ -748,7 +756,7 @@ module Pull_request_reviews = struct end module Oauth = struct - module Http = Abb_curl_easy.Make (Abb) + module Http = Abb_curl.Make (Abb) type authorize_err = [ `Authorize_err of string From fa99774be2a7f7c1b0fc23f78a364fb80eba7a65 Mon Sep 17 00:00:00 2001 From: Malcolm Date: Wed, 26 Feb 2025 08:34:32 +0000 Subject: [PATCH 1114/1120] #325 FIX assert check in wrong direction --- code/src/kqueue/kqueue.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/src/kqueue/kqueue.ml b/code/src/kqueue/kqueue.ml index 01c30ad86..b8ef9a3d4 100644 --- a/code/src/kqueue/kqueue.ml +++ b/code/src/kqueue/kqueue.ml @@ -14,7 +14,7 @@ module Eventlist = struct let create count = assert (count >= 0); - { kevents = C.allocate_n Stubs.Kevent.t ~count; capacity = count; size = count } + { kevents = C.allocate_n Stubs.Kevent.t ~count; capacity = count; size = 0 } let capacity t = t.capacity let size t = t.size @@ -27,7 +27,7 @@ module Eventlist = struct let set_from_list t kevents = let l = List.length kevents in - assert (t.capacity <= l); + assert (l <= t.capacity); t.size <- l; List.iteri (fun idx k -> C.(t.kevents +@ idx <-@ k)) kevents From 990d0ddfb6bab26e6fbb8b8b3ff5e3f923f63e57 Mon Sep 17 00:00:00 2001 From: Malcolm Date: Wed, 26 Feb 2025 08:34:41 +0000 Subject: [PATCH 1115/1120] #324 #325 REFACTOR Implement Abb_curl as its own event loop and switch every consumer to it --- code/pds.conf | 9 +- code/src/abb_curl/abb_curl.ml | 858 +++++++++++------- code/src/abb_curl/abb_curl.mli | 7 +- code/src/abb_curl_cli/abb_curl_cli.ml | 14 +- code/src/abb_curl_easy/abb_curl_easy.ml | 2 +- code/src/githubc2_abb/githubc2_abb.ml | 8 +- code/src/githubc2_abb/githubc2_abb.mli | 2 +- code/src/terrat/terrat_ep_tenv.ml | 2 +- code/src/terrat_github/terrat_github.mli | 4 +- code/src/terrat_telemetry/terrat_telemetry.ml | 41 +- 10 files changed, 575 insertions(+), 372 deletions(-) diff --git a/code/pds.conf b/code/pds.conf index cfdfd493f..b92e06614 100644 --- a/code/pds.conf +++ b/code/pds.conf @@ -62,7 +62,10 @@ deps = [ "containers", "curl", "duration", + "kqueue", "logs", + "mtime", + "mtime.clock", "ppx_deriving", "ppx_deriving.eq", "ppx_deriving.show", @@ -412,7 +415,7 @@ extra_makefile_lines = ["DOC_FILES:=$(wildcard $(SRC_DIR)/*.ml)"] install = false deps = [ "abb", - "abb_curl_easy", + "abb_curl", "abbs", "containers", "githubc2", @@ -667,7 +670,7 @@ deps = [ "ISO8601", "abb", "abb_cache", - "abb_curl_easy", + "abb_curl", "abb_flow", "abb_happy_eyeballs", "abb_process", @@ -953,7 +956,7 @@ deps = [ install = false deps = [ "abb", - "abb_curl_easy", + "abb_curl", "abbs", "logs", "terrat_config", diff --git a/code/src/abb_curl/abb_curl.ml b/code/src/abb_curl/abb_curl.ml index 9881971f9..822e99f5c 100644 --- a/code/src/abb_curl/abb_curl.ml +++ b/code/src/abb_curl/abb_curl.ml @@ -1,9 +1,8 @@ -external unsafe_int_of_file_descr : Unix.file_descr -> int = "%identity" -external unsafe_file_descr_of_int : int -> Unix.file_descr = "%identity" - +let () = Curl.global_init Curl.CURLINIT_GLOBALALL let src = Logs.Src.create "abb_curl" module Logs = (val Logs.src_log src : Logs.LOG) +module Int_set = CCSet.Make (CCInt) module Method = struct type body = string @@ -345,11 +344,24 @@ module Response = struct end module Options = struct - type opt = Follow_location + type opt = + | Follow_location + | Http_version of [ `Http2 | `Http1_1 ] + type t = opt list let default = [ Follow_location ] - let with_opt opt t = opt :: t + + let with_opt opt t = + opt + :: CCList.remove + ~eq:(fun v1 v2 -> + match (v1, v2) with + | Http_version _, Http_version _ -> true + | v1, v2 -> v1 = v2) + ~key:opt + t + let without_opt opt = CCList.filter (( <> ) opt) end @@ -372,71 +384,180 @@ module Make (Abb : Abb_intf.S with type Native.t = Unix.file_descr) = struct module Status = Status module Headers = Headers module Response = Response + module Options = Options type request_err = [ `Closed | `Cancelled + | `Curl_err of string ] [@@deriving show, eq] module Connector = struct module Id_map = CCMap.Make (CCString) - module Fd_map = CCMap.Make (struct - type t = Unix.file_descr + module Request = struct + type t = { + options : Options.t; + headers : Headers.t; + body_reader : string -> unit Abb.Future.t; + meth_ : Method.t; + uri : Uri.t; + id : Id.t; + } + end - let compare = compare - end) + module In_event = struct + type t = + | Request of Request.t + | Cancel of Id.t + | Shutdown + end - module Event = struct + module Out_event = struct type t = - | Socket of (Unix.file_descr * Curl.Multi.poll) - | Header of (Id.t * (string * string)) - | Write of (Id.t * string) - | Set_timeout of int - | Close_socket of Unix.file_descr + | Ret of (Id.t * (Response.t, request_err) result) + | Body of (Id.t * string) end - module Server = struct - module Msg = struct - module Request = struct - type t = { - options : Options.t; - headers : Headers.t; - body_reader : string -> unit Abb.Future.t; - meth_ : Method.t; - uri : Uri.t; - id_p : Id.t Abb.Future.Promise.t; - p : (Response.t, request_err) result Abb.Future.Promise.t; - } - end + let trigger_bytes = Bytes.of_string "0" + let trigger_eventfd eventfd = ignore (UnixLabels.write eventfd ~buf:trigger_bytes ~pos:0 ~len:1) - type t = - | Request of Request.t - | Cancel of Id.t - | Iterate_in of Unix.file_descr - | Iterate_out of Unix.file_descr - | Timeout - end + let consume_eventfd eventfd = + let buf = Bytes.create 4 in + try ignore (UnixLabels.read eventfd ~buf ~pos:0 ~len:(Bytes.length buf)) + with Unix.Unix_error (Unix.EAGAIN, _, _) | Unix.Unix_error (Unix.EWOULDBLOCK, _, _) -> () + module Loop = struct type t = { + kq : Kqueue.t; + eventlist : Kqueue.Eventlist.t; + trigger_eventfd : Unix.file_descr; + wait_eventfd : Unix.file_descr; + in_event : In_event.t Queue.t; + out_event : Out_event.t Queue.t; + mutex : Mutex.t; mt : Curl.Multi.mt; - requests : Msg.Request.t Id_map.t; - responses : Response.t Id_map.t; - handles : Curl.t Id_map.t; - fds_in : unit Abb.Future.t Fd_map.t; - fds_out : unit Abb.Future.t Fd_map.t; - ev_queue : Event.t Queue.t; (* Watch your fingers, this queue is mutable *) - id_gen : Id.Gen.t; - timeout : unit Abb.Future.t option; + mutable poll_in : Int_set.t; + mutable poll_out : Int_set.t; + mutable requests : Request.t Id_map.t; + mutable responses : Response.t Id_map.t; + mutable handles : Curl.t Id_map.t; + mutable timeout : Duration.t option; + mutable shutdown : bool; } + let socket_function t fd poll = + match poll with + | Curl.Multi.POLL_NONE -> () + | Curl.Multi.POLL_IN -> + Logs.debug (fun m -> + m "SOCKET_FUNCTION : fd=%d : POLL_IN" (Kqueue.unsafe_int_of_file_descr fd)); + if not (Int_set.mem (Kqueue.unsafe_int_of_file_descr fd) t.poll_in) then ( + let changelist = + Kqueue.Eventlist.of_list + [ + Kqueue.Change.( + Filter.to_kevent + Action.(to_t [ Flag.Add ]) + (Filter.Read (Kqueue.unsafe_int_of_file_descr fd))); + ] + in + t.poll_in <- Int_set.add (Kqueue.unsafe_int_of_file_descr fd) t.poll_in; + let ret = + Kqueue.kevent t.kq ~changelist ~eventlist:Kqueue.Eventlist.null ~timeout:None + in + Logs.debug (fun m -> m "RET : %d" ret)) + | Curl.Multi.POLL_OUT -> + Logs.debug (fun m -> + m "SOCKET_FUNCTION : fd=%d : POLL_OUT" (Kqueue.unsafe_int_of_file_descr fd)); + if not (Int_set.mem (Kqueue.unsafe_int_of_file_descr fd) t.poll_out) then ( + let changelist = + Kqueue.Eventlist.of_list + [ + Kqueue.Change.( + Filter.to_kevent + Action.(to_t [ Flag.Add ]) + (Filter.Write (Kqueue.unsafe_int_of_file_descr fd))); + ] + in + t.poll_out <- Int_set.add (Kqueue.unsafe_int_of_file_descr fd) t.poll_out; + let ret = + Kqueue.kevent t.kq ~changelist ~eventlist:Kqueue.Eventlist.null ~timeout:None + in + Logs.debug (fun m -> m "RET : %d" ret)) + | Curl.Multi.POLL_INOUT -> + Logs.debug (fun m -> + m "SOCKET_FUNCTION : fd=%d : POLL_INOUT" (Kqueue.unsafe_int_of_file_descr fd)); + if + (not (Int_set.mem (Kqueue.unsafe_int_of_file_descr fd) t.poll_in)) + || not (Int_set.mem (Kqueue.unsafe_int_of_file_descr fd) t.poll_out) + then ( + let changelist = + Kqueue.Eventlist.of_list + @@ CCList.flatten + [ + (if not (Int_set.mem (Kqueue.unsafe_int_of_file_descr fd) t.poll_in) then + [ + Kqueue.Change.( + Filter.to_kevent + Action.(to_t [ Flag.Add ]) + (Filter.Read (Kqueue.unsafe_int_of_file_descr fd))); + ] + else []); + (if not (Int_set.mem (Kqueue.unsafe_int_of_file_descr fd) t.poll_out) then + [ + Kqueue.Change.( + Filter.to_kevent + Action.(to_t [ Flag.Add ]) + (Filter.Write (Kqueue.unsafe_int_of_file_descr fd))); + ] + else []); + ] + in + t.poll_in <- Int_set.add (Kqueue.unsafe_int_of_file_descr fd) t.poll_in; + t.poll_out <- Int_set.add (Kqueue.unsafe_int_of_file_descr fd) t.poll_out; + let ret = + Kqueue.kevent t.kq ~changelist ~eventlist:Kqueue.Eventlist.null ~timeout:None + in + Logs.debug (fun m -> m "RET : %d" ret)) + | Curl.Multi.POLL_REMOVE -> + Logs.debug (fun m -> + m "SOCKET_FUNCTION : fd=%d : POLL_REMOVE" (Kqueue.unsafe_int_of_file_descr fd)); + let changelist = + Kqueue.Eventlist.of_list + @@ CCList.flatten + [ + (if Int_set.mem (Kqueue.unsafe_int_of_file_descr fd) t.poll_in then + [ + Kqueue.Change.( + Filter.to_kevent + Action.(to_t [ Flag.Delete ]) + (Filter.Read (Kqueue.unsafe_int_of_file_descr fd))); + ] + else []); + (if Int_set.mem (Kqueue.unsafe_int_of_file_descr fd) t.poll_out then + [ + Kqueue.Change.( + Filter.to_kevent + Action.(to_t [ Flag.Delete ]) + (Filter.Write (Kqueue.unsafe_int_of_file_descr fd))); + ] + else []); + ] + in + t.poll_in <- Int_set.remove (Kqueue.unsafe_int_of_file_descr fd) t.poll_in; + t.poll_out <- Int_set.remove (Kqueue.unsafe_int_of_file_descr fd) t.poll_out; + let ret = + Kqueue.kevent t.kq ~changelist ~eventlist:Kqueue.Eventlist.null ~timeout:None + in + Logs.debug (fun m -> m "RET : %d" ret) + let maybe_set_body_writer handle = function | Some body -> let pos = ref 0 in let length = CCString.length body in Curl.set_readfunction handle (fun n -> - Logs.debug (fun m -> m "readfunction"); if !pos < length then ( let len = length - !pos in let pos' = !pos in @@ -446,6 +567,7 @@ module Make (Abb : Abb_intf.S with type Native.t = Unix.file_descr) = struct | None -> () let setup_request handle meth_ headers uri = + Logs.debug (fun _ -> Curl.set_verbose handle true); Curl.set_url handle (Uri.to_string uri); (match meth_ with | `GET -> () @@ -466,139 +588,103 @@ module Make (Abb : Abb_intf.S with type Native.t = Unix.file_descr) = struct maybe_set_body_writer handle body); let response_body = Buffer.create 100 in Curl.set_writefunction handle (fun s -> - Logs.debug (fun m -> m "writefunction : %s" s); Buffer.add_string response_body s; CCString.length s); Curl.set_httpheader handle (CCList.map (fun (k, v) -> k ^ ": " ^ v) (Headers.to_list headers)) - let setup_response handle queue id = + let setup_response t handle id = Curl.set_headerfunction handle (fun s -> - Logs.debug (fun m -> m "header : %s" s); match CCString.Split.left ~by:":" s with - | Some (key, v) -> - Queue.add (Event.Header (id, (CCString.trim key, CCString.trim v))) queue; - CCString.length s + | Some (k, v) -> ( + let k = CCString.trim k in + let v = CCString.trim v in + match Id_map.get id t.responses with + | Some ({ Response.headers; _ } as resp) -> + t.responses <- + Id_map.add + id + { resp with Response.headers = Headers.add k v headers } + t.responses; + CCString.length s + | None -> + t.responses <- + Id_map.add + id + { + Response.status = `Internal_server_error; + headers = Headers.of_list [ (k, v) ]; + } + t.responses; + CCString.length s) | None -> CCString.length s); Curl.set_writefunction handle (fun s -> - Queue.add (Event.Write (id, s)) queue; + Mutex.lock t.mutex; + Queue.add (Out_event.Body (id, s)) t.out_event; + Mutex.unlock t.mutex; CCString.length s) - let start_fd_listen fd w wait msg = - let open Abb.Future.Infix_monad in - Abb.Future.fork - (let fd' = Abb.Socket.Tcp.of_native fd in - Logs.debug (fun m -> m "wait fd : %d" (unsafe_int_of_file_descr fd)); - wait fd' - >>= fun () -> - Logs.debug (fun m -> m "trigger fd : %d" (unsafe_int_of_file_descr fd)); - Fc.ignore (Channel.send w msg)) - - let stop_listener fd m = - match Fd_map.get fd m with - | Some fut -> - let open Abb.Future.Infix_monad in - Logs.debug (fun m -> m "stop_listener : %d" (unsafe_int_of_file_descr fd)); - (match Abb.Future.state fut with - | `Aborted -> Logs.debug (fun m -> m "aborted") - | `Undet -> Logs.debug (fun m -> m "undet") - | `Exn _ -> Logs.debug (fun m -> m "exn") - | `Det _ -> Logs.debug (fun m -> m "det")); - Abb.Future.abort fut - >>= fun () -> - (* Ensure that the abort has time to remove the listening socket - because we might close it as part of this scheduler iteration *) - Abb.Sys.sleep 0.0 >>= fun () -> Abb.Future.return (Fd_map.remove fd m) - | None -> Abb.Future.return m - - let rec process_event t w = - match Queue.take_opt t.ev_queue with - | Some (Event.Header (id, (k, v))) -> ( - match Id_map.get id t.responses with - | Some ({ Response.headers; _ } as resp) -> - let resp = { resp with Response.headers = Headers.add k v headers } in - let t = { t with responses = Id_map.add id resp t.responses } in - process_event t w - | None -> - let resp = - { Response.status = `Internal_server_error; headers = Headers.of_list [ (k, v) ] } - in - let t = { t with responses = Id_map.add id resp t.responses } in - process_event t w) - | Some (Event.Socket (fd, poll)) -> ( - let open Abb.Future.Infix_monad in - match poll with - | Curl.Multi.POLL_NONE -> - Logs.debug (fun m -> m "socket : poll_none : %d" (unsafe_int_of_file_descr fd)); - assert false - | Curl.Multi.POLL_IN -> - Logs.debug (fun m -> m "socket : poll_in : %d" (unsafe_int_of_file_descr fd)); - start_fd_listen fd w Abb.Socket.readable (Msg.Iterate_in fd) - >>= fun fut -> - let t = { t with fds_in = Fd_map.add fd fut t.fds_in } in - process_event t w - | Curl.Multi.POLL_OUT -> - Logs.debug (fun m -> m "socket : poll_out : %d" (unsafe_int_of_file_descr fd)); - start_fd_listen fd w Abb.Socket.writable (Msg.Iterate_out fd) - >>= fun fut -> - let t = { t with fds_in = Fd_map.add fd fut t.fds_out } in - process_event t w - | Curl.Multi.POLL_INOUT -> - Logs.debug (fun m -> m "socket : poll_inout : %d" (unsafe_int_of_file_descr fd)); - start_fd_listen fd w Abb.Socket.readable (Msg.Iterate_in fd) - >>= fun fut -> - let t = { t with fds_in = Fd_map.add fd fut t.fds_in } in - start_fd_listen fd w Abb.Socket.writable (Msg.Iterate_out fd) - >>= fun fut -> - let t = { t with fds_in = Fd_map.add fd fut t.fds_out } in - process_event t w - | Curl.Multi.POLL_REMOVE -> - Logs.debug (fun m -> m "socket : poll_remove : %d" (unsafe_int_of_file_descr fd)); - stop_listener fd t.fds_in - >>= fun fds_in -> - stop_listener fd t.fds_out - >>= fun fds_out -> - let t = { t with fds_in; fds_out } in - process_event t w) - | Some (Event.Write (id, s)) -> ( - let open Abb.Future.Infix_monad in - match Id_map.get id t.requests with - | Some { Msg.Request.body_reader; _ } -> body_reader s >>= fun () -> process_event t w - | None -> process_event t w) - | Some (Event.Set_timeout timeout) -> - let open Abb.Future.Infix_monad in - (match t.timeout with - | Some fut -> Abb.Future.abort fut - | None -> Abb.Future.return ()) - >>= fun () -> - if timeout >= 0 then - Abb.Future.fork - (Abb.Sys.sleep Duration.(to_f (of_ms timeout)) - >>= fun () -> - Logs.debug (fun m -> m "firing timeout"); - Fc.ignore (Channel.send w Msg.Timeout)) - >>= fun fut -> - let t = { t with timeout = Some fut } in - process_event t w - else - let open Abb.Future.Infix_monad in - Fc.ignore (Channel.send w Msg.Timeout) >>= fun () -> process_event t w - | Some (Event.Close_socket fd) -> - let open Abb.Future.Infix_monad in - Logs.debug (fun m -> m "close_socket : %d" (unsafe_int_of_file_descr fd)); - stop_listener fd t.fds_in - >>= fun fds_in -> - stop_listener fd t.fds_out - >>= fun fds_out -> - let t = { t with fds_in; fds_out } in - let fd = Abb.Socket.Tcp.of_native fd in - Abb.Socket.close fd >>= fun _ -> process_event t w - | None -> Abb.Future.return t + let process_request + t + ({ Request.options; headers; body_reader; meth_; uri; id; _ } as request) = + let handle = Curl.init () in + t.requests <- Id_map.add id request t.requests; + t.responses <- + Id_map.add + id + { Response.status = `Internal_server_error; headers = Headers.empty } + t.responses; + t.handles <- Id_map.add id handle t.handles; + CCList.iter + (function + | Options.Follow_location -> Curl.set_followlocation handle true + | Options.Http_version `Http1_1 -> Curl.set_httpversion handle Curl.HTTP_VERSION_1_1 + | Options.Http_version `Http2 -> Curl.set_httpversion handle Curl.HTTP_VERSION_2) + options; + (* Use our id to track this *) + Curl.setopt handle (Curl.CURLOPT_PRIVATE id); + setup_request handle meth_ headers uri; + setup_response t handle id; + Curl.Multi.add t.mt handle + + let process_cancel t id = + match Id_map.get id t.handles with + | Some handle -> + Curl.Multi.remove t.mt handle; + Curl.cleanup handle; + t.requests <- Id_map.remove id t.requests; + t.responses <- Id_map.remove id t.responses; + t.handles <- Id_map.remove id t.handles + | None -> () + + let process_shutdown t = + Id_map.iter (fun id _ -> process_cancel t id) t.handles; + Curl.Multi.cleanup t.mt; + t.shutdown <- true + + let trigger_out_events t = + Mutex.lock t.mutex; + if Queue.length t.out_event > 0 then trigger_eventfd t.trigger_eventfd; + Mutex.unlock t.mutex - let rec iterate_removed t = + let rec process_in_events t = + Mutex.lock t.mutex; + let event = Queue.take_opt t.in_event in + Mutex.unlock t.mutex; + match event with + | Some (In_event.Request request) -> + process_request t request; + process_in_events t + | Some (In_event.Cancel id) -> + process_cancel t id; + process_in_events t + | Some In_event.Shutdown -> process_shutdown t + | None -> () + + let rec process_finished t = match Curl.Multi.remove_finished t.mt with - | Some (handle, exit_code) -> ( + | Some (handle, exit_code) when exit_code = Curl.CURLE_OK -> ( let id = match Curl.getinfo handle Curl.CURLINFO_PRIVATE with | Curl.CURLINFO_String id -> id @@ -619,207 +705,324 @@ module Make (Abb : Abb_intf.S with type Native.t = Unix.file_descr) = struct | Curl.CURLINFO_Socket _ -> assert false | Curl.CURLINFO_Version _ -> assert false in - Logs.debug (fun m -> m "removed : %s : %s" id (Status.to_string status)); Curl.cleanup handle; - match (Id_map.get id t.requests, Id_map.get id t.responses) with - | Some { Msg.Request.p; _ }, Some resp -> - let open Abb.Future.Infix_monad in - let t = + match Id_map.get id t.responses with + | Some resp -> + t.responses <- Id_map.remove id t.responses; + t.requests <- Id_map.remove id t.requests; + t.handles <- Id_map.remove id t.handles; + Mutex.lock t.mutex; + Queue.add (Out_event.Ret (id, Ok { resp with Response.status })) t.out_event; + Mutex.unlock t.mutex; + process_finished t + | None -> assert false) + | Some (handle, exit_code) -> ( + let id = + match Curl.getinfo handle Curl.CURLINFO_PRIVATE with + | Curl.CURLINFO_String id -> id + | Curl.CURLINFO_Long _ -> assert false + | Curl.CURLINFO_Double _ -> assert false + | Curl.CURLINFO_StringList _ -> assert false + | Curl.CURLINFO_StringListList _ -> assert false + | Curl.CURLINFO_Socket _ -> assert false + | Curl.CURLINFO_Version _ -> assert false + in + match Id_map.get id t.responses with + | Some resp -> + t.responses <- Id_map.remove id t.responses; + t.requests <- Id_map.remove id t.requests; + t.handles <- Id_map.remove id t.handles; + Mutex.lock t.mutex; + Queue.add + (Out_event.Ret (id, Error (`Curl_err (Curl.strerror exit_code)))) + t.out_event; + Mutex.unlock t.mutex; + process_finished t + | None -> assert false) + | None -> () + + let rec loop t = + let timeout = + CCOption.map + (fun duration -> + let sec = Duration.to_f duration in + let frac, sec = modf sec in + let nsec = frac *. 1e9 in + Kqueue.Timeout.create ~sec:(CCFloat.to_int sec) ~nsec:(CCFloat.to_int nsec)) + t.timeout + in + Logs.debug (fun m -> m "WAIT : timeout=%a" (CCOption.pp Duration.pp) t.timeout); + let start = Mtime_clock.elapsed () in + let ret = + Kqueue.kevent t.kq ~changelist:Kqueue.Eventlist.null ~eventlist:t.eventlist ~timeout + in + assert (ret >= 0); + let end_ = Mtime_clock.elapsed () in + let wait_time = Mtime.Span.(to_float_ns (abs_diff start end_)) /. 1e9 in + t.timeout <- + CCOption.map + (fun timeout -> Duration.of_f (CCFloat.max 0.0 (Duration.to_f timeout -. wait_time))) + t.timeout; + Logs.debug (fun m -> m "RET : %d" ret); + if ret > 0 then ( + let eventfd_event = ref false in + Kqueue.Eventlist.iter + ~f:(fun event -> + match Kqueue.Event.of_kevent event with + | Kqueue.Event.Read r + when Kqueue.unsafe_file_descr_of_int r.Kqueue.Event.Read.descr = t.wait_eventfd -> + Logs.debug (fun m -> m "WAIT_EVENTFD : fd=%d" r.Kqueue.Event.Read.descr); + consume_eventfd t.wait_eventfd; + eventfd_event := true; + () + | Kqueue.Event.Read r -> + Logs.debug (fun m -> m "POLL_IN : fd=%d" r.Kqueue.Event.Read.descr); + let fd = Kqueue.unsafe_file_descr_of_int r.Kqueue.Event.Read.descr in + ignore (Curl.Multi.action t.mt fd Curl.Multi.EV_IN) + | Kqueue.Event.Write w -> + Logs.debug (fun m -> m "POLL_OUT : fd=%d" w.Kqueue.Event.Write.descr); + let fd = Kqueue.unsafe_file_descr_of_int w.Kqueue.Event.Write.descr in + ignore (Curl.Multi.action t.mt fd Curl.Multi.EV_OUT) + | _ -> ()) + t.eventlist; + if !eventfd_event && ret = 1 then Curl.Multi.action_timeout t.mt) + else Curl.Multi.action_timeout t.mt; + process_in_events t; + Curl.Multi.action_timeout t.mt; + if not t.shutdown then ( + process_finished t; + trigger_out_events t; + loop t) + + let start () = + let wait_loop_eventfd, trigger_server_eventfd = Unix.pipe ~cloexec:true () in + let wait_server_eventfd, trigger_loop_eventfd = Unix.pipe ~cloexec:true () in + UnixLabels.set_nonblock wait_loop_eventfd; + UnixLabels.set_nonblock trigger_loop_eventfd; + UnixLabels.set_nonblock wait_server_eventfd; + UnixLabels.set_nonblock trigger_server_eventfd; + let t = + { + kq = Kqueue.create (); + eventlist = Kqueue.Eventlist.create 1024; + trigger_eventfd = trigger_loop_eventfd; + wait_eventfd = wait_loop_eventfd; + in_event = Queue.create (); + out_event = Queue.create (); + mutex = Mutex.create (); + mt = Curl.Multi.create (); + poll_in = Int_set.empty; + poll_out = Int_set.empty; + requests = Id_map.empty; + responses = Id_map.empty; + handles = Id_map.empty; + timeout = None; + shutdown = false; + } + in + Curl.Multi.set_socket_function t.mt (socket_function t); + Curl.Multi.set_timer_function t.mt (function + | -1 -> + Logs.debug (fun m -> m "TIMER : DISABLE"); + t.timeout <- None + | timeout -> + Logs.debug (fun m -> m "TIMER : SET : %d" timeout); + t.timeout <- Some (Duration.of_ms timeout)); + ignore + (Domain.spawn (fun () -> + try + Kqueue.Eventlist.set_from_list + t.eventlist + [ + Kqueue.Change.( + Filter.to_kevent + Action.(to_t [ Flag.Add ]) + (Filter.Read (Kqueue.unsafe_int_of_file_descr t.wait_eventfd))); + ]; + let ret = + Kqueue.kevent + t.kq + ~changelist:t.eventlist + ~eventlist:Kqueue.Eventlist.null + ~timeout:None + in + if ret <> 0 then raise (Failure "kevent error"); + loop t + with exn -> Logs.err (fun m -> m "%s" (Printexc.to_string exn)))); + (wait_server_eventfd, trigger_server_eventfd, t.mutex, t.in_event, t.out_event) + end + + module Server = struct + module Msg = struct + type t = + | Request of { + request : Request.t; + p : (Response.t, request_err) result Abb.Future.Promise.t; + } + | Cancel of Id.t + | Iterate + end + + type t = { + wait_eventfd : Unix.file_descr; + trigger_eventfd : Unix.file_descr; + mutex : Mutex.t; + in_event : In_event.t Queue.t; + out_event : Out_event.t Queue.t; + iterate_fut : unit Abb.Future.t; + body_readers : (string -> unit Abb.Future.t) Id_map.t; + responses : (Request.t * (Response.t, request_err) result Abb.Future.Promise.t) Id_map.t; + } + + let rec process_events t = + Mutex.lock t.mutex; + let event = Queue.take_opt t.out_event in + Mutex.unlock t.mutex; + match event with + | Some (Out_event.Ret (id, ret)) -> ( + let open Abb.Future.Infix_monad in + match Id_map.get id t.responses with + | Some (request, p) -> + Logs.debug (fun m -> m "RET : id=%s : uri=%a" id Uri.pp request.Request.uri); + Abb.Future.Promise.set p ret + >>= fun () -> + process_events { t with + body_readers = Id_map.remove id t.body_readers; responses = Id_map.remove id t.responses; - requests = Id_map.remove id t.requests; - handles = Id_map.remove id t.handles; } - in - let resp = { resp with Response.status } in - Abb.Future.Promise.set p (Ok resp) >>= fun () -> iterate_removed t - | _, _ -> - Logs.debug (fun m -> m "impossible"); - assert false) + | None -> process_events t) + | Some (Out_event.Body (id, string)) -> ( + let open Abb.Future.Infix_monad in + match Id_map.get id t.body_readers with + | Some body_reader -> body_reader string >>= fun () -> process_events t + | None -> process_events t) | None -> Abb.Future.return t - let run_iter t w = - let open Abb.Future.Infix_monad in - Logs.debug (fun m -> m "perform"); - let still_running = Curl.Multi.perform t.mt in - Logs.debug (fun m -> m "still_running : %d" still_running); - process_event t w >>= fun t -> iterate_removed t - let handle_msg t w r = function - | Msg.Request - ({ Msg.Request.options; headers; body_reader; meth_; uri; id_p; _ } as request) -> - let open Abb.Future.Infix_monad in - let id, id_gen = Id.Gen.next t.id_gen in - Logs.debug (fun m -> m "request : %a : %s" Uri.pp uri id); - Abb.Future.Promise.set id_p id - >>= fun () -> - let handle = Curl.init () in - Logs.debug (fun m -> - Curl.set_verbose handle true; - m "verbose"); + | Msg.Request { request; p } -> + let id = request.Request.id in + Logs.debug (fun m -> m "MSG : REQUEST : id=%s : uri=%a" id Uri.pp request.Request.uri); + let body_reader = request.Request.body_reader in let t = { t with - id_gen; - requests = Id_map.add id request t.requests; - responses = - Id_map.add - id - { Response.status = `Internal_server_error; headers = Headers.empty } - t.responses; - handles = Id_map.add id handle t.handles; + body_readers = Id_map.add id body_reader t.body_readers; + responses = Id_map.add id (request, p) t.responses; } in - CCList.iter - (function - | Options.Follow_location -> Curl.set_followlocation handle true) - options; - (* Use our id to track this *) - Curl.setopt handle (Curl.CURLOPT_PRIVATE id); - setup_request handle meth_ headers uri; - setup_response handle t.ev_queue id; - Curl.Multi.add t.mt handle; - Abb.Future.return t - | Msg.Cancel id -> ( - Logs.debug (fun m -> m "canceling : %s" id); - match Id_map.get id t.handles with - | Some handle -> - let open Abb.Future.Infix_monad in - Curl.Multi.remove t.mt handle; - (match Id_map.get id t.requests with - | Some { Msg.Request.p; uri; _ } -> - Logs.debug (fun m -> m "canceled : %s : %a" id Uri.pp uri); - Abb.Future.Promise.set p (Error `Cancelled) - | None -> Abb.Future.return ()) - >>= fun () -> - Abb.Future.return - { - t with - requests = Id_map.remove id t.requests; - responses = Id_map.remove id t.responses; - handles = Id_map.remove id t.handles; - } - | None -> Abb.Future.return t) - | Msg.Iterate_in fd -> - let open Abb.Future.Infix_monad in - Logs.debug (fun m -> m "iterate_in : %d" (unsafe_int_of_file_descr fd)); - (* TODO: Handle errors *) - ignore (Curl.Multi.action t.mt fd Curl.Multi.EV_IN); - start_fd_listen fd w Abb.Socket.readable (Msg.Iterate_in fd) - >>= fun fut -> - let t = { t with fds_in = Fd_map.add fd fut t.fds_in } in + Mutex.lock t.mutex; + Queue.add (In_event.Request request) t.in_event; + Mutex.unlock t.mutex; + trigger_eventfd t.trigger_eventfd; Abb.Future.return t - | Msg.Iterate_out fd -> + | Msg.Cancel id -> let open Abb.Future.Infix_monad in - Logs.debug (fun m -> m "iterate_out : %d" (unsafe_int_of_file_descr fd)); - (* TODO: Handle errors *) - ignore (Curl.Multi.action t.mt fd Curl.Multi.EV_OUT); - start_fd_listen fd w Abb.Socket.writable (Msg.Iterate_out fd) - >>= fun fut -> - let t = { t with fds_in = Fd_map.add fd fut t.fds_out } in - Abb.Future.return t - | Msg.Timeout -> - Logs.debug (fun m -> m "timeout"); - Curl.Multi.action_timeout t.mt; - Abb.Future.return t + Logs.debug (fun m -> m "MSG : CANCEL : id=%s" id); + Mutex.lock t.mutex; + Queue.add (In_event.Cancel id) t.in_event; + Mutex.unlock t.mutex; + trigger_eventfd t.trigger_eventfd; + (match Id_map.get id t.responses with + | Some (_, p) -> Abb.Future.Promise.set p (Error `Cancelled) + | None -> Fc.unit) + >>= fun () -> + Abb.Future.return + { + t with + body_readers = Id_map.remove id t.body_readers; + responses = Id_map.remove id t.responses; + } + | Msg.Iterate -> process_events t let rec loop t w r = let open Abb.Future.Infix_monad in Channel.recv r >>= function - | `Ok msg -> handle_msg t w r msg >>= fun t -> run_iter t w >>= fun t -> loop t w r + | `Ok msg -> handle_msg t w r msg >>= fun t -> loop t w r | `Closed -> - let open Abb.Future.Infix_monad in - Logs.debug (fun m -> m "closing"); - run_iter t w - >>= fun t -> - Id_map.iter - (fun _ handle -> - Curl.Multi.remove t.mt handle; - Curl.cleanup handle) - t.handles; - Fc.List.iter - ~f:Abb.Future.abort - (CCList.map snd (Fd_map.to_list t.fds_in @ Fd_map.to_list t.fds_out)) - >>= fun () -> - let t = - { t with fds_in = Fd_map.empty; fds_out = Fd_map.empty; handles = Id_map.empty } - in - (try Curl.Multi.cleanup t.mt - with exn -> - Logs.debug (fun m -> m "failed : %s" (Printexc.to_string exn)); - raise exn); - Fc.ignore (process_event t w) - >>= fun () -> - Logs.debug (fun m -> m "closed"); + Mutex.lock t.mutex; + Queue.add In_event.Shutdown t.in_event; + Mutex.unlock t.mutex; + trigger_eventfd t.trigger_eventfd; Abb.Future.return () + + let rec iterate_loop eventfd buf w = + let open Abb.Future.Infix_monad in + Abb.File.read eventfd ~buf ~pos:0 ~len:(Bytes.length buf) + >>= fun _ -> + Channel.send w Msg.Iterate + >>= function + | `Ok () -> iterate_loop eventfd buf w + | `Closed -> Abb.Future.return () + + let start w r = + let open Abb.Future.Infix_monad in + let wait_eventfd, trigger_eventfd, mutex, in_event, out_event = Loop.start () in + Abb.Future.fork + (let buf = Bytes.create 4 in + let eventfd = Abb.File.of_native wait_eventfd in + iterate_loop eventfd buf w) + >>= fun iterate_fut -> + let t = + { + wait_eventfd; + trigger_eventfd; + mutex; + in_event; + out_event; + iterate_fut; + body_readers = Id_map.empty; + responses = Id_map.empty; + } + in + Logs.debug (fun m -> m "LOOP"); + loop t w r end - type t = Server.Msg.t Service_local.w + type t = { + w : Server.Msg.t Service_local.w; + mutable id_gen : Id.Gen.t; + } let create () = - Curl.global_init Curl.CURLINIT_GLOBALALL; - let t = - { - Server.mt = Curl.Multi.create (); - requests = Id_map.empty; - responses = Id_map.empty; - handles = Id_map.empty; - fds_in = Fd_map.empty; - fds_out = Fd_map.empty; - ev_queue = Queue.create (); - id_gen = Id.Gen.make (); - timeout = None; - } - in - Curl.Multi.set_socket_function t.Server.mt (fun fd poll -> - Logs.debug (fun m -> - m - "socket_function : %s : %d" - (match poll with - | Curl.Multi.POLL_NONE -> "poll_none" - | Curl.Multi.POLL_IN -> "poll_in" - | Curl.Multi.POLL_OUT -> "poll_out" - | Curl.Multi.POLL_INOUT -> "poll_inout" - | Curl.Multi.POLL_REMOVE -> "poll_remove") - (unsafe_int_of_file_descr fd)); - Queue.add (Event.Socket (fd, poll)) t.Server.ev_queue); - Curl.Multi.set_closesocket_function t.Server.mt (fun fd -> - Logs.debug (fun m -> m "closesocket_function : %d" (unsafe_int_of_file_descr fd)); - Queue.add (Event.Close_socket fd) t.Server.ev_queue); - Curl.Multi.set_timer_function t.Server.mt (fun timeout -> - Logs.debug (fun m -> m "timeout_function : %d" timeout); - Queue.add (Event.Set_timeout timeout) t.Server.ev_queue); - Service_local.create (Server.loop t) - - let destroy t = Fc.ignore (Channel.close t) + let open Abb.Future.Infix_monad in + Service_local.create Server.start + >>= fun w -> + Logs.debug (fun m -> m "STARTED"); + Abb.Future.return { w; id_gen = Id.Gen.make () } + + let destroy t = Fc.ignore (Channel.close t.w) let request t options headers body_reader meth_ uri = let open Fc.Infix_result_monad in - let id_p = Abb.Future.Promise.create () in + let id, id_gen = Id.Gen.next t.id_gen in + t.id_gen <- id_gen; let p = Abb.Future.Promise.create () in Channel.Combinators.to_result (Channel.send - t + t.w (Server.Msg.Request - { Server.Msg.Request.options; headers; body_reader; meth_; uri; id_p; p })) - >>= fun () -> Abb.Future.return (Ok (id_p, p)) + { request = { Request.options; headers; body_reader; meth_; uri; id }; p })) + >>= fun () -> Abb.Future.return (Ok (id, Abb.Future.Promise.future p)) - let cancel t id = Channel.Combinators.to_result (Channel.send t (Server.Msg.Cancel id)) + let cancel t id = Channel.Combinators.to_result (Channel.send t.w (Server.Msg.Cancel id)) end + let default_connector = Connector.create () + let call ?connector ?(options = Options.default) ?(headers = Headers.empty) meth_ uri = let open Abb.Future.Infix_monad in - let create_connector, destroy_connector = - match connector with - | None -> (Connector.create, Connector.destroy) - | Some connector -> ((fun _ -> Abb.Future.return connector), CCFun.const Fc.unit) - in Fc.protect_finally ~setup:(fun () -> let open Abb.Future.Infix_monad in - create_connector () + let connector = + match connector with + | None -> default_connector + | Some connector -> Abb.Future.return connector + in + connector >>= fun connector -> let open Fc.Infix_result_monad in let buf = Buffer.create 10 in @@ -828,15 +1031,12 @@ module Make (Abb : Abb_intf.S with type Native.t = Unix.file_descr) = struct Abb.Future.return () in Connector.request connector options headers body meth_ uri - >>= fun (id_p, p) -> - let open Abb.Future.Infix_monad in - Abb.Future.Promise.future id_p >>= fun id -> Abb.Future.return (Ok (connector, id, buf, p))) + >>= fun (id, p) -> Abb.Future.return (Ok (connector, id, buf, p))) (fun res -> let open Fc.Infix_result_monad in Abb.Future.return res >>= fun (_, _, buf, p) -> - Abb.Future.Promise.future p - >>= fun resp -> Abb.Future.return (Ok (resp, Buffer.contents buf))) + p >>= fun resp -> Abb.Future.return (Ok (resp, Buffer.contents buf))) ~finally:(fun res -> Fc.ignore (let open Fc.Infix_result_monad in @@ -846,7 +1046,7 @@ module Make (Abb : Abb_intf.S with type Native.t = Unix.file_descr) = struct however we got to this [finally], then cancel the request. If we are in the [finally] because the request ended successfully, then this is a noop. *) - Connector.cancel connector id >>= fun () -> Fc.to_result (destroy_connector connector))) + Connector.cancel connector id)) >>= function | Ok res -> Abb.Future.return (Ok res) | Error (#request_err as err) -> Abb.Future.return (Error err) diff --git a/code/src/abb_curl/abb_curl.mli b/code/src/abb_curl/abb_curl.mli index 1448e36f0..4fd50120b 100644 --- a/code/src/abb_curl/abb_curl.mli +++ b/code/src/abb_curl/abb_curl.mli @@ -120,7 +120,10 @@ module Response : sig end module Options : sig - type opt = Follow_location + type opt = + | Follow_location + | Http_version of [ `Http2 | `Http1_1 ] + type t = opt list val default : t @@ -133,6 +136,7 @@ module Make (Abb : Abb_intf.S with type Native.t = Unix.file_descr) : sig module Status = Status module Headers = Headers module Response = Response + module Options = Options module Connector : sig type t @@ -144,6 +148,7 @@ module Make (Abb : Abb_intf.S with type Native.t = Unix.file_descr) : sig type request_err = [ `Closed | `Cancelled + | `Curl_err of string ] [@@deriving show, eq] diff --git a/code/src/abb_curl_cli/abb_curl_cli.ml b/code/src/abb_curl_cli/abb_curl_cli.ml index 3eb05e825..50746b559 100644 --- a/code/src/abb_curl_cli/abb_curl_cli.ml +++ b/code/src/abb_curl_cli/abb_curl_cli.ml @@ -1,12 +1,16 @@ module Abb = Abb_scheduler_kqueue module Curl = Abb_curl.Make (Abb) +module Fc = Abb_future_combinators.Make (Abb.Future) let get uri = let open Abb.Future.Infix_monad in Curl.get uri >>= function | Ok (resp, body) -> - Printf.printf "%d\n" (CCString.length body); + CCList.iter (fun (k, v) -> Printf.printf "%s - %s: %s\n%!" (Uri.to_string uri) k v) + @@ Curl.Headers.to_list + @@ Curl.Response.headers resp; + Printf.printf "%s - %d\n" (Uri.to_string uri) (CCString.length body); Abb.Future.return () | Error _ -> assert false @@ -36,11 +40,9 @@ let main () = in Logs.set_reporter (reporter Format.std_formatter); Logs.set_level (Some Logs.Debug); - let rec run = function - | [] -> Abb.Future.return () - | uri :: xs -> - let open Abb.Future.Infix_monad in - get (Uri.of_string uri) >>= fun () -> run xs + let run uris = + let open Abb.Future.Infix_monad in + Fc.all (CCList.map (fun uri -> get (Uri.of_string uri)) uris) >>= fun _ -> Abb.Future.return () in match Abb.Scheduler.run_with_state (fun () -> run (List.drop 1 (Array.to_list Sys.argv))) with | `Det () -> () diff --git a/code/src/abb_curl_easy/abb_curl_easy.ml b/code/src/abb_curl_easy/abb_curl_easy.ml index addfaf806..0c8717aa0 100644 --- a/code/src/abb_curl_easy/abb_curl_easy.ml +++ b/code/src/abb_curl_easy/abb_curl_easy.ml @@ -1,5 +1,5 @@ let () = Curl.global_init Curl.CURLINIT_GLOBALALL -let src = Logs.Src.create "abb_curl" +let src = Logs.Src.create "abb_curl_easy" module Logs = (val Logs.src_log src : Logs.LOG) diff --git a/code/src/githubc2_abb/githubc2_abb.ml b/code/src/githubc2_abb/githubc2_abb.ml index 67c4fa13c..9758958c0 100644 --- a/code/src/githubc2_abb/githubc2_abb.ml +++ b/code/src/githubc2_abb/githubc2_abb.ml @@ -1,4 +1,4 @@ -module Http = Abb_curl_easy.Make (Abb) +module Http = Abb_curl.Make (Abb) let base_url = Uri.of_string "https://api.github.com/" @@ -19,11 +19,7 @@ module Io = struct | `Post -> `POST body in let headers' = Http.Headers.of_list headers in - Http.call - ~options:Http.Options.(with_opt (Timeout (Duration.of_sec 4)) default) - ~headers:headers' - meth' - uri + Http.call ~headers:headers' meth' uri >>= function | Ok (resp, body) -> let headers = resp |> Http.Response.headers |> Http.Headers.to_list in diff --git a/code/src/githubc2_abb/githubc2_abb.mli b/code/src/githubc2_abb/githubc2_abb.mli index 418e8608a..d1e93d835 100644 --- a/code/src/githubc2_abb/githubc2_abb.mli +++ b/code/src/githubc2_abb/githubc2_abb.mli @@ -8,7 +8,7 @@ end type call_err = [ `Conversion_err of string * string Openapi.Response.t | `Missing_response of string Openapi.Response.t - | `Io_err of Abb_curl_easy.Make(Abb).request_err + | `Io_err of Abb_curl.Make(Abb).request_err | `Timeout ] [@@deriving show] diff --git a/code/src/terrat/terrat_ep_tenv.ml b/code/src/terrat/terrat_ep_tenv.ml index f4e074772..6fc988288 100644 --- a/code/src/terrat/terrat_ep_tenv.ml +++ b/code/src/terrat/terrat_ep_tenv.ml @@ -1,4 +1,4 @@ -module Http = Abb_curl_easy.Make (Abb) +module Http = Abb_curl.Make (Abb) let github_api_host = Uri.of_string "https://api.github.com" let github_host = Uri.of_string "https://github.com" diff --git a/code/src/terrat_github/terrat_github.mli b/code/src/terrat_github/terrat_github.mli index b21798a19..93ddb2afb 100644 --- a/code/src/terrat_github/terrat_github.mli +++ b/code/src/terrat_github/terrat_github.mli @@ -371,14 +371,14 @@ val get_repo_collaborator_permission : module Oauth : sig type authorize_err = [ `Authorize_err of string - | Abb_curl_easy.Make(Abb).request_err + | Abb_curl.Make(Abb).request_err ] [@@deriving show] type refresh_err = [ `Refresh_err of string | `Bad_refresh_token - | Abb_curl_easy.Make(Abb).request_err + | Abb_curl.Make(Abb).request_err ] [@@deriving show] diff --git a/code/src/terrat_telemetry/terrat_telemetry.ml b/code/src/terrat_telemetry/terrat_telemetry.ml index 208552d29..dd519f81f 100644 --- a/code/src/terrat_telemetry/terrat_telemetry.ml +++ b/code/src/terrat_telemetry/terrat_telemetry.ml @@ -1,4 +1,4 @@ -module Http = Abb_curl_easy.Make (Abb) +module Http = Abb_curl.Make (Abb) let one_hour = 60.0 *. 60.0 @@ -33,13 +33,12 @@ let send' telemetry_config event = (* For some reason, on dev ngrok this request hangs if it is HTTP2, but forcing it to HTTP/1.1 works. *) Abbs_future_combinators.ignore - (Http.post - ~options: - Http.Options.( - with_opt (Http_version `Http1_1) - @@ with_opt (Timeout (Duration.of_sec 1)) default) - ~headers:http_headers - uri) + (Abbs_future_combinators.timeout + ~timeout:(Abb.Sys.sleep 1.0) + (Http.post + ~options:Http.Options.(with_opt (Http_version `Http1_1) default) + ~headers:http_headers + uri)) | Event.Run { github_app_id; step; owner; repo } -> let uri = Uri.with_path @@ -55,13 +54,12 @@ let send' telemetry_config event = (* For some reason, on dev ngrok this request hangs if it is HTTP2, but forcing it to HTTP/1.1 works. *) Abbs_future_combinators.ignore - (Http.post - ~options: - Http.Options.( - with_opt (Http_version `Http1_1) - @@ with_opt (Timeout (Duration.of_sec 1)) default) - ~headers:http_headers - uri) + (Abbs_future_combinators.timeout + ~timeout:(Abb.Sys.sleep 1.0) + (Http.post + ~options:Http.Options.(with_opt (Http_version `Http1_1) default) + ~headers:http_headers + uri)) | Event.Ping { github_app_id } -> let uri = Uri.with_path @@ -72,13 +70,12 @@ let send' telemetry_config event = (* For some reason, on dev ngrok this request hangs if it is HTTP2, but forcing it to HTTP/1.1 works. *) Abbs_future_combinators.ignore - (Http.post - ~options: - Http.Options.( - with_opt (Http_version `Http1_1) - @@ with_opt (Timeout (Duration.of_sec 1)) default) - ~headers:http_headers - uri)) + (Abbs_future_combinators.timeout + ~timeout:(Abb.Sys.sleep 1.0) + (Http.post + ~options:Http.Options.(with_opt (Http_version `Http1_1) default) + ~headers:http_headers + uri))) let send telemetry_config event = Abbs_future_combinators.ignore (Abb.Future.fork (send' telemetry_config event)) From a4aed67d0d03fc5e358f89d1654decf384079f9f Mon Sep 17 00:00:00 2001 From: Malcolm Date: Wed, 26 Feb 2025 13:00:13 +0000 Subject: [PATCH 1116/1120] #324 REFACTOR Make specifying loggers more fine-grained --- code/src/terrat_ee/terrat_ee.ml | 70 ++++++++++++++++++------------- code/src/terrat_oss/terrat_oss.ml | 70 ++++++++++++++++++------------- 2 files changed, 84 insertions(+), 56 deletions(-) diff --git a/code/src/terrat_ee/terrat_ee.ml b/code/src/terrat_ee/terrat_ee.ml index f0ce37f39..fd1aca350 100644 --- a/code/src/terrat_ee/terrat_ee.ml +++ b/code/src/terrat_ee/terrat_ee.ml @@ -43,44 +43,58 @@ module Cmdline = struct in { Logs.report } - let setup_log level dns_logging http_logging = + let setup_log level loggers = + let loggers = + CCOption.map_or + ~default:[] + (fun loggers -> + loggers + |> CCString.split_on_char ',' + |> CCList.map (function + | logger when CCString.length logger > 0 && CCString.get logger 0 = '+' -> + (`Add, CCString.drop 1 logger) + | logger when CCString.length logger > 0 && CCString.get logger 0 = '-' -> + (`Remove, CCString.drop 1 logger) + | logger -> raise (Failure (Printf.sprintf "Unknown logger: %S" logger)))) + loggers + in Logs.set_reporter (reporter Format.std_formatter); Logs.set_level level; + let default_remove_loggers = + [ + "happy-eyeballs"; + "dns_client"; + "dns_cache"; + "abb.dns"; + "cohttp_abb"; + "cohttp_abb.io"; + "abb_curl"; + "abb_curl_easy"; + ] + in + let loggers = + CCList.fold_left + (fun acc -> function + | `Add, logger -> CCList.remove ~eq:CCString.equal ~key:logger acc + | `Remove, logger -> logger :: acc) + default_remove_loggers + loggers + in CCList.iter (fun src -> - if - (not dns_logging) - && CCList.mem - ~eq:CCString.equal - (Logs.Src.name src) - [ "happy-eyeballs"; "dns_client"; "dns_cache"; "abb.dns" ] - || (not http_logging) - && CCList.mem - ~eq:CCString.equal - (Logs.Src.name src) - [ "cohttp_abb"; "cohttp_abb.io"; "abb_curl"; "abb_curl_easy" ] - then - (* Increase these loggers because they are too verbose *) + if CCList.mem ~eq:CCString.equal (Logs.Src.name src) loggers then Logs.Src.set_level src (Some Logs.Error)) (Logs.Src.list ()) - let dns_logging = - let env = - let doc = "Enable DNS logging" in - C.Cmd.Env.info ~doc "TERRAT_DNS_LOGGING" - in - let doc = "Log DNS operations." in - C.Arg.(value & flag & info [ "dns-logging" ] ~env ~doc) - - let http_logging = + let loggers = let env = - let doc = "Enable HTTP logging" in - C.Cmd.Env.info ~doc "TERRAT_HTTP_LOGGING" + let doc = "Specify logging subsystems" in + C.Cmd.Env.info ~doc "TERRAT_LOGGERS" in - let doc = "Log HTTP operations." in - C.Arg.(value & flag & info [ "http-logging" ] ~env ~doc) + let doc = "Specify logging subsystems. Comma separated." in + C.Arg.(value & opt (some string) None & info [ "loggers" ] ~env ~doc) - let logs = C.Term.(const setup_log $ Logs_cli.level () $ dns_logging $ http_logging) + let logs = C.Term.(const setup_log $ Logs_cli.level () $ loggers) let app_id = let doc = "App ID." in diff --git a/code/src/terrat_oss/terrat_oss.ml b/code/src/terrat_oss/terrat_oss.ml index 4e527f5fe..572f47c09 100644 --- a/code/src/terrat_oss/terrat_oss.ml +++ b/code/src/terrat_oss/terrat_oss.ml @@ -43,44 +43,58 @@ module Cmdline = struct in { Logs.report } - let setup_log level dns_logging http_logging = + let setup_log level loggers = + let loggers = + CCOption.map_or + ~default:[] + (fun loggers -> + loggers + |> CCString.split_on_char ',' + |> CCList.map (function + | logger when CCString.length logger > 0 && CCString.get logger 0 = '+' -> + (`Add, CCString.drop 1 logger) + | logger when CCString.length logger > 0 && CCString.get logger 0 = '-' -> + (`Remove, CCString.drop 1 logger) + | logger -> raise (Failure (Printf.sprintf "Unknown logger: %S" logger)))) + loggers + in Logs.set_reporter (reporter Format.std_formatter); Logs.set_level level; + let default_remove_loggers = + [ + "happy-eyeballs"; + "dns_client"; + "dns_cache"; + "abb.dns"; + "cohttp_abb"; + "cohttp_abb.io"; + "abb_curl"; + "abb_curl_easy"; + ] + in + let loggers = + CCList.fold_left + (fun acc -> function + | `Add, logger -> CCList.remove ~eq:CCString.equal ~key:logger acc + | `Remove, logger -> logger :: acc) + default_remove_loggers + loggers + in CCList.iter (fun src -> - if - (not dns_logging) - && CCList.mem - ~eq:CCString.equal - (Logs.Src.name src) - [ "happy-eyeballs"; "dns_client"; "dns_cache"; "abb.dns" ] - || (not http_logging) - && CCList.mem - ~eq:CCString.equal - (Logs.Src.name src) - [ "cohttp_abb"; "cohttp_abb.io"; "abb_curl"; "abb_curl_easy" ] - then - (* Increase these loggers because they are too verbose *) + if CCList.mem ~eq:CCString.equal (Logs.Src.name src) loggers then Logs.Src.set_level src (Some Logs.Error)) (Logs.Src.list ()) - let dns_logging = - let env = - let doc = "Enable DNS logging" in - C.Cmd.Env.info ~doc "TERRAT_DNS_LOGGING" - in - let doc = "Log DNS operations." in - C.Arg.(value & flag & info [ "dns-logging" ] ~env ~doc) - - let http_logging = + let loggers = let env = - let doc = "Enable HTTP logging" in - C.Cmd.Env.info ~doc "TERRAT_HTTP_LOGGING" + let doc = "Specify logging subsystems" in + C.Cmd.Env.info ~doc "TERRAT_LOGGERS" in - let doc = "Log HTTP operations." in - C.Arg.(value & flag & info [ "http-logging" ] ~env ~doc) + let doc = "Specify logging subsystems. Comma separated." in + C.Arg.(value & opt (some string) None & info [ "loggers" ] ~env ~doc) - let logs = C.Term.(const setup_log $ Logs_cli.level () $ dns_logging $ http_logging) + let logs = C.Term.(const setup_log $ Logs_cli.level () $ loggers) let app_id = let doc = "App ID." in From c83c13e19d7bf836fac39f84c49758dfdf09e0c4 Mon Sep 17 00:00:00 2001 From: Malcolm Date: Wed, 26 Feb 2025 16:39:34 +0000 Subject: [PATCH 1117/1120] #324 #325 #317 ADD strace debugging to startup --- docker/terrat/Dockerfile | 2 ++ docker/terrat/service/terrat | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/docker/terrat/Dockerfile b/docker/terrat/Dockerfile index 8ab7c8d18..52fffb85d 100644 --- a/docker/terrat/Dockerfile +++ b/docker/terrat/Dockerfile @@ -133,6 +133,7 @@ RUN apk add --no-cache \ py3-yaml \ python3 \ runit \ + strace \ yj RUN mkdir -p /usr/local/bin /etc/service/terrat /etc/service/nginx /usr/local/share/terrat/ui/assets COPY docker/terrat/service/terrat /etc/service/terrat/run @@ -161,6 +162,7 @@ RUN apk add --no-cache \ py3-yaml \ python3 \ runit \ + strace \ yj RUN mkdir -p /usr/local/bin /etc/service/terrat /etc/service/nginx /usr/local/share/terrat/ui/assets COPY docker/terrat/service/terrat /etc/service/terrat/run diff --git a/docker/terrat/service/terrat b/docker/terrat/service/terrat index 107ba6770..705ff1343 100755 --- a/docker/terrat/service/terrat +++ b/docker/terrat/service/terrat @@ -144,7 +144,22 @@ def main(): subprocess.check_call(['/usr/local/bin/terrat', 'migrate', '--verbosity=debug']) # Run server - os.execv('/usr/local/bin/terrat', ['/usr/local/bin/terrat', 'server', '--verbosity=debug']) + if os.environ.get('TERRAT_STRACE'): + os.execv('/usr/bin/strace', + [ + '/usr/bin/strace', + '-ff', + '-o', + '/tmp/strace.log', + '-t', + '-s', + '100', + '-v', + '/usr/local/bin/terrat', + 'server', '--verbosity=debug' + ]) + else: + os.execv('/usr/local/bin/terrat', ['/usr/local/bin/terrat', 'server', '--verbosity=debug']) if __name__ == '__main__': From ba25b6ed5673090aa8448311735edb3a92227b89 Mon Sep 17 00:00:00 2001 From: Malcolm Date: Wed, 26 Feb 2025 22:53:54 +0000 Subject: [PATCH 1118/1120] #324 #325 UPDATE Base image --- config/base_image_config.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/base_image_config.sh b/config/base_image_config.sh index e8a01eaf0..63e9ded54 100644 --- a/config/base_image_config.sh +++ b/config/base_image_config.sh @@ -1,5 +1,5 @@ : "${CONTAINER_REGISTRY:=ghcr.io}" : "${GITHUB_REPOSITORY_OWNER:=terrateamio}" : "${BASE_IMAGE_NAME:=terrat-base}" -BASE_IMAGE_TAG="20250219-1245-bcaf954" +BASE_IMAGE_TAG="20250226-2230-239ce4b" BASE_IMAGE="${CONTAINER_REGISTRY}/${GITHUB_REPOSITORY_OWNER}/${BASE_IMAGE_NAME}:${BASE_IMAGE_TAG}" From d6b3ff6949ce6d276303ebc9c1be0f83cb637c31 Mon Sep 17 00:00:00 2001 From: Malcolm Date: Wed, 26 Feb 2025 23:10:32 +0000 Subject: [PATCH 1119/1120] #324 #325 FIX Copy libkqueue.so.0 into container --- docker/terrat/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker/terrat/Dockerfile b/docker/terrat/Dockerfile index 52fffb85d..1b09a83e9 100644 --- a/docker/terrat/Dockerfile +++ b/docker/terrat/Dockerfile @@ -140,6 +140,7 @@ COPY docker/terrat/service/terrat /etc/service/terrat/run COPY docker/terrat/service/nginx /etc/service/nginx/run COPY docker/terrat/nginx.conf.template /etc/nginx/nginx.conf.template COPY --from=terrat-ee-build /usr/lib/libkqueue.so /usr/lib/libkqueue.so +COPY --from=terrat-ee-build /usr/lib/libkqueue.so.0 /usr/lib/libkqueue.so.0 COPY --from=terrat-ee-build /mono/code/build/release/terrat_ee/terrat_ee.native /usr/local/bin/terrat COPY --from=terrat-ee-build /mono/code/build/release/terrat_ui_files/assets /usr/local/share/terrat/ui/assets/ EXPOSE 8080 @@ -169,6 +170,7 @@ COPY docker/terrat/service/terrat /etc/service/terrat/run COPY docker/terrat/service/nginx /etc/service/nginx/run COPY docker/terrat/nginx.conf.template /etc/nginx/nginx.conf.template COPY --from=terrat-oss-build /usr/lib/libkqueue.so /usr/lib/libkqueue.so +COPY --from=terrat-oss-build /usr/lib/libkqueue.so.0 /usr/lib/libkqueue.so.0 COPY --from=terrat-oss-build /mono/code/build/release/terrat_oss/terrat_oss.native /usr/local/bin/terrat EXPOSE 8080 CMD ["runsvdir", "/etc/service"] From ed69aad26399c47c887e4391b556445dc9f22817 Mon Sep 17 00:00:00 2001 From: Malcolm Date: Thu, 27 Feb 2025 11:13:18 +0000 Subject: [PATCH 1120/1120] #325 REFACTOR Make documentation reflect actual code --- code/src/abb_curl/abb_curl.mli | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/code/src/abb_curl/abb_curl.mli b/code/src/abb_curl/abb_curl.mli index 4fd50120b..faca91718 100644 --- a/code/src/abb_curl/abb_curl.mli +++ b/code/src/abb_curl/abb_curl.mli @@ -1,11 +1,11 @@ -(** Curl interface using the multi interface. DO NOT USE, this is in development and depending on - changes in an upcoming version of Curl. Using this will crash the program. - - The underlying issue is that file descriptors that are sent to [socketfunction] are not always - ones that we can control when they are closed. Because we need to alter the world in the Abb - monad, and we do not have access to the state in the callback. However, for some sockets, Curl - will call it [socketfunction] with [POLL_REMOVE] and then immediately close the socket, when - wrecks havoc with Abb. We need a new callback (which will hopefully be added to curl soon). *) +(** Curl interface using the multi interface. This runs each [Connector] in its own domain with its + own event loop. This is because libcurl expects that every operation requested in the + [socket_function] callback is completed by the end of the callback. This is not possible in Abb + because we do not have access to the scheduler in the callback. This is especially problematic + because after the [POLL_REMOVE] request, libcurl might close the file descriptor (the + [closesocketfunction] does not help here because libcurl manages other file descriptors that the + callback is not used on) before we remove it from kqueue. So, instead, we implement its own + event loop that can interact directly with the kqueue in the [socket_function] callback. *) module Method : sig type body = string