]> granicus.if.org Git - libevent/commitdiff
more the signal base into the event base; this removes global state and makes signals
authorNiels Provos <provos@gmail.com>
Sat, 10 Mar 2007 06:37:53 +0000 (06:37 +0000)
committerNiels Provos <provos@gmail.com>
Sat, 10 Mar 2007 06:37:53 +0000 (06:37 +0000)
work better with threading; from Wouter Wijngaards
small fixes for kqueue and style by me

svn:r351

15 files changed:
WIN32-Code/win32.c
devpoll.c
epoll.c
event-internal.h
event.3
event.c
event.h
evport.c
evsignal.h
kqueue.c
poll.c
rtsig.c
select.c
signal.c
test/regress.c

index 867d1f22fd4382b59b5d3cdb248649f1d0c7c507..c051c9432dccddabe43dc2d60c6f90918385084f 100644 (file)
@@ -81,12 +81,12 @@ struct win32op {
        struct event **events;
 };
 
-void *win32_init       (void);
+void *win32_init       (struct event_base *);
 int win32_insert       (void *, struct event *);
 int win32_del  (void *, struct event *);
 int win32_recalc       (struct event_base *base, void *, int);
 int win32_dispatch     (struct event_base *base, void *, struct timeval *);
-void win32_dealloc     (void *);
+void win32_dealloc     (struct event_base *, void *);
 
 struct eventop win32ops = {
        "win32",
@@ -167,7 +167,7 @@ do_fd_clear(struct win32op *op, SOCKET s, int read)
 
 #define NEVENT 64
 void *
-win32_init(void)
+win32_init(struct event_base *)
 {
        struct win32op *winop;
        size_t size;
@@ -376,7 +376,7 @@ win32_dispatch(struct event_base *base, void *op,
 }
 
 void
-win32_dealloc(void *arg)
+win32_dealloc(struct event_base *, void *arg)
 {
        struct win32op *win32op = arg;
 
index db897a9de230897081305f3ccfc718b30eb32808..63e1dc90e92f64a1da4847b5a209da14ef871b72 100644 (file)
--- a/devpoll.c
+++ b/devpoll.c
@@ -50,8 +50,6 @@
 #include "evsignal.h"
 #include "log.h"
 
-extern volatile sig_atomic_t evsignal_caught;
-
 /* due to limitations in the devpoll interface, we need to keep track of
  * all file descriptors outself.
  */
@@ -70,12 +68,12 @@ struct devpollop {
        int nchanges;
 };
 
-void *devpoll_init     (void);
+void *devpoll_init     (struct event_base *);
 int devpoll_add        (void *, struct event *);
 int devpoll_del        (void *, struct event *);
 int devpoll_recalc     (struct event_base *, void *, int);
 int devpoll_dispatch   (struct event_base *, void *, struct timeval *);
-void devpoll_dealloc   (void *);
+void devpoll_dealloc   (struct event_base *, void *);
 
 struct eventop devpollops = {
        "devpoll",
@@ -126,7 +124,7 @@ devpoll_queue(struct devpollop *devpollop, int fd, int events) {
 }
 
 void *
-devpoll_init(void)
+devpoll_init(struct event_base *base)
 {
        int dpfd, nfiles = NEVENT;
        struct rlimit rl;
@@ -179,7 +177,7 @@ devpoll_init(void)
                return (NULL);
        }
 
-       evsignal_init();
+       evsignal_init(base);
 
        return (devpollop);
 }
@@ -237,10 +235,11 @@ devpoll_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: devpoll_wait reports %d", __func__, res));
 
@@ -398,10 +397,11 @@ devpoll_del(void *arg, struct event *ev)
 }
 
 void
-devpoll_dealloc(void *arg)
+devpoll_dealloc(struct event_base *base, void *arg)
 {
        struct devpollop *devpollop = arg;
 
+       evsignal_dealloc(base);
        if (devpollop->fds)
                free(devpollop->fds);
        if (devpollop->events)
diff --git a/epoll.c b/epoll.c
index e089e23d9e0928260e4651fad6ca43c26b0a0372..235977def1a92132b727df29f3487e99d6f4b6eb 100644 (file)
--- a/epoll.c
+++ b/epoll.c
@@ -30,6 +30,7 @@
 
 #include <stdint.h>
 #include <sys/types.h>
+#include <sys/tree.h>
 #include <sys/resource.h>
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
 #endif
 
 #include "event.h"
+#include "event-internal.h"
 #include "evsignal.h"
 #include "log.h"
 
-extern volatile sig_atomic_t evsignal_caught;
-
 /* due to limitations in the epoll interface, we need to keep track of
  * all file descriptors outself.
  */
@@ -70,12 +70,12 @@ struct epollop {
        int epfd;
 };
 
-void *epoll_init       (void);
+void *epoll_init       (struct event_base *);
 int epoll_add  (void *, struct event *);
 int epoll_del  (void *, struct event *);
 int epoll_recalc       (struct event_base *, void *, int);
 int epoll_dispatch     (struct event_base *, void *, struct timeval *);
-void epoll_dealloc     (void *);
+void epoll_dealloc     (struct event_base *, void *);
 
 struct eventop epollops = {
        "epoll",
@@ -99,7 +99,7 @@ struct eventop epollops = {
 #define NEVENT 32000
 
 void *
-epoll_init(void)
+epoll_init(struct event_base *base)
 {
        int epfd, nfiles = NEVENT;
        struct rlimit rl;
@@ -149,7 +149,7 @@ epoll_init(void)
        }
        epollop->nfds = nfiles;
 
-       evsignal_init();
+       evsignal_init(base);
 
        return (epollop);
 }
@@ -198,10 +198,11 @@ epoll_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: epoll_wait reports %d", __func__, res));
 
@@ -346,10 +347,11 @@ epoll_del(void *arg, struct event *ev)
 }
 
 void
-epoll_dealloc(void *arg)
+epoll_dealloc(struct event_base *base, void *arg)
 {
        struct epollop *epollop = arg;
 
+       evsignal_dealloc(base);
        if (epollop->fds)
                free(epollop->fds);
        if (epollop->events)
index becb6691d52acf42712d5587efa332300d6fcba9..7fd4b6c690f34885a1933e3128640b9114b40e2b 100644 (file)
@@ -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/event.3 b/event.3
index 132c30f02f8230a95c7ea87b21f05bbb49d0fa49..fc71b7dfdac62e641e69e480fa2d337dba3b7665 100644 (file)
--- a/event.3
+++ b/event.3
@@ -42,6 +42,7 @@
 .Nm event_add ,
 .Nm event_del ,
 .Nm event_once ,
+.Nm event_base_once ,
 .Nm event_pending ,
 .Nm event_initialized ,
 .Nm event_priority_init ,
 .Ft int
 .Fn "event_once" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" "struct timeval *tv"
 .Ft int
+.Fn "event_base_once" "struct event_base *base" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" "struct timeval *tv"
+.Ft int
 .Fn "event_pending" "struct event *ev" "short event" "struct timeval *tv"
 .Ft int
 .Fn "event_initialized" "struct event *ev"
diff --git a/event.c b/event.c
index f6d2b1cc42caa29cffaf4c90237f700b1f3eb8ce..2048157d9f399cef9708c228dddfd69027076ece 100644 (file)
--- a/event.c
+++ b/event.c
@@ -111,9 +111,8 @@ const struct eventop *eventops[] = {
 };
 
 /* Global state */
-struct event_list signalqueue;
-
 struct event_base *current_base = NULL;
+extern struct event_base *evsignal_base;
 
 /* Handle signals - This is a deprecated interface */
 int (*event_sigcb)(void);              /* Signal callback when gotsig is set */
@@ -174,36 +173,40 @@ 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(&current_base->event_tv);
+       gettime(&base->event_tv);
        
-       RB_INIT(&current_base->timetree);
-       TAILQ_INIT(&current_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 +220,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 +231,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 +346,6 @@ event_loopexit_cb(int fd, short what, void *arg)
 }
 
 /* not thread safe */
-
 int
 event_loopexit(struct timeval *tv)
 {
@@ -354,7 +356,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));
 }
 
@@ -374,6 +376,8 @@ event_base_loop(struct event_base *base, int flags)
        struct timeval tv;
        int res, done;
 
+       if(!TAILQ_EMPTY(&base->sig.signalqueue))
+               evsignal_base = base;
        done = 0;
        while (!done) {
                /* Calculate the initial events that we are waiting for */
@@ -422,6 +426,7 @@ event_base_loop(struct event_base *base, int flags)
 
                res = evsel->dispatch(base, evbase, &tv);
 
+
                if (res == -1)
                        return (-1);
 
@@ -459,11 +464,18 @@ 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;
@@ -496,7 +508,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);
@@ -521,7 +535,8 @@ event_set(struct event *ev, int fd, short events,
        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
@@ -801,7 +816,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 +858,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/event.h b/event.h
index 3f2032dd068ee675d8d403714cfe1ef154da0735..8687f19498d481c3c6e387aa2b9f90a599a7eb65 100644 (file)
--- a/event.h
+++ b/event.h
@@ -131,12 +131,12 @@ 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}
@@ -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 *);
index 89bbd1eddad4efd697a311e431b60b9de20e46c0..677ae832e5fb389fa335a3f59eff1adb825895ec 100644 (file)
--- a/evport.c
+++ b/evport.c
@@ -81,8 +81,6 @@
 #include "log.h"
 #include "evsignal.h"
 
-extern volatile sig_atomic_t evsignal_caught;
-
 
 /*
  * Default value for ed_nevents, which is the maximum file descriptor number we
@@ -123,7 +121,7 @@ struct evport_data {
        struct fd_info *ed_pending[EVENTS_PER_GETN];
 };
 
-static void*   evport_init     (void);
+static void*   evport_init     (struct event_base *);
 static int     evport_add      (void *, struct event *);
 static int     evport_del      (void *, struct event *);
 static int     evport_recalc   (struct event_base *, void *, int);
@@ -143,7 +141,7 @@ const struct eventop evportops = {
  */
 
 static void*
-evport_init(void)
+evport_init(struct event_base *base)
 {
        struct evport_data *evpd;
        /*
@@ -172,7 +170,7 @@ evport_init(void)
        evpd->ed_nevents = DEFAULT_NFDS;
        memset(&evpd->ed_pending, 0, EVENTS_PER_GETN * sizeof(struct fd_info*));
 
-       evsignal_init();
+       evsignal_init(base);
 
        return (evpd);
 }
@@ -332,7 +330,7 @@ evport_dispatch(struct event_base *base, void *arg, struct timeval *tv)
        if ((res = port_getn(epdp->ed_port, pevtlist, EVENTS_PER_GETN, 
                    &nevents, &ts)) == -1) {
                if (errno == EINTR) {
-                       evsignal_process();
+                       evsignal_process(base);
                        return (0);
                } else if (errno == ETIME) {
                        if (nevents == 0)
@@ -341,8 +339,8 @@ evport_dispatch(struct event_base *base, void *arg, struct timeval *tv)
                        perror("port_getn");
                        return (-1);
                }
-       } else if (evsignal_caught) {
-               evsignal_process();
+       } else if (base->sig.evsignal_caught) {
+               evsignal_process(base);
        }
        
        event_debug(("%s: port_getn reports %d events", __func__, nevents));
index 5b92bd6e55fb14c06c1c098633204b5a350544ec..7efbcabec8964cea4cb2583ae17be1cefb44a445 100644 (file)
 #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_ */
index 08369c6dd51d93fd62dfbe0577ff0fae8105a6c5..af2e0f167d0c67d133f565b8283c0e44f5897d70 100644 (file)
--- a/kqueue.c
+++ b/kqueue.c
@@ -69,13 +69,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 +88,7 @@ const struct eventop kqops = {
 };
 
 void *
-kq_init(void)
+kq_init(struct event_base *base)
 {
        int kq;
        struct kqop *kqueueop;
@@ -398,7 +398,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/poll.c b/poll.c
index 14ca8453739b4c4575f6a9195184d00973d8d2d7..84885984ff07ecf64ea354a79952b8fc355257e2 100644 (file)
--- a/poll.c
+++ b/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);
 }
@@ -164,10 +162,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 +369,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/rtsig.c b/rtsig.c
index 29aade6948dcdc23c2927e9c3dc7aa6453ff74b1..3267af9441205aa645451bf16045957bbbbe27f7 100644 (file)
--- a/rtsig.c
+++ b/rtsig.c
@@ -223,7 +223,7 @@ struct rtdata {
        int poll_position;
 };
 
-void *rtsig_init(void);
+void *rtsig_init(struct event_base *);
 int rtsig_add(void *, struct event *);
 int rtsig_del(void *, struct event *);
 int rtsig_recalc(struct event_base *, void *, int);
@@ -544,7 +544,7 @@ activate(struct event *ev, int flags)
 } while (0)
 
 void *
