Option to skip slow addr2line resolution in leak-detective
authorMartin Willi <martin@revosec.ch>
Wed, 19 May 2010 13:22:12 +0000 (15:22 +0200)
committerMartin Willi <martin@revosec.ch>
Thu, 20 May 2010 15:37:18 +0000 (17:37 +0200)
src/charon/charon.c
src/libstrongswan/library.c
src/libstrongswan/threading/lock_profiler.h
src/libstrongswan/utils/backtrace.c
src/libstrongswan/utils/backtrace.h
src/libstrongswan/utils/leak_detective.c
src/libstrongswan/utils/leak_detective.h

index 35be630..3386688 100644 (file)
@@ -190,7 +190,7 @@ static void segv_handler(int signal)
 
        DBG1(DBG_DMN, "thread %u received %d", thread_current_id(), signal);
        backtrace = backtrace_create(2);
-       backtrace->log(backtrace, stderr);
+       backtrace->log(backtrace, stderr, TRUE);
        backtrace->destroy(backtrace);
 
        DBG1(DBG_DMN, "killing ourself, received critical signal");
index 108ac2c..8166d24 100644 (file)
@@ -59,6 +59,10 @@ library_t *lib;
 void library_deinit()
 {
        private_library_t *this = (private_library_t*)lib;
+       bool detailed;
+
+       detailed = lib->settings->get_bool(lib->settings,
+                                                               "libstrongswan.leak_detective.detailed", TRUE);
 
        this->public.plugins->destroy(this->public.plugins);
        this->public.settings->destroy(this->public.settings);
@@ -76,6 +80,7 @@ void library_deinit()
 #ifdef LEAK_DETECTIVE
        if (this->detective)
        {
+               this->detective->report(this->detective, detailed);
                this->detective->destroy(this->detective);
        }
 #endif /* LEAK_DETECTIVE */
index b64453b..1ae4964 100644 (file)
@@ -63,7 +63,7 @@ static inline void profiler_cleanup(lock_profile_t *profile)
        {
                fprintf(stderr, "%d.%03ds / %d times in lock created at:",
                        profile->waited.tv_sec, profile->waited.tv_usec, profile->locked);
-               profile->backtrace->log(profile->backtrace, stderr);
+               profile->backtrace->log(profile->backtrace, stderr, TRUE);
        }
        profile->backtrace->destroy(profile->backtrace);
 }
