2 Unix SMB/CIFS implementation.
4 common events code for signal events
6 Copyright (C) Andrew Tridgell 2007
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "system/filesys.h"
25 #include "system/select.h"
26 #include "lib/util/dlinklist.h"
27 #include "lib/events/events.h"
28 #include "lib/events/events_internal.h"
30 #define NUM_SIGNALS 64
33 the poor design of signals means that this table must be static global
36 struct signal_event *sig_handlers[NUM_SIGNALS];
37 uint32_t signal_count[NUM_SIGNALS];
44 signal handler - redirects to registered signals
46 static void signal_handler(int signum)
49 sig_state.signal_count[signum]++;
50 sig_state.got_signal++;
51 /* doesn't matter if this pipe overflows */
52 write(sig_state.pipe_hack[1], &c, 1);
57 destroy a signal event
59 static int signal_event_destructor(struct signal_event *se)
61 se->event_ctx->num_signal_handlers--;
62 DLIST_REMOVE(sig_state.sig_handlers[se->signum], se);
63 if (sig_state.sig_handlers[se->signum] == NULL) {
64 signal(se->signum, SIG_DFL);
70 this is part of the pipe hack needed to avoid the signal race condition
72 static void signal_pipe_handler(struct event_context *ev, struct fd_event *fde,
73 uint16_t flags, void *private)
76 /* its non-blocking, doesn't matter if we read too much */
77 read(sig_state.pipe_hack[0], c, sizeof(c));
82 return NULL on failure (memory allocation error)
84 struct signal_event *common_event_add_signal(struct event_context *ev,
87 event_signal_handler_t handler,
90 struct signal_event *se;
92 if (signum >= NUM_SIGNALS) {
96 se = talloc(mem_ctx?mem_ctx:ev, struct signal_event);
97 if (se == NULL) return NULL;
100 se->handler = handler;
101 se->private_data = private_data;
104 if (sig_state.sig_handlers[signum] == NULL) {
105 signal(signum, signal_handler);
108 DLIST_ADD(sig_state.sig_handlers[signum], se);
110 talloc_set_destructor(se, signal_event_destructor);
112 if (ev->pipe_fde == NULL) {
113 if (sig_state.pipe_hack[0] == 0 &&
114 sig_state.pipe_hack[1] == 0) {
115 pipe(sig_state.pipe_hack);
116 set_blocking(sig_state.pipe_hack[0], False);
117 set_blocking(sig_state.pipe_hack[1], False);
119 ev->pipe_fde = event_add_fd(ev, ev, sig_state.pipe_hack[0],
120 EVENT_FD_READ, signal_pipe_handler, NULL);
122 ev->num_signal_handlers++;
129 check if a signal is pending
130 return != 0 if a signal was pending
132 int common_event_check_signal(struct event_context *ev)
135 if (sig_state.got_signal == 0) {
139 for (i=0;i<NUM_SIGNALS+1;i++) {
140 uint32_t count = sig_state.signal_count[i];
142 struct signal_event *se, *next;
143 for (se=sig_state.sig_handlers[i];se;se=next) {
145 se->handler(ev, se, i, count, se->private_data);
147 sig_state.signal_count[i] -= count;
148 sig_state.got_signal -= count;