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>
(cherry picked from commit 615f9f18fc025757a255f936748fc1e86e922783)
This commit is contained in:
David Lamparter 2013-11-18 23:52:02 +01:00 committed by Donald Sharp
parent 9c7753e41a
commit d1265948c3
4 changed files with 55 additions and 0 deletions

View File

@ -459,6 +459,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
}
@ -616,6 +650,16 @@ ZLOG_FUNC(zlog_debug, LOG_DEBUG)
#undef ZLOG_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)
@ -628,6 +672,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();
}

View File

@ -121,6 +121,8 @@ extern void zlog_info (const char *format, ...) PRINTF_ATTRIBUTE(1, 2);
extern void zlog_notice (const char *format, ...) PRINTF_ATTRIBUTE(1, 2);
extern void zlog_debug (const char *format, ...) PRINTF_ATTRIBUTE(1, 2);
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

View File

@ -1526,6 +1526,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. */
@ -1555,7 +1557,9 @@ thread_call (struct thread *thread)
GETRUSAGE (&before);
thread->real = before.real;
thread_current = thread;
(*thread->func) (thread);
thread_current = NULL;
GETRUSAGE (&after);

View File

@ -265,4 +265,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 */