summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/tevent/tevent_aio.c4
-rw-r--r--lib/tevent/tevent_epoll.c4
-rw-r--r--lib/tevent/tevent_internal.h6
-rw-r--r--lib/tevent/tevent_select.c4
-rw-r--r--lib/tevent/tevent_signal.c52
-rw-r--r--lib/tevent/tevent_standard.c8
6 files changed, 57 insertions, 21 deletions
diff --git a/lib/tevent/tevent_aio.c b/lib/tevent/tevent_aio.c
index b15dab3aaf3..28134bef5ee 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 38357743499..9dc6e8ba5ed 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 f29e9c62f5b..e090ee2bb1b 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 cf4453f64fa..c1b01bb84fe 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 031845927b9..f4a56cda6c6 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 2a292a4c396..2d8a2305d9c 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;
}