Coverage Report

Created: 2026-01-17 06:57

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