summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2009-08-28 12:08:47 +0930
committerAndrew Tridgell <tridge@samba.org>2009-08-28 14:09:09 +1000
commitbe4ac227842530d484659f2db683453366326d8b (patch)
treeb25bff85d32a796032e949e0f91965925df557bd
parent6abb637e3e0d23635fdbbb91c163731b325d696d (diff)
downloadsamba-be4ac227842530d484659f2db683453366326d8b.tar.gz
samba-be4ac227842530d484659f2db683453366326d8b.tar.bz2
samba-be4ac227842530d484659f2db683453366326d8b.zip
lib/tevent: handle tevent_common_add_signal on different event contexts.
I don't know if this is a problem in real life. The code assumes there's only one tevent_context; all signals will notify the first event context. That's counter-intuitive if you ever use more than one, and there's nothing else in this code which prevents it AFAICT. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--lib/tevent/tevent_internal.h1
-rw-r--r--lib/tevent/tevent_signal.c44
2 files changed, 31 insertions, 14 deletions
diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h
index 513ca1c732..4e3b7b5718 100644
--- a/lib/tevent/tevent_internal.h
+++ b/lib/tevent/tevent_internal.h
@@ -240,6 +240,7 @@ struct tevent_context {
/* pipe hack used with signal handlers */
struct tevent_fd *pipe_fde;
+ int pipe_fds[2];
/* debugging operations */
struct tevent_debug_ops debug_ops;
diff --git a/lib/tevent/tevent_signal.c b/lib/tevent/tevent_signal.c
index 5e4e81b73c..0333325ef0 100644
--- a/lib/tevent/tevent_signal.c
+++ b/lib/tevent/tevent_signal.c
@@ -57,7 +57,6 @@ static struct sig_state {
struct sigaction *oldact[NUM_SIGNALS+1];
struct sigcounter signal_count[NUM_SIGNALS+1];
struct sigcounter got_signal;
- int pipe_hack[2];
#ifdef SA_SIGINFO
/* with SA_SIGINFO we get quite a lot of info per signal */
siginfo_t *sig_info[NUM_SIGNALS+1];
@@ -80,10 +79,20 @@ static void tevent_common_signal_handler(int signum)
{
char c = 0;
ssize_t res;
+ struct tevent_common_signal_list *sl;
+ struct tevent_context *ev = NULL;
+
SIG_INCREMENT(sig_state->signal_count[signum]);
SIG_INCREMENT(sig_state->got_signal);
- /* doesn't matter if this pipe overflows */
- res = write(sig_state->pipe_hack[1], &c, 1);
+
+ /* Write to each unique event context. */
+ for (sl = sig_state->sig_handlers[signum]; sl; sl = sl->next) {
+ if (sl->se->event_ctx != ev) {
+ /* doesn't matter if this pipe overflows */
+ res = write(ev->pipe_fds[1], &c, 1);
+ ev = sl->se->event_ctx;
+ }
+ }
}
#ifdef SA_SIGINFO
@@ -160,7 +169,7 @@ static void signal_pipe_handler(struct tevent_context *ev, struct tevent_fd *fde
char c[16];
ssize_t res;
/* its non-blocking, doesn't matter if we read too much */
- res = read(sig_state->pipe_hack[0], c, sizeof(c));
+ res = read(fde->fd, c, sizeof(c));
}
/*
@@ -178,6 +187,7 @@ struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev,
{
struct tevent_signal *se;
struct tevent_common_signal_list *sl;
+ sigset_t set, oldset;
if (signum >= NUM_SIGNALS) {
errno = EINVAL;
@@ -222,18 +232,18 @@ struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev,
/* we need to setup the pipe hack handler if not already
setup */
if (ev->pipe_fde == NULL) {
- if (sig_state->pipe_hack[0] == 0 &&
- sig_state->pipe_hack[1] == 0) {
- if (pipe(sig_state->pipe_hack) == -1) {
- talloc_free(se);
- return NULL;
- }
- ev_set_blocking(sig_state->pipe_hack[0], false);
- ev_set_blocking(sig_state->pipe_hack[1], false);
+ if (pipe(ev->pipe_fds) == -1) {
+ talloc_free(se);
+ return NULL;
}
- ev->pipe_fde = tevent_add_fd(ev, ev, sig_state->pipe_hack[0],
- TEVENT_FD_READ, signal_pipe_handler, NULL);
+ ev_set_blocking(ev->pipe_fds[0], false);
+ ev_set_blocking(ev->pipe_fds[1], false);
+ ev->pipe_fde = tevent_add_fd(ev, ev, ev->pipe_fds[0],
+ TEVENT_FD_READ,
+ signal_pipe_handler, NULL);
if (!ev->pipe_fde) {
+ close(ev->pipe_fds[0]);
+ close(ev->pipe_fds[1]);
talloc_free(se);
return NULL;
}
@@ -270,7 +280,13 @@ struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev,
}
DLIST_ADD(se->event_ctx->signal_events, se);
+
+ /* Make sure the signal doesn't come in while we're mangling list. */
+ sigemptyset(&set);
+ sigaddset(&set, signum);
+ sigprocmask(SIG_BLOCK, &set, &oldset);
DLIST_ADD(sig_state->sig_handlers[signum], sl);
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
talloc_set_destructor(se, tevent_signal_destructor);
talloc_set_destructor(sl, tevent_common_signal_list_destructor);