leak-detective: Optionally write report to a log file
authorTobias Brunner <tobias@strongswan.org>
Tue, 13 Sep 2016 08:06:28 +0000 (10:06 +0200)
committerTobias Brunner <tobias@strongswan.org>
Tue, 20 Sep 2016 13:36:09 +0000 (15:36 +0200)
src/libstrongswan/library.c

index e130b93..f694509 100644 (file)
@@ -55,6 +55,13 @@ struct private_library_t {
         */
        bool integrity_failed;
 
+#ifdef LEAK_DETECTIVE
+       /**
+        * Where to write leak detective output to
+        */
+       FILE *ld_out;
+#endif
+
        /**
         * Number of times we have been initialized
         */
@@ -95,32 +102,34 @@ library_t *lib = NULL;
 /**
  * Default leak report callback
  */
-static void report_leaks(void *user, int count, size_t bytes,
-                                                backtrace_t *bt, bool detailed)
+CALLBACK(report_leaks, void,
+       private_library_t *this, int count, size_t bytes, backtrace_t *bt,
+       bool detailed)
 {
-       fprintf(stderr, "%zu bytes total, %d allocations, %zu bytes average:\n",
+       fprintf(this->ld_out, "%zu bytes total, %d allocations, %zu bytes average:\n",
                        bytes, count, bytes / count);
-       bt->log(bt, stderr, detailed);
+       bt->log(bt, this->ld_out, detailed);
 }
 
 /**
  * Default leak report summary callback
  */
-static void sum_leaks(void* user, int count, size_t bytes, int whitelisted)
+CALLBACK(sum_leaks, void,
+       private_library_t *this, int count, size_t bytes, int whitelisted)
 {
        switch (count)
        {
                case 0:
-                       fprintf(stderr, "No leaks detected");
+                       fprintf(this->ld_out, "No leaks detected");
                        break;
                case 1:
-                       fprintf(stderr, "One leak detected");
+                       fprintf(this->ld_out, "One leak detected");
                        break;
                default:
-                       fprintf(stderr, "%d leaks detected, %zu bytes", count, bytes);
+                       fprintf(this->ld_out, "%d leaks detected, %zu bytes", count, bytes);
                        break;
        }
-       fprintf(stderr, ", %d suppressed by whitelist\n", whitelisted);
+       fprintf(this->ld_out, ", %d suppressed by whitelist\n", whitelisted);
 }
 #endif /* LEAK_DETECTIVE */
 
@@ -166,12 +175,18 @@ void library_deinit()
                this->public.integrity->destroy(this->public.integrity);
        }
 
+#ifdef LEAK_DETECTIVE
        if (lib->leak_detective)
        {
                lib->leak_detective->report(lib->leak_detective, detailed);
                lib->leak_detective->destroy(lib->leak_detective);
                lib->leak_detective = NULL;
        }
+       if (this->ld_out && this->ld_out != stderr)
+       {
+               fclose(this->ld_out);
+       }
+#endif /* LEAK_DETECTIVE */
 
        backtrace_deinit();
        arrays_deinit();
@@ -301,11 +316,22 @@ bool library_init(char *settings, const char *namespace)
        backtrace_init();
 
 #ifdef LEAK_DETECTIVE
+       {
+               FILE *out = NULL;
+               char *log;
+
+               log = getenv("LEAK_DETECTIVE_LOG");
+               if (log)
+               {
+                       out = fopen(log, "a");
+               }
+               this->ld_out = out ?: stderr;
+       }
        lib->leak_detective = leak_detective_create();
        if (lib->leak_detective)
        {
                lib->leak_detective->set_report_cb(lib->leak_detective,
-                                                                                  report_leaks, sum_leaks, NULL);
+                                                                                  report_leaks, sum_leaks, this);
        }
 #endif /* LEAK_DETECTIVE */