diff options
author | Samuel Ortiz <sameo@linux.intel.com> | 2010-08-17 17:10:46 +0200 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2010-08-17 17:11:49 +0200 |
commit | ff4679178975cede4a4173bcf03447f1c0058d73 (patch) | |
tree | d99d039631a372b50cdc6f797a3dd4e6369511f1 /src/log.c | |
parent | 5f06e7b159df42ceafafe9a7266148f658a91fad (diff) | |
download | connman-ff4679178975cede4a4173bcf03447f1c0058d73.tar.gz connman-ff4679178975cede4a4173bcf03447f1c0058d73.tar.bz2 connman-ff4679178975cede4a4173bcf03447f1c0058d73.zip |
ConnMan backtrace support
Add a generic signal handler in order to dump ConnMan backtrace when
crashing. The implementation is based on glibc backtrace() routines and
thus can not resolve static function names. A little python wrapper over
addr2line fixes that by taking a full backtrace from a complete connman
log file.
Diffstat (limited to 'src/log.c')
-rw-r--r-- | src/log.c | 51 |
1 files changed, 51 insertions, 0 deletions
@@ -23,8 +23,12 @@ #include <config.h> #endif +#define _GNU_SOURCE #include <stdarg.h> #include <syslog.h> +#include <execinfo.h> +#include <dlfcn.h> +#include <stdlib.h> #include "connman.h" @@ -148,6 +152,49 @@ static connman_bool_t is_enabled(struct connman_debug_desc *desc) return FALSE; } +static void signal_handler(int signo) +{ + void *frames[64]; + char **symbols; + size_t n_ptrs; + unsigned int i; + + n_ptrs = backtrace(frames, G_N_ELEMENTS(frames)); + symbols = backtrace_symbols(frames, n_ptrs); + if (symbols == NULL) { + connman_error("No backtrace symbols"); + exit(1); + } + + connman_error("Aborting (signal %d)", signo); + connman_error("++++++++ ConnMan backtrace ++++++++"); + + for (i = 1; i < n_ptrs; i++) + connman_error("[%d]: %s", i - 1, symbols[i]); + + connman_error("++++++++++++++++++++++++++++++++++++"); + + g_free(symbols); + exit(1); +} + +static void signal_setup(sighandler_t handler) +{ + struct sigaction sa; + sigset_t mask; + + sigemptyset(&mask); + sa.sa_handler = handler; + sa.sa_mask = mask; + sa.sa_flags = 0; + sigaction(SIGBUS, &sa, NULL); + sigaction(SIGILL, &sa, NULL); + sigaction(SIGFPE, &sa, NULL); + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGABRT, &sa, NULL); + sigaction(SIGPIPE, &sa, NULL); +} + int __connman_log_init(const char *debug, connman_bool_t detach) { int option = LOG_NDELAY | LOG_PID; @@ -179,6 +226,8 @@ int __connman_log_init(const char *debug, connman_bool_t detach) if (detach == FALSE) option |= LOG_PERROR; + signal_setup(signal_handler); + openlog("connmand", option, LOG_DAEMON); syslog(LOG_INFO, "Connection Manager version %s", VERSION); @@ -193,4 +242,6 @@ void __connman_log_cleanup(void) closelog(); g_strfreev(enabled); + + signal_setup(SIG_DFL); } |