2004-11-26 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* log.c: (zlog_backtrace) New function to log a backtrace.
(zlog_backtrace_safe) Log a backtrace in an async-signal-safe way.
Unfortunately, this function does not support syslog logging yet.
(zlog_signal) Move backtrace code into separate function
zlog_backtrace_safe.
(_zlog_assert_failed) Call zlog_backtrace before aborting.
* log.h: Declare new functions zlog_backtrace and zlog_backtrace_safe.
* memory.c: (zerror) Call zlog_backtrace before aborting.
diff --git a/lib/ChangeLog b/lib/ChangeLog
index 64c0ae8..19fb03f 100644
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -1,5 +1,16 @@
2004-11-26 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
+ * log.c: (zlog_backtrace) New function to log a backtrace.
+ (zlog_backtrace_safe) Log a backtrace in an async-signal-safe way.
+ Unfortunately, this function does not support syslog logging yet.
+ (zlog_signal) Move backtrace code into separate function
+ zlog_backtrace_safe.
+ (_zlog_assert_failed) Call zlog_backtrace before aborting.
+ * log.h: Declare new functions zlog_backtrace and zlog_backtrace_safe.
+ * memory.c: (zerror) Call zlog_backtrace before aborting.
+
+2004-11-26 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
+
* Makefile.am: Need to add zassert.h to pkginclude_HEADERS.
2004-11-25 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
diff --git a/lib/log.c b/lib/log.c
index 9d56680..6623b5c 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -186,14 +186,14 @@
return str_append(s,len,t);
}
-/* Note: the goal here is to use only async-signal-safe functions. */
+/* Note: the goal here is to use only async-signal-safe functions.
+ Needs to be enhanced to support syslog logging. */
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);
@@ -226,18 +226,33 @@
}
#undef DUMP
- /* Now try for a backtrace. */
-#ifdef HAVE_GLIBC_BACKTRACE
- {
- void *array[20];
- int size;
+ zlog_backtrace_safe(LOG_ERR);
+#undef LOC
+}
- if ((size = backtrace(array,sizeof(array)/sizeof(array[0]))) <= 0)
- return;
- s = buf;
- s = str_append(LOC,"Backtrace for ");
- s = num_append(LOC,size);
- s = str_append(LOC," stack frames:\n");
+/* Log a backtrace using only async-signal-safe functions.
+ Needs to be enhanced to support syslog logging. */
+void
+zlog_backtrace_safe(int priority)
+{
+#ifdef HAVE_GLIBC_BACKTRACE
+ void *array[20];
+ int size;
+ char buf[100];
+ char *s;
+#define LOC s,buf+sizeof(buf)-s
+
+ /* only log this information if it has not been masked out */
+ if (zlog_default && (priority > zlog_default->maskpri))
+ return;
+
+ if (((size = backtrace(array,sizeof(array)/sizeof(array[0]))) <= 0) ||
+ ((size_t)size > sizeof(array)/sizeof(array[0])))
+ return;
+ 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); \
@@ -249,17 +264,50 @@
else
{
if ((zlog_default->flags & ZLOG_FILE) && zlog_default->fp)
- DUMP(zlog_default->fp)
+ DUMP(zlog_default->fp)
if (zlog_default->flags & ZLOG_STDOUT)
- DUMP(stdout)
+ DUMP(stdout)
if (zlog_default->flags & ZLOG_STDERR)
- DUMP(stderr)
+ DUMP(stderr)
/* Is there a signal-safe way to send a syslog message? */
}
#undef DUMP
- }
-#endif /* HAVE_GLIBC_BACKTRACE */
#undef LOC
+#endif /* HAVE_GLIBC_BACKTRACE */
+}
+
+void
+zlog_backtrace(int priority)
+{
+#ifndef HAVE_GLIBC_BACKTRACE
+ zlog(NULL, priority, "No backtrace available on this platform.");
+#else
+ void *array[20];
+ int size, i;
+ char **strings;
+
+ if (((size = backtrace(array,sizeof(array)/sizeof(array[0]))) <= 0) ||
+ ((size_t)size > sizeof(array)/sizeof(array[0])))
+ {
+ zlog_err("Cannot get backtrace, returned invalid # of frames %d "
+ "(valid range is between 1 and %u)",
+ size, sizeof(array)/sizeof(array[0]));
+ return;
+ }
+ zlog(NULL, priority, "Backtrace for %d stack frames:", size);
+ if (!(strings = backtrace_symbols(array, size)))
+ {
+ zlog_err("Cannot get backtrace symbols (out of memory?)");
+ for (i = 0; i < size; i++)
+ zlog(NULL, priority, "[bt %d] %p",i,array[i]);
+ }
+ else
+ {
+ for (i = 0; i < size; i++)
+ zlog(NULL, priority, "[bt %d] %s",i,strings[i]);
+ free(strings);
+ }
+#endif /* HAVE_GLIBC_BACKTRACE */
}
void
@@ -322,6 +370,7 @@
{
zlog_err("Assertion `%s' failed in file %s, line %u, function %s",
assertion,file,line,(function ? function : "?"));
+ zlog_backtrace(LOG_ERR);
abort();
}
diff --git a/lib/log.h b/lib/log.h
index 1fd4fe0..0df75e7 100644
--- a/lib/log.h
+++ b/lib/log.h
@@ -125,4 +125,13 @@
/* To be called when a fatal signal is caught. */
extern void zlog_signal(int signo, const char *action);
+/* Log a backtrace. */
+extern void zlog_backtrace(int priority);
+
+/* Log a backtrace, but in an async-signal-safe way. Should not be
+ called unless the program is about to exit or abort, since it messes
+ up the state of zlog file pointers. This function needs to be enhanced
+ to support syslog logging. */
+extern void zlog_backtrace_safe(int priority);
+
#endif /* _ZEBRA_LOG_H */
diff --git a/lib/memory.c b/lib/memory.c
index 6eb135f..0d23e54 100644
--- a/lib/memory.c
+++ b/lib/memory.c
@@ -46,6 +46,11 @@
zlog_err ("%s : can't allocate memory for `%s' size %d: %s\n",
fname, lookup (mstr, type), (int) size, safe_strerror(errno));
log_memstats(LOG_WARNING);
+ /* N.B. It might be preferable to call zlog_backtrace_safe here, since
+ that function should definitely be safe in an OOM condition. But
+ unfortunately zlog_backtrace_safe does not support syslog logging at
+ this time... */
+ zlog_backtrace(LOG_WARNING);
abort();
}