summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/log.c10
-rw-r--r--lib/log.h3
-rw-r--r--lib/memory.c6
-rw-r--r--lib/sigevent.c57
-rw-r--r--lib/sigevent.h9
5 files changed, 71 insertions, 14 deletions
diff --git a/lib/log.c b/lib/log.c
index 32b11b76..72f967f6 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -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();
}
diff --git a/lib/log.h b/lib/log.h
index 1894aff2..dda773ea 100644
--- a/lib/log.h
+++ b/lib/log.h
@@ -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 */