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

7
common/memleak.h

@ -11,10 +11,13 @@
#endif /* !HAVE_TYPEOF */ #endif /* !HAVE_TYPEOF */
/* Mark a pointer as not being leaked. */ /* 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 #if DEVELOPER
void *notleak_(const void *ptr); void *notleak_(const void *ptr, bool plus_children);
struct htable; struct htable;
struct backtrace_state; struct backtrace_state;

Loading…
Cancel
Save