diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/log.c | 10 | ||||
-rw-r--r-- | lib/log.h | 3 | ||||
-rw-r--r-- | lib/memory.c | 6 | ||||
-rw-r--r-- | lib/sigevent.c | 57 | ||||
-rw-r--r-- | lib/sigevent.h | 9 |
5 files changed, 71 insertions, 14 deletions
@@ -38,6 +38,7 @@ #endif #include "qpthreads.h" #include "qfstring.h" +#include "sigevent.h" /* log is protected by the same mutext as vty, see comments in vty.c */ @@ -519,6 +520,13 @@ zlog_signal(int signo, const char *action #undef LOC } +/* Ring down the curtain -- turn of SIGABRT handler and abort() */ +void zabort_abort(void) +{ + quagga_sigabrt_no_trap() ; + abort() ; +} + /* Log a backtrace using only async-signal-safe functions. Needs to be enhanced to support syslog logging. */ void @@ -776,7 +784,7 @@ zlog_abort (const char *mess) uzlog(NULL, LOG_CRIT, "%s", mess); uzlog_backtrace(LOG_CRIT); - abort(); + zabort_abort(); } @@ -193,6 +193,9 @@ extern void zlog_signal(int signo, const char *action #endif ); +/* Ring down the curtain -- turn of SIGABRT handler and abort() */ +extern void zabort_abort(void) __attribute__ ((noreturn)) ; + /* Log a backtrace. */ extern void zlog_backtrace(int priority); diff --git a/lib/memory.c b/lib/memory.c index 5ee33aa8..2e295566 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -107,7 +107,7 @@ zerror (const char *fname, int type, size_t size) unfortunately zlog_backtrace_sigsafe does not support syslog logging at this time... */ zlog_backtrace(LOG_WARNING); - abort(); + zabort_abort(); } /*------------------------------------------------------------------------------ @@ -205,13 +205,15 @@ zfree (enum MTYPE mtype, void *ptr) { LOCK ; - free (ptr); + assert(mstat.mt[mtype].alloc > 0) ; mstat.mt[mtype].alloc--; #ifdef MEMORY_TRACKER mem_md_free(mtype, ptr) ; #endif + free (ptr); + UNLOCK ; } ; diff --git a/lib/sigevent.c b/lib/sigevent.c index 6e50d631..18fcffb0 100644 --- a/lib/sigevent.c +++ b/lib/sigevent.c @@ -220,18 +220,25 @@ core_handler(int signo , siginfo, program_counter(context) #endif ); - abort(); + zabort_abort(); } +/* For the signals known to Quagga, and which are in their default state, + * set a Quagga default handler. + */ static void trap_default_signals(void) { static const int core_signals[] = { SIGQUIT, SIGILL, + SIGABRT, #ifdef SIGEMT SIGEMT, #endif +#ifdef SIGIOT + SIGIOT, +#endif SIGFPE, SIGBUS, SIGSEGV, @@ -245,6 +252,7 @@ trap_default_signals(void) SIGXFSZ, #endif }; + static const int exit_signals[] = { SIGHUP, SIGINT, @@ -262,9 +270,11 @@ trap_default_signals(void) SIGSTKFLT, #endif }; + static const int ignore_signals[] = { SIGPIPE, }; + static const struct { const int *sigs; u_int nsigs; @@ -287,28 +297,39 @@ trap_default_signals(void) 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)) + if (sigaction(sigmap[i].sigs[j], NULL, &oact) < 0) + zlog_warn("Unable to get signal handler for signal %d: %s", + sigmap[i].sigs[j], errtoa(errno, 0).str); + else { +#ifdef SA_SIGINFO + if (oact.sa_flags & SA_SIGINFO) + continue ; /* Don't set again */ +#endif + if (oact.sa_handler != SIG_DFL) + continue ; /* Don't set again */ + } + if ( (sigaction(sigmap[i].sigs[j], NULL, &oact) == 0) && + (oact.sa_handler == SIG_DFL) ) { struct sigaction act; sigfillset (&act.sa_mask); if (sigmap[i].handler == NULL) { act.sa_handler = SIG_IGN; - act.sa_flags = 0; + act.sa_flags = 0; } else { #ifdef SA_SIGINFO /* Request extra arguments to signal handler. */ act.sa_sigaction = sigmap[i].handler; - act.sa_flags = SA_SIGINFO; + act.sa_flags = SA_SIGINFO; #else - act.sa_handler = sigmap[i].handler; - act.sa_flags = 0; + act.sa_handler = sigmap[i].handler; + act.sa_flags = 0; #endif } - if (sigaction(sigmap[i].sigs[j],&act,NULL) < 0) + if (sigaction(sigmap[i].sigs[j], &act, NULL) < 0) zlog_warn("Unable to set signal handler for signal %d: %s", sigmap[i].sigs[j], errtoa(errno, 0).str); @@ -346,3 +367,23 @@ signal_init (struct thread_master *m, int sigc, QUAGGA_SIGNAL_TIMER_INTERVAL); #endif /* SIGEVENT_SCHEDULE_THREAD */ } + +/* turn off trap for SIGABRT ! */ +extern void quagga_sigabrt_no_trap(void) +{ + struct sigaction new_act ; + sigset_t set ; + + sigfillset(&set) ; + + new_act.sa_handler = SIG_DFL ; + new_act.sa_mask = set ; + new_act.sa_flags = 0 ; + sigaction(SIGABRT, &new_act, NULL) ; + + sigemptyset(&set) ; + sigaddset(&set, SIGABRT) ; + sigprocmask(SIG_UNBLOCK, &set, NULL) ; + +} ; + diff --git a/lib/sigevent.h b/lib/sigevent.h index 62b944a7..57486bc2 100644 --- a/lib/sigevent.h +++ b/lib/sigevent.h @@ -1,4 +1,4 @@ -/* +/* * Quagga Signal handling header. * * Copyright (C) 2004 Paul Jakma. @@ -18,7 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Quagga; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * 02111-1307, USA. */ #ifndef _QUAGGA_SIGNAL_H @@ -44,10 +44,13 @@ struct quagga_signal_t * - array of quagga_signal_t's describing signals to handle * and handlers to use for each signal */ -extern void signal_init (struct thread_master *m, int sigc, +extern void signal_init (struct thread_master *m, int sigc, struct quagga_signal_t *signals); /* check whether there are signals to handle, process any found */ extern int quagga_sigevent_process (void); +/* turn off trap for SIGABRT ! */ +extern void quagga_sigabrt_no_trap(void) ; + #endif /* _QUAGGA_SIGNAL_H */ |