1 /* Copyright (c) 2001-2018 Dovecot authors, see the included COPYING file */
2
3 #include "lib.h"
4 #include "array.h"
5 #include "ioloop.h"
6 #include "write-full.h"
7 #include "llist.h"
8 #include "lib-signals.h"
9
10 #include <stdio.h>
11 #include <signal.h>
12 #include <unistd.h>
13
14 #define MAX_SIGNAL_VALUE 63
15
16 #define SIGNAL_IS_TERMINAL(signo) \
17 ((signo) == SIGINT || (signo) == SIGQUIT || (signo) == SIGTERM)
18
19 #if !defined(SA_SIGINFO) && !defined(SI_NOINFO)
20 /* without SA_SIGINFO we don't know what the real code is. we need SI_NOINFO
21 to make sure lib_signal_code_to_str() returns "". */
22 # define SI_NOINFO -1
23 #endif
24
25 struct signal_ioloop {
26 struct signal_ioloop *prev, *next;
27
28 int refcount;
29 struct ioloop *ioloop;
30 struct io *io;
31 };
32
33 struct signal_handler {
34 signal_handler_t *handler;
35 void *context;
36
37 enum libsig_flags flags;
38 struct signal_handler *next;
39 struct signal_ioloop *sig_ioloop;
40
41 bool expected:1;
42 bool shadowed:1;
43 };
44
45 volatile unsigned int signal_term_counter = 0;
46
47 /* Remember that these are accessed inside signal handler which may be called
48 even while we're initializing/deinitializing. Try hard to keep everything
49 in consistent state. */
50 static struct signal_handler *signal_handlers[MAX_SIGNAL_VALUE+1] = { NULL, };
51 static int sig_pipe_fd[2] = { -1, -1 };
52
53 static bool signals_initialized = FALSE;
54 static unsigned int signals_expected = 0;
55 static struct signal_ioloop *signal_ioloops = NULL;
56
57 static siginfo_t pending_signals[MAX_SIGNAL_VALUE+1];
58 static ARRAY(siginfo_t) pending_shadowed_signals;
59 static bool have_pending_signals = FALSE;
60 static bool have_missing_ioloops = FALSE;
61 static bool ioloop_switched = FALSE;
62
63 static void signal_read(void *context);
64
lib_signal_code_to_str(int signo,int sicode)65 const char *lib_signal_code_to_str(int signo, int sicode)
66 {
67 /* common */
68 switch (sicode) {
69 #ifdef SI_NOINFO
70 case SI_NOINFO:
71 return "";
72 #endif
73 case SI_USER:
74 return "kill";
75 #ifdef SI_KERNEL
76 case SI_KERNEL:
77 return "kernel";
78 #endif
79 case SI_TIMER:
80 return "timer";
81 }
82
83 /* If SEGV_MAPERR is supported, the rest of them must be too.
84 FreeBSD 6 at least doesn't support these. */
85 #ifdef SEGV_MAPERR
86 switch (signo) {
87 case SIGSEGV:
88 switch (sicode) {
89 case SEGV_MAPERR:
90 return "address not mapped";
91 case SEGV_ACCERR:
92 return "invalid permissions";
93 }
94 break;
95 case SIGBUS:
96 switch (sicode) {
97 case BUS_ADRALN:
98 return "invalid address alignment";
99 #ifdef BUS_ADRERR /* for OSX 10.3 */
100 case BUS_ADRERR:
101 return "nonexistent physical address";
102 #endif
103 #ifdef BUS_OBJERR /* for OSX 10.3 */
104 case BUS_OBJERR:
105 return "object-specific hardware error";
106 #endif
107 }
108 }
109 #endif
110 return t_strdup_printf("unknown %d", sicode);
111 }
112
113 #ifdef SA_SIGINFO
sig_handler(int signo,siginfo_t * si,void * context ATTR_UNUSED)114 static void sig_handler(int signo, siginfo_t *si, void *context ATTR_UNUSED)
115 #else
116 static void sig_handler(int signo)
117 #endif
118 {
119 struct signal_handler *h;
120 int saved_errno;
121 char c = 0;
122
123 #if defined(SI_NOINFO) || !defined(SA_SIGINFO)
124 #ifndef SA_SIGINFO
125 siginfo_t *si = NULL;
126 #endif
127 siginfo_t tmp_si;
128
129 if (si == NULL) {
130 /* Solaris can leave this to NULL */
131 i_zero(&tmp_si);
132 tmp_si.si_signo = signo;
133 tmp_si.si_code = SI_NOINFO;
134 si = &tmp_si;
135 }
136 #endif
137
138 if (signo < 0 || signo > MAX_SIGNAL_VALUE)
139 return;
140
141 if (SIGNAL_IS_TERMINAL(signo))
142 signal_term_counter++;
143
144 /* remember that we're inside a signal handler which might have been
145 called at any time. don't do anything that's unsafe. we might also
146 get interrupted by another signal while inside this handler. */
147 saved_errno = errno;
148 for (h = signal_handlers[signo]; h != NULL; h = h->next) {
149 if ((h->flags & LIBSIG_FLAG_DELAYED) == 0)
150 h->handler(si, h->context);
151 else if (pending_signals[signo].si_signo == 0) {
152 pending_signals[signo] = *si;
153 if (!have_pending_signals) {
154 if (write(sig_pipe_fd[1], &c, 1) != 1) {
155 lib_signals_syscall_error(
156 "signal: write(sigpipe) failed: ");
157 }
158 have_pending_signals = TRUE;
159 }
160 }
161 }
162 errno = saved_errno;
163 }
164
165 #ifdef SA_SIGINFO
sig_ignore(int signo ATTR_UNUSED,siginfo_t * si ATTR_UNUSED,void * context ATTR_UNUSED)166 static void sig_ignore(int signo ATTR_UNUSED, siginfo_t *si ATTR_UNUSED,
167 void *context ATTR_UNUSED)
168 #else
169 static void sig_ignore(int signo ATTR_UNUSED)
170 #endif
171 {
172 /* if we used SIG_IGN instead of this function,
173 the system call might be restarted */
174 }
175
176 static struct signal_ioloop *
lib_signals_ioloop_find(struct ioloop * ioloop)177 lib_signals_ioloop_find(struct ioloop *ioloop)
178 {
179 struct signal_ioloop *l;
180
181 for (l = signal_ioloops; l != NULL; l = l->next) {
182 if (l->ioloop == ioloop)
183 break;
184 }
185 return l;
186 }
187
lib_signals_init_io(struct signal_ioloop * l)188 static void lib_signals_init_io(struct signal_ioloop *l)
189 {
190 i_assert(sig_pipe_fd[0] != -1);
191
192 l->io = io_add_to(l->ioloop, sig_pipe_fd[0], IO_READ, signal_read, NULL);
193 io_set_never_wait_alone(l->io, signals_expected == 0);
194 }
195
196 static struct signal_ioloop *
lib_signals_ioloop_ref(struct ioloop * ioloop)197 lib_signals_ioloop_ref(struct ioloop *ioloop)
198 {
199 struct signal_ioloop *l;
200
201 l = lib_signals_ioloop_find(ioloop);
202 if (l == NULL) {
203 l = i_new(struct signal_ioloop, 1);
204 l->ioloop = ioloop;
205 lib_signals_init_io(l);
206 DLLIST_PREPEND(&signal_ioloops, l);
207 }
208 l->refcount++;
209 return l;
210 }
211
lib_signals_ioloop_unref(struct signal_ioloop ** _sig_ioloop)212 static void lib_signals_ioloop_unref(struct signal_ioloop **_sig_ioloop)
213 {
214 struct signal_ioloop *sig_ioloop = *_sig_ioloop;
215
216 *_sig_ioloop = NULL;
217
218 if (sig_ioloop == NULL)
219 return;
220 i_assert(sig_ioloop->refcount > 0);
221 if (--sig_ioloop->refcount > 0)
222 return;
223 io_remove(&sig_ioloop->io);
224 DLLIST_REMOVE(&signal_ioloops, sig_ioloop);
225 i_free(sig_ioloop);
226 }
227
signal_handler_switch_ioloop(struct signal_handler * h)228 static void signal_handler_switch_ioloop(struct signal_handler *h)
229 {
230 lib_signals_ioloop_unref(&h->sig_ioloop);
231 if (current_ioloop != NULL)
232 h->sig_ioloop = lib_signals_ioloop_ref(current_ioloop);
233 else
234 have_missing_ioloops = TRUE;
235 }
236
signal_handler_free(struct signal_handler * h)237 static void signal_handler_free(struct signal_handler *h)
238 {
239 lib_signals_ioloop_unref(&h->sig_ioloop);
240 i_free(h);
241 }
242
signal_handle_shadowed(void)243 static void signal_handle_shadowed(void)
244 {
245 const siginfo_t *sis;
246 unsigned int count, i;
247
248 if (!array_is_created(&pending_shadowed_signals) ||
249 array_count(&pending_shadowed_signals) == 0)
250 return;
251
252 sis = array_get(&pending_shadowed_signals, &count);
253 for (i = 0; i < count; i++) {
254 struct signal_handler *h;
255 bool shadowed = FALSE;
256
257 i_assert(sis[i].si_signo > 0);
258 for (h = signal_handlers[sis[i].si_signo]; h != NULL;
259 h = h->next) {
260 i_assert(h->sig_ioloop != NULL);
261 if ((h->flags & LIBSIG_FLAG_DELAYED) == 0 ||
262 (h->flags & LIBSIG_FLAG_IOLOOP_AUTOMOVE) != 0)
263 continue;
264 if (h->shadowed &&
265 h->sig_ioloop->ioloop != current_ioloop) {
266 shadowed = TRUE;
267 continue;
268 }
269 /* handler can be called now */
270 h->shadowed = FALSE;
271 h->handler(&sis[i], h->context);
272 }
273 if (!shadowed) {
274 /* no handlers are shadowed anymore; delete the signal
275 info */
276 array_delete(&pending_shadowed_signals, i, 1);
277 sis = array_get(&pending_shadowed_signals, &count);
278 }
279 }
280 }
281
signal_check_shadowed(void)282 static void signal_check_shadowed(void)
283 {
284 struct signal_ioloop *sig_ioloop;
285
286 if (!array_is_created(&pending_shadowed_signals) ||
287 array_count(&pending_shadowed_signals) == 0)
288 return;
289
290 sig_ioloop = lib_signals_ioloop_find(current_ioloop);
291 if (sig_ioloop != NULL)
292 io_set_pending(sig_ioloop->io);
293 }
294
signal_shadow(int signo,const siginfo_t * si)295 static void signal_shadow(int signo, const siginfo_t *si)
296 {
297 const siginfo_t *sis;
298 unsigned int count, i;
299
300 /* remember last signal info for handlers that cannot run in
301 current ioloop */
302 if (!array_is_created(&pending_shadowed_signals))
303 i_array_init(&pending_shadowed_signals, 4);
304 sis = array_get(&pending_shadowed_signals, &count);
305 for (i = 0; i < count; i++) {
306 i_assert(sis[i].si_signo != 0);
307 if (sis[i].si_signo == signo)
308 break;
309 }
310 array_idx_set(&pending_shadowed_signals, i, si);
311 }
312
signal_read(void * context ATTR_UNUSED)313 static void ATTR_NULL(1) signal_read(void *context ATTR_UNUSED)
314 {
315 siginfo_t signals[MAX_SIGNAL_VALUE+1];
316 sigset_t fullset, oldset;
317 struct signal_handler *h;
318 char buf[64];
319 int signo;
320 ssize_t ret;
321
322 if (ioloop_switched) {
323 ioloop_switched = FALSE;
324 /* handle any delayed signal handlers that emerged from the
325 shadow */
326 signal_handle_shadowed();
327 }
328
329 if (sigfillset(&fullset) < 0)
330 i_fatal("sigfillset() failed: %m");
331 if (sigprocmask(SIG_BLOCK, &fullset, &oldset) < 0)
332 i_fatal("sigprocmask() failed: %m");
333
334 /* typically we should read only a single byte, but if a signal is sent
335 while signal handler is running we might get more. */
336 ret = read(sig_pipe_fd[0], buf, sizeof(buf));
337 if (ret > 0) {
338 memcpy(signals, pending_signals, sizeof(signals));
339 memset(pending_signals, 0, sizeof(pending_signals));
340 have_pending_signals = FALSE;
341 } else if (ret < 0) {
342 if (errno != EAGAIN)
343 i_fatal("read(sigpipe) failed: %m");
344 } else {
345 i_fatal("read(sigpipe) failed: EOF");
346 }
347 if (sigprocmask(SIG_SETMASK, &oldset, NULL) < 0)
348 i_fatal("sigprocmask() failed: %m");
349
350 if (ret < 0)
351 return;
352
353 /* call the delayed handlers after signals are copied and unblocked */
354 for (signo = 0; signo < MAX_SIGNAL_VALUE; signo++) {
355 bool shadowed = FALSE;
356
357 if (signals[signo].si_signo == 0)
358 continue;
359
360 for (h = signal_handlers[signo]; h != NULL; h = h->next) {
361 i_assert(h->sig_ioloop != NULL);
362 if ((h->flags & LIBSIG_FLAG_DELAYED) == 0) {
363 /* handler already called immediately in signal
364 context */
365 continue;
366 }
367 if ((h->flags & LIBSIG_FLAG_IOLOOP_AUTOMOVE) == 0 &&
368 h->sig_ioloop->ioloop != current_ioloop) {
369 /* cannot run handler in current ioloop
370 (shadowed) */
371 h->shadowed = TRUE;
372 shadowed = TRUE;
373 continue;
374 }
375 /* handler can be called now */
376 h->handler(&signals[signo], h->context);
377 }
378
379 if (shadowed) {
380 /* remember last signal info for handlers that cannot
381 run in current ioloop (shadowed) */
382 signal_shadow(signo, &signals[signo]);
383 }
384 }
385 }
386
lib_signals_update_expected_signals(bool expected)387 static void lib_signals_update_expected_signals(bool expected)
388 {
389 struct signal_ioloop *sig_ioloop;
390
391 if (expected)
392 signals_expected++;
393 else {
394 i_assert(signals_expected > 0);
395 signals_expected--;
396 }
397
398 sig_ioloop = signal_ioloops;
399 for (; sig_ioloop != NULL; sig_ioloop = sig_ioloop->next) {
400 if (sig_ioloop->io != NULL) {
401 io_set_never_wait_alone(sig_ioloop->io,
402 signals_expected == 0);
403 }
404 }
405 }
406
lib_signals_ioloop_switch(void)407 static void lib_signals_ioloop_switch(void)
408 {
409 struct signal_handler *h;
410
411 if (current_ioloop == NULL || sig_pipe_fd[0] <= 0)
412 return;
413
414 /* initialize current_ioloop for signal handlers created before the
415 first ioloop. */
416 for (int signo = 0; signo < MAX_SIGNAL_VALUE; signo++) {
417 for (h = signal_handlers[signo]; h != NULL; h = h->next) {
418 if ((h->flags & LIBSIG_FLAG_IOLOOP_AUTOMOVE) != 0)
419 lib_signals_ioloop_unref(&h->sig_ioloop);
420 if (h->sig_ioloop == NULL)
421 h->sig_ioloop = lib_signals_ioloop_ref(current_ioloop);
422 }
423 }
424 have_missing_ioloops = FALSE;
425 }
426
lib_signals_ioloop_switched(struct ioloop * prev_ioloop ATTR_UNUSED)427 static void lib_signals_ioloop_switched(struct ioloop *prev_ioloop ATTR_UNUSED)
428 {
429 ioloop_switched = TRUE;
430
431 lib_signals_ioloop_switch();
432
433 /* check whether we can now handle any shadowed delayed signals */
434 signal_check_shadowed();
435 }
436
lib_signals_ioloop_destroyed(struct ioloop * ioloop)437 static void lib_signals_ioloop_destroyed(struct ioloop *ioloop)
438 {
439 struct signal_ioloop *sig_ioloop;
440
441 sig_ioloop = lib_signals_ioloop_find(ioloop);
442 if (sig_ioloop != NULL) {
443 io_remove(&sig_ioloop->io);
444 sig_ioloop->ioloop = NULL;
445 }
446 }
447
lib_signals_ioloop_detach(void)448 void lib_signals_ioloop_detach(void)
449 {
450 struct signal_handler *h;
451
452 for (int signo = 0; signo < MAX_SIGNAL_VALUE; signo++) {
453 for (h = signal_handlers[signo]; h != NULL; h = h->next) {
454 if (h->sig_ioloop != NULL) {
455 lib_signals_ioloop_unref(&h->sig_ioloop);
456 have_missing_ioloops = TRUE;
457 }
458 }
459 }
460 }
461
lib_signals_ioloop_attach(void)462 void lib_signals_ioloop_attach(void)
463 {
464 if (have_missing_ioloops)
465 lib_signals_ioloop_switch();
466 }
467
lib_signals_set(int signo,enum libsig_flags flags)468 static void lib_signals_set(int signo, enum libsig_flags flags)
469 {
470 struct sigaction act;
471
472 if (sigemptyset(&act.sa_mask) < 0)
473 i_fatal("sigemptyset(): %m");
474 #ifdef SA_SIGINFO
475 act.sa_flags = SA_SIGINFO;
476 act.sa_sigaction = sig_handler;
477 #else
478 act.sa_flags = 0;
479 act.sa_handler = sig_handler;
480 #endif
481 if ((flags & LIBSIG_FLAG_RESTART) != 0)
482 act.sa_flags |= SA_RESTART;
483 if (sigaction(signo, &act, NULL) < 0)
484 i_fatal("sigaction(%d): %m", signo);
485 }
486
lib_signals_set_handler(int signo,enum libsig_flags flags,signal_handler_t * handler,void * context)487 void lib_signals_set_handler(int signo, enum libsig_flags flags,
488 signal_handler_t *handler, void *context)
489 {
490 struct signal_handler *h;
491
492 i_assert(handler != NULL);
493
494 if (signo < 0 || signo > MAX_SIGNAL_VALUE) {
495 i_panic("Trying to set signal %d handler, but max is %d",
496 signo, MAX_SIGNAL_VALUE);
497 }
498
499 if (signal_handlers[signo] == NULL && signals_initialized)
500 lib_signals_set(signo, flags);
501
502 h = i_new(struct signal_handler, 1);
503 h->handler = handler;
504 h->context = context;
505 h->flags = flags;
506
507 /* atomically set to signal_handlers[] list */
508 h->next = signal_handlers[signo];
509 signal_handlers[signo] = h;
510
511 if ((flags & LIBSIG_FLAG_DELAYED) != 0 && sig_pipe_fd[0] == -1) {
512 /* first delayed handler */
513 if (pipe(sig_pipe_fd) < 0)
514 i_fatal("pipe() failed: %m");
515 fd_set_nonblock(sig_pipe_fd[0], TRUE);
516 fd_set_nonblock(sig_pipe_fd[1], TRUE);
517 fd_close_on_exec(sig_pipe_fd[0], TRUE);
518 fd_close_on_exec(sig_pipe_fd[1], TRUE);
519 }
520 signal_handler_switch_ioloop(h);
521 }
522
lib_signals_ignore_forced(int signo,bool restart_syscalls)523 static void lib_signals_ignore_forced(int signo, bool restart_syscalls)
524 {
525 struct sigaction act;
526
527 if (sigemptyset(&act.sa_mask) < 0)
528 i_fatal("sigemptyset(): %m");
529 if (restart_syscalls) {
530 act.sa_flags = SA_RESTART;
531 act.sa_handler = SIG_IGN;
532 } else {
533 #ifdef SA_SIGINFO
534 act.sa_flags = SA_SIGINFO;
535 act.sa_sigaction = sig_ignore;
536 #else
537 act.sa_flags = 0;
538 act.sa_handler = sig_ignore;
539 #endif
540 }
541
542 if (sigaction(signo, &act, NULL) < 0)
543 i_fatal("sigaction(%d): %m", signo);
544 }
545
lib_signals_ignore(int signo,bool restart_syscalls)546 void lib_signals_ignore(int signo, bool restart_syscalls)
547 {
548 if (signo < 0 || signo > MAX_SIGNAL_VALUE) {
549 i_panic("Trying to ignore signal %d, but max is %d",
550 signo, MAX_SIGNAL_VALUE);
551 }
552
553 i_assert(signal_handlers[signo] == NULL);
554
555 lib_signals_ignore_forced(signo, restart_syscalls);
556 }
557
lib_signals_clear_handlers_and_ignore(int signo)558 void lib_signals_clear_handlers_and_ignore(int signo)
559 {
560 struct signal_handler *h;
561
562 if (signal_handlers[signo] == NULL)
563 return;
564
565 lib_signals_ignore_forced(signo, TRUE);
566
567 h = signal_handlers[signo];
568 signal_handlers[signo] = NULL;
569
570 while (h != NULL) {
571 struct signal_handler *h_next = h->next;
572
573 if (h->expected)
574 signals_expected--;
575 signal_handler_free(h);
576 h = h_next;
577 }
578 }
579
lib_signals_unset_handler(int signo,signal_handler_t * handler,void * context)580 void lib_signals_unset_handler(int signo, signal_handler_t *handler,
581 void *context)
582 {
583 struct signal_handler *h, **p;
584
585 for (p = &signal_handlers[signo]; *p != NULL; p = &(*p)->next) {
586 if ((*p)->handler == handler && (*p)->context == context) {
587 if (p == &signal_handlers[signo] &&
588 (*p)->next == NULL) {
589 /* last handler is to be removed */
590 lib_signals_ignore_forced(signo, TRUE);
591 }
592 h = *p;
593 *p = h->next;
594 if (h->expected)
595 lib_signals_update_expected_signals(FALSE);
596 signal_handler_free(h);
597 return;
598 }
599 }
600
601 i_panic("lib_signals_unset_handler(%d, %p, %p): handler not found",
602 signo, (void *)handler, context);
603 }
604
lib_signals_set_expected(int signo,bool expected,signal_handler_t * handler,void * context)605 void lib_signals_set_expected(int signo, bool expected,
606 signal_handler_t *handler, void *context)
607 {
608 struct signal_handler *h;
609
610 for (h = signal_handlers[signo]; h != NULL; h = h->next) {
611 if (h->handler == handler && h->context == context) {
612 if (h->expected == expected)
613 return;
614 h->expected = expected;
615 lib_signals_update_expected_signals(expected);
616 return;
617 }
618 }
619
620 i_panic("lib_signals_set_expected(%d, %p, %p): handler not found",
621 signo, (void *)handler, context);
622 }
623
lib_signals_switch_ioloop(int signo,signal_handler_t * handler,void * context)624 void lib_signals_switch_ioloop(int signo,
625 signal_handler_t *handler, void *context)
626 {
627 struct signal_handler *h;
628
629 for (h = signal_handlers[signo]; h != NULL; h = h->next) {
630 if (h->handler == handler && h->context == context) {
631 i_assert((h->flags & LIBSIG_FLAG_DELAYED) != 0);
632 i_assert((h->flags & LIBSIG_FLAG_IOLOOP_AUTOMOVE) == 0);
633 signal_handler_switch_ioloop(h);
634 /* check whether we can now handle any shadowed delayed
635 signals */
636 signal_check_shadowed();
637 return;
638 }
639 }
640
641 i_panic("lib_signals_switch_ioloop(%d, %p, %p): handler not found",
642 signo, (void *)handler, context);
643 }
644
lib_signals_syscall_error(const char * prefix)645 void lib_signals_syscall_error(const char *prefix)
646 {
647 /* @UNSAFE: We're in a signal handler. It's very limited what is
648 allowed in here. Especially strerror() isn't at least officially
649 allowed. */
650 char errno_buf[MAX_INT_STRLEN], *errno_str;
651 errno_str = dec2str_buf(errno_buf, errno);
652
653 size_t prefix_len = strlen(prefix);
654 size_t errno_str_len = strlen(errno_str);
655 char buf[prefix_len + errno_str_len + 1];
656
657 memcpy(buf, prefix, prefix_len);
658 memcpy(buf + prefix_len, errno_str, errno_str_len);
659 buf[prefix_len + errno_str_len] = '\n';
660 if (write_full(STDERR_FILENO, buf,
661 prefix_len + errno_str_len + 1) < 0) {
662 /* can't really do anything */
663 }
664 }
665
lib_signals_init(void)666 void lib_signals_init(void)
667 {
668 int i;
669
670 signals_initialized = TRUE;
671 io_loop_add_switch_callback(lib_signals_ioloop_switched);
672 io_loop_add_destroy_callback(lib_signals_ioloop_destroyed);
673
674 /* add signals that were already registered */
675 for (i = 0; i < MAX_SIGNAL_VALUE; i++) {
676 if (signal_handlers[i] != NULL)
677 lib_signals_set(i, signal_handlers[i]->flags);
678 }
679 }
680
lib_signals_deinit(void)681 void lib_signals_deinit(void)
682 {
683 int i;
684
685 for (i = 0; i < MAX_SIGNAL_VALUE; i++) {
686 if (signal_handlers[i] != NULL)
687 lib_signals_clear_handlers_and_ignore(i);
688 }
689 i_assert(signals_expected == 0);
690
691 if (sig_pipe_fd[0] != -1) {
692 if (close(sig_pipe_fd[0]) < 0)
693 i_error("close(sigpipe) failed: %m");
694 if (close(sig_pipe_fd[1]) < 0)
695 i_error("close(sigpipe) failed: %m");
696 sig_pipe_fd[0] = sig_pipe_fd[1] = -1;
697 }
698
699 if (array_is_created(&pending_shadowed_signals))
700 array_free(&pending_shadowed_signals);
701 i_assert(signal_ioloops == NULL);
702 }
703