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");
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);
#ifdef LEAK_DETECTIVE
if (this->detective)
{
+ this->detective->report(this->detective, detailed);
this->detective->destroy(this->detective);
}
#endif /* LEAK_DETECTIVE */
{
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);
}
/**
* 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;
{
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",
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
{
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;
/**
* 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.
/**
* 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);
}
/**
fprintf(stderr, "freeing invalid memory (%p)", ptr);
}
backtrace = backtrace_create(3);
- backtrace->log(backtrace, stderr);
+ backtrace->log(backtrace, stderr, TRUE);
backtrace->destroy(backtrace);
}
else
"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 */
if (installed)
{
uninstall_hooks();
- report_leaks();
}
free(this);
}
{
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)
typedef struct leak_detective_t leak_detective_t;
+#include <library.h>
+
/**
* Leak detective finds leaks and bad frees using malloc hooks.
*
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);