summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@opensourcerouting.org>2013-11-18 23:52:02 +0100
committerDavid Lamparter <equinox@opensourcerouting.org>2014-09-15 18:38:56 +0200
commit615f9f18fc025757a255f936748fc1e86e922783 (patch)
treeb9cd79ef71984932f4eb5f73437f9593ad2a2604
parent3493b7731b750cbc62f00be94b624a08ccccf0b2 (diff)
downloadquagga-615f9f18fc025757a255f936748fc1e86e922783.tar.bz2
quagga-615f9f18fc025757a255f936748fc1e86e922783.tar.xz
lib: include thread information in backtraces
now that we know what thread we're currently executing, let's add that information to SEGV / assert backtraces. Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
-rw-r--r--lib/log.c45
-rw-r--r--lib/log.h2
-rw-r--r--lib/thread.c4
-rw-r--r--lib/thread.h4
4 files changed, 55 insertions, 0 deletions
diff --git a/lib/log.c b/lib/log.c
index 1058844b..04f8fab6 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -425,6 +425,40 @@ zlog_signal(int signo, const char *action
NULL
#endif
);
+
+ s = buf;
+ if (!thread_current)
+ s = str_append (LOC, "no thread information available\n");
+ else
+ {
+ s = str_append (LOC, "in thread ");
+ s = str_append (LOC, thread_current->funcname);
+ s = str_append (LOC, " scheduled from ");
+ s = str_append (LOC, thread_current->schedfrom);
+ s = str_append (LOC, ":");
+ s = num_append (LOC, thread_current->schedfrom_line);
+ s = str_append (LOC, "\n");
+ }
+
+#define DUMP(FD) write(FD, buf, s-buf);
+ /* If no file logging configured, try to write to fallback log file. */
+ if (logfile_fd >= 0)
+ DUMP(logfile_fd)
+ if (!zlog_default)
+ DUMP(STDERR_FILENO)
+ else
+ {
+ if (PRI <= zlog_default->maxlvl[ZLOG_DEST_STDOUT])
+ DUMP(STDOUT_FILENO)
+ /* Remove trailing '\n' for monitor and syslog */
+ *--s = '\0';
+ if (PRI <= zlog_default->maxlvl[ZLOG_DEST_MONITOR])
+ vty_log_fixed(buf,s-buf);
+ if (PRI <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG])
+ syslog_sigsafe(PRI|zlog_default->facility,msgstart,s-msgstart);
+ }
+#undef DUMP
+
#undef PRI
#undef LOC
}
@@ -604,6 +638,16 @@ PLOG_FUNC(plog_debug, LOG_DEBUG)
#undef PLOG_FUNC
+void zlog_thread_info (int log_level)
+{
+ if (thread_current)
+ zlog(NULL, log_level, "Current thread function %s, scheduled from "
+ "file %s, line %u", thread_current->funcname,
+ thread_current->schedfrom, thread_current->schedfrom_line);
+ else
+ zlog(NULL, log_level, "Current thread not known/applicable");
+}
+
void
_zlog_assert_failed (const char *assertion, const char *file,
unsigned int line, const char *function)
@@ -616,6 +660,7 @@ _zlog_assert_failed (const char *assertion, const char *file,
zlog(NULL, LOG_CRIT, "Assertion `%s' failed in file %s, line %u, function %s",
assertion,file,line,(function ? function : "?"));
zlog_backtrace(LOG_CRIT);
+ zlog_thread_info(LOG_CRIT);
abort();
}
diff --git a/lib/log.h b/lib/log.h
index cf247a83..f3b43ad1 100644
--- a/lib/log.h
+++ b/lib/log.h
@@ -132,6 +132,8 @@ extern void plog_notice (struct zlog *, const char *format, ...)
extern void plog_debug (struct zlog *, const char *format, ...)
PRINTF_ATTRIBUTE(2, 3);
+extern void zlog_thread_info (int log_level);
+
/* Set logging level for the given destination. If the log_level
argument is ZLOG_DISABLED, then the destination is disabled.
This function should not be used for file logging (use zlog_set_file
diff --git a/lib/thread.c b/lib/thread.c
index 9de5f94f..9c3ee823 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -1217,6 +1217,8 @@ thread_getrusage (RUSAGE_T *r)
#endif /* HAVE_CLOCK_MONOTONIC */
}
+struct thread *thread_current = NULL;
+
/* We check thread consumed time. If the system has getrusage, we'll
use that to get in-depth stats on the performance of the thread in addition
to wall clock time stats from gettimeofday. */
@@ -1246,7 +1248,9 @@ thread_call (struct thread *thread)
GETRUSAGE (&before);
thread->real = before.real;
+ thread_current = thread;
(*thread->func) (thread);
+ thread_current = NULL;
GETRUSAGE (&after);
diff --git a/lib/thread.h b/lib/thread.h
index a088b472..9743a22d 100644
--- a/lib/thread.h
+++ b/lib/thread.h
@@ -234,4 +234,8 @@ extern unsigned long thread_consumed_time(RUSAGE_T *after, RUSAGE_T *before,
extern struct timeval recent_time;
/* Similar to recent_time, but a monotonically increasing time value */
extern struct timeval recent_relative_time (void);
+
+/* only for use in logging functions! */
+extern struct thread *thread_current;
+
#endif /* _ZEBRA_THREAD_H */