]> granicus.if.org Git - libevent/commitdiff
signal support for kqueue; support of EV_PERSIST flag to event_set
authorNiels Provos <provos@gmail.com>
Wed, 10 Apr 2002 02:10:47 +0000 (02:10 +0000)
committerNiels Provos <provos@gmail.com>
Wed, 10 Apr 2002 02:10:47 +0000 (02:10 +0000)
svn:r18

event.c
event.h
kqueue.c
sample/signal-test.c
select.c

diff --git a/event.c b/event.c
index 64636c9f8759c5b5a171720b171c3401c01231a9..882830d86ac977f1c042862f70f57d2d69b771a9 100644 (file)
--- 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 7420a938a2e6676ef9b6806094263bf0d62eb5f3..03eeb576b286ee9b48019dcccc656fdc8b751ad9 100644 (file)
--- 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 <sys/queue.h> */
 #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 *);
 
index 594fe16d7be847cfc9ab781e6e2a89e7c42e5364..9daafa7ee88a9760ff6551e3a9011f34060417ba 100644 (file)
--- a/kqueue.c
+++ b/kqueue.c
@@ -33,6 +33,7 @@
 #include <sys/time.h>
 #include <sys/queue.h>
 #include <sys/event.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -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;
index 3e5145dd9d0440b0fd31ff759540600833096a71..562bcf1e33c574e7e5acf16bf994178258aeae95 100644 (file)
@@ -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);
 
index 7489285b5bb92021b04b984f49e91eb91e6d578a..afafb44408767968a674bfe93ac9df99503aec25 100644 (file)
--- 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));