Mercurial > hg > dhcpcd
changeset 5366:1d7408a4160b draft
eloop: Try and survive a signal storm
Shouldn't happen in production, but you never know.
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Tue, 16 Jun 2020 14:35:49 +0100 |
| parents | 57b9f2292dfb |
| children | fce20bebb28a |
| files | src/eloop.c |
| diffstat | 1 files changed, 14 insertions(+), 41 deletions(-) [+] |
line wrap: on
line diff
--- a/src/eloop.c Tue Jun 16 11:58:16 2020 +0000 +++ b/src/eloop.c Tue Jun 16 14:35:49 2020 +0100 @@ -92,6 +92,8 @@ #include <stdio.h> #endif +#define ELOOP_NSIGNALS 5 /* Allow a backlog of signals */ + /* * time_t is a signed integer of an unspecified size. * To adjust for time_t wrapping, we need to work the maximum signed @@ -133,8 +135,6 @@ TAILQ_HEAD (timeout_head, eloop_timeout) timeouts; struct timeout_head free_timeouts; - void (*timeout0)(void *); - void *timeout0_arg; const int *signals; size_t signals_len; void (*signal_cb)(int, void *); @@ -517,17 +517,6 @@ (unsigned int)seconds, (unsigned int)nseconds, callback, arg); } -static int -eloop_timeout_add_now(struct eloop *eloop, - void (*callback)(void *), void *arg) -{ - - assert(eloop->timeout0 == NULL); - eloop->timeout0 = callback; - eloop->timeout0_arg = arg; - return 0; -} - int eloop_q_timeout_delete(struct eloop *eloop, int queue, void (*callback)(void *), void *arg) @@ -582,32 +571,20 @@ eloop->signal_cb_ctx = signal_cb_ctx; } -struct eloop_siginfo { - int sig; - struct eloop *eloop; -}; -static struct eloop_siginfo _eloop_siginfo; -static struct eloop *_eloop; - -static void -eloop_signal1(void *arg) -{ - struct eloop_siginfo *si = arg; - - si->eloop->signal_cb(si->sig, si->eloop->signal_cb_ctx); -} +static volatile int _eloop_sig[ELOOP_NSIGNALS]; +static volatile size_t _eloop_nsig; static void eloop_signal3(int sig, __unused siginfo_t *siginfo, __unused void *arg) { - /* So that we can operate safely under a signal we instruct - * eloop to pass a copy of the siginfo structure to handle_signal1 - * as the very first thing to do. */ - _eloop_siginfo.eloop = _eloop; - _eloop_siginfo.sig = sig; - eloop_timeout_add_now(_eloop_siginfo.eloop, - eloop_signal1, &_eloop_siginfo); + if (_eloop_nsig == __arraycount(_eloop_sig)) { + fprintf(stderr, "%s: signal storm, discarding signal %d", + __func__, sig); + return; + } + + _eloop_sig[_eloop_nsig++] = sig; } int @@ -628,7 +605,6 @@ if (sigprocmask(SIG_SETMASK, &newset, oldset) == -1) return -1; - _eloop = eloop; sigemptyset(&sa.sa_mask); for (i = 0; i < eloop->signals_len; i++) { @@ -711,7 +687,6 @@ int n; struct eloop_event *e; struct eloop_timeout *t; - void (*t0)(void *); struct timespec ts, *tsp; assert(eloop != NULL); @@ -720,11 +695,9 @@ if (eloop->exitnow) break; - /* Run all timeouts first. */ - if (eloop->timeout0) { - t0 = eloop->timeout0; - eloop->timeout0 = NULL; - t0(eloop->timeout0_arg); + if (_eloop_nsig != 0 && eloop->signal_cb != NULL) { + n = _eloop_sig[--_eloop_nsig]; + eloop->signal_cb(n, eloop->signal_cb_ctx); continue; }
