leak-detective: Use hashtable to cache ignored/whitelisted backtraces

Checking for whitelisted functions in every backtrace is not very
efficient.  And because OpenSSL 1.1 does no proper cleanup anymore until
the process is terminated there are now a lot more "leaks" to ignore.
For instance, in the openssl-ikev2/rw-cert scenario, just starting and
stopping the daemon (test vectors are checked) now causes 3594 whitelisted
leaks compared to the 849 before.  This prolonged the shutdown of the
daemon on each guest in every scenario, amounting to multiple seconds of
additional runtime for every affected scenario.  But even with this
patch there is still some overhead, compared to running the scenarios on
jessie.
This commit is contained in:
Tobias Brunner 2018-10-05 11:23:36 +02:00
parent 0f7055b22c
commit 8eea28063d
1 changed files with 25 additions and 6 deletions

View File

@ -679,7 +679,8 @@ static int print_traces(private_leak_detective_t *this,
int leaks = 0;
memory_header_t *hdr;
enumerator_t *enumerator;
hashtable_t *entries;
hashtable_t *entries, *ignored = NULL;
backtrace_t *bt;
struct {
/** associated backtrace */
backtrace_t *backtrace;
@ -694,15 +695,32 @@ static int print_traces(private_leak_detective_t *this,
entries = hashtable_create((hashtable_hash_t)hash,
(hashtable_equals_t)equals, 1024);
if (whitelisted)
{
ignored = hashtable_create((hashtable_hash_t)hash,
(hashtable_equals_t)equals, 1024);
}
lock->lock(lock);
for (hdr = first_header.next; hdr != NULL; hdr = hdr->next)
{
if (whitelisted &&
hdr->backtrace->contains_function(hdr->backtrace,
whitelist, countof(whitelist)))
if (whitelisted)
{
(*whitelisted)++;
continue;
bt = ignored->get(ignored, hdr->backtrace);
if (!bt)
{
if (hdr->backtrace->contains_function(hdr->backtrace, whitelist,
countof(whitelist)))
{
bt = hdr->backtrace;
ignored->put(ignored, bt, bt);
}
}
if (bt)
{
(*whitelisted)++;
continue;
}
}
entry = entries->get(entries, hdr->backtrace);
if (entry)
@ -726,6 +744,7 @@ static int print_traces(private_leak_detective_t *this,
leaks++;
}
lock->unlock(lock);
DESTROY_IF(ignored);
enumerator = entries->create_enumerator(entries);
while (enumerator->enumerate(enumerator, NULL, &entry))