diff options
author | Max Laier <mlaier@FreeBSD.org> | 2008-12-10 21:08:42 +0000 |
---|---|---|
committer | Max Laier <mlaier@FreeBSD.org> | 2008-12-10 21:08:42 +0000 |
commit | 89a3159080a774bd9de50eaf1861a1f0c1657a9f (patch) | |
tree | c096fbed43e7e27c693d9c76d395f03a6c790ac2 /libevent | |
parent | a13f3058fbd67e3bbda784171bacc8343faf6edf (diff) |
Import OPENBSD_4_4_BASE and libevent 1.3evendor/pf/4.4
Notes
Notes:
svn path=/vendor/pf/dist/; revision=185882
svn path=/vendor/pf/4.4/; revision=185883; tag=vendor/pf/4.4
Diffstat (limited to 'libevent')
-rw-r--r-- | libevent/buffer.c | 22 | ||||
-rw-r--r-- | libevent/event-internal.h | 5 | ||||
-rw-r--r-- | libevent/event.c | 170 | ||||
-rw-r--r-- | libevent/event.h | 41 | ||||
-rw-r--r-- | libevent/evsignal.h | 13 | ||||
-rw-r--r-- | libevent/kqueue.c | 32 | ||||
-rw-r--r-- | libevent/poll.c | 29 | ||||
-rw-r--r-- | libevent/select.c | 25 | ||||
-rw-r--r-- | libevent/signal.c | 85 |
9 files changed, 258 insertions, 164 deletions
diff --git a/libevent/buffer.c b/libevent/buffer.c index 77efd0cfa3e2..0327eb549383 100644 --- a/libevent/buffer.c +++ b/libevent/buffer.c @@ -44,6 +44,7 @@ #include <sys/ioctl.h> #endif +#include <assert.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> @@ -106,7 +107,7 @@ evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf) /* * Optimization comes with a price; we need to notify the * buffer if necessary of the changes. oldoff is the amount - * of data that we tranfered from inbuf to outbuf + * of data that we transfered from inbuf to outbuf */ if (inbuf->off != oldoff && inbuf->cb != NULL) (*inbuf->cb)(inbuf, oldoff, inbuf->off, inbuf->cbarg); @@ -134,9 +135,13 @@ evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap) int sz; va_list aq; + /* make sure that at least some space is available */ + evbuffer_expand(buf, 64); for (;;) { + size_t used = buf->misalign + buf->off; buffer = (char *)buf->buffer + buf->off; - space = buf->totallen - buf->misalign - buf->off; + assert(buf->totallen >= used); + space = buf->totallen - used; #ifndef va_copy #define va_copy(dst, src) memcpy(&(dst), &(src), sizeof(va_list)) @@ -152,7 +157,7 @@ evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap) va_end(aq); - if (sz == -1) + if (sz < 0) return (-1); if (sz < space) { buf->off += sz; @@ -244,7 +249,7 @@ evbuffer_readline(struct evbuffer *buffer) /* Adds data to an event buffer */ -static inline void +static void evbuffer_align(struct evbuffer *buf) { memmove(buf->orig_buffer, buf->buffer, buf->off); @@ -431,13 +436,12 @@ evbuffer_write(struct evbuffer *buffer, int fd) u_char * evbuffer_find(struct evbuffer *buffer, const u_char *what, size_t len) { - size_t remain = buffer->off; - u_char *search = buffer->buffer; + u_char *search = buffer->buffer, *end = search + buffer->off; u_char *p; - while ((p = memchr(search, *what, remain)) != NULL) { - remain = buffer->off - (size_t)(search - buffer->buffer); - if (remain < len) + while (search < end && + (p = memchr(search, *what, end - search)) != NULL) { + if (p + len > end) break; if (memcmp(p, what, len) == 0) return (p); diff --git a/libevent/event-internal.h b/libevent/event-internal.h index becb6691d52a..7fd4b6c690f3 100644 --- a/libevent/event-internal.h +++ b/libevent/event-internal.h @@ -31,6 +31,8 @@ extern "C" { #endif +#include "evsignal.h" + struct event_base { const struct eventop *evsel; void *evbase; @@ -43,6 +45,9 @@ struct event_base { struct event_list **activequeues; int nactivequeues; + /* signal handling info */ + struct evsignal_info sig; + struct event_list eventqueue; struct timeval event_tv; diff --git a/libevent/event.c b/libevent/event.c index f6d2b1cc42ca..15bf14cf3b48 100644 --- a/libevent/event.c +++ b/libevent/event.c @@ -51,6 +51,7 @@ #include <signal.h> #include <string.h> #include <assert.h> +#include <time.h> #include "event.h" #include "event-internal.h" @@ -111,9 +112,9 @@ const struct eventop *eventops[] = { }; /* Global state */ -struct event_list signalqueue; - struct event_base *current_base = NULL; +extern struct event_base *evsignal_base; +static int use_monotonic; /* Handle signals - This is a deprecated interface */ int (*event_sigcb)(void); /* Signal callback when gotsig is set */ @@ -126,7 +127,7 @@ static int event_haveevents(struct event_base *); static void event_process_active(struct event_base *); -static int timeout_next(struct event_base *, struct timeval *); +static int timeout_next(struct event_base *, struct timeval **); static void timeout_process(struct event_base *); static void timeout_correct(struct event_base *, struct timeval *); @@ -144,25 +145,34 @@ compare(struct event *a, struct event *b) return (0); } +static void +detect_monotonic(void) +{ +#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) + struct timespec ts; + + if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) + use_monotonic = 1; +#endif +} + static int gettime(struct timeval *tp) { -#ifdef HAVE_CLOCK_GETTIME +#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) struct timespec ts; -#ifdef HAVE_CLOCK_MONOTONIC - if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) -#else - if (clock_gettime(CLOCK_REALTIME, &ts) == -1) -#endif - return (-1); - tp->tv_sec = ts.tv_sec; - tp->tv_usec = ts.tv_nsec / 1000; -#else - gettimeofday(tp, NULL); + if (use_monotonic) { + if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) + return (-1); + + tp->tv_sec = ts.tv_sec; + tp->tv_usec = ts.tv_nsec / 1000; + return (0); + } #endif - return (0); + return (gettimeofday(tp, NULL)); } RB_PROTOTYPE(event_tree, event, ev_timeout_node, compare); @@ -174,36 +184,42 @@ void * event_init(void) { int i; + struct event_base *base; - if ((current_base = calloc(1, sizeof(struct event_base))) == NULL) + if ((base = calloc(1, sizeof(struct event_base))) == NULL) event_err(1, "%s: calloc"); event_sigcb = NULL; event_gotsig = 0; - gettime(¤t_base->event_tv); + + detect_monotonic(); + gettime(&base->event_tv); - RB_INIT(¤t_base->timetree); - TAILQ_INIT(¤t_base->eventqueue); - TAILQ_INIT(&signalqueue); + RB_INIT(&base->timetree); + TAILQ_INIT(&base->eventqueue); + TAILQ_INIT(&base->sig.signalqueue); + base->sig.ev_signal_pair[0] = -1; + base->sig.ev_signal_pair[1] = -1; - current_base->evbase = NULL; - for (i = 0; eventops[i] && !current_base->evbase; i++) { - current_base->evsel = eventops[i]; + base->evbase = NULL; + for (i = 0; eventops[i] && !base->evbase; i++) { + base->evsel = eventops[i]; - current_base->evbase = current_base->evsel->init(); + base->evbase = base->evsel->init(base); } - if (current_base->evbase == NULL) + if (base->evbase == NULL) event_errx(1, "%s: no event mechanism available", __func__); if (getenv("EVENT_SHOW_METHOD")) event_msgx("libevent using: %s\n", - current_base->evsel->name); + base->evsel->name); /* allocate a single active event queue */ - event_base_priority_init(current_base, 1); + event_base_priority_init(base, 1); - return (current_base); + current_base = base; + return (base); } void @@ -217,7 +233,8 @@ event_base_free(struct event_base *base) current_base = NULL; assert(base); - assert(TAILQ_EMPTY(&base->eventqueue)); + if (base->evsel->dealloc != NULL) + base->evsel->dealloc(base, base->evbase); for (i=0; i < base->nactivequeues; ++i) assert(TAILQ_EMPTY(base->activequeues[i])); @@ -227,8 +244,7 @@ event_base_free(struct event_base *base) free(base->activequeues[i]); free(base->activequeues); - if (base->evsel->dealloc != NULL) - base->evsel->dealloc(base->evbase); + assert(TAILQ_EMPTY(&base->eventqueue)); free(base); } @@ -343,7 +359,6 @@ event_loopexit_cb(int fd, short what, void *arg) } /* not thread safe */ - int event_loopexit(struct timeval *tv) { @@ -354,7 +369,7 @@ event_loopexit(struct timeval *tv) int event_base_loopexit(struct event_base *event_base, struct timeval *tv) { - return (event_once(-1, EV_TIMEOUT, event_loopexit_cb, + return (event_base_once(event_base, -1, EV_TIMEOUT, event_loopexit_cb, event_base, tv)); } @@ -372,8 +387,13 @@ event_base_loop(struct event_base *base, int flags) const struct eventop *evsel = base->evsel; void *evbase = base->evbase; struct timeval tv; + struct timeval *tv_p; int res, done; +#ifndef WIN32 + if(!TAILQ_EMPTY(&base->sig.signalqueue)) + evsignal_base = base; +#endif done = 0; while (!done) { /* Calculate the initial events that we are waiting for */ @@ -398,21 +418,18 @@ event_base_loop(struct event_base *base, int flags) } } - /* Check if time is running backwards */ - gettime(&tv); - if (timercmp(&tv, &base->event_tv, <)) { - struct timeval off; - event_debug(("%s: time is running backwards, corrected", - __func__)); - timersub(&base->event_tv, &tv, &off); - timeout_correct(base, &off); - } - base->event_tv = tv; + timeout_correct(base, &tv); - if (!base->event_count_active && !(flags & EVLOOP_NONBLOCK)) - timeout_next(base, &tv); - else + tv_p = &tv; + if (!base->event_count_active && !(flags & EVLOOP_NONBLOCK)) { + timeout_next(base, &tv_p); + } else { + /* + * if we have active events, we just poll new events + * without waiting. + */ timerclear(&tv); + } /* If we have no events, we just exit */ if (!event_haveevents(base)) { @@ -420,7 +437,8 @@ event_base_loop(struct event_base *base, int flags) return (1); } - res = evsel->dispatch(base, evbase, &tv); + res = evsel->dispatch(base, evbase, tv_p); + if (res == -1) return (-1); @@ -459,12 +477,19 @@ event_once_cb(int fd, short events, void *arg) free(eonce); } -/* Schedules an event once */ - +/* not threadsafe, event scheduled once. */ int event_once(int fd, short events, void (*callback)(int, short, void *), void *arg, struct timeval *tv) { + return event_base_once(current_base, fd, events, callback, arg, tv); +} + +/* Schedules an event once */ +int +event_base_once(struct event_base *base, int fd, short events, + void (*callback)(int, short, void *), void *arg, struct timeval *tv) +{ struct event_once *eonce; struct timeval etv; int res; @@ -496,7 +521,9 @@ event_once(int fd, short events, return (-1); } - res = event_add(&eonce->ev, tv); + res = event_base_set(base, &eonce->ev); + if (res == 0) + res = event_add(&eonce->ev, tv); if (res != 0) { free(eonce); return (res); @@ -516,12 +543,14 @@ event_set(struct event *ev, int fd, short events, ev->ev_arg = arg; ev->ev_fd = fd; ev->ev_events = events; + ev->ev_res = 0; ev->ev_flags = EVLIST_INIT; ev->ev_ncalls = 0; ev->ev_pncalls = NULL; /* by default, we put new events into the middle priority */ - ev->ev_pri = current_base->nactivequeues/2; + if(current_base) + ev->ev_pri = current_base->nactivequeues/2; } int @@ -710,16 +739,16 @@ event_active(struct event *ev, int res, short ncalls) event_queue_insert(ev->ev_base, ev, EVLIST_ACTIVE); } -int -timeout_next(struct event_base *base, struct timeval *tv) +static int +timeout_next(struct event_base *base, struct timeval **tv_p) { - struct timeval dflt = TIMEOUT_DEFAULT; - struct timeval now; struct event *ev; + struct timeval *tv = *tv_p; if ((ev = RB_MIN(event_tree, &base->timetree)) == NULL) { - *tv = dflt; + /* if no time-based events are active wait for I/O */ + *tv_p = NULL; return (0); } @@ -740,17 +769,38 @@ timeout_next(struct event_base *base, struct timeval *tv) return (0); } +/* + * Determines if the time is running backwards by comparing the current + * time against the last time we checked. Not needed when using clock + * monotonic. + */ + static void -timeout_correct(struct event_base *base, struct timeval *off) +timeout_correct(struct event_base *base, struct timeval *tv) { struct event *ev; + struct timeval off; + + if (use_monotonic) + return; + + /* Check if time is running backwards */ + gettime(tv); + if (timercmp(tv, &base->event_tv, >=)) { + base->event_tv = *tv; + return; + } + + event_debug(("%s: time is running backwards, corrected", + __func__)); + timersub(&base->event_tv, tv, &off); /* * We can modify the key element of the node without destroying * the key, beause we apply it to all in the right order. */ RB_FOREACH(ev, event_tree, &base->timetree) - timersub(&ev->ev_timeout, off, &ev->ev_timeout); + timersub(&ev->ev_timeout, &off, &ev->ev_timeout); } void @@ -801,7 +851,7 @@ event_queue_remove(struct event_base *base, struct event *ev, int queue) ev, ev_active_next); break; case EVLIST_SIGNAL: - TAILQ_REMOVE(&signalqueue, ev, ev_signal_next); + TAILQ_REMOVE(&base->sig.signalqueue, ev, ev_signal_next); break; case EVLIST_TIMEOUT: RB_REMOVE(event_tree, &base->timetree, ev); @@ -843,7 +893,7 @@ event_queue_insert(struct event_base *base, struct event *ev, int queue) ev,ev_active_next); break; case EVLIST_SIGNAL: - TAILQ_INSERT_TAIL(&signalqueue, ev, ev_signal_next); + TAILQ_INSERT_TAIL(&base->sig.signalqueue, ev, ev_signal_next); break; case EVLIST_TIMEOUT: { struct event *tmp = RB_INSERT(event_tree, &base->timetree, ev); diff --git a/libevent/event.h b/libevent/event.h index 3f2032dd068e..4c39939cc501 100644 --- a/libevent/event.h +++ b/libevent/event.h @@ -31,6 +31,8 @@ extern "C" { #endif +#include <sys/time.h> +#include <stdint.h> #include <stdarg.h> #ifdef WIN32 @@ -131,16 +133,14 @@ TAILQ_HEAD (evkeyvalq, evkeyval); struct eventop { char *name; - void *(*init)(void); + void *(*init)(struct event_base *); int (*add)(void *, struct event *); int (*del)(void *, struct event *); int (*recalc)(struct event_base *, void *, int); int (*dispatch)(struct event_base *, void *, struct timeval *); - void (*dealloc)(void *); + void (*dealloc)(struct event_base *, void *); }; -#define TIMEOUT_DEFAULT {5, 0} - void *event_init(void); int event_dispatch(void); int event_base_dispatch(struct event_base *); @@ -184,6 +184,7 @@ int event_base_loopexit(struct event_base *, struct timeval *); void event_set(struct event *, int, short, void (*)(int, short, void *), void *); int event_once(int, short, void (*)(int, short, void *), void *, struct timeval *); +int event_base_once(struct event_base *, int, short, void (*)(int, short, void *), void *, struct timeval *); int event_add(struct event *, struct timeval *); int event_del(struct event *); @@ -299,39 +300,37 @@ void evbuffer_setcb(struct evbuffer *, void (*)(struct evbuffer *, size_t, size_ void evtag_init(void); -void evtag_marshal(struct evbuffer *evbuf, u_int8_t tag, const void *data, - u_int32_t len); +void evtag_marshal(struct evbuffer *evbuf, uint8_t tag, const void *data, + uint32_t len); -void encode_int(struct evbuffer *evbuf, u_int32_t number); +void encode_int(struct evbuffer *evbuf, uint32_t number); -void evtag_marshal_int(struct evbuffer *evbuf, u_int8_t tag, - u_int32_t integer); +void evtag_marshal_int(struct evbuffer *evbuf, uint8_t tag, uint32_t integer); -void evtag_marshal_string(struct evbuffer *buf, u_int8_t tag, +void evtag_marshal_string(struct evbuffer *buf, uint8_t tag, const char *string); -void evtag_marshal_timeval(struct evbuffer *evbuf, u_int8_t tag, +void evtag_marshal_timeval(struct evbuffer *evbuf, uint8_t tag, struct timeval *tv); void evtag_test(void); -int evtag_unmarshal(struct evbuffer *src, u_int8_t *ptag, - struct evbuffer *dst); -int evtag_peek(struct evbuffer *evbuf, u_int8_t *ptag); -int evtag_peek_length(struct evbuffer *evbuf, u_int32_t *plength); -int evtag_payload_length(struct evbuffer *evbuf, u_int32_t *plength); +int evtag_unmarshal(struct evbuffer *src, uint8_t *ptag, struct evbuffer *dst); +int evtag_peek(struct evbuffer *evbuf, uint8_t *ptag); +int evtag_peek_length(struct evbuffer *evbuf, uint32_t *plength); +int evtag_payload_length(struct evbuffer *evbuf, uint32_t *plength); int evtag_consume(struct evbuffer *evbuf); -int evtag_unmarshal_int(struct evbuffer *evbuf, u_int8_t need_tag, - u_int32_t *pinteger); +int evtag_unmarshal_int(struct evbuffer *evbuf, uint8_t need_tag, + uint32_t *pinteger); -int evtag_unmarshal_fixed(struct evbuffer *src, u_int8_t need_tag, void *data, +int evtag_unmarshal_fixed(struct evbuffer *src, uint8_t need_tag, void *data, size_t len); -int evtag_unmarshal_string(struct evbuffer *evbuf, u_int8_t need_tag, +int evtag_unmarshal_string(struct evbuffer *evbuf, uint8_t need_tag, char **pstring); -int evtag_unmarshal_timeval(struct evbuffer *evbuf, u_int8_t need_tag, +int evtag_unmarshal_timeval(struct evbuffer *evbuf, uint8_t need_tag, struct timeval *ptv); #ifdef __cplusplus diff --git a/libevent/evsignal.h b/libevent/evsignal.h index 5b92bd6e55fb..7efbcabec896 100644 --- a/libevent/evsignal.h +++ b/libevent/evsignal.h @@ -27,9 +27,18 @@ #ifndef _EVSIGNAL_H_ #define _EVSIGNAL_H_ -void evsignal_init(void); -void evsignal_process(void); +struct evsignal_info { + struct event_list signalqueue; + struct event ev_signal; + int ev_signal_pair[2]; + int ev_signal_added; + volatile sig_atomic_t evsignal_caught; + sig_atomic_t evsigcaught[NSIG]; +}; +void evsignal_init(struct event_base *); +void evsignal_process(struct event_base *); int evsignal_add(struct event *); int evsignal_del(struct event *); +void evsignal_dealloc(struct event_base *); #endif /* _EVSIGNAL_H_ */ diff --git a/libevent/kqueue.c b/libevent/kqueue.c index 08369c6dd51d..059d94a0b4d5 100644 --- a/libevent/kqueue.c +++ b/libevent/kqueue.c @@ -48,10 +48,13 @@ #include <inttypes.h> #endif -#if defined(HAVE_INTTYPES_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__) -#define INTPTR(x) (intptr_t)x +/* Some platforms apparently define the udata field of struct kevent as + * ntptr_t, whereas others define it as void*. There doesn't seem to be an + * easy way to tell them apart via autoconf, so we need to use OS macros. */ +#if defined(HAVE_INTTYPES_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__darwin__) && !defined(__APPLE__) +#define PTR_TO_UDATA(x) ((intptr_t)(x)) #else -#define INTPTR(x) x +#define PTR_TO_UDATA(x) (x) #endif #include "event.h" @@ -69,13 +72,13 @@ struct kqop { int kq; }; -void *kq_init (void); +void *kq_init (struct event_base *); int kq_add (void *, struct event *); int kq_del (void *, struct event *); int kq_recalc (struct event_base *, void *, int); int kq_dispatch (struct event_base *, void *, struct timeval *); int kq_insert (struct kqop *, struct kevent *); -void kq_dealloc (void *); +void kq_dealloc (struct event_base *, void *); const struct eventop kqops = { "kqueue", @@ -88,7 +91,7 @@ const struct eventop kqops = { }; void * -kq_init(void) +kq_init(struct event_base *base) { int kq; struct kqop *kqueueop; @@ -212,13 +215,16 @@ kq_dispatch(struct event_base *base, void *arg, struct timeval *tv) struct kevent *changes = kqop->changes; struct kevent *events = kqop->events; struct event *ev; - struct timespec ts; + struct timespec ts, *ts_p = NULL; int i, res; - TIMEVAL_TO_TIMESPEC(tv, &ts); + if (tv != NULL) { + TIMEVAL_TO_TIMESPEC(tv, &ts); + ts_p = &ts; + } res = kevent(kqop->kq, changes, kqop->nchanges, - events, kqop->nevents, &ts); + events, kqop->nevents, ts_p); kqop->nchanges = 0; if (res == -1) { if (errno != EINTR) { @@ -294,7 +300,7 @@ kq_add(void *arg, struct event *ev) kev.flags = EV_ADD; if (!(ev->ev_events & EV_PERSIST)) kev.flags |= EV_ONESHOT; - kev.udata = INTPTR(ev); + kev.udata = PTR_TO_UDATA(ev); if (kq_insert(kqop, &kev) == -1) return (-1); @@ -317,7 +323,7 @@ kq_add(void *arg, struct event *ev) kev.flags = EV_ADD; if (!(ev->ev_events & EV_PERSIST)) kev.flags |= EV_ONESHOT; - kev.udata = INTPTR(ev); + kev.udata = PTR_TO_UDATA(ev); if (kq_insert(kqop, &kev) == -1) return (-1); @@ -332,7 +338,7 @@ kq_add(void *arg, struct event *ev) kev.flags = EV_ADD; if (!(ev->ev_events & EV_PERSIST)) kev.flags |= EV_ONESHOT; - kev.udata = INTPTR(ev); + kev.udata = PTR_TO_UDATA(ev); if (kq_insert(kqop, &kev) == -1) return (-1); @@ -398,7 +404,7 @@ kq_del(void *arg, struct event *ev) } void -kq_dealloc(void *arg) +kq_dealloc(struct event_base *base, void *arg) { struct kqop *kqop = arg; diff --git a/libevent/poll.c b/libevent/poll.c index 14ca8453739b..123d36a56023 100644 --- a/libevent/poll.c +++ b/libevent/poll.c @@ -54,8 +54,6 @@ #include "evsignal.h" #include "log.h" -extern volatile sig_atomic_t evsignal_caught; - struct pollop { int event_count; /* Highest number alloc */ int nfds; /* Size of event_* */ @@ -68,12 +66,12 @@ struct pollop { * "no entry." */ }; -void *poll_init (void); +void *poll_init (struct event_base *); int poll_add (void *, struct event *); int poll_del (void *, struct event *); int poll_recalc (struct event_base *, void *, int); int poll_dispatch (struct event_base *, void *, struct timeval *); -void poll_dealloc (void *); +void poll_dealloc (struct event_base *, void *); const struct eventop pollops = { "poll", @@ -86,7 +84,7 @@ const struct eventop pollops = { }; void * -poll_init(void) +poll_init(struct event_base *base) { struct pollop *pollop; @@ -97,7 +95,7 @@ poll_init(void) if (!(pollop = calloc(1, sizeof(struct pollop)))) return (NULL); - evsignal_init(); + evsignal_init(base); return (pollop); } @@ -150,13 +148,16 @@ poll_check_ok(struct pollop *pop) int poll_dispatch(struct event_base *base, void *arg, struct timeval *tv) { - int res, i, sec, nfds; + int res, i, msec = -1, nfds; struct pollop *pop = arg; poll_check_ok(pop); - sec = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000; + + if (tv != NULL) + msec = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000; + nfds = pop->nfds; - res = poll(pop->event_set, nfds, sec); + res = poll(pop->event_set, nfds, msec); if (res == -1) { if (errno != EINTR) { @@ -164,10 +165,11 @@ poll_dispatch(struct event_base *base, void *arg, struct timeval *tv) return (-1); } - evsignal_process(); + evsignal_process(base); return (0); - } else if (evsignal_caught) - evsignal_process(); + } else if (base->sig.evsignal_caught) { + evsignal_process(base); + } event_debug(("%s: poll reports %d", __func__, res)); @@ -370,10 +372,11 @@ poll_del(void *arg, struct event *ev) } void -poll_dealloc(void *arg) +poll_dealloc(struct event_base *base, void *arg) { struct pollop *pop = arg; + evsignal_dealloc(base); if (pop->event_set) free(pop->event_set); if (pop->event_r_back) diff --git a/libevent/select.c b/libevent/select.c index 6ce81a232bbe..d645f1a37030 100644 --- a/libevent/select.c +++ b/libevent/select.c @@ -36,6 +36,9 @@ #else #include <sys/_time.h> #endif +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif #include <sys/queue.h> #include <sys/tree.h> #include <signal.h> @@ -57,8 +60,6 @@ #define howmany(x, y) (((x)+((y)-1))/(y)) #endif -extern volatile sig_atomic_t evsignal_caught; - struct selectop { int event_fds; /* Highest fd in fd set */ int event_fdsz; @@ -70,12 +71,12 @@ struct selectop { struct event **event_w_by_fd; }; -void *select_init (void); +void *select_init (struct event_base *); int select_add (void *, struct event *); int select_del (void *, struct event *); int select_recalc (struct event_base *, void *, int); int select_dispatch (struct event_base *, void *, struct timeval *); -void select_dealloc (void *); +void select_dealloc (struct event_base *, void *); const struct eventop selectops = { "select", @@ -90,7 +91,7 @@ const struct eventop selectops = { static int select_resize(struct selectop *sop, int fdsz); void * -select_init(void) +select_init(struct event_base *base) { struct selectop *sop; @@ -103,7 +104,7 @@ select_init(void) select_resize(sop, howmany(32 + 1, NFDBITS)*sizeof(fd_mask)); - evsignal_init(); + evsignal_init(base); return (sop); } @@ -113,7 +114,7 @@ static void check_selectop(struct selectop *sop) { int i; - for (i=0;i<=sop->event_fds;++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); @@ -174,10 +175,11 @@ select_dispatch(struct event_base *base, void *arg, struct timeval *tv) return (-1); } - evsignal_process(); + evsignal_process(base); return (0); - } else if (evsignal_caught) - evsignal_process(); + } else if (base->sig.evsignal_caught) { + evsignal_process(base); + } event_debug(("%s: select reports %d", __func__, res)); @@ -348,10 +350,11 @@ select_del(void *arg, struct event *ev) } void -select_dealloc(void *arg) +select_dealloc(struct event_base *base, void *arg) { struct selectop *sop = arg; + evsignal_dealloc(base); if (sop->event_readset_in) free(sop->event_readset_in); if (sop->event_writeset_in) diff --git a/libevent/signal.c b/libevent/signal.c index 71bcffcba5b3..6c0953d9e121 100644 --- a/libevent/signal.c +++ b/libevent/signal.c @@ -31,6 +31,7 @@ #endif #include <sys/types.h> +#include <sys/tree.h> #ifdef HAVE_SYS_TIME_H #include <sys/time.h> #else @@ -47,19 +48,14 @@ #ifdef HAVE_FCNTL_H #include <fcntl.h> #endif +#include <assert.h> #include "event.h" +#include "event-internal.h" #include "evsignal.h" #include "log.h" -extern struct event_list signalqueue; - -static sig_atomic_t evsigcaught[NSIG]; -volatile sig_atomic_t evsignal_caught = 0; - -static struct event ev_signal; -static int ev_signal_pair[2]; -static int ev_signal_added; +struct event_base *evsignal_base = NULL; static void evsignal_handler(int sig); @@ -87,24 +83,27 @@ evsignal_cb(int fd, short what, void *arg) #endif void -evsignal_init(void) +evsignal_init(struct event_base *base) { /* * Our signal handler is going to write to one end of the socket * pair to wake up our event loop. The event loop then scans for * signals that got delivered. */ - if (socketpair(AF_UNIX, SOCK_STREAM, 0, ev_signal_pair) == -1) + if (socketpair(AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair) == -1) event_err(1, "%s: socketpair", __func__); - FD_CLOSEONEXEC(ev_signal_pair[0]); - FD_CLOSEONEXEC(ev_signal_pair[1]); + FD_CLOSEONEXEC(base->sig.ev_signal_pair[0]); + FD_CLOSEONEXEC(base->sig.ev_signal_pair[1]); + base->sig.evsignal_caught = 0; + memset(&base->sig.evsigcaught, 0, sizeof(sig_atomic_t)*NSIG); - fcntl(ev_signal_pair[0], F_SETFL, O_NONBLOCK); + fcntl(base->sig.ev_signal_pair[0], F_SETFL, O_NONBLOCK); - event_set(&ev_signal, ev_signal_pair[1], EV_READ, - evsignal_cb, &ev_signal); - ev_signal.ev_flags |= EVLIST_INTERNAL; + event_set(&base->sig.ev_signal, base->sig.ev_signal_pair[1], EV_READ, + evsignal_cb, &base->sig.ev_signal); + base->sig.ev_signal.ev_base = base; + base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL; } int @@ -112,6 +111,7 @@ evsignal_add(struct event *ev) { int evsignal; struct sigaction sa; + struct event_base *base = ev->ev_base; if (ev->ev_events & (EV_READ|EV_WRITE)) event_errx(1, "%s: EV_SIGNAL incompatible use", __func__); @@ -121,29 +121,23 @@ evsignal_add(struct event *ev) sa.sa_handler = evsignal_handler; sigfillset(&sa.sa_mask); sa.sa_flags |= SA_RESTART; + /* catch signals if they happen quickly */ + evsignal_base = base; if (sigaction(evsignal, &sa, NULL) == -1) return (-1); - if (!ev_signal_added) { - ev_signal_added = 1; - event_add(&ev_signal, NULL); + if (!base->sig.ev_signal_added) { + base->sig.ev_signal_added = 1; + event_add(&base->sig.ev_signal, NULL); } return (0); } -/* - * Nothing to be done here. - */ - int evsignal_del(struct event *ev) { - int evsignal; - - evsignal = EVENT_SIGNAL(ev); - return (sigaction(EVENT_SIGNAL(ev),(struct sigaction *)SIG_DFL, NULL)); } @@ -152,29 +146,50 @@ evsignal_handler(int sig) { int save_errno = errno; - evsigcaught[sig]++; - evsignal_caught = 1; + if(evsignal_base == NULL) { + event_warn( + "%s: received signal %s, but have no base configured", + __func__, sig); + return; + } + + evsignal_base->sig.evsigcaught[sig]++; + evsignal_base->sig.evsignal_caught = 1; /* Wake up our notification mechanism */ - write(ev_signal_pair[0], "a", 1); + write(evsignal_base->sig.ev_signal_pair[0], "a", 1); errno = save_errno; } void -evsignal_process(void) +evsignal_process(struct event_base *base) { struct event *ev; sig_atomic_t ncalls; - evsignal_caught = 0; - TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) { - ncalls = evsigcaught[EVENT_SIGNAL(ev)]; + base->sig.evsignal_caught = 0; + TAILQ_FOREACH(ev, &base->sig.signalqueue, ev_signal_next) { + ncalls = base->sig.evsigcaught[EVENT_SIGNAL(ev)]; if (ncalls) { if (!(ev->ev_events & EV_PERSIST)) event_del(ev); event_active(ev, EV_SIGNAL, ncalls); - evsigcaught[EVENT_SIGNAL(ev)] = 0; + base->sig.evsigcaught[EVENT_SIGNAL(ev)] = 0; } } } +void +evsignal_dealloc(struct event_base *base) +{ + if(base->sig.ev_signal_added) { + event_del(&base->sig.ev_signal); + base->sig.ev_signal_added = 0; + } + assert(TAILQ_EMPTY(&base->sig.signalqueue)); + + close(base->sig.ev_signal_pair[0]); + base->sig.ev_signal_pair[0] = -1; + close(base->sig.ev_signal_pair[1]); + base->sig.ev_signal_pair[1] = -1; +} |