tevent: keep a linked list of signal events
authorStefan Metzmacher <metze@samba.org>
Mon, 5 Jan 2009 15:55:00 +0000 (16:55 +0100)
committerStefan Metzmacher <metze@samba.org>
Mon, 5 Jan 2009 21:44:53 +0000 (22:44 +0100)
metze

lib/tevent/tevent_aio.c
lib/tevent/tevent_epoll.c
lib/tevent/tevent_internal.h
lib/tevent/tevent_select.c
lib/tevent/tevent_signal.c
lib/tevent/tevent_standard.c

index b15dab3aaf310f58464dacb7da76824ac2a07493..28134bef5eeb9366a60d78cd5fc8612d7faa90f6 100644 (file)
@@ -260,7 +260,7 @@ static int aio_event_loop(struct aio_event_context *aio_ev, struct timeval *tval
 
        if (aio_ev->epoll_fd == -1) return -1;
 
-       if (aio_ev->ev->num_signal_handlers && 
+       if (aio_ev->ev->signal_events &&
            tevent_common_check_signal(aio_ev->ev)) {
                return 0;
        }
@@ -278,7 +278,7 @@ static int aio_event_loop(struct aio_event_context *aio_ev, struct timeval *tval
                           events, tvalp?&timeout:NULL);
 
        if (ret == -EINTR) {
-               if (aio_ev->ev->num_signal_handlers) {
+               if (aio_ev->ev->signal_events) {
                        tevent_common_check_signal(aio_ev->ev);
                }
                return 0;
index 38357743499c44b44f7398ed6e22022072877764..9dc6e8ba5edb29bbd5c780d153050121ec7e9267 100644 (file)
@@ -256,14 +256,14 @@ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval
                timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
        }
 
-       if (epoll_ev->ev->num_signal_handlers && 
+       if (epoll_ev->ev->signal_events &&
            tevent_common_check_signal(epoll_ev->ev)) {
                return 0;
        }
 
        ret = epoll_wait(epoll_ev->epoll_fd, events, MAXEVENTS, timeout);
 
-       if (ret == -1 && errno == EINTR && epoll_ev->ev->num_signal_handlers) {
+       if (ret == -1 && errno == EINTR && epoll_ev->ev->signal_events) {
                if (tevent_common_check_signal(epoll_ev->ev)) {
                        return 0;
                }
index f29e9c62f5ba423e927c832289119e922a73511e..e090ee2bb1bd4fb86834345904f25d0dfca96a88 100644 (file)
@@ -133,12 +133,12 @@ struct tevent_context {
        /* list of timed events - used by common code */
        struct tevent_timer *timer_events;
 
+       /* list of signal events - used by common code */
+       struct tevent_signal *signal_events;
+
        /* this is private for the events_ops implementation */
        void *additional_data;
 
-       /* number of signal event handlers */
-       int num_signal_handlers;
-
        /* pipe hack used with signal handlers */
        struct tevent_fd *pipe_fde;
 
index cf4453f64fa649940e457ff2e66979310fedb143..c1b01bb84febef880a85c7f4ffc9eaf0340d7f34 100644 (file)
@@ -177,7 +177,7 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru
                }
        }
 
-       if (select_ev->ev->num_signal_handlers && 
+       if (select_ev->ev->signal_events &&
            tevent_common_check_signal(select_ev->ev)) {
                return 0;
        }
@@ -185,7 +185,7 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru
        selrtn = select(select_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
 
        if (selrtn == -1 && errno == EINTR && 
-           select_ev->ev->num_signal_handlers) {
+           select_ev->ev->signal_events) {
                tevent_common_check_signal(select_ev->ev);
                return 0;
        }
index 031845927b957c2afeb743b04416a4637d238584..f4a56cda6c6b876b2fb4bccddd61fd4a0f5285ac 100644 (file)
@@ -40,12 +40,16 @@ struct sigcounter {
 #define SIG_SEEN(s, n) (s).seen += (n)
 #define SIG_PENDING(s) ((s).seen != (s).count)
 
+struct tevent_common_signal_list {
+       struct tevent_common_signal_list *prev, *next;
+       struct tevent_signal *se;
+};
 
 /*
   the poor design of signals means that this table must be static global
 */
 static struct sig_state {
-       struct tevent_signal *sig_handlers[NUM_SIGNALS+1];
+       struct tevent_common_signal_list *sig_handlers[NUM_SIGNALS+1];
        struct sigaction *oldact[NUM_SIGNALS+1];
        struct sigcounter signal_count[NUM_SIGNALS+1];
        struct sigcounter got_signal;
@@ -104,13 +108,27 @@ static void signal_handler_info(int signum, siginfo_t *info, void *uctx)
 }
 #endif
 
+static int tevent_common_signal_list_destructor(struct tevent_common_signal_list *sl)
+{
+       DLIST_REMOVE(sig_state->sig_handlers[sl->se->signum], sl);
+       return 0;
+}
+
 /*
   destroy a signal event
 */
 static int tevent_signal_destructor(struct tevent_signal *se)
 {
-       se->event_ctx->num_signal_handlers--;
-       DLIST_REMOVE(sig_state->sig_handlers[se->signum], se);
+       struct tevent_common_signal_list *sl;
+       sl = talloc_get_type(se->additional_data,
+                            struct tevent_common_signal_list);
+
+       if (se->event_ctx) {
+               DLIST_REMOVE(se->event_ctx->signal_events, se);
+       }
+
+       talloc_free(sl);
+
        if (sig_state->sig_handlers[se->signum] == NULL) {
                /* restore old handler, if any */
                sigaction(se->signum, sig_state->oldact[se->signum], NULL);
@@ -122,6 +140,7 @@ static int tevent_signal_destructor(struct tevent_signal *se)
                }
 #endif
        }
+
        return 0;
 }
 
@@ -150,8 +169,10 @@ struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev,
                                               const char *location)
 {
        struct tevent_signal *se;
+       struct tevent_common_signal_list *sl;
 
        if (signum >= NUM_SIGNALS) {
+               errno = EINVAL;
                return NULL;
        }
 
@@ -176,8 +197,17 @@ struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev,
        se->location            = location;
        se->additional_data     = NULL;
 
+       sl = talloc(se, struct tevent_common_signal_list);
+       if (!sl) {
+               talloc_free(se);
+               return NULL;
+       }
+       sl->se = se;
+       se->additional_data     = sl;
+
        /* Ensure, no matter the destruction order, that we always have a handle on the global sig_state */
        if (!talloc_reference(se, sig_state)) {
+               talloc_free(se);
                return NULL;
        }
 
@@ -211,9 +241,11 @@ struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev,
                }
        }
 
-       DLIST_ADD(sig_state->sig_handlers[signum], se);
+       DLIST_ADD(se->event_ctx->signal_events, se);
+       DLIST_ADD(sig_state->sig_handlers[signum], sl);
 
        talloc_set_destructor(se, tevent_signal_destructor);
+       talloc_set_destructor(sl, tevent_common_signal_list_destructor);
 
        /* we need to setup the pipe hack handler if not already
           setup */
@@ -226,8 +258,11 @@ struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev,
                }
                ev->pipe_fde = tevent_add_fd(ev, ev, sig_state->pipe_hack[0],
                                             TEVENT_FD_READ, signal_pipe_handler, NULL);
+               if (!ev->pipe_fde) {
+                       talloc_free(se);
+                       return NULL;
+               }
        }
-       ev->num_signal_handlers++;
 
        return se;
 }
@@ -246,15 +281,16 @@ int tevent_common_check_signal(struct tevent_context *ev)
        }
        
        for (i=0;i<NUM_SIGNALS+1;i++) {
-               struct tevent_signal *se, *next;
+               struct tevent_common_signal_list *sl, *next;
                struct sigcounter counter = sig_state->signal_count[i];
                uint32_t count = sig_count(counter);
 
                if (count == 0) {
                        continue;
                }
-               for (se=sig_state->sig_handlers[i];se;se=next) {
-                       next = se->next;
+               for (sl=sig_state->sig_handlers[i];sl;sl=next) {
+                       struct tevent_signal *se = sl->se;
+                       next = sl->next;
 #ifdef SA_SIGINFO
                        if (se->sa_flags & SA_SIGINFO) {
                                int j;
index 2a292a4c3966ed27b7440917c6ac2eb2d3f5ce21..2d8a2305d9cbc1faedaf9b1b1334ef58f86a2a8b 100644 (file)
@@ -264,14 +264,14 @@ static int epoll_event_loop(struct std_event_context *std_ev, struct timeval *tv
                timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
        }
 
-       if (std_ev->ev->num_signal_handlers && 
+       if (std_ev->ev->signal_events &&
            tevent_common_check_signal(std_ev->ev)) {
                return 0;
        }
 
        ret = epoll_wait(std_ev->epoll_fd, events, MAXEVENTS, timeout);
 
-       if (ret == -1 && errno == EINTR && std_ev->ev->num_signal_handlers) {
+       if (ret == -1 && errno == EINTR && std_ev->ev->signal_events) {
                if (tevent_common_check_signal(std_ev->ev)) {
                        return 0;
                }
@@ -490,7 +490,7 @@ static int std_event_loop_select(struct std_event_context *std_ev, struct timeva
                }
        }
 
-       if (std_ev->ev->num_signal_handlers && 
+       if (std_ev->ev->signal_events &&
            tevent_common_check_signal(std_ev->ev)) {
                return 0;
        }
@@ -498,7 +498,7 @@ static int std_event_loop_select(struct std_event_context *std_ev, struct timeva
        selrtn = select(std_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
 
        if (selrtn == -1 && errno == EINTR && 
-           std_ev->ev->num_signal_handlers) {
+           std_ev->ev->signal_events) {
                tevent_common_check_signal(std_ev->ev);
                return 0;
        }