X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Flog.c;h=7d1896c4a82a79a9cf3d94dfa2e6799aac01d262;hb=6c8213f23b60fb46e6cd2572a6adc7ce4da13691;hp=33d2bf507c3eff3252afbddbb8ea1e609ec42e89;hpb=9911ffd65ccd2d2cacfa1bf55ac70e3c1ec00a67;p=framework%2Fconnectivity%2Fconnman.git diff --git a/src/log.c b/src/log.c index 33d2bf5..7d1896c 100644 --- a/src/log.c +++ b/src/log.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2009 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -23,12 +23,20 @@ #include #endif +#define _GNU_SOURCE +#include +#include #include +#include +#include #include +#include +#include #include "connman.h" -static volatile gboolean debug_enabled = FALSE; +static const char *program_exec; +static const char *program_path; /** * connman_info: @@ -49,6 +57,24 @@ void connman_info(const char *format, ...) } /** + * connman_warn: + * @format: format string + * @Varargs: list of arguments + * + * Output warning messages + */ +void connman_warn(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + + vsyslog(LOG_WARNING, format, ap); + + va_end(ap); +} + +/** * connman_error: * @format: format string * @varargs: list of arguments @@ -72,17 +98,11 @@ void connman_error(const char *format, ...) * @varargs: list of arguments * * Output debug message - * - * The actual output of the debug message is controlled via a command line - * switch. If not enabled, these messages will be ignored. */ void connman_debug(const char *format, ...) { va_list ap; - if (debug_enabled == FALSE) - return; - va_start(ap, format); vsyslog(LOG_DEBUG, format, ap); @@ -90,18 +110,209 @@ void connman_debug(const char *format, ...) va_end(ap); } -int __connman_log_init(gboolean detach, gboolean debug) +static void print_backtrace(unsigned int offset) +{ + void *frames[99]; + size_t n_ptrs; + unsigned int i; + int outfd[2], infd[2]; + int pathlen; + pid_t pid; + + if (program_exec == NULL) + return; + + pathlen = strlen(program_path); + + n_ptrs = backtrace(frames, G_N_ELEMENTS(frames)); + if (n_ptrs < offset) + return; + + if (pipe(outfd) < 0) + return; + + if (pipe(infd) < 0) { + close(outfd[0]); + close(outfd[1]); + return; + } + + pid = fork(); + if (pid < 0) { + close(outfd[0]); + close(outfd[1]); + close(infd[0]); + close(infd[1]); + return; + } + + if (pid == 0) { + close(outfd[1]); + close(infd[0]); + + dup2(outfd[0], STDIN_FILENO); + dup2(infd[1], STDOUT_FILENO); + + execlp("addr2line", "-C", "-f", "-e", program_exec, NULL); + + exit(EXIT_FAILURE); + } + + close(outfd[0]); + close(infd[1]); + + connman_error("++++++++ backtrace ++++++++"); + + for (i = offset; i < n_ptrs - 1; i++) { + Dl_info info; + char addr[20], buf[PATH_MAX * 2]; + int len, written; + char *ptr, *pos; + + dladdr(frames[i], &info); + + len = snprintf(addr, sizeof(addr), "%p\n", frames[i]); + if (len < 0) + break; + + written = write(outfd[1], addr, len); + if (written < 0) + break; + + len = read(infd[0], buf, sizeof(buf)); + if (len < 0) + break; + + buf[len] = '\0'; + + pos = strchr(buf, '\n'); + *pos++ = '\0'; + + if (strcmp(buf, "??") == 0) { + connman_error("#%-2u %p in %s", i - offset, + frames[i], info.dli_fname); + continue; + } + + ptr = strchr(pos, '\n'); + *ptr++ = '\0'; + + if (strncmp(pos, program_path, pathlen) == 0) + pos += pathlen + 1; + + connman_error("#%-2u %p in %s() at %s", i - offset, + frames[i], buf, pos); + } + + connman_error("+++++++++++++++++++++++++++"); + + kill(pid, SIGTERM); + + close(outfd[1]); + close(infd[0]); +} + +static void signal_handler(int signo) +{ + connman_error("Aborting (signal %d) [%s]", signo, program_exec); + + print_backtrace(2); + + exit(EXIT_FAILURE); +} + +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); +} + +extern struct connman_debug_desc __start___debug[]; +extern struct connman_debug_desc __stop___debug[]; + +static gchar **enabled = NULL; + +static connman_bool_t is_enabled(struct connman_debug_desc *desc) +{ + int i; + + if (enabled == NULL) + return FALSE; + + for (i = 0; enabled[i] != NULL; i++) { + if (desc->name != NULL && g_pattern_match_simple(enabled[i], + desc->name) == TRUE) + return TRUE; + if (desc->file != NULL && g_pattern_match_simple(enabled[i], + desc->file) == TRUE) + return TRUE; + } + + return FALSE; +} + +void __connman_log_enable(struct connman_debug_desc *start, + struct connman_debug_desc *stop) { + struct connman_debug_desc *desc; + const char *name = NULL, *file = NULL; + + if (start == NULL || stop == NULL) + return; + + for (desc = start; desc < stop; desc++) { + if (desc->flags & CONNMAN_DEBUG_FLAG_ALIAS) { + file = desc->file; + name = desc->name; + continue; + } + + if (file != NULL || name != NULL) { + if (g_strcmp0(desc->file, file) == 0) { + if (desc->name == NULL) + desc->name = name; + } else + file = NULL; + } + + if (is_enabled(desc) == TRUE) + desc->flags |= CONNMAN_DEBUG_FLAG_PRINT; + } +} + +int __connman_log_init(const char *program, const char *debug, + connman_bool_t detach) +{ + static char path[PATH_MAX]; int option = LOG_NDELAY | LOG_PID; + program_exec = program; + program_path = getcwd(path, sizeof(path)); + + if (debug != NULL) + enabled = g_strsplit_set(debug, ":, ", 0); + + __connman_log_enable(__start___debug, __stop___debug); + if (detach == FALSE) option |= LOG_PERROR; - openlog("connmand", option, LOG_DAEMON); + signal_setup(signal_handler); - syslog(LOG_INFO, "Connection Manager version %s", VERSION); + openlog(basename(program), option, LOG_DAEMON); - debug_enabled = debug; + syslog(LOG_INFO, "Connection Manager version %s", VERSION); return 0; } @@ -111,9 +322,8 @@ void __connman_log_cleanup(void) syslog(LOG_INFO, "Exit"); closelog(); -} -gboolean __connman_debug_enabled(void) -{ - return debug_enabled; + signal_setup(SIG_DFL); + + g_strfreev(enabled); }