diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rwxr-xr-x | configure.ac | 7 | ||||
-rw-r--r-- | lib/ChangeLog | 17 | ||||
-rw-r--r-- | lib/log.c | 22 | ||||
-rw-r--r-- | lib/log.h | 5 | ||||
-rw-r--r-- | lib/sigevent.c | 56 |
6 files changed, 88 insertions, 24 deletions
@@ -1,5 +1,10 @@ 2005-01-12 Andrew J. Schorr <ajschorr@alumni.princeton.edu> + * configure.ac: Test for header file <ucontext.h> (for use in + signal processing). + +2005-01-12 Andrew J. Schorr <ajschorr@alumni.princeton.edu> + * configure.ac: If configure is invoked with --enable-snmp, but the configure script is unable to find SNMP support on the platform, then configure should give an error message and exit. diff --git a/configure.ac b/configure.ac index 61a00d95..ff424e8b 100755 --- a/configure.ac +++ b/configure.ac @@ -5,7 +5,7 @@ ## Copyright (c) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro <kunihiro@zebra.org> ## Portions Copyright (c) 2003 Paul Jakma <paul@dishone.st> ## -## $Id: configure.ac,v 1.86 2005/01/12 16:52:55 ajs Exp $ +## $Id: configure.ac,v 1.87 2005/01/12 17:27:27 ajs Exp $ AC_PREREQ(2.53) AC_INIT(Quagga, 0.98.0, [http://bugzilla.quagga.net]) @@ -1107,6 +1107,11 @@ if test "${enable_capabilities}" != "no"; then fi AC_SUBST(LIBCAP) +dnl ------------------- +dnl test for ucontext.h +dnl ------------------- +AC_CHECK_HEADERS(ucontext.h) + dnl --------------------------- dnl check for glibc 'backtrace' dnl --------------------------- diff --git a/lib/ChangeLog b/lib/ChangeLog index 4b245bec..4410fb24 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,5 +1,22 @@ 2005-01-12 Andrew J. Schorr <ajschorr@alumni.princeton.edu> + * sigevent.c: (trap_default_signals) Use the SA_SIGINFO flag to + pass additional siginfo_t and ucontext_t arguments to core_handler + and exit_handler. + (core_handler,exit_handler) Now invoked with 3 arguments (using + SA_SIGINFO). Pass additional info to zlog_signal. + (program_counter) New function to find program counter in ucontext_t, + needs to be enhanced to support more platforms (currently works only + on Linux/x86). + * log.h: Change the zlog_signal prototype to add new arguments + siginfo_t * and program_counter. + * log.c: (zlog_signal) Add new arguments siginfo and program_counter. + Include si_addr and program counter (if non-NULL) in message. + And remove #ifdef HAVE_GLIBC_BACKTRACE around hex_append, since + that is now used to render the si_addr and PC pointers. + +2005-01-12 Andrew J. Schorr <ajschorr@alumni.princeton.edu> + * zebra.h: If not C99 and no va_copy macro available, fall back to memcpy (solves a build problem on FreeBSD 4.x). @@ -1,5 +1,5 @@ /* - * $Id: log.c,v 1.20 2004/12/10 22:43:17 ajs Exp $ + * $Id: log.c,v 1.21 2005/01/12 17:27:27 ajs Exp $ * * Logging of zebra * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro @@ -177,10 +177,6 @@ num_append(char *s, int len, u_long x) return str_append(s,len,t); } -#ifdef HAVE_GLIBC_BACKTRACE - -/* This function is used only in zlog_backtrace_sigsafe when glibc - backtraces are available. */ static char * hex_append(char *s, int len, u_long x) { @@ -199,8 +195,6 @@ hex_append(char *s, int len, u_long x) return str_append(s,len,t); } -#endif /* HAVE_GLIBC_BACKTRACE */ - static int syslog_fd = -1; /* Needs to be enhanced to support Solaris. */ @@ -264,10 +258,11 @@ syslog_sigsafe(int priority, const char *msg, size_t msglen) /* Note: the goal here is to use only async-signal-safe functions. */ void -zlog_signal(int signo, const char *action) +zlog_signal(int signo, const char *action, siginfo_t *siginfo, + void *program_counter) { time_t now; - char buf[sizeof("DEFAULT: Received signal S at T; aborting...")+60]; + char buf[sizeof("DEFAULT: Received signal S at T (si_addr 0xP, PC 0xP); aborting...")+100]; char *s = buf; char *msgstart = buf; #define LOC s,buf+sizeof(buf)-s @@ -284,7 +279,14 @@ zlog_signal(int signo, const char *action) s = num_append(LOC,signo); s = str_append(LOC," at "); s = num_append(LOC,now); - s = str_append(LOC,"; "); + s = str_append(LOC," (si_addr 0x"); + s = hex_append(LOC,(u_long)(siginfo->si_addr)); + if (program_counter) + { + s = str_append(LOC,", PC 0x"); + s = hex_append(LOC,(u_long)program_counter); + } + s = str_append(LOC,"); "); s = str_append(LOC,action); if (s < buf+sizeof(buf)) *s++ = '\n'; @@ -1,5 +1,5 @@ /* - * $Id: log.h,v 1.14 2004/12/07 15:39:32 ajs Exp $ + * $Id: log.h,v 1.15 2005/01/12 17:27:27 ajs Exp $ * * Zebra logging funcions. * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro @@ -153,7 +153,8 @@ extern const char *zlog_proto_names[]; extern const char *safe_strerror(int errnum); /* To be called when a fatal signal is caught. */ -extern void zlog_signal(int signo, const char *action); +extern void zlog_signal(int signo, const char *action, + siginfo_t *siginfo, void *program_counter); /* Log a backtrace. */ extern void zlog_backtrace(int priority); diff --git a/lib/sigevent.c b/lib/sigevent.c index 5ac226a4..7acdad29 100644 --- a/lib/sigevent.c +++ b/lib/sigevent.c @@ -23,6 +23,15 @@ #include <sigevent.h> #include <log.h> +#ifdef HAVE_UCONTEXT_H +#ifdef GNU_LINUX +/* get REG_EIP from ucontext.h */ +#define __USE_GNU +#endif /* GNU_LINUX */ +#include <ucontext.h> +#endif /* HAVE_UCONTEXT_H */ + + /* master signals descriptor struct */ struct quagga_sigevent_master_t { @@ -124,7 +133,7 @@ quagga_signal_timer (struct thread *t) #endif /* SIGEVENT_SCHEDULE_THREAD */ /* Initialization of signal handles. */ -/* Signale wrapper. */ +/* Signal wrapper. */ static int signal_set (int signo) { @@ -152,17 +161,33 @@ signal_set (int signo) return 0; } +/* 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 +#ifdef REG_EIP + if (context) + return (void *)(((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP]); +#endif /* REG_EIP */ +#endif /* GNU_LINUX */ +#endif /* HAVE_UCONTEXT_H */ + return NULL; +} + static void -exit_handler(int signo) +exit_handler(int signo, siginfo_t *siginfo, void *context) { - zlog_signal(signo,"exiting..."); + zlog_signal(signo, "exiting...", siginfo, program_counter(context)); _exit(128+signo); } static void -core_handler(int signo) +core_handler(int signo, siginfo_t *siginfo, void *context) { - zlog_signal(signo,"aborting..."); + zlog_signal(signo, "aborting...", siginfo, program_counter(context)); abort(); } @@ -211,11 +236,11 @@ trap_default_signals(void) static const struct { const int *sigs; u_int nsigs; - void (*handler)(int); + void (*handler)(int signo, siginfo_t *info, void *context); } sigmap[] = { - { core_signals, sizeof(core_signals)/sizeof(core_signals[0]),core_handler }, - { exit_signals, sizeof(exit_signals)/sizeof(exit_signals[0]),exit_handler }, - { ignore_signals, sizeof(ignore_signals)/sizeof(ignore_signals[0]),SIG_IGN}, + { core_signals, sizeof(core_signals)/sizeof(core_signals[0]), core_handler}, + { exit_signals, sizeof(exit_signals)/sizeof(exit_signals[0]), exit_handler}, + { ignore_signals, sizeof(ignore_signals)/sizeof(ignore_signals[0]), NULL}, }; u_int i; @@ -230,9 +255,18 @@ trap_default_signals(void) (oact.sa_handler == SIG_DFL)) { struct sigaction act; - act.sa_handler = sigmap[i].handler; sigfillset (&act.sa_mask); - act.sa_flags = 0; + 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; + } if (sigaction(sigmap[i].sigs[j],&act,NULL) < 0) zlog_warn("Unable to set signal handler for signal %d: %s", sigmap[i].sigs[j],safe_strerror(errno)); |