X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=common-src%2Fevent.c;h=0959c721ebb47c58d9b8ce4ffc9e91dbeac99871;hb=d3b2175e084f88c8736ad7073eacbf4670147aec;hp=6809ca117c3c61c1f9a364014d72dfce42ea417e;hpb=1194fb66aa28d9929c3f2bef3cc6c1c3f40a60a4;p=debian%2Famanda diff --git a/common-src/event.c b/common-src/event.c index 6809ca1..0959c72 100644 --- a/common-src/event.c +++ b/common-src/event.c @@ -24,24 +24,23 @@ * file named AUTHORS, in the root directory of this distribution. */ /* - * $Id: event.c,v 1.20 2005/10/02 15:31:07 martinea Exp $ + * $Id: event.c,v 1.24 2006/06/16 10:55:05 martinea Exp $ * * Event handler. Serializes different kinds of events to allow for * a uniform interface, central state storage, and centralized * interdependency logic. */ -/*#define EVENT_DEBUG*/ - -#ifdef EVENT_DEBUG -#define eventprintf(x) dbprintf(x) -#else -#define eventprintf(x) -#endif - #include "amanda.h" #include "event.h" #include "queue.h" +#include "conffile.h" + +#define event_debug(i,x) do { \ + if ((i) <= debug_event) { \ + dbprintf(x); \ + } \ +} while (0) /* * The opaque handle passed back to the caller. This is typedefed to @@ -86,53 +85,50 @@ static struct { static struct sigtabent { event_handle_t *handle; /* handle for this signal */ int score; /* number of signals recvd since last checked */ - void (*oldhandler) P((int));/* old handler (for unsetting) */ + void (*oldhandler)(int);/* old handler (for unsetting) */ } sigtable[NSIG]; -#ifdef EVENT_DEBUG -static const char *event_type2str P((event_type_t)); -#endif +static const char *event_type2str(event_type_t); #define fire(eh) (*(eh)->fn)((eh)->arg) -static void signal_handler P((int)); -static event_handle_t *gethandle P((void)); -static void puthandle P((event_handle_t *)); +static void signal_handler(int); +static event_handle_t *gethandle(void); +static void puthandle(event_handle_t *); +static int event_loop_wait (event_handle_t *, const int); /* * Add a new event. See the comment in event.h for what the arguments * mean. */ event_handle_t * -event_register(data, type, fn, arg) - event_id_t data; - event_type_t type; - event_fn_t fn; - void *arg; +event_register( + event_id_t data, + event_type_t type, + event_fn_t fn, + void *arg) { event_handle_t *handle; - switch (type) { - case EV_READFD: - case EV_WRITEFD: + if ((type == EV_READFD) || (type == EV_WRITEFD)) { /* make sure we aren't given a high fd that will overflow a fd_set */ - assert(data < FD_SETSIZE); - break; - - case EV_SIG: + if (data >= FD_SETSIZE) { + error("event_register: Invalid file descriptor %lu", data); + /*NOTREACHED*/ + } +#if !defined(__lint) /* Global checking knows that these are never called */ + } else if (type == EV_SIG) { /* make sure signals are within range */ - assert(data < NSIG); - /* make sure we don't double-register a signal */ - assert(sigtable[data].handle == NULL); - break; - - case EV_TIME: - case EV_WAIT: - break; - - case EV_DEAD: - default: - /* callers can't register EV_DEAD */ - assert(0); - break; + if (data >= NSIG) { + error("event_register: Invalid signal %lu", data); + /*NOTREACHED*/ + } + if (sigtable[data].handle != NULL) { + error("event_register: signal %lu already registered", data); + /*NOTREACHED*/ + } + } else if (type >= EV_DEAD) { + error("event_register: Invalid event type %d", type); + /*NOTREACHED*/ +#endif } handle = gethandle(); @@ -144,8 +140,9 @@ event_register(data, type, fn, arg) eventq_add(eventq, handle); eventq.qlength++; - eventprintf(("%s: event: register: %X data=%lu, type=%s\n", debug_prefix_time(NULL), (int)handle, - handle->data, event_type2str(handle->type))); + event_debug(1, ("%s: event: register: %p->data=%lu, type=%s\n", + debug_prefix_time(NULL), handle, handle->data, + event_type2str(handle->type))); return (handle); } @@ -155,14 +152,15 @@ event_register(data, type, fn, arg) * the event. */ void -event_release(handle) - event_handle_t *handle; +event_release( + event_handle_t *handle) { assert(handle != NULL); - eventprintf(("%s: event: release (mark): %X data=%lu, type=%s\n", debug_prefix_time(NULL), - (int)handle, handle->data, event_type2str(handle->type))); + event_debug(1, ("%s: event: release (mark): %p data=%lu, type=%s\n", + debug_prefix_time(NULL), handle, handle->data, + event_type2str(handle->type))); assert(handle->type != EV_DEAD); /* @@ -173,7 +171,7 @@ event_release(handle) struct sigtabent *se = &sigtable[handle->data]; assert(se->handle == handle); - signal(handle->data, se->oldhandler); + signal((int)handle->data, se->oldhandler); se->handle = NULL; se->score = 0; } @@ -194,20 +192,20 @@ event_release(handle) * Fire all EV_WAIT events waiting on the specified id. */ int -event_wakeup(id) - event_id_t id; +event_wakeup( + event_id_t id) { event_handle_t *eh; int nwaken = 0; - eventprintf(("%s: event: wakeup: enter (%lu)\n", debug_prefix_time(NULL), id)); - - assert(id >= 0); + event_debug(1, ("%s: event: wakeup: enter (%lu)\n", + debug_prefix_time(NULL), id)); for (eh = eventq_first(eventq); eh != NULL; eh = eventq_next(eh)) { if (eh->type == EV_WAIT && eh->data == id) { - eventprintf(("%s: event: wakeup: %X id=%lu\n", debug_prefix_time(NULL), (int)eh, id)); + event_debug(1, ("%s: event: wakeup: %p id=%lu\n", + debug_prefix_time(NULL), eh, id)); fire(eh); nwaken++; } @@ -222,27 +220,53 @@ event_wakeup(id) * we need to make sure we don't end up referencing a dead event handle. */ void -event_loop(dontblock) - const int dontblock; +event_loop( + const int dontblock) +{ + event_loop_wait((event_handle_t *)NULL, dontblock); +} + + + +int +event_wait( + event_handle_t *eh) +{ + return event_loop_wait(eh, 0); +} + +/* + * The event loop. We need to be specially careful here with adds and + * deletes. Since adds and deletes will often happen while this is running, + * we need to make sure we don't end up referencing a dead event handle. + */ +static int +event_loop_wait( + event_handle_t *wait_eh, + const int dontblock) { #ifdef ASSERTIONS static int entry = 0; #endif - fd_set readfds, writefds, errfds, werrfds; + SELECT_ARG_TYPE readfds, writefds, errfds, werrfds; struct timeval timeout, *tvptr; - int ntries, maxfd, rc, interval; + int ntries, maxfd, rc; + long interval; time_t curtime; event_handle_t *eh, *nexteh; struct sigtabent *se; + int event_wait_fired = 0; + int see_event; - eventprintf(("%s: event: loop: enter: dontblock=%d, qlength=%d\n", debug_prefix_time(NULL), - dontblock, eventq.qlength)); + event_debug(1, ("%s: event: loop: enter: dontblock=%d, qlength=%d, eh=%p\n", + debug_prefix_time(NULL), + dontblock, eventq.qlength, wait_eh)); /* * If we have no events, we have nothing to do */ if (eventq.qlength == 0) - return; + return 0; /* * We must not be entered twice @@ -258,14 +282,17 @@ event_loop(dontblock) curtime = time(NULL); do { -#ifdef EVENT_DEBUG - eventprintf(("%s: event: loop: dontblock=%d, qlength=%d\n", debug_prefix_time(NULL), dontblock, - eventq.qlength)); - for (eh = eventq_first(eventq); eh != NULL; eh = eventq_next(eh)) { - eventprintf(("%s: %X: %s data=%lu fn=0x%x arg=0x%x\n", debug_prefix_time(NULL), (int)eh, - event_type2str(eh->type), eh->data, (int)eh->fn, (int)eh->arg)); + if (debug_event >= 1) { + event_debug(1, ("%s: event: loop: dontblock=%d, qlength=%d eh=%p\n", + debug_prefix_time(NULL), dontblock, eventq.qlength, + wait_eh)); + for (eh = eventq_first(eventq); eh != NULL; eh = eventq_next(eh)) { + event_debug(1, ("%s: %p): %s data=%lu fn=%p arg=%p\n", + debug_prefix_time(NULL), eh, + event_type2str(eh->type), eh->data, eh->fn, + eh->arg)); + } } -#endif /* * Set ourselves up with no timeout initially. */ @@ -294,6 +321,7 @@ event_loop(dontblock) FD_ZERO(&errfds); maxfd = 0; + see_event = (wait_eh == (event_handle_t *)NULL); /* * Run through each event handle and setup the events. * We save our next pointer early in case we GC some dead @@ -308,18 +336,20 @@ event_loop(dontblock) * Read fds just get set into the select bitmask */ case EV_READFD: - FD_SET(eh->data, &readfds); - FD_SET(eh->data, &errfds); - maxfd = max(maxfd, eh->data); + FD_SET((int)eh->data, &readfds); + FD_SET((int)eh->data, &errfds); + maxfd = max(maxfd, (int)eh->data); + see_event |= (eh == wait_eh); break; /* * Likewise with write fds */ case EV_WRITEFD: - FD_SET(eh->data, &writefds); - FD_SET(eh->data, &errfds); - maxfd = max(maxfd, eh->data); + FD_SET((int)eh->data, &writefds); + FD_SET((int)eh->data, &errfds); + maxfd = max(maxfd, (int)eh->data); + see_event |= (eh == wait_eh); break; /* @@ -328,6 +358,7 @@ event_loop(dontblock) */ case EV_SIG: se = &sigtable[eh->data]; + see_event |= (eh == wait_eh); if (se->handle == eh) break; @@ -336,7 +367,9 @@ event_loop(dontblock) assert(se->handle == NULL); se->handle = eh; se->score = 0; - se->oldhandler = signal(eh->data, signal_handler); + /*@ignore@*/ + se->oldhandler = signal((int)eh->data, signal_handler); + /*@end@*/ break; /* @@ -350,7 +383,7 @@ event_loop(dontblock) if (eh->lastfired == -1) eh->lastfired = curtime; - interval = eh->data - (curtime - eh->lastfired); + interval = (long)(eh->data - (curtime - eh->lastfired)); if (interval < 0) interval = 0; @@ -361,12 +394,14 @@ event_loop(dontblock) tvptr = &timeout; timeout.tv_sec = interval; } + see_event |= (eh == wait_eh); break; /* * Wait events are processed immediately by event_wakeup() */ case EV_WAIT: + see_event |= (eh == wait_eh); break; /* @@ -383,13 +418,21 @@ event_loop(dontblock) } } + if(!see_event) { + assert(--entry == 0); + return 0; + } + /* * Let 'er rip */ - eventprintf(("%s: event: select: dontblock=%d, maxfd=%d, timeout=%ld\n", debug_prefix_time(NULL), - dontblock, maxfd, tvptr != NULL ? timeout.tv_sec : -1)); + event_debug(1, + ("%s: event: select: dontblock=%d, maxfd=%d, timeout=%ld\n", + debug_prefix_time(NULL), dontblock, maxfd, + tvptr != NULL ? timeout.tv_sec : -1)); rc = select(maxfd + 1, &readfds, &writefds, &errfds, tvptr); - eventprintf(("%s: event: select returns %d\n", debug_prefix_time(NULL), rc)); + event_debug(1, ("%s: event: select returns %d\n", + debug_prefix_time(NULL), rc)); /* * Select errors can mean many things. Interrupted events should @@ -398,8 +441,10 @@ event_loop(dontblock) */ if (rc < 0) { if (errno != EINTR) { - if (++ntries > 5) + if (++ntries > 5) { error("select failed: %s", strerror(errno)); + /*NOTREACHED*/ + } continue; } /* proceed if errno == EINTR, we may have caught a signal */ @@ -420,24 +465,26 @@ event_loop(dontblock) * that are being polled for both reading and writing have * both of their poll events 'see' the error. */ - memcpy(&werrfds, &errfds, sizeof(werrfds)); + memcpy(&werrfds, &errfds, SIZEOF(werrfds)); /* * Now run through the events and fire the ones that are ready. * Don't handle file descriptor events if the select failed. */ for (eh = eventq_first(eventq); eh != NULL; eh = eventq_next(eh)) { + switch (eh->type) { /* * Read fds: just fire the event if set in the bitmask */ case EV_READFD: - if (FD_ISSET(eh->data, &readfds) || - FD_ISSET(eh->data, &errfds)) { - FD_CLR(eh->data, &readfds); - FD_CLR(eh->data, &errfds); + if (FD_ISSET((int)eh->data, &readfds) || + FD_ISSET((int)eh->data, &errfds)) { + FD_CLR((int)eh->data, &readfds); + FD_CLR((int)eh->data, &errfds); fire(eh); + if(eh == wait_eh) event_wait_fired = 1; } break; @@ -445,11 +492,12 @@ event_loop(dontblock) * Write fds: same as Read fds */ case EV_WRITEFD: - if (FD_ISSET(eh->data, &writefds) || - FD_ISSET(eh->data, &werrfds)) { - FD_CLR(eh->data, &writefds); - FD_CLR(eh->data, &werrfds); + if (FD_ISSET((int)eh->data, &writefds) || + FD_ISSET((int)eh->data, &werrfds)) { + FD_CLR((int)eh->data, &writefds); + FD_CLR((int)eh->data, &werrfds); fire(eh); + if(eh == wait_eh) event_wait_fired = 1; } break; @@ -463,6 +511,7 @@ event_loop(dontblock) assert(se->handle == eh); se->score = 0; fire(eh); + if(eh == wait_eh) event_wait_fired = 1; } break; @@ -473,9 +522,10 @@ event_loop(dontblock) case EV_TIME: if (eh->lastfired == -1) eh->lastfired = curtime; - if (curtime - eh->lastfired >= eh->data) { + if ((curtime - eh->lastfired) >= (time_t)eh->data) { eh->lastfired = curtime; fire(eh); + if(eh == wait_eh) event_wait_fired = 1; } break; @@ -492,9 +542,11 @@ event_loop(dontblock) break; } } - } while (!dontblock && eventq.qlength > 0); + } while (!dontblock && eventq.qlength > 0 && event_wait_fired == 0); assert(--entry == 0); + + return (event_wait_fired == 1); } /* @@ -502,11 +554,11 @@ event_loop(dontblock) * loop. */ static void -signal_handler(signo) - int signo; +signal_handler( + int signo) { - assert(signo >= 0 && signo < sizeof(sigtable) / sizeof(sigtable[0])); + assert((signo >= 0) && ((size_t)signo < (size_t)(sizeof(sigtable) / sizeof(sigtable[0])))); sigtable[signo].score++; } @@ -515,7 +567,7 @@ signal_handler(signo) * alloc a new one. */ static event_handle_t * -gethandle() +gethandle(void) { event_handle_t *eh; @@ -526,7 +578,7 @@ gethandle() return (eh); } assert(cache.qlength == 0); - return (alloc(sizeof(*eh))); + return (alloc(SIZEOF(*eh))); } /* @@ -534,8 +586,8 @@ gethandle() * Otherwise, free it. */ static void -puthandle(eh) - event_handle_t *eh; +puthandle( + event_handle_t *eh) { if (cache.qlength > CACHEDEPTH) { @@ -546,13 +598,12 @@ puthandle(eh) cache.qlength++; } -#ifdef EVENT_DEBUG /* * Convert an event type into a string */ static const char * -event_type2str(type) - event_type_t type; +event_type2str( + event_type_t type) { static const struct { event_type_t type; @@ -567,11 +618,10 @@ event_type2str(type) X(EV_DEAD), #undef X }; - int i; + size_t i; - for (i = 0; i < sizeof(event_types) / sizeof(event_types[0]); i++) + for (i = 0; i < (size_t)(sizeof(event_types) / sizeof(event_types[0])); i++) if (type == event_types[i].type) return (event_types[i].name); return ("BOGUS EVENT TYPE"); } -#endif /* EVENT_DEBUG */