summaryrefslogtreecommitdiff
path: root/lib/log.c
diff options
context:
space:
mode:
authorajs <ajs>2004-11-23 18:19:14 +0000
committerajs <ajs>2004-11-23 18:19:14 +0000
commit59a06a915da9129a4e756c2b4d42449aa71a0ee4 (patch)
tree44090f696cbec97cab5e5b090b22c7431a5d6490 /lib/log.c
parentd246bd965898f0ba6781f2b2048af9a5eba079d3 (diff)
2004-11-23 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* sigevent.c: (signal_init) Set up some default signal handlers so that processes will issue an error message before terminating or dumping core. (trap_default_signals) New function to set up signal handlers for various signals that may kill the process. (exit_handler) Call zlog_signal, then _exit. (core_handler) Call zlog_signal, then abort. * log.h: Declare new function zlog_signal. * log.c: (zlog_signal) New function to log information about a received signal before the process dies. Try to log a backtrace also. (quagga_signal_handler,signal_set) Should be static.
Diffstat (limited to 'lib/log.c')
-rw-r--r--lib/log.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/lib/log.c b/lib/log.c
index 205b7c0d..c55bfcb1 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -163,6 +163,104 @@ vzlog (struct zlog *zl, int priority, const char *format, va_list args)
vty_log (zlog_proto_names[zl->protocol], format, args);
}
+static char *
+str_append(char *dst, int len, const char *src)
+{
+ while ((len-- > 0) && *src)
+ *dst++ = *src++;
+ return dst;
+}
+
+static char *
+num_append(char *s, int len, u_long x)
+{
+ char buf[30];
+ char *t = &buf[29];
+
+ *t = '\0';
+ while (x && (t > buf))
+ {
+ *--t = '0'+(x % 10);
+ x /= 10;
+ }
+ return str_append(s,len,t);
+}
+
+/* Note: the goal here is to use only async-signal-safe functions. */
+void
+zlog_signal(int signo, const char *action)
+{
+ time_t now;
+ char buf[sizeof("DEFAULT: Received signal S at T; aborting...")+60];
+ char *s = buf;
+
+#define LOC s,buf+sizeof(buf)-s
+
+ time(&now);
+ if (zlog_default)
+ {
+ s = str_append(LOC,zlog_proto_names[zlog_default->protocol]);
+ *s++ = ':';
+ *s++ = ' ';
+ }
+ s = str_append(LOC,"Received signal ");
+ s = num_append(LOC,signo);
+ s = str_append(LOC," at ");
+ s = num_append(LOC,now);
+ s = str_append(LOC,"; ");
+ s = str_append(LOC,action);
+ *s++ = '\n';
+
+#define DUMP(FP) write(fileno(FP),buf,s-buf);
+ if (!zlog_default)
+ DUMP(stderr)
+ else
+ {
+ if ((zlog_default->flags & ZLOG_FILE) && zlog_default->fp)
+ DUMP(zlog_default->fp)
+ if (zlog_default->flags & ZLOG_STDOUT)
+ DUMP(stdout)
+ if (zlog_default->flags & ZLOG_STDERR)
+ DUMP(stderr)
+ /* Is there a signal-safe way to send a syslog message? */
+ }
+#undef DUMP
+
+ /* Now try for a backtrace. */
+#ifdef HAVE_GLIBC_BACKTRACE
+ {
+ void *array[20];
+ size_t size;
+
+ size = backtrace(array,sizeof(array)/sizeof(array[0]));
+ s = buf;
+ s = str_append(LOC,"Backtrace for ");
+ s = num_append(LOC,size);
+ s = str_append(LOC," stack frames:\n");
+
+#define DUMP(FP) { \
+ write(fileno(FP),buf,s-buf); \
+ backtrace_symbols_fd(array, size, fileno(FP)); \
+}
+
+ if (!zlog_default)
+ DUMP(stderr)
+ else
+ {
+ if ((zlog_default->flags & ZLOG_FILE) && zlog_default->fp)
+ DUMP(zlog_default->fp)
+ if (zlog_default->flags & ZLOG_STDOUT)
+ DUMP(stdout)
+ if (zlog_default->flags & ZLOG_STDERR)
+ DUMP(stderr)
+ /* Is there a signal-safe way to send a syslog message? */
+ }
+#undef DUMP
+ }
+#endif /* HAVE_GLIBC_BACKTRACE */
+#undef LOC
+}
+
void
zlog (struct zlog *zl, int priority, const char *format, ...)
{