summaryrefslogtreecommitdiff
path: root/src/libstrongswan/utils/leak_detective.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/utils/leak_detective.c')
-rw-r--r--src/libstrongswan/utils/leak_detective.c112
1 files changed, 71 insertions, 41 deletions
diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c
index 725e04f7c..82eadcb97 100644
--- a/src/libstrongswan/utils/leak_detective.c
+++ b/src/libstrongswan/utils/leak_detective.c
@@ -59,6 +59,21 @@ struct private_leak_detective_t {
* public functions
*/
leak_detective_t public;
+
+ /**
+ * Registered report() function
+ */
+ leak_detective_report_cb_t report_cb;
+
+ /**
+ * Registered report() summary function
+ */
+ leak_detective_summary_cb_t report_scb;
+
+ /**
+ * Registered user data for callbacks
+ */
+ void *report_data;
};
/**
@@ -318,9 +333,16 @@ HOOK(size_t, size, const void *ptr)
*/
static bool register_hooks()
{
+ static bool once = FALSE;
malloc_zone_t *zone;
void *page;
+ if (once)
+ {
+ return TRUE;
+ }
+ once = TRUE;
+
zone = malloc_default_zone();
if (zone->version != MALLOC_ZONE_VERSION)
{
@@ -461,7 +483,7 @@ static void* real_realloc(void *ptr, size_t size)
static bool register_hooks()
{
void *buf = real_malloc(8);
- real_realloc(buf, 16);
+ buf = real_realloc(buf, 16);
real_free(buf);
return TRUE;
}
@@ -477,7 +499,7 @@ static bool register_hooks()
char *whitelist[] = {
/* backtraces, including own */
"backtrace_create",
- "safe_strerror",
+ "strerror_safe",
/* pthread stuff */
"pthread_create",
"pthread_setspecific",
@@ -565,7 +587,12 @@ char *whitelist[] = {
*/
static void init_static_allocations()
{
+ struct tm tm;
+ time_t t = 0;
+
tzset();
+ gmtime_r(&t, &tm);
+ localtime_r(&t, &tm);
}
/**
@@ -599,7 +626,8 @@ static bool equals(backtrace_t *a, backtrace_t *b)
* Summarize and print backtraces
*/
static int print_traces(private_leak_detective_t *this,
- FILE *out, int thresh, int thresh_count,
+ leak_detective_report_cb_t cb, void *user,
+ int thresh, int thresh_count,
bool detailed, int *whitelisted, size_t *sum)
{
int leaks = 0;
@@ -652,16 +680,20 @@ static int print_traces(private_leak_detective_t *this,
leaks++;
}
lock->unlock(lock);
+
enumerator = entries->create_enumerator(entries);
while (enumerator->enumerate(enumerator, NULL, &entry))
{
- if (out &&
- (!thresh || entry->bytes >= thresh) &&
- (!thresh_count || entry->count >= thresh_count))
+ if (cb)
{
- fprintf(out, "%d bytes total, %d allocations, %d bytes average:\n",
- entry->bytes, entry->count, entry->bytes / entry->count);
- entry->backtrace->log(entry->backtrace, out, detailed);
+ if (!thresh || entry->bytes >= thresh)
+ {
+ if (!thresh_count || entry->count >= thresh_count)
+ {
+ this->report_cb(this->report_data, entry->count,
+ entry->bytes, entry->backtrace, detailed);
+ }
+ }
}
entry->backtrace->destroy(entry->backtrace);
free(entry);
@@ -681,38 +713,30 @@ METHOD(leak_detective_t, report, void,
int leaks, whitelisted = 0;
size_t sum = 0;
- leaks = print_traces(this, stderr, 0, 0, detailed, &whitelisted, &sum);
- switch (leaks)
+ leaks = print_traces(this, this->report_cb, this->report_data,
+ 0, 0, detailed, &whitelisted, &sum);
+ if (this->report_scb)
{
- case 0:
- fprintf(stderr, "No leaks detected");
- break;
- case 1:
- fprintf(stderr, "One leak detected");
- break;
- default:
- fprintf(stderr, "%d leaks detected, %zu bytes", leaks, sum);
- break;
+ this->report_scb(this->report_data, leaks, sum, whitelisted);
}
- fprintf(stderr, ", %d suppressed by whitelist\n", whitelisted);
- }
- else
- {
- fprintf(stderr, "Leak detective disabled\n");
}
}
+METHOD(leak_detective_t, set_report_cb, void,
+ private_leak_detective_t *this, leak_detective_report_cb_t cb,
+ leak_detective_summary_cb_t scb, void *user)
+{
+ this->report_cb = cb;
+ this->report_scb = scb;
+ this->report_data = user;
+}
+
METHOD(leak_detective_t, leaks, int,
private_leak_detective_t *this)
{
- if (lib->leak_detective)
- {
- int leaks, whitelisted = 0;
+ int whitelisted = 0;
- leaks = print_traces(this, NULL, 0, 0, FALSE, &whitelisted, NULL);
- return leaks;
- }
- return 0;
+ return print_traces(this, NULL, NULL, 0, 0, FALSE, &whitelisted, NULL);
}
METHOD(leak_detective_t, set_state, bool,
@@ -722,22 +746,26 @@ METHOD(leak_detective_t, set_state, bool,
}
METHOD(leak_detective_t, usage, void,
- private_leak_detective_t *this, FILE *out)
+ private_leak_detective_t *this, leak_detective_report_cb_t cb,
+ leak_detective_summary_cb_t scb, void *user)
{
bool detailed;
- int thresh, thresh_count;
+ int thresh, thresh_count, leaks, whitelisted = 0;
size_t sum = 0;
thresh = lib->settings->get_int(lib->settings,
- "libstrongswan.leak_detective.usage_threshold", 10240);
+ "%s.leak_detective.usage_threshold", 10240, lib->ns);
thresh_count = lib->settings->get_int(lib->settings,
- "libstrongswan.leak_detective.usage_threshold_count", 0);
+ "%s.leak_detective.usage_threshold_count", 0, lib->ns);
detailed = lib->settings->get_bool(lib->settings,
- "libstrongswan.leak_detective.detailed", TRUE);
+ "%s.leak_detective.detailed", TRUE, lib->ns);
- print_traces(this, out, thresh, thresh_count, detailed, NULL, &sum);
-
- fprintf(out, "Total memory usage: %zu\n", sum);
+ leaks = print_traces(this, cb, user, thresh, thresh_count,
+ detailed, &whitelisted, &sum);
+ if (scb)
+ {
+ scb(user, leaks, sum, whitelisted);
+ }
}
/**
@@ -924,6 +952,7 @@ METHOD(leak_detective_t, destroy, void,
lock->destroy(lock);
thread_disabled->destroy(thread_disabled);
free(this);
+ first_header.next = NULL;
}
/*
@@ -936,8 +965,9 @@ leak_detective_t *leak_detective_create()
INIT(this,
.public = {
.report = _report,
- .leaks = _leaks,
+ .set_report_cb = _set_report_cb,
.usage = _usage,
+ .leaks = _leaks,
.set_state = _set_state,
.destroy = _destroy,
},