index 5bba8ec..a672451 100644 (file)
@@ -53,7 +53,7 @@ struct private_backtrace_t {
 /**
  * Implementation of backtrace_t.log
  */
-static void log_(private_backtrace_t *this, FILE *file)
+static void log_(private_backtrace_t *this, FILE *file, bool detailed)
 {
 #ifdef HAVE_BACKTRACE
        size_t i;
@@ -78,7 +78,6 @@ static void log_(private_backtrace_t *this, FILE *file)
                        {
                                ptr = (void*)(this->frames[i] - info.dli_fbase);
                        }
-                       snprintf(cmd, sizeof(cmd), "addr2line -e %s %p", info.dli_fname, ptr);
                        if (info.dli_sname)
                        {
                                fprintf(file, "  \e[33m%s\e[0m @ %p (\e[31m%s\e[0m+0x%x) [%p]\n",
@@ -90,28 +89,33 @@ static void log_(private_backtrace_t *this, FILE *file)
                                fprintf(file, "  \e[33m%s\e[0m @ %p [%p]\n", info.dli_fname,
                                                info.dli_fbase, this->frames[i]);
                        }
-                       fprintf(file, "    -> \e[32m");
-                       output = popen(cmd, "r");
-                       if (output)
+                       if (detailed)
                        {
-                               while (TRUE)
+                               fprintf(file, "    -> \e[32m");
+                               snprintf(cmd, sizeof(cmd), "addr2line -e %s %p",
+                                                info.dli_fname, ptr);
+                               output = popen(cmd, "r");
+                               if (output)
                                {
-                                       c = getc(output);
-                                       if (c == '\n' || c == EOF)
+                                       while (TRUE)
                                        {
-                                               break;
+                                               c = getc(output);
+                                               if (c == '\n' || c == EOF)
+                                               {
+                                                       break;
+                                               }
+                                               fputc(c, file);
                                        }
-                                       fputc(c, file);
+                                       pclose(output);
                                }
-                               pclose(output);
-                       }
-                       else
-                       {
-#endif /* HAVE_DLADDR */
-                               fprintf(file, "    %s\n", strings[i]);
-#ifdef HAVE_DLADDR
+                               else
+                               {
+       #endif /* HAVE_DLADDR */
+                                       fprintf(file, "    %s\n", strings[i]);
+       #ifdef HAVE_DLADDR
+                               }
+                               fprintf(file, "\n\e[0m");
                        }
-                       fprintf(file, "\n\e[0m");
                }
                else
                {
@@ -174,7 +178,7 @@ backtrace_t *backtrace_create(int skip)
        memcpy(this->frames, frames + skip, frame_count * sizeof(void*));
        this->frame_count = frame_count;
 
-       this->public.log = (void(*)(backtrace_t*,FILE*))log_;
+       this->public.log = (void(*)(backtrace_t*,FILE*,bool))log_;
        this->public.contains_function = (bool(*)(backtrace_t*, char *function))contains_function;
        this->public.destroy = (void(*)(backtrace_t*))destroy;
 
index c4d4284..c6b0ec7 100644 (file)
@@ -34,8 +34,11 @@ struct backtrace_t {
 
        /**
         * Log the backtrace to a FILE stream.
+        *
+        * @param file          FILE to log backtrace to
+        * @param detailed      TRUE to resolve line/file using addr2line (slow)
         */
-       void (*log)(backtrace_t *this, FILE *file);
+       void (*log)(backtrace_t *this, FILE *file, bool detailed);
 
        /**
         * Check if the backtrace contains a frame in a specific function.
index 2f8a718..74bcdc4 100644 (file)
@@ -233,39 +233,45 @@ static bool is_whitelisted(backtrace_t *backtrace)
 /**
  * Report leaks at library destruction
  */
-void report_leaks()
+static void report(private_leak_detective_t *this, bool detailed)
 {
-       memory_header_t *hdr;
-       int leaks = 0, whitelisted = 0;
-
-       for (hdr = first_header.next; hdr != NULL; hdr = hdr->next)
+       if (lib->leak_detective)
        {
-               if (is_whitelisted(hdr->backtrace))
+               memory_header_t *hdr;
+               int leaks = 0, whitelisted = 0;
+
+               for (hdr = first_header.next; hdr != NULL; hdr = hdr->next)
                {
-                       whitelisted++;
+                       if (is_whitelisted(hdr->backtrace))
+                       {
+                               whitelisted++;
+                       }
+                       else
+                       {
+                               fprintf(stderr, "Leak (%d bytes at %p):\n", hdr->bytes, hdr + 1);
+                               /* skip the first frame, contains leak detective logic */
+                               hdr->backtrace->log(hdr->backtrace, stderr, detailed);
+                               leaks++;
+                       }
                }
-               else
+               switch (leaks)
                {
-                       fprintf(stderr, "Leak (%d bytes at %p):\n", hdr->bytes, hdr + 1);
-                       /* skip the first frame, contains leak detective logic */
-                       hdr->backtrace->log(hdr->backtrace, stderr);
-                       leaks++;
+                       case 0:
+                               fprintf(stderr, "No leaks detected");
+                               break;
+                       case 1:
+                               fprintf(stderr, "One leak detected");
+                               break;
+                       default:
+                               fprintf(stderr, "%d leaks detected", leaks);
+                               break;
                }
+               fprintf(stderr, ", %d suppressed by whitelist\n", whitelisted);
        }
-
-       switch (leaks)
+       else
        {
-               case 0:
-                       fprintf(stderr, "No leaks detected");
-                       break;
-               case 1:
-                       fprintf(stderr, "One leak detected");
-                       break;
-               default:
-                       fprintf(stderr, "%d leaks detected", leaks);
-                       break;
+               fprintf(stderr, "Leak detective disabled\n");
        }
-       fprintf(stderr, ", %d suppressed by whitelist\n", whitelisted);
 }
 
 /**
@@ -395,7 +401,7 @@ void free_hook(void *ptr, const void *caller)
                        fprintf(stderr, "freeing invalid memory (%p)", ptr);
                }
                backtrace = backtrace_create(3);
-               backtrace->log(backtrace, stderr);
+               backtrace->log(backtrace, stderr, TRUE);
                backtrace->destroy(backtrace);
        }
        else
@@ -454,7 +460,7 @@ void *realloc_hook(void *old, size_t bytes, const void *caller)
                                "header magic 0x%x, tail magic 0x%x:\n",
                                old, hdr->magic, tail->magic);
                backtrace = backtrace_create(3);
-               backtrace->log(backtrace, stderr);
+               backtrace->log(backtrace, stderr, TRUE);
                backtrace->destroy(backtrace);
        }
        /* clear tail magic, allocate, set tail magic */
@@ -487,7 +493,6 @@ static void destroy(private_leak_detective_t *this)
        if (installed)
        {
                uninstall_hooks();
-               report_leaks();
        }
        free(this);
 }
@@ -499,6 +504,7 @@ leak_detective_t *leak_detective_create()
 {
        private_leak_detective_t *this = malloc_thing(private_leak_detective_t);
 
+       this->public.report = (void(*)(leak_detective_t*,bool))report;
        this->public.destroy = (void(*)(leak_detective_t*))destroy;
 
        if (getenv("LEAK_DETECTIVE_DISABLE") == NULL)
index 181f8f3..fa45a60 100644 (file)
@@ -23,6 +23,8 @@
 
 typedef struct leak_detective_t leak_detective_t;
 
+#include <library.h>
+
 /**
  * Leak detective finds leaks and bad frees using malloc hooks.
  *
@@ -34,6 +36,13 @@ typedef struct leak_detective_t leak_detective_t;
 struct leak_detective_t {
 
        /**
+        * Report leaks to stderr.
+        *
+        * @param detailed              TRUE to resolve line/filename of leak (slow)
+        */
+       void (*report)(leak_detective_t *this, bool detailed);
+
+       /**
         * Destroy a leak_detective instance.
         */
        void (*destroy)(leak_detective_t *this);