leak-detective: Optionally write report to a log file

This commit is contained in:
Tobias Brunner
2016-09-20 15:36:09 +02:00
parent d344474b3d
commit 4f1c6bc5a6
+36 -10
View File
@@ -55,6 +55,13 @@ struct private_library_t {
*/ */
bool integrity_failed; bool integrity_failed;
#ifdef LEAK_DETECTIVE
/**
* Where to write leak detective output to
*/
FILE *ld_out;
#endif
/** /**
* Number of times we have been initialized * Number of times we have been initialized
*/ */
@@ -95,32 +102,34 @@ library_t *lib = NULL;
/** /**
* Default leak report callback * Default leak report callback
*/ */
static void report_leaks(void *user, int count, size_t bytes, CALLBACK(report_leaks, void,
backtrace_t *bt, bool detailed) 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); bytes, count, bytes / count);
bt->log(bt, stderr, detailed); bt->log(bt, this->ld_out, detailed);
} }
/** /**
* Default leak report summary callback * 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) switch (count)
{ {
case 0: case 0:
fprintf(stderr, "No leaks detected"); fprintf(this->ld_out, "No leaks detected");
break; break;
case 1: case 1:
fprintf(stderr, "One leak detected"); fprintf(this->ld_out, "One leak detected");
break; break;
default: default:
fprintf(stderr, "%d leaks detected, %zu bytes", count, bytes); fprintf(this->ld_out, "%d leaks detected, %zu bytes", count, bytes);
break; break;
} }
fprintf(stderr, ", %d suppressed by whitelist\n", whitelisted); fprintf(this->ld_out, ", %d suppressed by whitelist\n", whitelisted);
} }
#endif /* LEAK_DETECTIVE */ #endif /* LEAK_DETECTIVE */
@@ -166,12 +175,18 @@ void library_deinit()
this->public.integrity->destroy(this->public.integrity); this->public.integrity->destroy(this->public.integrity);
} }
#ifdef LEAK_DETECTIVE
if (lib->leak_detective) if (lib->leak_detective)
{ {
lib->leak_detective->report(lib->leak_detective, detailed); lib->leak_detective->report(lib->leak_detective, detailed);
lib->leak_detective->destroy(lib->leak_detective); lib->leak_detective->destroy(lib->leak_detective);
lib->leak_detective = NULL; lib->leak_detective = NULL;
} }
if (this->ld_out && this->ld_out != stderr)
{
fclose(this->ld_out);
}
#endif /* LEAK_DETECTIVE */
backtrace_deinit(); backtrace_deinit();
arrays_deinit(); arrays_deinit();
@@ -301,11 +316,22 @@ bool library_init(char *settings, const char *namespace)
backtrace_init(); backtrace_init();
#ifdef LEAK_DETECTIVE #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(); lib->leak_detective = leak_detective_create();
if (lib->leak_detective) if (lib->leak_detective)
{ {
lib->leak_detective->set_report_cb(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 */ #endif /* LEAK_DETECTIVE */