osaf/libs/core/common/daemon.c | 117 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 117 insertions(+), 0 deletions(-)
Use dlsym on bactrace symbols to circumvent lsb compliance problems. diff --git a/osaf/libs/core/common/daemon.c b/osaf/libs/core/common/daemon.c --- a/osaf/libs/core/common/daemon.c +++ b/osaf/libs/core/common/daemon.c @@ -34,6 +34,8 @@ #include <sys/stat.h> #include <sys/file.h> +#include <dlfcn.h> + #include <configmake.h> #include "daemon.h" @@ -43,6 +45,8 @@ #include <os_defs.h> #include <osaf_secutil.h> +#include <sys/types.h> +#include <time.h> #define DEFAULT_RUNAS_USERNAME "opensaf" @@ -57,6 +61,8 @@ static unsigned int __tracemask; static unsigned int __nofork = 0; static int __logmask; +static void install_fatal_signal_handlers(); + static void __print_usage(const char* progname, FILE* stream, int exit_code) { fprintf(stream, "Usage: %s [OPTIONS]...\n", progname); @@ -350,6 +356,9 @@ void daemonize(int argc, char *argv[]) } #endif + /* install fatal signal handlers for writing backtrace to file */ + install_fatal_signal_handlers(); + /* Initialize the log/trace interface */ if (logtrace_init_daemon(basename(argv[0]), __tracefile, __tracemask, __logmask) != 0) exit(EXIT_FAILURE); @@ -414,3 +423,111 @@ void daemon_sigterm_install(int *term_fd *term_fd = term_sel_obj.rmv_obj; } + +static char bt_filename[80]; + +static int (*plibc_backtrace) (void **buffer, int size) = NULL; +static int (*plibc_backtrace_symbols_fd) (void *const *buffer, int size, int fd) = NULL; + +static int init_backtrace_fptrs() +{ + plibc_backtrace = dlsym(RTLD_NEXT, "backtrace"); + if (plibc_backtrace == NULL) { + syslog(LOG_ERR, "unable to find \"backrace\" symbol"); + return -1; + } + plibc_backtrace_symbols_fd = dlsym(RTLD_NEXT, "backtrace_symbols_fd"); + if (plibc_backtrace_symbols_fd == NULL) { + syslog(LOG_ERR, "unable to find \"backrace_symbols_fd\" symbol"); + return -1; + } + return 0; +} + +/** + * Signal handler for fatal errors. Writes a backtrace and "re-throws" the signal. + */ +static void fatal_signal_handler(int sig, siginfo_t* siginfo, void* ctx) +{ + const int BT_ARRAY_SIZE = 20; + void *bt_array[BT_ARRAY_SIZE]; + size_t bt_size; + int fd; + char bt_header[30]; + + if ((fd = open(bt_filename, O_RDWR|O_CREAT, 0644)) < 0) { + goto done; + } + + snprintf(bt_header, sizeof(bt_header), "signal: %d\n", sig); + + if (write(fd, bt_header, strlen(bt_header)) < 0) { + close(fd); + goto done; + } + + bt_size = plibc_backtrace(bt_array, BT_ARRAY_SIZE); + plibc_backtrace_symbols_fd(bt_array, bt_size, fd); + + close(fd); +done: + // re-throw the signal + raise(sig); +} + +/** + * Install signal handlers for fatal errors to be able to print a backtrace. + */ +static void install_fatal_signal_handlers() +{ + + time_t current_time; + char time_string[20]; + + struct sigaction action; + int i = 0; + const int HANDLED_SIGNALS_MAX = 7; + static const int handled_signals[] = { + SIGHUP, + SIGILL, + SIGABRT, + SIGFPE, + SIGSEGV, + SIGPIPE, + SIGBUS + }; + + // to circumvent lsb use dlsym to retrieve backtrace in runtime + if (init_backtrace_fptrs() < 0) { + syslog(LOG_WARNING, "backtrace symbols not found, no fatal signal handlers will be installed"); + } + else { + + // prepare a filename for backtrace + time_string[0] = '\0'; + + if (time(¤t_time) < 0) { + syslog(LOG_WARNING, "time failed: %s", strerror(errno)); + } + else { + if (strftime(time_string, sizeof(time_string), "%Y%m%d_%T", localtime(¤t_time)) == 0) { + syslog(LOG_WARNING, "strftime failed"); + } + } + + snprintf(bt_filename, sizeof(bt_filename), PKGLOGDIR "/bt_%s_%d", time_string, getpid()); + + memset(&action, 0, sizeof(action)); + action.sa_sigaction = fatal_signal_handler; + sigfillset(&action.sa_mask); + action.sa_flags = SA_RESETHAND | SA_SIGINFO; + + for (i = 0; i < HANDLED_SIGNALS_MAX; ++i) + { + if (sigaction(handled_signals[i], &action, NULL) < 0) + { + syslog(LOG_WARNING, "sigaction %d failed: %s", handled_signals[i], strerror(errno)); + } + } + } +} ------------------------------------------------------------------------------ Dive into the World of Parallel Programming The Go Parallel Website, sponsored by Intel and developed in partnership with Slashdot Media, is your hub for all things parallel software development, from weekly thought leadership blogs to news, videos, case studies, tutorials and more. Take a look and join the conversation now. http://goparallel.sourceforge.net/ _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel