From: Niels Provos Date: Wed, 10 Apr 2002 02:10:47 +0000 (+0000) Subject: signal support for kqueue; support of EV_PERSIST flag to event_set X-Git-Tag: release-1.1b~151 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d10f85dbce67c2835eb09c712da691a46d319aac;p=libevent signal support for kqueue; support of EV_PERSIST flag to event_set svn:r18 --- diff --git a/event.c b/event.c index 64636c9f..882830d8 100644 --- a/event.c +++ b/event.c @@ -143,7 +143,8 @@ event_process_active(void) ev = TAILQ_FIRST(&activequeue)) { event_queue_remove(ev, EVLIST_ACTIVE); - (*ev->ev_callback)(ev->ev_fd, ev->ev_res, ev->ev_arg); + while (ev->ev_ncalls--) + (*ev->ev_callback)(ev->ev_fd, ev->ev_res, ev->ev_arg); } } @@ -324,9 +325,10 @@ event_del(struct event *ev) } void -event_active(struct event *ev, int res) +event_active(struct event *ev, int res, short ncalls) { ev->ev_res = res; + ev->ev_ncalls = ncalls; event_queue_insert(ev, EVLIST_ACTIVE); } @@ -389,7 +391,7 @@ timeout_process(void) LOG_DBG((LOG_MISC, 60, "timeout_process: call %p", ev->ev_callback)); - event_active(ev, EV_TIMEOUT); + event_active(ev, EV_TIMEOUT, 1); } } diff --git a/event.h b/event.h index 7420a938..03eeb576 100644 --- a/event.h +++ b/event.h @@ -47,6 +47,7 @@ extern "C" { #define EV_READ 0x02 #define EV_WRITE 0x04 #define EV_SIGNAL 0x08 +#define EV_PERSIST 0x10 /* Persistant event */ /* Fix so that ppl dont have to run with */ #ifndef TAILQ_ENTRY @@ -76,6 +77,7 @@ struct event { int ev_fd; short ev_events; + short ev_ncalls; struct timeval ev_timeout; @@ -128,10 +130,17 @@ void timeout_process(void); #define timeout_pending(ev, tv) event_pending(ev, EV_TIMEOUT, tv) #define timeout_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) +#define signal_add(ev, tv) event_add(ev, tv) +#define signal_set(ev, x, cb, arg) \ + event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg) +#define signal_del(ev) event_del(ev) +#define signal_pending(ev, tv) event_pending(ev, EV_SIGNAL, tv) +#define signal_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) + void event_set(struct event *, int, short, void (*)(int, short, void *), void *); int event_add(struct event *, struct timeval *); int event_del(struct event *); - void event_active(struct event *, int); +void event_active(struct event *, int, short); int event_pending(struct event *, short, struct timeval *); diff --git a/kqueue.c b/kqueue.c index 594fe16d..9daafa7e 100644 --- a/kqueue.c +++ b/kqueue.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -215,12 +216,17 @@ kq_dispatch(void *arg, struct timeval *tv) which |= EV_READ; } else if (events[i].filter == EVFILT_WRITE) { which |= EV_WRITE; + } else if (events[i].filter == EVFILT_SIGNAL) { + which |= EV_SIGNAL; } if (which) { - ev->ev_flags &= ~EVLIST_X_KQINKERNEL; - event_del(ev); - event_active(ev, which); + if (!(ev->ev_events & EV_PERSIST)) { + ev->ev_flags &= ~EVLIST_X_KQINKERNEL; + event_del(ev); + } + event_active(ev, which, + ev->ev_events & EV_SIGNAL ? events[i].data : 1); } } @@ -234,6 +240,27 @@ kq_add(void *arg, struct event *ev) struct kqop *kqop = arg; struct kevent kev; + if (ev->ev_events & EV_SIGNAL) { + int nsignal = EVENT_SIGNAL(ev); + + memset(&kev, 0, sizeof(kev)); + kev.ident = nsignal; + kev.filter = EVFILT_SIGNAL; + kev.flags = EV_ADD; + if (!(ev->ev_events & EV_PERSIST)) + kev.filter |= EV_ONESHOT; + kev.udata = ev; + + if (kq_insert(kqop, &kev) == -1) + return (-1); + + if (signal(nsignal, SIG_IGN) == SIG_ERR) + return (-1); + + ev->ev_flags |= EVLIST_X_KQINKERNEL; + return (0); + } + if (ev->ev_events & EV_READ) { memset(&kev, 0, sizeof(kev)); kev.ident = ev->ev_fd; @@ -272,6 +299,24 @@ kq_del(void *arg, struct event *ev) if (!(ev->ev_flags & EVLIST_X_KQINKERNEL)) return (0); + if (ev->ev_events & EV_SIGNAL) { + int nsignal = EVENT_SIGNAL(ev); + + memset(&kev, 0, sizeof(kev)); + kev.ident = signal; + kev.filter = EVFILT_SIGNAL; + kev.flags = EV_DELETE; + + if (kq_insert(kqop, &kev) == -1) + return (-1); + + if (signal(nsignal, SIG_DFL) == SIG_ERR) + return (-1); + + ev->ev_flags &= ~EVLIST_X_KQINKERNEL; + return (0); + } + if (ev->ev_events & EV_READ) { memset(&kev, 0, sizeof(kev)); kev.ident = ev->ev_fd; diff --git a/sample/signal-test.c b/sample/signal-test.c index 3e5145dd..562bcf1e 100644 --- a/sample/signal-test.c +++ b/sample/signal-test.c @@ -41,7 +41,8 @@ main (int argc, char **argv) event_init(); /* Initalize one event */ - event_set(&signal_int, SIGINT, EV_SIGNAL, signal_cb, &signal_int); + event_set(&signal_int, SIGINT, EV_SIGNAL|EV_PERSIST, signal_cb, + &signal_int); event_add(&signal_int, NULL); diff --git a/select.c b/select.c index 7489285b..afafb444 100644 --- a/select.c +++ b/select.c @@ -56,7 +56,7 @@ extern struct event_list signalqueue; #define howmany(x, y) (((x)+((y)-1))/(y)) #endif -int evsigcaught[NSIG]; +short evsigcaught[NSIG]; struct selectop { int event_fds; /* Highest fd in fd set */ @@ -192,8 +192,9 @@ select_dispatch(void *arg, struct timeval *tv) res &= ev->ev_events; if (res) { - event_del(ev); - event_active(ev, res); + if (!(ev->ev_events & EV_PERSIST)) + event_del(ev); + event_active(ev, res, 1); } else if (ev->ev_fd > maxfd) maxfd = ev->ev_fd; } @@ -291,10 +292,15 @@ void signal_process(void) { struct event *ev; + short ncalls; TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) { - if (evsigcaught[EVENT_SIGNAL(ev)]) - event_active(ev, EV_SIGNAL); + ncalls = evsigcaught[EVENT_SIGNAL(ev)]; + if (ncalls) { + if (!(ev->ev_events & EV_PERSIST)) + event_del(ev); + event_active(ev, EV_SIGNAL, ncalls); + } } memset(evsigcaught, 0, sizeof(evsigcaught));