diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2005-06-18 01:52:23 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2005-06-18 01:52:23 +0000 |
commit | d6e2399b27e4680a5b1c6b7b93859abf0cadbf41 (patch) | |
tree | 21689a02039d22a9d8c83dfb15c24eb525a00abc | |
parent | 0cb1eefb1a92308c42327cdf4df7f473db8952d6 (diff) |
update to libevent 1.1a; keep local changes
ok grunk@
-rw-r--r-- | lib/libevent/buffer.c | 8 | ||||
-rw-r--r-- | lib/libevent/event.3 | 6 | ||||
-rw-r--r-- | lib/libevent/event.h | 4 | ||||
-rw-r--r-- | lib/libevent/kqueue.c | 26 | ||||
-rw-r--r-- | lib/libevent/poll.c | 244 | ||||
-rw-r--r-- | lib/libevent/select.c | 249 |
6 files changed, 371 insertions, 166 deletions
diff --git a/lib/libevent/buffer.c b/lib/libevent/buffer.c index 446f1d9ba2d..379415a7f33 100644 --- a/lib/libevent/buffer.c +++ b/lib/libevent/buffer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: buffer.c,v 1.5 2005/05/04 03:17:48 brad Exp $ */ +/* $OpenBSD: buffer.c,v 1.6 2005/06/18 01:52:22 brad Exp $ */ /* * Copyright (c) 2002, 2003 Niels Provos <provos@citi.umich.edu> @@ -186,10 +186,10 @@ evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen) char * evbuffer_readline(struct evbuffer *buffer) { - char *data = EVBUFFER_DATA(buffer); + u_char *data = EVBUFFER_DATA(buffer); size_t len = EVBUFFER_LENGTH(buffer); char *line; - int i; + u_int i; for (i = 0; i < len; i++) { if (data[i] == '\r' || data[i] == '\n') @@ -334,7 +334,7 @@ evbuffer_read(struct evbuffer *buf, int fd, int howmuch) #endif #ifdef FIONREAD - if (ioctl(fd, FIONREAD, &n) == -1) + if (ioctl(fd, FIONREAD, &n) == -1 || n == 0) n = EVBUFFER_MAX_READ; #endif if (howmuch < 0 || howmuch > n) diff --git a/lib/libevent/event.3 b/lib/libevent/event.3 index 25cb2e48eff..4eedc9edcc2 100644 --- a/lib/libevent/event.3 +++ b/lib/libevent/event.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: event.3,v 1.20 2005/05/04 03:17:48 brad Exp $ +.\" $OpenBSD: event.3,v 1.21 2005/06/18 01:52:22 brad Exp $ .\" .\" Copyright (c) 2000 Artur Grabowski <art@openbsd.org> .\" All rights reserved. @@ -196,7 +196,7 @@ After the signal handler sets .Nm event_dispatch will execute the callback function to process received signals. The callback returns 1 when no events are registered any more. -It can return -1 to indicate an error to the +It can return \-1 to indicate an error to the .Nm event library, causing .Fn event_dispatch @@ -366,7 +366,7 @@ The functions and .Fn evtimer_pending are abbreviations for common situations where only a timeout is required. -The file descriptor passed will be 0, and the event type will be +The file descriptor passed will be \-1, and the event type will be .Va EV_TIMEOUT . .Pp The functions diff --git a/lib/libevent/event.h b/lib/libevent/event.h index 44c3a6391be..2b3332f9fc5 100644 --- a/lib/libevent/event.h +++ b/lib/libevent/event.h @@ -1,4 +1,4 @@ -/* $OpenBSD: event.h,v 1.11 2005/05/07 03:07:53 brad Exp $ */ +/* $OpenBSD: event.h,v 1.12 2005/06/18 01:52:22 brad Exp $ */ /* * Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu> @@ -40,7 +40,7 @@ extern "C" { typedef unsigned char u_char; #endif -#define LIBEVENT_VERSION "1.0e" +#define LIBEVENT_VERSION "1.1a" #define EVLIST_TIMEOUT 0x01 #define EVLIST_INSERTED 0x02 diff --git a/lib/libevent/kqueue.c b/lib/libevent/kqueue.c index a1a02ff993b..2bdcf78b215 100644 --- a/lib/libevent/kqueue.c +++ b/lib/libevent/kqueue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kqueue.c,v 1.16 2005/05/04 03:17:48 brad Exp $ */ +/* $OpenBSD: kqueue.c,v 1.17 2005/06/18 01:52:22 brad Exp $ */ /* * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu> @@ -122,6 +122,27 @@ kq_init(void) } kqueueop->nevents = NEVENT; + /* Check for Mac OS X kqueue bug. */ + kqueueop->changes[0].ident = -1; + kqueueop->changes[0].filter = EVFILT_READ; + kqueueop->changes[0].flags = EV_ADD; + /* + * If kqueue works, then kevent will succeed, and it will + * stick an error in events[0]. If kqueue is broken, then + * kevent will fail. + */ + if (kevent(kq, + kqueueop->changes, 1, kqueueop->events, NEVENT, NULL) != 1 || + kqueueop->events[0].ident != -1 || + kqueueop->events[0].flags != EV_ERROR) { + event_warn("%s: detected broken kqueue; not using.", __func__); + free(kqueueop->changes); + free(kqueueop->events); + free(kqueueop); + close(kq); + return (NULL); + } + return (kqueueop); } @@ -218,11 +239,14 @@ kq_dispatch(struct event_base *base, void *arg, struct timeval *tv) * closed, * ENOENT when the file discriptor was closed and * then reopened. + * EINVAL for some reasons not understood; EINVAL + * should not be returned ever; but FreeBSD does :-\ * An error is also indicated when a callback deletes * an event we are still processing. In that case * the data field is set to ENOENT. */ if (events[i].data == EBADF || + events[i].data == EINVAL || events[i].data == ENOENT) continue; errno = events[i].data; diff --git a/lib/libevent/poll.c b/lib/libevent/poll.c index 35d5d4525dd..8f691bbae0d 100644 --- a/lib/libevent/poll.c +++ b/lib/libevent/poll.c @@ -1,4 +1,4 @@ -/* $OpenBSD: poll.c,v 1.8 2005/05/06 18:22:53 brad Exp $ */ +/* $OpenBSD: poll.c,v 1.9 2005/06/18 01:52:22 brad Exp $ */ /* * Copyright 2000-2003 Niels Provos <provos@citi.umich.edu> @@ -45,6 +45,9 @@ #include <string.h> #include <unistd.h> #include <errno.h> +#ifdef CHECK_INVARIANTS +#include <assert.h> +#endif #include "event.h" #include "event-internal.h" @@ -55,6 +58,7 @@ extern volatile sig_atomic_t evsignal_caught; struct pollop { int event_count; /* Highest number alloc */ + int nfds; /* Size of event_* */ int fd_count; /* Size of idxplus1_by_fd */ struct pollfd *event_set; struct event **event_r_back; @@ -110,97 +114,52 @@ poll_recalc(struct event_base *base, void *arg, int max) return (evsignal_recalc(&pop->evsigmask)); } -int -poll_dispatch(struct event_base *base, void *arg, struct timeval *tv) +#ifdef CHECK_INVARIANTS +static void +poll_check_ok(struct pollop *pop) { - int res, i, count, fd_count, sec, nfds; + int i, idx; struct event *ev; - struct pollop *pop = arg; - int *idxplus1_by_fd; - - count = pop->event_count; - fd_count = pop->fd_count; - idxplus1_by_fd = pop->idxplus1_by_fd; - memset(idxplus1_by_fd, 0, sizeof(int)*fd_count); - nfds = 0; - - TAILQ_FOREACH(ev, &base->eventqueue, ev_next) { - struct pollfd *pfd = NULL; - if (nfds + 1 >= count) { - if (count < 32) - count = 32; - else - count *= 2; - - /* We need more file descriptors */ - pop->event_set = realloc(pop->event_set, - count * sizeof(struct pollfd)); - if (pop->event_set == NULL) { - event_warn("realloc"); - return (-1); - } - pop->event_r_back = realloc(pop->event_r_back, - count * sizeof(struct event *)); - pop->event_w_back = realloc(pop->event_w_back, - count * sizeof(struct event *)); - if (pop->event_r_back == NULL || - pop->event_w_back == NULL) { - event_warn("realloc"); - return (-1); - } - pop->event_count = count; - } - if (!(ev->ev_events & (EV_READ|EV_WRITE))) - continue; - if (ev->ev_fd >= fd_count) { - int new_count; - if (fd_count < 32) - new_count = 32; - else - new_count = fd_count * 2; - while (new_count <= ev->ev_fd) - new_count *= 2; - idxplus1_by_fd = pop->idxplus1_by_fd = - realloc(pop->idxplus1_by_fd, new_count*sizeof(int)); - if (idxplus1_by_fd == NULL) { - event_warn("realloc"); - return (-1); - } - memset(pop->idxplus1_by_fd + fd_count, - 0, sizeof(int)*(new_count-fd_count)); - fd_count = pop->fd_count = new_count; - } - i = idxplus1_by_fd[ev->ev_fd] - 1; - if (i >= 0) { - pfd = &pop->event_set[i]; - } else { - i = nfds++; - pfd = &pop->event_set[i]; - pop->event_w_back[i] = pop->event_r_back[i] = NULL; - pfd->events = 0; - idxplus1_by_fd[ev->ev_fd] = i + 1; - } - - if (ev->ev_events & EV_WRITE) { - pfd->fd = ev->ev_fd; - pfd->events |= POLLOUT; - pfd->revents = 0; - pop->event_w_back[i] = ev; + for (i = 0; i < pop->fd_count; ++i) { + idx = pop->idxplus1_by_fd[i]-1; + if (idx < 0) + continue; + assert(pop->event_set[idx].fd == i); + if (pop->event_set[idx].events & POLLIN) { + ev = pop->event_r_back[idx]; + assert(ev); + assert(ev->ev_events & EV_READ); + assert(ev->ev_fd == i); } - if (ev->ev_events & EV_READ) { - pfd->fd = ev->ev_fd; - pfd->events |= POLLIN; - pfd->revents = 0; - - pop->event_r_back[i] = ev; + if (pop->event_set[idx].events & POLLOUT) { + ev = pop->event_w_back[idx]; + assert(ev); + assert(ev->ev_events & EV_WRITE); + assert(ev->ev_fd == i); } } + for (i = 0; i < pop->nfds; ++i) { + struct pollfd *pfd = &pop->event_set[i]; + assert(pop->idxplus1_by_fd[pfd->fd] == i+1); + } +} +#else +#define poll_check_ok(pop) +#endif + +int +poll_dispatch(struct event_base *base, void *arg, struct timeval *tv) +{ + int res, i, sec, nfds; + struct pollop *pop = arg; if (evsignal_deliver(&pop->evsigmask) == -1) return (-1); + poll_check_ok(pop); sec = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000; + nfds = pop->nfds; res = poll(pop->event_set, nfds, sec); if (evsignal_recalc(&pop->evsigmask) == -1) @@ -226,13 +185,14 @@ poll_dispatch(struct event_base *base, void *arg, struct timeval *tv) int what = pop->event_set[i].revents; struct event *r_ev = NULL, *w_ev = NULL; + if (!what) + continue; + res = 0; /* If the file gets closed notify */ - if (what & POLLHUP) + if (what & (POLLHUP|POLLERR)) what |= POLLIN|POLLOUT; - if (what & POLLERR) - what |= POLLIN|POLLOUT; if (what & POLLIN) { res |= EV_READ; r_ev = pop->event_r_back[i]; @@ -263,9 +223,79 @@ int poll_add(void *arg, struct event *ev) { struct pollop *pop = arg; + struct pollfd *pfd = NULL; + int i; if (ev->ev_events & EV_SIGNAL) return (evsignal_add(&pop->evsigmask, ev)); + if (!(ev->ev_events & (EV_READ|EV_WRITE))) + return (0); + + poll_check_ok(pop); + if (pop->nfds + 1 >= pop->event_count) { + if (pop->event_count < 32) + pop->event_count = 32; + else + pop->event_count *= 2; + + /* We need more file descriptors */ + pop->event_set = realloc(pop->event_set, + pop->event_count * sizeof(struct pollfd)); + if (pop->event_set == NULL) { + event_warn("realloc"); + return (-1); + } + pop->event_r_back = realloc(pop->event_r_back, + pop->event_count * sizeof(struct event *)); + pop->event_w_back = realloc(pop->event_w_back, + pop->event_count * sizeof(struct event *)); + if (pop->event_r_back == NULL || + pop->event_w_back == NULL) { + event_warn("realloc"); + return (-1); + } + } + if (ev->ev_fd >= pop->fd_count) { + int new_count; + if (pop->fd_count < 32) + new_count = 32; + else + new_count = pop->fd_count * 2; + while (new_count <= ev->ev_fd) + new_count *= 2; + pop->idxplus1_by_fd = + realloc(pop->idxplus1_by_fd, new_count*sizeof(int)); + if (pop->idxplus1_by_fd == NULL) { + event_warn("realloc"); + return (-1); + } + memset(pop->idxplus1_by_fd + pop->fd_count, + 0, sizeof(int)*(new_count - pop->fd_count)); + pop->fd_count = new_count; + } + + i = pop->idxplus1_by_fd[ev->ev_fd] - 1; + if (i >= 0) { + pfd = &pop->event_set[i]; + } else { + i = pop->nfds++; + pfd = &pop->event_set[i]; + pfd->events = 0; + pfd->fd = ev->ev_fd; + pop->event_w_back[i] = pop->event_r_back[i] = NULL; + pop->idxplus1_by_fd[ev->ev_fd] = i + 1; + } + + pfd->revents = 0; + if (ev->ev_events & EV_WRITE) { + pfd->events |= POLLOUT; + pop->event_w_back[i] = ev; + } + if (ev->ev_events & EV_READ) { + pfd->events |= POLLIN; + pop->event_r_back[i] = ev; + } + poll_check_ok(pop); return (0); } @@ -278,9 +308,51 @@ int poll_del(void *arg, struct event *ev) { struct pollop *pop = arg; + struct pollfd *pfd = NULL; + int i; + + if (ev->ev_events & EV_SIGNAL) + return (evsignal_del(&pop->evsigmask, ev)); + + if (!(ev->ev_events & (EV_READ|EV_WRITE))) + return (0); + + poll_check_ok(pop); + i = pop->idxplus1_by_fd[ev->ev_fd] - 1; + if (i < 0) + return (-1); - if (!(ev->ev_events & EV_SIGNAL)) + /* Do we still want to read or write? */ + pfd = &pop->event_set[i]; + if (ev->ev_events & EV_READ) { + pfd->events &= ~POLLIN; + pop->event_r_back[i] = NULL; + } + if (ev->ev_events & EV_WRITE) { + pfd->events &= ~POLLOUT; + pop->event_w_back[i] = NULL; + } + poll_check_ok(pop); + if (pfd->events) + /* Another event cares about that fd. */ return (0); - return (evsignal_del(&pop->evsigmask, ev)); + /* Okay, so we aren't interested in that fd anymore. */ + pop->idxplus1_by_fd[ev->ev_fd] = 0; + + --pop->nfds; + if (i != pop->nfds) { + /* + * Shift the last pollfd down into the now-unoccupied + * position. + */ + memcpy(&pop->event_set[i], &pop->event_set[pop->nfds], + sizeof(struct pollfd)); + pop->event_r_back[i] = pop->event_r_back[pop->nfds]; + pop->event_w_back[i] = pop->event_w_back[pop->nfds]; + pop->idxplus1_by_fd[pop->event_set[i].fd] = i + 1; + } + + poll_check_ok(pop); + return (0); } diff --git a/lib/libevent/select.c b/lib/libevent/select.c index d334b902ae6..48ab2e3ec0c 100644 --- a/lib/libevent/select.c +++ b/lib/libevent/select.c @@ -1,4 +1,4 @@ -/* $OpenBSD: select.c,v 1.10 2005/05/06 18:22:53 brad Exp $ */ +/* $OpenBSD: select.c,v 1.11 2005/06/18 01:52:22 brad Exp $ */ /* * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu> @@ -44,6 +44,9 @@ #include <string.h> #include <unistd.h> #include <errno.h> +#ifdef CHECK_INVARIANTS +#include <assert.h> +#endif #include "event.h" #include "event-internal.h" @@ -59,8 +62,12 @@ extern volatile sig_atomic_t evsignal_caught; struct selectop { int event_fds; /* Highest fd in fd set */ int event_fdsz; - fd_set *event_readset; - fd_set *event_writeset; + fd_set *event_readset_in; + fd_set *event_writeset_in; + fd_set *event_readset_out; + fd_set *event_writeset_out; + struct event **event_r_by_fd; + struct event **event_w_by_fd; sigset_t evsigmask; }; @@ -79,6 +86,8 @@ const struct eventop selectops = { select_dispatch }; +static int select_resize(struct selectop *sop, int fdsz); + void * select_init(void) { @@ -91,11 +100,40 @@ select_init(void) if (!(sop = calloc(1, sizeof(struct selectop)))) return (NULL); + select_resize(sop, howmany(32 + 1, NFDBITS)*sizeof(fd_mask)); + evsignal_init(&sop->evsigmask); return (sop); } +#ifdef CHECK_INVARIANTS +static void +check_selectop(struct selectop *sop) +{ + int i; + for (i=0;i<=sop->event_fds;++i) { + if (FD_ISSET(i, sop->event_readset_in)) { + assert(sop->event_r_by_fd[i]); + assert(sop->event_r_by_fd[i]->ev_events & EV_READ); + assert(sop->event_r_by_fd[i]->ev_fd == i); + } else { + assert(! sop->event_r_by_fd[i]); + } + if (FD_ISSET(i, sop->event_writeset_in)) { + assert(sop->event_w_by_fd[i]); + assert(sop->event_w_by_fd[i]->ev_events & EV_WRITE); + assert(sop->event_w_by_fd[i]->ev_fd == i); + } else { + assert(! sop->event_w_by_fd[i]); + } + } + +} +#else +#define check_selectop(sop) +#endif + /* * Called with the highest fd that we know about. If it is 0, completely * recalculate everything. @@ -105,41 +143,8 @@ int select_recalc(struct event_base *base, void *arg, int max) { struct selectop *sop = arg; - fd_set *readset, *writeset; - struct event *ev; - int fdsz; - - if (sop->event_fds < max) - sop->event_fds = max; - if (!sop->event_fds) { - TAILQ_FOREACH(ev, &base->eventqueue, ev_next) - if (ev->ev_fd > sop->event_fds) - sop->event_fds = ev->ev_fd; - } - - fdsz = howmany(sop->event_fds + 1, NFDBITS) * sizeof(fd_mask); - if (fdsz > sop->event_fdsz) { - if ((readset = realloc(sop->event_readset, fdsz)) == NULL) { - event_warn("malloc"); - return (-1); - } - - if ((writeset = realloc(sop->event_writeset, fdsz)) == NULL) { - event_warn("malloc"); - free(readset); - return (-1); - } - - memset((char *)readset + sop->event_fdsz, 0, - fdsz - sop->event_fdsz); - memset((char *)writeset + sop->event_fdsz, 0, - fdsz - sop->event_fdsz); - - sop->event_readset = readset; - sop->event_writeset = writeset; - sop->event_fdsz = fdsz; - } + check_selectop(sop); return (evsignal_recalc(&sop->evsigmask)); } @@ -147,26 +152,23 @@ select_recalc(struct event_base *base, void *arg, int max) int select_dispatch(struct event_base *base, void *arg, struct timeval *tv) { - int maxfd, res; - struct event *ev, *next; + int res, i; struct selectop *sop = arg; - memset(sop->event_readset, 0, sop->event_fdsz); - memset(sop->event_writeset, 0, sop->event_fdsz); + check_selectop(sop); - TAILQ_FOREACH(ev, &base->eventqueue, ev_next) { - if (ev->ev_events & EV_WRITE) - FD_SET(ev->ev_fd, sop->event_writeset); - if (ev->ev_events & EV_READ) - FD_SET(ev->ev_fd, sop->event_readset); - } + memcpy(sop->event_readset_out, sop->event_readset_in, + sop->event_fdsz); + memcpy(sop->event_writeset_out, sop->event_writeset_in, + sop->event_fdsz); if (evsignal_deliver(&sop->evsigmask) == -1) return (-1); - res = select(sop->event_fds + 1, sop->event_readset, - sop->event_writeset, NULL, tv); + res = select(sop->event_fds + 1, sop->event_readset_out, + sop->event_writeset_out, NULL, tv); + check_selectop(sop); if (evsignal_recalc(&sop->evsigmask) == -1) return (-1); @@ -183,32 +185,94 @@ select_dispatch(struct event_base *base, void *arg, struct timeval *tv) event_debug(("%s: select reports %d", __func__, res)); - maxfd = 0; - for (ev = TAILQ_FIRST(&base->eventqueue); ev != NULL; ev = next) { - next = TAILQ_NEXT(ev, ev_next); - + check_selectop(sop); + for (i = 0; i <= sop->event_fds; ++i) { + struct event *r_ev = NULL, *w_ev = NULL; res = 0; - if (FD_ISSET(ev->ev_fd, sop->event_readset)) + if (FD_ISSET(i, sop->event_readset_out)) { + r_ev = sop->event_r_by_fd[i]; res |= EV_READ; - if (FD_ISSET(ev->ev_fd, sop->event_writeset)) + } + if (FD_ISSET(i, sop->event_writeset_out)) { + w_ev = sop->event_w_by_fd[i]; res |= EV_WRITE; - res &= ev->ev_events; - - if (res) { - if (!(ev->ev_events & EV_PERSIST)) - event_del(ev); - else if (ev->ev_fd > maxfd) - maxfd = ev->ev_fd; - event_active(ev, res, 1); - } else if (ev->ev_fd > maxfd) - maxfd = ev->ev_fd; + } + if (r_ev && (res & r_ev->ev_events)) { + if (!(r_ev->ev_events & EV_PERSIST)) + event_del(r_ev); + event_active(r_ev, res & r_ev->ev_events, 1); + } + if (w_ev && w_ev != r_ev && (res & w_ev->ev_events)) { + if (!(w_ev->ev_events & EV_PERSIST)) + event_del(w_ev); + event_active(w_ev, res & w_ev->ev_events, 1); + } } + check_selectop(sop); - sop->event_fds = maxfd; + return (0); +} + + +static int +select_resize(struct selectop *sop, int fdsz) +{ + int n_events, n_events_old; + + fd_set *readset_in = NULL; + fd_set *writeset_in = NULL; + fd_set *readset_out = NULL; + fd_set *writeset_out = NULL; + struct event **r_by_fd = NULL; + struct event **w_by_fd = NULL; + + n_events = (fdsz/sizeof(fd_mask)) * NFDBITS; + n_events_old = (sop->event_fdsz/sizeof(fd_mask)) * NFDBITS; + + if (sop->event_readset_in) + check_selectop(sop); + + if ((readset_in = realloc(sop->event_readset_in, fdsz)) == NULL) + goto error; + sop->event_readset_in = readset_in; + if ((readset_out = realloc(sop->event_readset_out, fdsz)) == NULL) + goto error; + sop->event_readset_out = readset_out; + if ((writeset_in = realloc(sop->event_writeset_in, fdsz)) == NULL) + goto error; + sop->event_writeset_in = writeset_in; + if ((writeset_out = realloc(sop->event_writeset_out, fdsz)) == NULL) + goto error; + sop->event_writeset_out = writeset_out; + if ((r_by_fd = realloc(sop->event_r_by_fd, + n_events*sizeof(struct event*))) == NULL) + goto error; + sop->event_r_by_fd = r_by_fd; + if ((w_by_fd = realloc(sop->event_w_by_fd, + n_events * sizeof(struct event*))) == NULL) + goto error; + sop->event_w_by_fd = w_by_fd; + + memset((char *)sop->event_readset_in + sop->event_fdsz, 0, + fdsz - sop->event_fdsz); + memset((char *)sop->event_writeset_in + sop->event_fdsz, 0, + fdsz - sop->event_fdsz); + memset(sop->event_r_by_fd + n_events_old, 0, + (n_events-n_events_old) * sizeof(struct event*)); + memset(sop->event_w_by_fd + n_events_old, 0, + (n_events-n_events_old) * sizeof(struct event*)); + + sop->event_fdsz = fdsz; + check_selectop(sop); return (0); + + error: + event_warn("malloc"); + return (-1); } + int select_add(void *arg, struct event *ev) { @@ -217,12 +281,40 @@ select_add(void *arg, struct event *ev) if (ev->ev_events & EV_SIGNAL) return (evsignal_add(&sop->evsigmask, ev)); - /* + check_selectop(sop); + /* * Keep track of the highest fd, so that we can calculate the size * of the fd_sets for select(2) */ - if (sop->event_fds < ev->ev_fd) + if (sop->event_fds < ev->ev_fd) { + int fdsz = sop->event_fdsz; + + if (fdsz < sizeof(fd_mask)) + fdsz = sizeof(fd_mask); + + while (fdsz < + (howmany(ev->ev_fd + 1, NFDBITS) * sizeof(fd_mask))) + fdsz *= 2; + + if (fdsz != sop->event_fdsz) { + if (select_resize(sop, fdsz)) { + check_selectop(sop); + return (-1); + } + } + sop->event_fds = ev->ev_fd; + } + + if (ev->ev_events & EV_READ) { + FD_SET(ev->ev_fd, sop->event_readset_in); + sop->event_r_by_fd[ev->ev_fd] = ev; + } + if (ev->ev_events & EV_WRITE) { + FD_SET(ev->ev_fd, sop->event_writeset_in); + sop->event_w_by_fd[ev->ev_fd] = ev; + } + check_selectop(sop); return (0); } @@ -236,8 +328,25 @@ select_del(void *arg, struct event *ev) { struct selectop *sop = arg; - if (!(ev->ev_events & EV_SIGNAL)) + check_selectop(sop); + if (ev->ev_events & EV_SIGNAL) + return (evsignal_del(&sop->evsigmask, ev)); + + if (sop->event_fds < ev->ev_fd) { + check_selectop(sop); return (0); + } + + if (ev->ev_events & EV_READ) { + FD_CLR(ev->ev_fd, sop->event_readset_in); + sop->event_r_by_fd[ev->ev_fd] = NULL; + } - return (evsignal_del(&sop->evsigmask, ev)); + if (ev->ev_events & EV_WRITE) { + FD_CLR(ev->ev_fd, sop->event_writeset_in); + sop->event_w_by_fd[ev->ev_fd] = NULL; + } + + check_selectop(sop); + return (0); } |