]> git.puffer.fish Git - matthieu/frr.git/commitdiff
2004-11-26 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
authorajs <ajs>
Fri, 26 Nov 2004 18:11:14 +0000 (18:11 +0000)
committerajs <ajs>
Fri, 26 Nov 2004 18:11:14 +0000 (18:11 +0000)
* 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.

lib/ChangeLog
lib/log.c
lib/log.h
lib/memory.c

index 64c0ae8d8594fb6b4461287cc080d9e60cc919c2..19fb03fe960267316dba99352fce26d41c27fca4 100644 (file)
@@ -1,3 +1,14 @@
+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.
index 9d5668062e8c993269fd430b92d93f02f8e2b3b7..6623b5c91a6f846e31a7d96a93799d5b613a7d9e 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -186,14 +186,14 @@ num_append(char *s, int len, u_long x)
   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 @@ zlog_signal(int signo, const char *action)
     }
 #undef DUMP
 
-  /* Now try for a backtrace. */
+  zlog_backtrace_safe(LOG_ERR);
+#undef LOC
+}
+
+/* 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;
+  void *array[20];
+  int size;
+  char buf[100];
+  char *s;
+#define LOC s,buf+sizeof(buf)-s
 
-    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");
+  /* 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 @@ zlog_signal(int signo, const char *action)
   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_assert_failed (const char *assertion, const char *file,
 {
   zlog_err("Assertion `%s' failed in file %s, line %u, function %s",
           assertion,file,line,(function ? function : "?"));
+  zlog_backtrace(LOG_ERR);
   abort();
 }
 
index 1fd4fe0c73a6f45b0b7cc6120f3b9f17e3a2c1a3..0df75e733733602cb7d53a895695b87ee9508ee5 100644 (file)
--- a/lib/log.h
+++ b/lib/log.h
@@ -125,4 +125,13 @@ 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);
 
+/* 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 */
index 6eb135f02c46a8c7360def5a595feb122b4e68d6..0d23e542d5127fc8d6a461b568a2dd49ae1a7a71 100644 (file)
@@ -46,6 +46,11 @@ zerror (const char *fname, int type, size_t size)
   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();
 }