summaryrefslogtreecommitdiff
path: root/src/log.c
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2010-08-17 17:10:46 +0200
committerSamuel Ortiz <sameo@linux.intel.com>2010-08-17 17:11:49 +0200
commitff4679178975cede4a4173bcf03447f1c0058d73 (patch)
treed99d039631a372b50cdc6f797a3dd4e6369511f1 /src/log.c
parent5f06e7b159df42ceafafe9a7266148f658a91fad (diff)
downloadconnman-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.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/log.c b/src/log.c
index 327731f2..4dee0031 100644
--- a/src/log.c
+++ b/src/log.c
@@ -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);
}