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(&current_time) < 0) {
+                       syslog(LOG_WARNING, "time failed: %s", strerror(errno));
+               }
+               else {
+                       if (strftime(time_string, sizeof(time_string), 
"%Y%m%d_%T", localtime(&current_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

Reply via email to