diff options
Diffstat (limited to 'lib/tevent')
-rw-r--r-- | lib/tevent/tevent_aio.c | 4 | ||||
-rw-r--r-- | lib/tevent/tevent_epoll.c | 4 | ||||
-rw-r--r-- | lib/tevent/tevent_internal.h | 6 | ||||
-rw-r--r-- | lib/tevent/tevent_select.c | 4 | ||||
-rw-r--r-- | lib/tevent/tevent_signal.c | 52 | ||||
-rw-r--r-- | lib/tevent/tevent_standard.c | 8 |
6 files changed, 57 insertions, 21 deletions
diff --git a/lib/tevent/tevent_aio.c b/lib/tevent/tevent_aio.c index b15dab3aaf..28134bef5e 100644 --- a/lib/tevent/tevent_aio.c +++ b/lib/tevent/tevent_aio.c @@ -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; diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 3835774349..9dc6e8ba5e 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -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; } diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h index f29e9c62f5..e090ee2bb1 100644 --- a/lib/tevent/tevent_internal.h +++ b/lib/tevent/tevent_internal.h @@ -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; diff --git a/lib/tevent/tevent_select.c b/lib/tevent/tevent_select.c index cf4453f64f..c1b01bb84f 100644 --- a/lib/tevent/tevent_select.c +++ b/lib/tevent/tevent_select.c @@ -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; } diff --git a/lib/tevent/tevent_signal.c b/lib/tevent/tevent_signal.c index 031845927b..f4a56cda6c 100644 --- a/lib/tevent/tevent_signal.c +++ b/lib/tevent/tevent_signal.c @@ -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; diff --git a/lib/tevent/tevent_standard.c b/lib/tevent/tevent_standard.c index 2a292a4c39..2d8a2305d9 100644 --- a/lib/tevent/tevent_standard.c +++ b/lib/tevent/tevent_standard.c @@ -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; } |