-rtsig_init(void)
+rtsig_init(struct event_base *)
 {
        struct rtsigop *op;
        int sockets[2];
index 6ce81a232bbeebc97a1ff603dfcb7358374f3c20..3affa12d45301d35d59a24d8a2c35cbe32f1921e 100644 (file)
--- a/select.c
+++ b/select.c
@@ -57,8 +57,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 +68,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 +88,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 +101,7 @@ select_init(void)
 
        select_resize(sop, howmany(32 + 1, NFDBITS)*sizeof(fd_mask));
 
-       evsignal_init();
+       evsignal_init(base);
 
        return (sop);
 }
@@ -113,7 +111,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 +172,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 +347,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)
index 71bcffcba5b39953c7c49105e82d51dd8d86caa7..6c0953d9e121ee88ff419729808dfafa1769d3e8 100644 (file)
--- a/signal.c
+++ b/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
 #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;
+}
index ff134dade5e8f62260a5f736baafbf590a62753f..9cd739da70772a277aedd10a578ddbf9058db02b 100644 (file)
@@ -35,6 +35,7 @@
 #endif
 
 #include <sys/types.h>
+#include <sys/tree.h>
 #include <sys/stat.h>
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
@@ -53,6 +54,7 @@
 #include <errno.h>
 
 #include "event.h"
