summaryrefslogtreecommitdiff
path: root/source4/lib/events/events_signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/events/events_signal.c')
-rw-r--r--source4/lib/events/events_signal.c86
1 files changed, 48 insertions, 38 deletions
diff --git a/source4/lib/events/events_signal.c b/source4/lib/events/events_signal.c
index 21542d863b..2c18a677b1 100644
--- a/source4/lib/events/events_signal.c
+++ b/source4/lib/events/events_signal.c
@@ -45,7 +45,7 @@ struct sigcounter {
/*
the poor design of signals means that this table must be static global
*/
-static struct {
+static struct sig_state {
struct signal_event *sig_handlers[NUM_SIGNALS];
struct sigaction *oldact[NUM_SIGNALS];
struct sigcounter signal_count[NUM_SIGNALS];
@@ -56,7 +56,7 @@ static struct {
siginfo_t *sig_info[NUM_SIGNALS];
struct sigcounter sig_blocked[NUM_SIGNALS];
#endif
-} sig_state;
+} *sig_state;
/*
return number of sigcounter events not processed yet
@@ -75,10 +75,10 @@ static uint32_t sig_count(struct sigcounter s)
static void signal_handler(int signum)
{
char c = 0;
- SIG_INCREMENT(sig_state.signal_count[signum]);
- SIG_INCREMENT(sig_state.got_signal);
+ SIG_INCREMENT(sig_state->signal_count[signum]);
+ SIG_INCREMENT(sig_state->got_signal);
/* doesn't matter if this pipe overflows */
- write(sig_state.pipe_hack[1], &c, 1);
+ write(sig_state->pipe_hack[1], &c, 1);
}
#ifdef SA_SIGINFO
@@ -87,8 +87,8 @@ static void signal_handler(int signum)
*/
static void signal_handler_info(int signum, siginfo_t *info, void *uctx)
{
- uint32_t count = sig_count(sig_state.signal_count[signum]);
- sig_state.sig_info[signum][count] = *info;
+ uint32_t count = sig_count(sig_state->signal_count[signum]);
+ sig_state->sig_info[signum][count] = *info;
signal_handler(signum);
@@ -100,7 +100,7 @@ static void signal_handler_info(int signum, siginfo_t *info, void *uctx)
sigemptyset(&set);
sigaddset(&set, signum);
sigprocmask(SIG_BLOCK, &set, NULL);
- SIG_INCREMENT(sig_state.sig_blocked[signum]);
+ SIG_INCREMENT(sig_state->sig_blocked[signum]);
}
}
#endif
@@ -111,15 +111,15 @@ static void signal_handler_info(int signum, siginfo_t *info, void *uctx)
static int signal_event_destructor(struct signal_event *se)
{
se->event_ctx->num_signal_handlers--;
- DLIST_REMOVE(sig_state.sig_handlers[se->signum], se);
- if (sig_state.sig_handlers[se->signum] == NULL) {
+ DLIST_REMOVE(sig_state->sig_handlers[se->signum], se);
+ if (sig_state->sig_handlers[se->signum] == NULL) {
/* restore old handler, if any */
- sigaction(se->signum, sig_state.oldact[se->signum], NULL);
- sig_state.oldact[se->signum] = NULL;
+ sigaction(se->signum, sig_state->oldact[se->signum], NULL);
+ sig_state->oldact[se->signum] = NULL;
#ifdef SA_SIGINFO
if (se->sa_flags & SA_SIGINFO) {
- talloc_free(sig_state.sig_info[se->signum]);
- sig_state.sig_info[se->signum] = NULL;
+ talloc_free(sig_state->sig_info[se->signum]);
+ sig_state->sig_info[se->signum] = NULL;
}
#endif
}
@@ -134,7 +134,7 @@ static void signal_pipe_handler(struct event_context *ev, struct fd_event *fde,
{
char c[16];
/* its non-blocking, doesn't matter if we read too much */
- read(sig_state.pipe_hack[0], c, sizeof(c));
+ read(sig_state->pipe_hack[0], c, sizeof(c));
}
/*
@@ -154,6 +154,15 @@ struct signal_event *common_event_add_signal(struct event_context *ev,
return NULL;
}
+ /* the sig_state needs to be on a global context as it can last across
+ multiple event contexts */
+ if (sig_state == NULL) {
+ sig_state = talloc_zero(talloc_autofree_context(), struct sig_state);
+ if (sig_state == NULL) {
+ return NULL;
+ }
+ }
+
se = talloc(mem_ctx?mem_ctx:ev, struct signal_event);
if (se == NULL) return NULL;
@@ -164,7 +173,7 @@ struct signal_event *common_event_add_signal(struct event_context *ev,
se->sa_flags = sa_flags;
/* only install a signal handler if not already installed */
- if (sig_state.sig_handlers[signum] == NULL) {
+ if (sig_state->sig_handlers[signum] == NULL) {
struct sigaction act;
ZERO_STRUCT(act);
act.sa_handler = signal_handler;
@@ -173,40 +182,40 @@ struct signal_event *common_event_add_signal(struct event_context *ev,
if (sa_flags & SA_SIGINFO) {
act.sa_handler = NULL;
act.sa_sigaction = signal_handler_info;
- if (sig_state.sig_info[signum] == NULL) {
- sig_state.sig_info[signum] = talloc_array(ev, siginfo_t, SA_INFO_QUEUE_COUNT);
- if (sig_state.sig_info[signum] == NULL) {
+ if (sig_state->sig_info[signum] == NULL) {
+ sig_state->sig_info[signum] = talloc_array(sig_state, siginfo_t, SA_INFO_QUEUE_COUNT);
+ if (sig_state->sig_info[signum] == NULL) {
talloc_free(se);
return NULL;
}
}
}
#endif
- sig_state.oldact[signum] = talloc(ev, struct sigaction);
- if (sig_state.oldact[signum] == NULL) {
+ sig_state->oldact[signum] = talloc(sig_state, struct sigaction);
+ if (sig_state->oldact[signum] == NULL) {
talloc_free(se);
return NULL;
}
- if (sigaction(signum, &act, sig_state.oldact[signum]) == -1) {
+ if (sigaction(signum, &act, sig_state->oldact[signum]) == -1) {
talloc_free(se);
return NULL;
}
}
- DLIST_ADD(sig_state.sig_handlers[signum], se);
+ DLIST_ADD(sig_state->sig_handlers[signum], se);
talloc_set_destructor(se, signal_event_destructor);
/* 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) {
- pipe(sig_state.pipe_hack);
- set_blocking(sig_state.pipe_hack[0], False);
- set_blocking(sig_state.pipe_hack[1], False);
+ if (sig_state->pipe_hack[0] == 0 &&
+ sig_state->pipe_hack[1] == 0) {
+ pipe(sig_state->pipe_hack);
+ set_blocking(sig_state->pipe_hack[0], False);
+ set_blocking(sig_state->pipe_hack[1], False);
}
- ev->pipe_fde = event_add_fd(ev, ev, sig_state.pipe_hack[0],
+ ev->pipe_fde = event_add_fd(ev, ev, sig_state->pipe_hack[0],
EVENT_FD_READ, signal_pipe_handler, NULL);
}
ev->num_signal_handlers++;
@@ -222,19 +231,20 @@ struct signal_event *common_event_add_signal(struct event_context *ev,
int common_event_check_signal(struct event_context *ev)
{
int i;
- if (!SIG_PENDING(sig_state.got_signal)) {
+
+ if (!sig_state || !SIG_PENDING(sig_state->got_signal)) {
return 0;
}
for (i=0;i<NUM_SIGNALS+1;i++) {
struct signal_event *se, *next;
- struct sigcounter counter = sig_state.signal_count[i];
+ 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) {
+ for (se=sig_state->sig_handlers[i];se;se=next) {
next = se->next;
#ifdef SA_SIGINFO
if (se->sa_flags & SA_SIGINFO) {
@@ -244,17 +254,17 @@ int common_event_check_signal(struct event_context *ev)
ring buffer */
int ofs = (counter.count + j) % SA_INFO_QUEUE_COUNT;
se->handler(ev, se, i, 1,
- (void*)&sig_state.sig_info[i][ofs],
+ (void*)&sig_state->sig_info[i][ofs],
se->private_data);
}
- if (SIG_PENDING(sig_state.sig_blocked[i])) {
+ if (SIG_PENDING(sig_state->sig_blocked[i])) {
/* we'd filled the queue, unblock the
signal now */
sigset_t set;
sigemptyset(&set);
sigaddset(&set, i);
- SIG_SEEN(sig_state.sig_blocked[i],
- sig_count(sig_state.sig_blocked[i]));
+ SIG_SEEN(sig_state->sig_blocked[i],
+ sig_count(sig_state->sig_blocked[i]));
sigprocmask(SIG_UNBLOCK, &set, NULL);
}
if (se->sa_flags & SA_RESETHAND) {
@@ -268,8 +278,8 @@ int common_event_check_signal(struct event_context *ev)
talloc_free(se);
}
}
- SIG_SEEN(sig_state.signal_count[i], count);
- SIG_SEEN(sig_state.got_signal, count);
+ SIG_SEEN(sig_state->signal_count[i], count);
+ SIG_SEEN(sig_state->got_signal, count);
}
return 1;