2023-02-08 13:17:09 +01:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2004-01-19 22:23:37 +01:00
|
|
|
/* Quagga signal handling functions.
|
|
|
|
* Copyright (C) 2004 Paul Jakma,
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
#include <sigevent.h>
|
|
|
|
#include <log.h>
|
2012-09-26 10:39:10 +02:00
|
|
|
#include <memory.h>
|
2018-06-14 15:13:18 +02:00
|
|
|
#include <lib_errors.h>
|
2004-01-19 22:23:37 +01:00
|
|
|
|
2005-01-12 18:27:27 +01:00
|
|
|
#ifdef HAVE_UCONTEXT_H
|
|
|
|
#ifdef GNU_LINUX
|
|
|
|
/* get REG_EIP from ucontext.h */
|
2005-04-08 21:02:04 +02:00
|
|
|
#ifndef __USE_GNU
|
2005-01-12 18:27:27 +01:00
|
|
|
#define __USE_GNU
|
2005-04-08 21:02:04 +02:00
|
|
|
#endif /* __USE_GNU */
|
2005-01-12 18:27:27 +01:00
|
|
|
#endif /* GNU_LINUX */
|
|
|
|
#include <ucontext.h>
|
|
|
|
#endif /* HAVE_UCONTEXT_H */
|
|
|
|
|
|
|
|
|
2004-07-22 21:14:27 +02:00
|
|
|
/* master signals descriptor struct */
|
2021-11-11 20:28:54 +01:00
|
|
|
static struct frr_sigevent_master_t {
|
2022-03-01 22:18:12 +01:00
|
|
|
struct event *t;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2021-11-11 20:28:54 +01:00
|
|
|
struct frr_signal_t *signals;
|
2004-01-19 22:23:37 +01:00
|
|
|
int sigc;
|
|
|
|
|
2004-07-22 21:14:27 +02:00
|
|
|
volatile sig_atomic_t caught;
|
|
|
|
} sigmaster;
|
2004-01-19 22:23:37 +01:00
|
|
|
|
|
|
|
/* Generic signal handler
|
|
|
|
* Schedules signal event thread
|
|
|
|
*/
|
2021-11-11 20:28:54 +01:00
|
|
|
static void frr_signal_handler(int signo)
|
2004-01-19 22:23:37 +01:00
|
|
|
{
|
|
|
|
int i;
|
2021-11-11 20:28:54 +01:00
|
|
|
struct frr_signal_t *sig;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-01-19 22:23:37 +01:00
|
|
|
for (i = 0; i < sigmaster.sigc; i++) {
|
|
|
|
sig = &(sigmaster.signals[i]);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-01-19 22:23:37 +01:00
|
|
|
if (sig->signal == signo)
|
2004-07-22 21:14:27 +02:00
|
|
|
sig->caught = 1;
|
2004-01-19 22:23:37 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-07-22 21:14:27 +02:00
|
|
|
sigmaster.caught = 1;
|
2004-01-19 22:23:37 +01:00
|
|
|
}
|
|
|
|
|
2020-09-02 22:25:00 +02:00
|
|
|
/*
|
|
|
|
* Check whether any signals have been received and are pending. This is done
|
|
|
|
* with the application's key signals blocked. The complete set of signals
|
|
|
|
* is returned in 'setp', so the caller can restore them when appropriate.
|
|
|
|
* If there are pending signals, returns 'true', 'false' otherwise.
|
|
|
|
*/
|
|
|
|
bool frr_sigevent_check(sigset_t *setp)
|
|
|
|
{
|
|
|
|
sigset_t blocked;
|
|
|
|
int i;
|
|
|
|
bool ret;
|
|
|
|
|
|
|
|
sigemptyset(setp);
|
|
|
|
sigemptyset(&blocked);
|
|
|
|
|
|
|
|
/* Set up mask of application's signals */
|
|
|
|
for (i = 0; i < sigmaster.sigc; i++)
|
|
|
|
sigaddset(&blocked, sigmaster.signals[i].signal);
|
|
|
|
|
|
|
|
pthread_sigmask(SIG_BLOCK, &blocked, setp);
|
|
|
|
|
|
|
|
/* Now that the application's signals are blocked, test. */
|
|
|
|
ret = (sigmaster.caught != 0);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2004-07-22 21:14:27 +02:00
|
|
|
/* check if signals have been caught and run appropriate handlers */
|
2021-11-11 20:28:54 +01:00
|
|
|
int frr_sigevent_process(void)
|
2004-01-19 22:23:37 +01:00
|
|
|
{
|
2021-11-11 20:28:54 +01:00
|
|
|
struct frr_signal_t *sig;
|
2004-01-19 22:23:37 +01:00
|
|
|
int i;
|
2004-07-22 21:14:27 +02:00
|
|
|
#ifdef SIGEVENT_BLOCK_SIGNALS
|
2021-10-05 23:33:14 +02:00
|
|
|
/* shouldn't need to block signals, but potentially may be needed */
|
2004-07-22 21:14:27 +02:00
|
|
|
sigset_t newmask, oldmask;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-07-13 15:47:25 +02:00
|
|
|
/*
|
|
|
|
* Block most signals, but be careful not to defer SIGTRAP because
|
|
|
|
* doing so breaks gdb, at least on NetBSD 2.0. Avoid asking to
|
|
|
|
* block SIGKILL, just because we shouldn't be able to do so.
|
|
|
|
*/
|
2004-01-19 22:23:37 +01:00
|
|
|
sigfillset(&newmask);
|
2004-07-13 15:47:25 +02:00
|
|
|
sigdelset(&newmask, SIGTRAP);
|
|
|
|
sigdelset(&newmask, SIGKILL);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-01-19 22:23:37 +01:00
|
|
|
if ((sigprocmask(SIG_BLOCK, &newmask, &oldmask)) < 0) {
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err_sys(EC_LIB_SYSTEM_CALL,
|
2021-11-11 20:28:54 +01:00
|
|
|
"frr_signal_timer: couldnt block signals!");
|
2004-01-19 22:23:37 +01:00
|
|
|
return -1;
|
|
|
|
}
|
2004-07-22 21:14:27 +02:00
|
|
|
#endif /* SIGEVENT_BLOCK_SIGNALS */
|
|
|
|
|
|
|
|
if (sigmaster.caught > 0) {
|
|
|
|
sigmaster.caught = 0;
|
|
|
|
/* must not read or set sigmaster.caught after here,
|
|
|
|
* race condition with per-sig caught flags if one does
|
|
|
|
*/
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-07-22 21:14:27 +02:00
|
|
|
for (i = 0; i < sigmaster.sigc; i++) {
|
|
|
|
sig = &(sigmaster.signals[i]);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-07-22 21:14:27 +02:00
|
|
|
if (sig->caught > 0) {
|
|
|
|
sig->caught = 0;
|
2017-03-26 01:28:13 +01:00
|
|
|
if (sig->handler)
|
|
|
|
sig->handler();
|
2004-07-22 21:14:27 +02:00
|
|
|
}
|
2004-01-19 22:23:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-07-22 21:14:27 +02:00
|
|
|
#ifdef SIGEVENT_BLOCK_SIGNALS
|
2004-01-19 22:23:37 +01:00
|
|
|
if (sigprocmask(SIG_UNBLOCK, &oldmask, NULL) < 0)
|
2022-08-25 11:51:46 +02:00
|
|
|
return -1;
|
2004-07-22 21:14:27 +02:00
|
|
|
#endif /* SIGEVENT_BLOCK_SIGNALS */
|
|
|
|
|
2004-01-19 22:23:37 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-07-22 21:14:27 +02:00
|
|
|
#ifdef SIGEVENT_SCHEDULE_THREAD
|
2021-10-05 23:33:14 +02:00
|
|
|
/* timer thread to check signals. shouldn't be needed */
|
2022-03-01 22:18:12 +01:00
|
|
|
void frr_signal_timer(struct event *t)
|
2004-07-22 21:14:27 +02:00
|
|
|
{
|
2021-11-11 20:28:54 +01:00
|
|
|
struct frr_sigevent_master_t *sigm;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-07-22 21:14:27 +02:00
|
|
|
sigm = THREAD_ARG(t);
|
2017-05-05 23:22:25 +02:00
|
|
|
sigm->t = NULL;
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_timer(sigm->t->master, frr_signal_timer, &sigmaster,
|
|
|
|
FRR_SIGNAL_TIMER_INTERVAL, &sigm->t);
|
2022-02-23 01:04:25 +01:00
|
|
|
frr_sigevent_process();
|
2004-07-22 21:14:27 +02:00
|
|
|
}
|
|
|
|
#endif /* SIGEVENT_SCHEDULE_THREAD */
|
|
|
|
|
2004-01-19 22:23:37 +01:00
|
|
|
/* Initialization of signal handles. */
|
2005-01-12 18:27:27 +01:00
|
|
|
/* Signal wrapper. */
|
2004-01-19 22:23:37 +01:00
|
|
|
static int signal_set(int signo)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct sigaction sig;
|
|
|
|
struct sigaction osig;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2021-11-11 20:28:54 +01:00
|
|
|
sig.sa_handler = &frr_signal_handler;
|
2004-01-19 22:23:37 +01:00
|
|
|
sigfillset(&sig.sa_mask);
|
|
|
|
sig.sa_flags = 0;
|
|
|
|
if (signo == SIGALRM) {
|
|
|
|
#ifdef SA_INTERRUPT
|
|
|
|
sig.sa_flags |= SA_INTERRUPT; /* SunOS */
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
#ifdef SA_RESTART
|
|
|
|
sig.sa_flags |= SA_RESTART;
|
|
|
|
#endif /* SA_RESTART */
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = sigaction(signo, &sig, &osig);
|
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-01-12 18:27:27 +01:00
|
|
|
/* XXX This function should be enhanced to support more platforms
|
|
|
|
(it currently works only on Linux/x86). */
|
|
|
|
static void *program_counter(void *context)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_UCONTEXT_H
|
|
|
|
#ifdef GNU_LINUX
|
2009-06-25 17:40:06 +02:00
|
|
|
/* these are from GNU libc, rather than Linux, strictly speaking */
|
|
|
|
#if defined(REG_EIP)
|
|
|
|
# define REG_INDEX REG_EIP
|
|
|
|
#elif defined(REG_RIP)
|
|
|
|
# define REG_INDEX REG_RIP
|
|
|
|
#elif defined(__powerpc__)
|
|
|
|
# define REG_INDEX 32
|
|
|
|
#endif
|
2005-01-12 18:27:27 +01:00
|
|
|
#endif /* GNU_LINUX */
|
2009-06-25 17:40:06 +02:00
|
|
|
|
|
|
|
#ifdef REG_INDEX
|
|
|
|
#ifdef HAVE_UCONTEXT_T_UC_MCONTEXT_GREGS
|
|
|
|
# define REGS gregs[REG_INDEX]
|
|
|
|
#elif defined(HAVE_UCONTEXT_T_UC_MCONTEXT_UC_REGS)
|
|
|
|
# define REGS uc_regs->gregs[REG_INDEX]
|
|
|
|
#endif /* HAVE_UCONTEXT_T_UC_MCONTEXT_GREGS */
|
|
|
|
#endif /* REG_INDEX */
|
|
|
|
|
|
|
|
#ifdef REGS
|
|
|
|
if (context)
|
|
|
|
return (void *)(((ucontext_t *)context)->uc_mcontext.REGS);
|
|
|
|
#elif defined(HAVE_UCONTEXT_T_UC_MCONTEXT_REGS__NIP)
|
|
|
|
/* older Linux / struct pt_regs ? */
|
|
|
|
if (context)
|
|
|
|
return (void *)(((ucontext_t *)context)->uc_mcontext.regs->nip);
|
|
|
|
#endif /* REGS */
|
|
|
|
|
2005-01-12 18:27:27 +01:00
|
|
|
#endif /* HAVE_UCONTEXT_H */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2005-05-06 Paul Jakma <paul@dishone.st>
* (general) extern and static'ification of functions in code and
header.
Cleanup any definitions with unspecified arguments.
Add casts for callback assignments where the callback is defined,
typically, as passing void *, but the function being assigned has
some other pointer type defined as its argument, as gcc complains
about casts from void * to X* via function arguments.
Fix some old K&R style function argument definitions.
Add noreturn gcc attribute to some functions, as appropriate.
Add unused gcc attribute to some functions (eg ones meant to help
while debugging)
Add guard defines to headers which were missing them.
* command.c: (install_node) add const qualifier, still doesnt shut
up the warning though, because of the double pointer.
(cmp_node) ditto
* keychain.c: (key_str2time) Add GET_LONG_RANGE() macro, derived
fromn vty.h ones to fix some of the (long) < 0 warnings.
* thread.c: (various) use thread_empty
(cpu_record_hash_key) should cast to uintptr_t, a stdint.h type
* vty.h: Add VTY_GET_IPV4_ADDRESS and VTY_GET_IPV4_PREFIX so they
removed from ospfd/ospf_vty.h
* zebra.h: Move definition of ZEBRA_PORT to here, to remove
dependence of lib on zebra/zserv.h
2005-05-06 23:25:49 +02:00
|
|
|
static void __attribute__((noreturn))
|
2019-06-21 07:45:50 +02:00
|
|
|
exit_handler(int signo, siginfo_t *siginfo, void *context)
|
2004-11-23 19:19:14 +01:00
|
|
|
{
|
2019-06-03 18:04:32 +02:00
|
|
|
void *pc = program_counter(context);
|
|
|
|
|
|
|
|
zlog_signal(signo, "exiting...", siginfo, pc);
|
2004-11-23 19:19:14 +01:00
|
|
|
_exit(128 + signo);
|
|
|
|
}
|
|
|
|
|
2005-05-06 Paul Jakma <paul@dishone.st>
* (general) extern and static'ification of functions in code and
header.
Cleanup any definitions with unspecified arguments.
Add casts for callback assignments where the callback is defined,
typically, as passing void *, but the function being assigned has
some other pointer type defined as its argument, as gcc complains
about casts from void * to X* via function arguments.
Fix some old K&R style function argument definitions.
Add noreturn gcc attribute to some functions, as appropriate.
Add unused gcc attribute to some functions (eg ones meant to help
while debugging)
Add guard defines to headers which were missing them.
* command.c: (install_node) add const qualifier, still doesnt shut
up the warning though, because of the double pointer.
(cmp_node) ditto
* keychain.c: (key_str2time) Add GET_LONG_RANGE() macro, derived
fromn vty.h ones to fix some of the (long) < 0 warnings.
* thread.c: (various) use thread_empty
(cpu_record_hash_key) should cast to uintptr_t, a stdint.h type
* vty.h: Add VTY_GET_IPV4_ADDRESS and VTY_GET_IPV4_PREFIX so they
removed from ospfd/ospf_vty.h
* zebra.h: Move definition of ZEBRA_PORT to here, to remove
dependence of lib on zebra/zserv.h
2005-05-06 23:25:49 +02:00
|
|
|
static void __attribute__((noreturn))
|
2019-06-21 07:45:50 +02:00
|
|
|
core_handler(int signo, siginfo_t *siginfo, void *context)
|
2004-11-23 19:19:14 +01:00
|
|
|
{
|
2019-06-03 18:04:32 +02:00
|
|
|
void *pc = program_counter(context);
|
|
|
|
|
2016-01-11 16:02:49 +01:00
|
|
|
/* make sure we don't hang in here. default for SIGALRM is terminate.
|
|
|
|
* - if we're in backtrace for more than a second, abort. */
|
|
|
|
struct sigaction sa_default = {.sa_handler = SIG_DFL};
|
2021-04-16 04:38:25 +02:00
|
|
|
|
2016-01-11 16:02:49 +01:00
|
|
|
sigaction(SIGALRM, &sa_default, NULL);
|
2021-04-16 04:38:25 +02:00
|
|
|
sigaction(signo, &sa_default, NULL);
|
2016-01-11 16:02:49 +01:00
|
|
|
|
|
|
|
sigset_t sigset;
|
2021-04-16 04:38:25 +02:00
|
|
|
|
2016-01-11 16:02:49 +01:00
|
|
|
sigemptyset(&sigset);
|
|
|
|
sigaddset(&sigset, SIGALRM);
|
|
|
|
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
|
|
|
|
|
|
|
|
alarm(1);
|
|
|
|
|
2019-06-03 18:04:32 +02:00
|
|
|
zlog_signal(signo, "aborting...", siginfo, pc);
|
|
|
|
|
2016-04-19 18:42:25 +02:00
|
|
|
/* dump memory stats on core */
|
2017-08-23 16:18:49 +02:00
|
|
|
log_memstats(stderr, "core_handler");
|
2020-11-16 21:12:43 +01:00
|
|
|
|
|
|
|
zlog_tls_buffer_fini();
|
2021-04-16 04:38:25 +02:00
|
|
|
|
|
|
|
/* give the kernel a chance to generate a coredump */
|
|
|
|
sigaddset(&sigset, signo);
|
|
|
|
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
|
|
|
|
raise(signo);
|
|
|
|
|
|
|
|
/* only chance to end up here is if the default action for signo is
|
|
|
|
* something other than kill or coredump the process
|
|
|
|
*/
|
|
|
|
_exit(128 + signo);
|
2004-11-23 19:19:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void trap_default_signals(void)
|
|
|
|
{
|
|
|
|
static const int core_signals[] = {
|
2021-01-21 23:45:10 +01:00
|
|
|
SIGQUIT, SIGILL, SIGABRT,
|
2004-11-23 19:19:14 +01:00
|
|
|
#ifdef SIGEMT
|
|
|
|
SIGEMT,
|
|
|
|
#endif
|
|
|
|
SIGFPE, SIGBUS, SIGSEGV,
|
|
|
|
#ifdef SIGSYS
|
|
|
|
SIGSYS,
|
|
|
|
#endif
|
|
|
|
#ifdef SIGXCPU
|
|
|
|
SIGXCPU,
|
|
|
|
#endif
|
|
|
|
#ifdef SIGXFSZ
|
|
|
|
SIGXFSZ,
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
static const int exit_signals[] = {
|
|
|
|
SIGHUP, SIGINT, SIGALRM, SIGTERM, SIGUSR1, SIGUSR2,
|
|
|
|
#ifdef SIGPOLL
|
|
|
|
SIGPOLL,
|
|
|
|
#endif
|
|
|
|
#ifdef SIGVTALRM
|
|
|
|
SIGVTALRM,
|
|
|
|
#endif
|
|
|
|
#ifdef SIGSTKFLT
|
|
|
|
SIGSTKFLT,
|
|
|
|
#endif
|
|
|
|
};
|
2004-12-15 18:41:14 +01:00
|
|
|
static const int ignore_signals[] = {
|
|
|
|
SIGPIPE,
|
|
|
|
};
|
2004-11-23 19:19:14 +01:00
|
|
|
static const struct {
|
|
|
|
const int *sigs;
|
2018-03-27 21:13:34 +02:00
|
|
|
unsigned int nsigs;
|
2019-06-21 07:45:50 +02:00
|
|
|
void (*handler)(int signo, siginfo_t *info, void *context);
|
2004-12-15 18:41:14 +01:00
|
|
|
} sigmap[] = {
|
2012-09-26 10:39:10 +02:00
|
|
|
{core_signals, array_size(core_signals), core_handler},
|
|
|
|
{exit_signals, array_size(exit_signals), exit_handler},
|
|
|
|
{ignore_signals, array_size(ignore_signals), NULL},
|
2004-11-23 19:19:14 +01:00
|
|
|
};
|
2018-03-27 21:13:34 +02:00
|
|
|
unsigned int i;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2012-09-26 10:39:10 +02:00
|
|
|
for (i = 0; i < array_size(sigmap); i++) {
|
2018-03-27 21:13:34 +02:00
|
|
|
unsigned int j;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-11-23 19:19:14 +01:00
|
|
|
for (j = 0; j < sigmap[i].nsigs; j++) {
|
|
|
|
struct sigaction oact;
|
|
|
|
if ((sigaction(sigmap[i].sigs[j], NULL, &oact) == 0)
|
|
|
|
&& (oact.sa_handler == SIG_DFL)) {
|
|
|
|
struct sigaction act;
|
|
|
|
sigfillset(&act.sa_mask);
|
2005-01-12 18:27:27 +01:00
|
|
|
if (sigmap[i].handler == NULL) {
|
|
|
|
act.sa_handler = SIG_IGN;
|
|
|
|
act.sa_flags = 0;
|
|
|
|
} else {
|
|
|
|
/* Request extra arguments to signal
|
|
|
|
* handler. */
|
|
|
|
act.sa_sigaction = sigmap[i].handler;
|
|
|
|
act.sa_flags = SA_SIGINFO;
|
2016-01-11 16:02:49 +01:00
|
|
|
#ifdef SA_RESETHAND
|
|
|
|
/* don't try to print backtraces
|
|
|
|
* recursively */
|
|
|
|
if (sigmap[i].handler == core_handler)
|
|
|
|
act.sa_flags |= SA_RESETHAND;
|
2005-01-18 23:18:59 +01:00
|
|
|
#endif
|
2005-01-12 18:27:27 +01:00
|
|
|
}
|
2004-11-23 19:19:14 +01:00
|
|
|
if (sigaction(sigmap[i].sigs[j], &act, NULL)
|
|
|
|
< 0)
|
2018-08-20 16:33:32 +02:00
|
|
|
flog_err(
|
2018-09-13 21:34:28 +02:00
|
|
|
EC_LIB_SYSTEM_CALL,
|
2004-11-23 19:19:14 +01:00
|
|
|
"Unable to set signal handler for signal %d: %s",
|
|
|
|
sigmap[i].sigs[j],
|
|
|
|
safe_strerror(errno));
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2004-11-23 19:19:14 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-11 17:20:40 +01:00
|
|
|
void signal_init(struct event_master *m, int sigc,
|
2021-11-11 20:28:54 +01:00
|
|
|
struct frr_signal_t signals[])
|
2004-01-19 22:23:37 +01:00
|
|
|
{
|
|
|
|
|
|
|
|
int i = 0;
|
2021-11-11 20:28:54 +01:00
|
|
|
struct frr_signal_t *sig;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-11-23 19:19:14 +01:00
|
|
|
/* First establish some default handlers that can be overridden by
|
|
|
|
the application. */
|
|
|
|
trap_default_signals();
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-01-19 22:23:37 +01:00
|
|
|
while (i < sigc) {
|
|
|
|
sig = &signals[i];
|
|
|
|
if (signal_set(sig->signal) < 0)
|
|
|
|
exit(-1);
|
|
|
|
i++;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-01-19 22:23:37 +01:00
|
|
|
sigmaster.sigc = sigc;
|
|
|
|
sigmaster.signals = signals;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-07-22 21:14:27 +02:00
|
|
|
#ifdef SIGEVENT_SCHEDULE_THREAD
|
2017-05-05 23:22:25 +02:00
|
|
|
sigmaster.t = NULL;
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_timer(m, frr_signal_timer, &sigmaster,
|
|
|
|
FRR_SIGNAL_TIMER_INTERVAL, &sigmaster.t);
|
2004-07-22 21:14:27 +02:00
|
|
|
#endif /* SIGEVENT_SCHEDULE_THREAD */
|
2004-01-19 22:23:37 +01:00
|
|
|
}
|