+#include "event-internal.h"
 #include "log.h"
 
 #include "regress.h"
@@ -465,6 +467,96 @@ test_immediatesignal(void)
        signal_del(&ev);
        cleanup_test();
 }
+
+void
+test_signal_dealloc(void)
+{
+       /* make sure that signal_event is event_del'ed and pipe closed */
+       struct event ev;
+       struct event_base *base = event_init();
+       printf("Signal dealloc: ");
+       signal_set(&ev, SIGUSR1, signal_cb, &ev);
+       signal_add(&ev, NULL);
+       signal_del(&ev);
+       event_base_free(base);
+       errno = EINTR;
+       if (base->sig.ev_signal_added) {
+               printf("ev_signal not removed (evsignal_dealloc needed) ");
+               test_ok = 0;
+       } else if (close(base->sig.ev_signal_pair[0]) != -1 ||
+           errno != EBADF) {
+               /* fd must be closed, so second close gives -1, EBADF */
+               printf("signal pipe still open (evsignal_dealloc needed) ");
+               test_ok = 0;
+       } else {
+               test_ok = 1;
+       }
+       cleanup_test();
+}
+
+void
+test_signal_pipeloss(void)
+{
+       /* make sure that the base1 pipe is closed correctly. */
+       struct event_base *base1, *base2;
+       int pipe1;
+       printf("Signal pipeloss: ");
+       base1 = event_init();
+       pipe1 = base1->sig.ev_signal_pair[0];
+       base2 = event_init();
+       event_base_free(base2);
+       event_base_free(base1);
+       if (close(pipe1) != -1 || errno!=EBADF) {
+               /* fd must be closed, so second close gives -1, EBADF */
+               printf("signal pipe not closed. ");
+               test_ok = 0;
+       } else {
+               test_ok = 1;
+       }
+       cleanup_test();
+}
+
+/*
+ * make two bases to catch signals, use both of them.  this only works
+ * for event mechanisms that use our signal pipe trick.  kqueue handles
+ * signals internally, and it looks like the first kqueue always gets the
+ * signal.
+ */
+void
+test_signal_switchbase(void)
+{
+       struct event ev1, ev2;
+       struct event_base *base1, *base2;
+       printf("Signal switchbase: ");
+       base1 = event_init();
+       base2 = event_init();
+       signal_set(&ev1, SIGUSR1, signal_cb, &ev1);
+       signal_set(&ev2, SIGUSR1, signal_cb, &ev2);
+       if (event_base_set(base1, &ev1) ||
+           event_base_set(base2, &ev2) ||
+           event_add(&ev1, NULL) ||
+           event_add(&ev2, NULL)) {
+               fprintf(stderr, "%s: cannot set base, add\n", __func__);
+               exit(1);
+       }
+
+       test_ok = 0;
+       /* can handle signal before loop is called */
+       raise(SIGUSR1);
+       event_base_loop(base2, EVLOOP_NONBLOCK);
+       event_base_loop(base1, EVLOOP_NONBLOCK);
+       if (test_ok) {
+               test_ok = 0;
+               /* set base1 to handle signals */
+               event_base_loop(base1, EVLOOP_NONBLOCK);
+               raise(SIGUSR1);
+               event_base_loop(base1, EVLOOP_NONBLOCK);
+               event_base_loop(base2, EVLOOP_NONBLOCK);
+       }
+       event_base_free(base1);
+       event_base_free(base2);
+       cleanup_test();
+}
 #endif
 
 void
@@ -930,6 +1022,12 @@ main (int argc, char **argv)
        test_multiple_events_for_same_fd();
 
        test_want_only_once();
+
+#ifndef WIN32
+       test_signal_dealloc();
+       test_signal_pipeloss();
+       test_signal_switchbase();
+#endif
        
        evtag_test();