From 063ee52af64472474af2fa4b3cb2ba9ced746b9f Mon Sep 17 00:00:00 2001 From: ajs Date: Fri, 26 Nov 2004 18:11:14 +0000 Subject: 2004-11-26 Andrew J. Schorr * 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 | 11 ++++++++ lib/log.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++------------ lib/log.h | 9 +++++++ lib/memory.c | 5 ++++ 4 files changed, 91 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/ChangeLog b/lib/ChangeLog index 64c0ae8d..19fb03fe 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,14 @@ +2004-11-26 Andrew J. Schorr + + * 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 * Makefile.am: Need to add zassert.h to pkginclude_HEADERS. diff --git a/lib/log.c b/lib/log.c index 9d566806..6623b5c9 100644 --- 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(); } diff --git a/lib/log.h b/lib/log.h index 1fd4fe0c..0df75e73 100644 --- 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 */ diff --git a/lib/memory.c b/lib/memory.c index 6eb135f0..0d23e542 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -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(); } -- cgit v1.2.1