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