+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
## 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])
fi
AC_SUBST(LIBCAP)
+dnl -------------------
+dnl test for ucontext.h
+dnl -------------------
+AC_CHECK_HEADERS(ucontext.h)
+
dnl ---------------------------
dnl check for glibc 'backtrace'
dnl ---------------------------
+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
/*
- * $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
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)
{
return str_append(s,len,t);
}
-#endif /* HAVE_GLIBC_BACKTRACE */
-
static int syslog_fd = -1;
/* Needs to be enhanced to support Solaris. */
/* 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
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';
/*
- * $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
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);
#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
{
#endif /* SIGEVENT_SCHEDULE_THREAD */
/* Initialization of signal handles. */
-/* Signale wrapper. */
+/* Signal wrapper. */
static int
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();
}
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;
(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));