Browse Source

memleak: allow marking of entire tal trees to be noleak.

In particular, the pay command attaches all kinds of stuff to the
struct command; they're not really a leak, since commands expire.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
committed by Christian Decker
parent
commit
20fcb5d6ef
  1. 38
      common/memleak.c
  2. 7
      common/memleak.h

38
common/memleak.c

@ -9,6 +9,7 @@
#if DEVELOPER
static struct backtrace_state *backtrace_state;
static const void **notleaks;
static bool *notleak_children;
static size_t find_notleak(const tal_t *ptr)
{
@ -30,14 +31,18 @@ static void notleak_change(tal_t *ctx,
i = find_notleak(ctx);
memmove(notleaks + i, notleaks + i + 1,
sizeof(*notleaks) * (tal_count(notleaks) - i - 1));
memmove(notleak_children + i, notleak_children + i + 1,
sizeof(*notleak_children)
* (tal_count(notleak_children) - i - 1));
tal_resize(&notleaks, tal_count(notleaks) - 1);
tal_resize(&notleak_children, tal_count(notleak_children) - 1);
} else if (type == TAL_NOTIFY_MOVE) {
i = find_notleak(info);
notleaks[i] = ctx;
}
}
void *notleak_(const void *ptr)
void *notleak_(const void *ptr, bool plus_children)
{
size_t nleaks;
@ -47,7 +52,9 @@ void *notleak_(const void *ptr)
nleaks = tal_count(notleaks);
tal_resize(&notleaks, nleaks+1);
tal_resize(&notleak_children, nleaks+1);
notleaks[nleaks] = ptr;
notleak_children[nleaks] = plus_children;
tal_add_notifier(ptr, TAL_NOTIFY_FREE|TAL_NOTIFY_MOVE, notleak_change);
return cast_const(void *, ptr);
@ -130,23 +137,33 @@ void memleak_scan_region(struct htable *memtable, const void *ptr)
scan_for_pointers(memtable, ptr);
}
static void remove_with_children(struct htable *memtable, const tal_t *p)
{
const tal_t *i;
pointer_referenced(memtable, p);
for (i = tal_first(p); i; i = tal_next(i))
remove_with_children(memtable, i);
}
void memleak_remove_referenced(struct htable *memtable, const void *root)
{
size_t i;
/* Now delete the ones which are referenced. */
memleak_scan_region(memtable, root);
memleak_scan_region(memtable, notleaks);
/* Remove memtable itself */
pointer_referenced(memtable, memtable);
}
/* Those who asked tal children to be removed, do so. */
for (i = 0; i < tal_count(notleaks); i++)
if (notleak_children[i])
remove_with_children(memtable, notleaks[i]);
static void remove_with_children(struct htable *memtable, const tal_t *p)
{
const tal_t *i;
/* notleak_children array is not a leak */
pointer_referenced(memtable, notleak_children);
pointer_referenced(memtable, p);
for (i = tal_first(p); i; i = tal_next(i))
remove_with_children(memtable, i);
/* Remove memtable itself */
pointer_referenced(memtable, memtable);
}
static bool ptr_match(const void *candidate, void *ptr)
@ -214,6 +231,7 @@ void memleak_init(const tal_t *root, struct backtrace_state *bstate)
assert(!notleaks);
backtrace_state = bstate;
notleaks = tal_arr(NULL, const void *, 0);
notleak_children = tal_arr(notleaks, bool, 0);
if (backtrace_state)
tal_add_notifier(root, TAL_NOTIFY_ADD_CHILD, add_backtrace);

7
common/memleak.h

@ -11,10 +11,13 @@
#endif /* !HAVE_TYPEOF */
/* Mark a pointer as not being leaked. */
#define notleak(p) ((memleak_typeof(p))notleak_(p))
#define notleak(p) ((memleak_typeof(p))notleak_((p), false))
/* Mark a pointer and all its tal children as not being leaked. */
#define notleak_with_children(p) ((memleak_typeof(p))notleak_((p), true))
#if DEVELOPER
void *notleak_(const void *ptr);
void *notleak_(const void *ptr, bool plus_children);
struct htable;
struct backtrace_state;

Loading…
Cancel
Save