Fix some blank line endings
[sfrench/samba-autobuild/.git] / lib / tevent / tevent_signal.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    common events code for signal events
5
6    Copyright (C) Andrew Tridgell        2007
7
8      ** NOTE! The following LGPL license applies to the tevent
9      ** library. This does NOT imply that all of Samba is released
10      ** under the LGPL
11
12    This library is free software; you can redistribute it and/or
13    modify it under the terms of the GNU Lesser General Public
14    License as published by the Free Software Foundation; either
15    version 3 of the License, or (at your option) any later version.
16
17    This library is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20    Lesser General Public License for more details.
21
22    You should have received a copy of the GNU Lesser General Public
23    License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include "replace.h"
27 #include "system/filesys.h"
28 #include "system/wait.h"
29 #include "tevent.h"
30 #include "tevent_internal.h"
31 #include "tevent_util.h"
32
33 /* maximum number of SA_SIGINFO signals to hold in the queue.
34   NB. This *MUST* be a power of 2, in order for the ring buffer
35   wrap to work correctly. Thanks to Petr Vandrovec <petr@vandrovec.name>
36   for this. */
37
38 #define TEVENT_SA_INFO_QUEUE_COUNT 64
39
40 struct tevent_sigcounter {
41         uint32_t count;
42         uint32_t seen;
43 };
44
45 #define TEVENT_SIG_INCREMENT(s) (s).count++
46 #define TEVENT_SIG_SEEN(s, n) (s).seen += (n)
47 #define TEVENT_SIG_PENDING(s) ((s).seen != (s).count)
48
49 struct tevent_common_signal_list {
50         struct tevent_common_signal_list *prev, *next;
51         struct tevent_signal *se;
52 };
53
54 /*
55   the poor design of signals means that this table must be static global
56 */
57 static struct tevent_sig_state {
58         struct tevent_common_signal_list *sig_handlers[TEVENT_NUM_SIGNALS+1];
59         struct sigaction *oldact[TEVENT_NUM_SIGNALS+1];
60         struct tevent_sigcounter signal_count[TEVENT_NUM_SIGNALS+1];
61         struct tevent_sigcounter got_signal;
62 #ifdef SA_SIGINFO
63         /* with SA_SIGINFO we get quite a lot of info per signal */
64         siginfo_t *sig_info[TEVENT_NUM_SIGNALS+1];
65         struct tevent_sigcounter sig_blocked[TEVENT_NUM_SIGNALS+1];
66 #endif
67 } *sig_state;
68
69 /*
70   return number of sigcounter events not processed yet
71 */
72 static uint32_t tevent_sig_count(struct tevent_sigcounter s)
73 {
74         return s.count - s.seen;
75 }
76
77 /*
78   signal handler - redirects to registered signals
79 */
80 static void tevent_common_signal_handler(int signum)
81 {
82         char c = 0;
83         struct tevent_common_signal_list *sl;
84         struct tevent_context *ev = NULL;
85         int saved_errno = errno;
86
87         TEVENT_SIG_INCREMENT(sig_state->signal_count[signum]);
88         TEVENT_SIG_INCREMENT(sig_state->got_signal);
89
90         /* Write to each unique event context. */
91         for (sl = sig_state->sig_handlers[signum]; sl; sl = sl->next) {
92                 if (sl->se->event_ctx && sl->se->event_ctx != ev) {
93                         ev = sl->se->event_ctx;
94                         /* doesn't matter if this pipe overflows */
95                         (void) write(ev->pipe_fds[1], &c, 1);
96                 }
97         }
98
99         errno = saved_errno;
100 }
101
102 #ifdef SA_SIGINFO
103 /*
104   signal handler with SA_SIGINFO - redirects to registered signals
105 */
106 static void tevent_common_signal_handler_info(int signum, siginfo_t *info,
107                                               void *uctx)
108 {
109         uint32_t count = tevent_sig_count(sig_state->signal_count[signum]);
110         /* sig_state->signal_count[signum].seen % TEVENT_SA_INFO_QUEUE_COUNT
111          * is the base of the unprocessed signals in the ringbuffer. */
112         uint32_t ofs = (sig_state->signal_count[signum].seen + count) %
113                                 TEVENT_SA_INFO_QUEUE_COUNT;
114         sig_state->sig_info[signum][ofs] = *info;
115
116         tevent_common_signal_handler(signum);
117
118         /* handle SA_SIGINFO */
119         if (count+1 == TEVENT_SA_INFO_QUEUE_COUNT) {
120                 /* we've filled the info array - block this signal until
121                    these ones are delivered */
122 #ifdef HAVE_UCONTEXT_T
123                 /*
124                  * This is the only way for this to work.
125                  * By default signum is blocked inside this
126                  * signal handler using a temporary mask,
127                  * but what we really need to do now is
128                  * block it in the callers mask, so it
129                  * stays blocked when the temporary signal
130                  * handler mask is replaced when we return
131                  * from here. The callers mask can be found
132                  * in the ucontext_t passed in as the
133                  * void *uctx argument.
134                  */
135                 ucontext_t *ucp = (ucontext_t *)uctx;
136                 sigaddset(&ucp->uc_sigmask, signum);
137 #else
138                 /*
139                  * WARNING !!! WARNING !!!!
140                  *
141                  * This code doesn't work.
142                  * By default signum is blocked inside this
143                  * signal handler, but calling sigprocmask
144                  * modifies the temporary signal mask being
145                  * used *inside* this handler, which will be
146                  * replaced by the callers signal mask once
147                  * we return from here. See Samba
148                  * bug #9550 for details.
149                  */
150                 sigset_t set;
151                 sigemptyset(&set);
152                 sigaddset(&set, signum);
153                 sigprocmask(SIG_BLOCK, &set, NULL);
154 #endif
155                 TEVENT_SIG_INCREMENT(sig_state->sig_blocked[signum]);
156         }
157 }
158 #endif
159
160 static int tevent_common_signal_list_destructor(struct tevent_common_signal_list *sl)
161 {
162         if (sig_state->sig_handlers[sl->se->signum]) {
163                 DLIST_REMOVE(sig_state->sig_handlers[sl->se->signum], sl);
164         }
165         return 0;
166 }
167
168 /*
169   destroy a signal event
170 */
171 static int tevent_signal_destructor(struct tevent_signal *se)
172 {
173         struct tevent_common_signal_list *sl;
174         sl = talloc_get_type(se->additional_data,
175                              struct tevent_common_signal_list);
176
177         if (se->event_ctx) {
178                 DLIST_REMOVE(se->event_ctx->signal_events, se);
179         }
180
181         talloc_free(sl);
182
183         if (sig_state->sig_handlers[se->signum] == NULL) {
184                 /* restore old handler, if any */
185                 if (sig_state->oldact[se->signum]) {
186                         sigaction(se->signum, sig_state->oldact[se->signum], NULL);
187                         sig_state->oldact[se->signum] = NULL;
188                 }
189 #ifdef SA_SIGINFO
190                 if (se->sa_flags & SA_SIGINFO) {
191                         if (sig_state->sig_info[se->signum]) {
192                                 talloc_free(sig_state->sig_info[se->signum]);
193                                 sig_state->sig_info[se->signum] = NULL;
194                         }
195                 }
196 #endif
197         }
198
199         return 0;
200 }
201
202 /*
203   this is part of the pipe hack needed to avoid the signal race condition
204 */
205 static void signal_pipe_handler(struct tevent_context *ev, struct tevent_fd *fde, 
206                                 uint16_t flags, void *_private)
207 {
208         char c[16];
209         /* its non-blocking, doesn't matter if we read too much */
210         (void) read(fde->fd, c, sizeof(c));
211 }
212
213 /*
214   add a signal event
215   return NULL on failure (memory allocation error)
216 */
217 struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev,
218                                                TALLOC_CTX *mem_ctx,
219                                                int signum,
220                                                int sa_flags,
221                                                tevent_signal_handler_t handler,
222                                                void *private_data,
223                                                const char *handler_name,
224                                                const char *location)
225 {
226         struct tevent_signal *se;
227         struct tevent_common_signal_list *sl;
228         sigset_t set, oldset;
229
230         if (signum >= TEVENT_NUM_SIGNALS) {
231                 errno = EINVAL;
232                 return NULL;
233         }
234
235         /* the sig_state needs to be on a global context as it can last across
236            multiple event contexts */
237         if (sig_state == NULL) {
238                 sig_state = talloc_zero(NULL, struct tevent_sig_state);
239                 if (sig_state == NULL) {
240                         return NULL;
241                 }
242         }
243
244         se = talloc(mem_ctx?mem_ctx:ev, struct tevent_signal);
245         if (se == NULL) return NULL;
246
247         se->event_ctx           = ev;
248         se->signum              = signum;
249         se->sa_flags            = sa_flags;
250         se->handler             = handler;
251         se->private_data        = private_data;
252         se->handler_name        = handler_name;
253         se->location            = location;
254         se->additional_data     = NULL;
255
256         sl = talloc(se, struct tevent_common_signal_list);
257         if (!sl) {
258                 talloc_free(se);
259                 return NULL;
260         }
261         sl->se = se;
262         se->additional_data     = sl;
263
264         /* Ensure, no matter the destruction order, that we always have a handle on the global sig_state */
265         if (!talloc_reference(se, sig_state)) {
266                 talloc_free(se);
267                 return NULL;
268         }
269
270         /* we need to setup the pipe hack handler if not already
271            setup */
272         if (ev->pipe_fde == NULL) {
273                 if (pipe(ev->pipe_fds) == -1) {
274                         talloc_free(se);
275                         return NULL;
276                 }
277                 ev_set_blocking(ev->pipe_fds[0], false);
278                 ev_set_blocking(ev->pipe_fds[1], false);
279                 ev->pipe_fde = tevent_add_fd(ev, ev, ev->pipe_fds[0],
280                                              TEVENT_FD_READ,
281                                              signal_pipe_handler, NULL);
282                 if (!ev->pipe_fde) {
283                         close(ev->pipe_fds[0]);
284                         close(ev->pipe_fds[1]);
285                         talloc_free(se);
286                         return NULL;
287                 }
288         }
289
290         /* only install a signal handler if not already installed */
291         if (sig_state->sig_handlers[signum] == NULL) {
292                 struct sigaction act;
293                 ZERO_STRUCT(act);
294                 act.sa_handler = tevent_common_signal_handler;
295                 act.sa_flags = sa_flags;
296 #ifdef SA_SIGINFO
297                 if (sa_flags & SA_SIGINFO) {
298                         act.sa_handler   = NULL;
299                         act.sa_sigaction = tevent_common_signal_handler_info;
300                         if (sig_state->sig_info[signum] == NULL) {
301                                 sig_state->sig_info[signum] =
302                                         talloc_zero_array(sig_state, siginfo_t,
303                                                           TEVENT_SA_INFO_QUEUE_COUNT);
304                                 if (sig_state->sig_info[signum] == NULL) {
305                                         talloc_free(se);
306                                         return NULL;
307                                 }
308                         }
309                 }
310 #endif
311                 sig_state->oldact[signum] = talloc(sig_state, struct sigaction);
312                 if (sig_state->oldact[signum] == NULL) {
313                         talloc_free(se);
314                         return NULL;
315                 }
316                 if (sigaction(signum, &act, sig_state->oldact[signum]) == -1) {
317                         talloc_free(se);
318                         return NULL;
319                 }
320         }
321
322         DLIST_ADD(se->event_ctx->signal_events, se);
323
324         /* Make sure the signal doesn't come in while we're mangling list. */
325         sigemptyset(&set);
326         sigaddset(&set, signum);
327         sigprocmask(SIG_BLOCK, &set, &oldset);
328         DLIST_ADD(sig_state->sig_handlers[signum], sl);
329         sigprocmask(SIG_SETMASK, &oldset, NULL);
330
331         talloc_set_destructor(se, tevent_signal_destructor);
332         talloc_set_destructor(sl, tevent_common_signal_list_destructor);
333
334         return se;
335 }
336
337 struct tevent_se_exists {
338         struct tevent_se_exists **myself;
339 };
340
341 static int tevent_se_exists_destructor(struct tevent_se_exists *s)
342 {
343         *s->myself = NULL;
344         return 0;
345 }
346
347 /*
348   check if a signal is pending
349   return != 0 if a signal was pending
350 */
351 int tevent_common_check_signal(struct tevent_context *ev)
352 {
353         int i;
354
355         if (!sig_state || !TEVENT_SIG_PENDING(sig_state->got_signal)) {
356                 return 0;
357         }
358
359         for (i=0;i<TEVENT_NUM_SIGNALS+1;i++) {
360                 struct tevent_common_signal_list *sl, *next;
361                 struct tevent_sigcounter counter = sig_state->signal_count[i];
362                 uint32_t count = tevent_sig_count(counter);
363 #ifdef SA_SIGINFO
364                 /* Ensure we null out any stored siginfo_t entries
365                  * after processing for debugging purposes. */
366                 bool clear_processed_siginfo = false;
367 #endif
368
369                 if (count == 0) {
370                         continue;
371                 }
372                 for (sl=sig_state->sig_handlers[i];sl;sl=next) {
373                         struct tevent_signal *se = sl->se;
374                         struct tevent_se_exists *exists;
375
376                         next = sl->next;
377
378                         /*
379                          * We have to be careful to not touch "se"
380                          * after it was deleted in its handler. Thus
381                          * we allocate a child whose destructor will
382                          * tell by nulling out itself that its parent
383                          * is gone.
384                          */
385                         exists = talloc(se, struct tevent_se_exists);
386                         if (exists == NULL) {
387                                 continue;
388                         }
389                         exists->myself = &exists;
390                         talloc_set_destructor(
391                                 exists, tevent_se_exists_destructor);
392
393 #ifdef SA_SIGINFO
394                         if (se->sa_flags & SA_SIGINFO) {
395                                 uint32_t j;
396
397                                 clear_processed_siginfo = true;
398
399                                 for (j=0;j<count;j++) {
400                                         /* sig_state->signal_count[i].seen
401                                          * % TEVENT_SA_INFO_QUEUE_COUNT is
402                                          * the base position of the unprocessed
403                                          * signals in the ringbuffer. */
404                                         uint32_t ofs = (counter.seen + j)
405                                                 % TEVENT_SA_INFO_QUEUE_COUNT;
406                                         se->handler(ev, se, i, 1,
407                                                     (void*)&sig_state->sig_info[i][ofs],
408                                                     se->private_data);
409                                         if (!exists) {
410                                                 break;
411                                         }
412                                 }
413 #ifdef SA_RESETHAND
414                                 if (exists && (se->sa_flags & SA_RESETHAND)) {
415                                         talloc_free(se);
416                                 }
417 #endif
418                                 talloc_free(exists);
419                                 continue;
420                         }
421 #endif
422                         se->handler(ev, se, i, count, NULL, se->private_data);
423 #ifdef SA_RESETHAND
424                         if (exists && (se->sa_flags & SA_RESETHAND)) {
425                                 talloc_free(se);
426                         }
427 #endif
428                         talloc_free(exists);
429                 }
430
431 #ifdef SA_SIGINFO
432                 if (clear_processed_siginfo) {
433                         uint32_t j;
434                         for (j=0;j<count;j++) {
435                                 uint32_t ofs = (counter.seen + j)
436                                         % TEVENT_SA_INFO_QUEUE_COUNT;
437                                 memset((void*)&sig_state->sig_info[i][ofs],
438                                         '\0',
439                                         sizeof(siginfo_t));
440                         }
441                 }
442 #endif
443
444                 TEVENT_SIG_SEEN(sig_state->signal_count[i], count);
445                 TEVENT_SIG_SEEN(sig_state->got_signal, count);
446
447 #ifdef SA_SIGINFO
448                 if (TEVENT_SIG_PENDING(sig_state->sig_blocked[i])) {
449                         /* We'd filled the queue, unblock the
450                            signal now the queue is empty again.
451                            Note we MUST do this after the
452                            TEVENT_SIG_SEEN(sig_state->signal_count[i], count)
453                            call to prevent a new signal running
454                            out of room in the sig_state->sig_info[i][]
455                            ring buffer. */
456                         sigset_t set;
457                         sigemptyset(&set);
458                         sigaddset(&set, i);
459                         TEVENT_SIG_SEEN(sig_state->sig_blocked[i],
460                                  tevent_sig_count(sig_state->sig_blocked[i]));
461                         sigprocmask(SIG_UNBLOCK, &set, NULL);
462                 }
463 #endif
464         }
465
466         return 1;
467 }
468
469 void tevent_cleanup_pending_signal_handlers(struct tevent_signal *se)
470 {
471         struct tevent_common_signal_list *sl;
472         sl = talloc_get_type(se->additional_data,
473                              struct tevent_common_signal_list);
474
475         tevent_common_signal_list_destructor(sl);
476
477         if (sig_state->sig_handlers[se->signum] == NULL) {
478                 if (sig_state->oldact[se->signum]) {
479                         sigaction(se->signum, sig_state->oldact[se->signum], NULL);
480                         sig_state->oldact[se->signum] = NULL;
481                 }
482         }
483         return;
484 }