Skip to content

Commit

Permalink
memleak: remove exclusions from memleak_start()
Browse files Browse the repository at this point in the history
Add memleak_ignore_children() so callers can do exclusions themselves.

Having two exclusions was always such a hack!

Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell committed Sep 19, 2022
1 parent 3380f55 commit 701dd3d
Show file tree
Hide file tree
Showing 14 changed files with 48 additions and 34 deletions.
3 changes: 2 additions & 1 deletion channeld/channeld.c
Original file line number Diff line number Diff line change
Expand Up @@ -3652,7 +3652,8 @@ static void handle_dev_memleak(struct peer *peer, const u8 *msg)
struct htable *memtable;
bool found_leak;

memtable = memleak_start(tmpctx, msg, msg);
memtable = memleak_start(tmpctx);
memleak_ptr(memtable, msg);

/* Now delete peer and things it has pointers to. */
memleak_scan_obj(memtable, peer);
Expand Down
2 changes: 1 addition & 1 deletion closingd/closingd.c
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ static void closing_dev_memleak(const tal_t *ctx,
u8 *scriptpubkey[NUM_SIDES],
const u8 *funding_wscript)
{
struct htable *memtable = memleak_start(tmpctx, NULL, NULL);
struct htable *memtable = memleak_start(tmpctx);

memleak_ptr(memtable, ctx);
memleak_ptr(memtable, scriptpubkey[LOCAL]);
Expand Down
19 changes: 9 additions & 10 deletions common/memleak.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,13 @@ bool memleak_ptr(struct htable *memtable, const void *p)
return htable_del(memtable, hash_ptr(p, NULL), p);
}

static void children_into_htable(const void *exclude1, const void *exclude2,
struct htable *memtable, const tal_t *p)
static void children_into_htable(struct htable *memtable, const tal_t *p)
{
const tal_t *i;

for (i = tal_first(p); i; i = tal_next(i)) {
const char *name = tal_name(i);

if (i == exclude1 || i == exclude2)
continue;

if (name) {
/* Don't add backtrace objects. */
if (streq(name, "backtrace"))
Expand All @@ -108,7 +104,7 @@ static void children_into_htable(const void *exclude1, const void *exclude2,
continue;
}
htable_add(memtable, hash_ptr(i, NULL), i);
children_into_htable(exclude1, exclude2, memtable, i);
children_into_htable(memtable, i);
}
}

Expand Down Expand Up @@ -268,6 +264,11 @@ void memleak_add_helper_(const tal_t *p,
mh->cb = cb;
}

void memleak_ignore_children(struct htable *memtable, const void *p)
{
for (const tal_t *i = tal_first(p); i; i = tal_next(i))
remove_with_children(memtable, i);
}

/* Handle allocations marked with helpers or notleak() */
static void call_memleak_helpers(struct htable *memtable, const tal_t *p)
Expand Down Expand Up @@ -297,16 +298,14 @@ static void call_memleak_helpers(struct htable *memtable, const tal_t *p)
}
}

struct htable *memleak_start(const tal_t *ctx,
const void *exclude1,
const void *exclude2)
struct htable *memleak_start(const tal_t *ctx)
{
struct htable *memtable = tal(ctx, struct htable);
htable_init(memtable, hash_ptr, NULL);

if (memleak_track) {
/* First, add all pointers off NULL to table. */
children_into_htable(exclude1, exclude2, memtable, NULL);
children_into_htable(memtable, NULL);

/* Iterate and call helpers to eliminate hard-to-get references. */
call_memleak_helpers(memtable, NULL);
Expand Down
18 changes: 11 additions & 7 deletions common/memleak.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,8 @@ void memleak_add_helper_(const tal_t *p, void (*cb)(struct htable *memtable,
/**
* memleak_start: allocate a htable with all tal objects
* @ctx: the context to allocate the htable from
* @exclude1: one tal pointer to exclude from adding (if non-NULL)
* @exclude2: second tal pointer to exclude from adding (if non-NULL)
*
* Note that exclude1 and exclude2's tal children are also not added.
*/
struct htable *memleak_start(const tal_t *ctx,
const void *exclude1,
const void *exclude2);
struct htable *memleak_start(const tal_t *ctx);

/**
* memleak_ptr: this pointer is not a memleak.
Expand Down Expand Up @@ -131,6 +125,16 @@ void memleak_scan_intmap_(struct htable *memtable, const struct intmap *m);
memleak_scan_strmap_((memtable), tcon_unwrap(strmap))
void memleak_scan_strmap_(struct htable *memtable, const struct strmap *m);

/**
* memleak_ignore_children - ignore all this tal object's children.
* @memtable: the memtable created by memleak_start
* @p: the tal pointer.
*
* This is equivalent to calling memleak_ptr() on every child of @p
* recursively. This is a big hammer, so be careful!
*/
void memleak_ignore_children(struct htable *memtable, const void *p);

/**
* memleak_get: get (and remove) a leak from memtable, or NULL
* @memtable: the memtable after all known allocations removed.
Expand Down
3 changes: 2 additions & 1 deletion connectd/connectd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1860,7 +1860,8 @@ static void dev_connect_memleak(struct daemon *daemon, const u8 *msg)
struct htable *memtable;
bool found_leak;

memtable = memleak_start(tmpctx, msg, msg);
memtable = memleak_start(tmpctx);
memleak_ptr(memtable, msg);

/* Now delete daemon and those which it has pointers to. */
memleak_scan_obj(memtable, daemon);
Expand Down
4 changes: 2 additions & 2 deletions gossipd/gossipd.c
Original file line number Diff line number Diff line change
Expand Up @@ -807,8 +807,8 @@ static void dev_gossip_memleak(struct daemon *daemon, const u8 *msg)
struct htable *memtable;
bool found_leak;

memtable = memleak_start(tmpctx, msg, msg);

memtable = memleak_start(tmpctx);
memleak_ptr(memtable, msg);
/* Now delete daemon and those which it has pointers to. */
memleak_scan_obj(memtable, daemon);

Expand Down
3 changes: 2 additions & 1 deletion hsmd/hsmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,8 @@ static struct io_plan *handle_memleak(struct io_conn *conn,
bool found_leak;
u8 *reply;

memtable = memleak_start(tmpctx, msg_in, msg_in);
memtable = memleak_start(tmpctx);
memleak_ptr(memtable, msg_in);

/* Now note clients and anything they point to. */
memleak_scan_region(memtable, dbid_zero_clients, sizeof(dbid_zero_clients));
Expand Down
6 changes: 5 additions & 1 deletion lightningd/memdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,11 @@ static void finish_report(const struct leak_detect *leaks)
ld = cmd->ld;

/* Enter everything, except this cmd and its jcon */
memtable = memleak_start(cmd, cmd, cmd->jcon);
memtable = memleak_start(cmd);

/* This command is not a leak! */
memleak_ptr(memtable, cmd);
memleak_ignore_children(memtable, cmd);

/* First delete known false positives. */
memleak_scan_htable(memtable, &ld->topology->txwatches.raw);
Expand Down
4 changes: 3 additions & 1 deletion onchaind/onchaind.c
Original file line number Diff line number Diff line change
Expand Up @@ -2101,7 +2101,9 @@ static bool handle_dev_memleak(struct tracked_output **outs, const u8 *msg)
if (!fromwire_onchaind_dev_memleak(msg))
return false;

memtable = memleak_start(tmpctx, msg, msg);
memtable = memleak_start(tmpctx);
memleak_ptr(memtable, msg);

/* Top-level context is parent of outs */
memleak_remove_globals(memtable, tal_parent(outs));
memleak_scan_obj(memtable, outs);
Expand Down
4 changes: 1 addition & 3 deletions onchaind/test/run-grind_feerate-bug.c
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,7 @@ void memleak_scan_obj(struct htable *memtable UNNEEDED, const void *obj UNNEEDED
void memleak_scan_region(struct htable *memtable UNNEEDED, const void *p UNNEEDED, size_t len UNNEEDED)
{ fprintf(stderr, "memleak_scan_region called!\n"); abort(); }
/* Generated stub for memleak_start */
struct htable *memleak_start(const tal_t *ctx UNNEEDED,
const void *exclude1 UNNEEDED,
const void *exclude2 UNNEEDED)
struct htable *memleak_start(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "memleak_start called!\n"); abort(); }
/* Generated stub for memleak_status_broken */
void memleak_status_broken(const char *fmt UNNEEDED, ...)
Expand Down
4 changes: 1 addition & 3 deletions onchaind/test/run-grind_feerate.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,7 @@ void master_badmsg(u32 type_expected UNNEEDED, const u8 *msg)
void memleak_scan_obj(struct htable *memtable UNNEEDED, const void *obj UNNEEDED)
{ fprintf(stderr, "memleak_scan_obj called!\n"); abort(); }
/* Generated stub for memleak_start */
struct htable *memleak_start(const tal_t *ctx UNNEEDED,
const void *exclude1 UNNEEDED,
const void *exclude2 UNNEEDED)
struct htable *memleak_start(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "memleak_start called!\n"); abort(); }
/* Generated stub for new_coin_channel_close */
struct chain_coin_mvt *new_coin_channel_close(const tal_t *ctx UNNEEDED,
Expand Down
3 changes: 2 additions & 1 deletion openingd/dualopend.c
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,8 @@ static void handle_dev_memleak(struct state *state, const u8 *msg)

/* Populate a hash table with all our allocations (except msg, which
* is in use right now). */
memtable = memleak_start(tmpctx, msg, msg);
memtable = memleak_start(tmpctx);
memleak_ptr(memtable, msg);

/* Now delete state and things it has pointers to. */
memleak_scan_obj(memtable, state);
Expand Down
3 changes: 2 additions & 1 deletion openingd/openingd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1301,7 +1301,8 @@ static void handle_dev_memleak(struct state *state, const u8 *msg)

/* Populate a hash table with all our allocations (except msg, which
* is in use right now). */
memtable = memleak_start(tmpctx, msg, msg);
memtable = memleak_start(tmpctx);
memleak_ptr(memtable, msg);

/* Now delete state and things it has pointers to. */
memleak_scan_obj(memtable, state);
Expand Down
6 changes: 5 additions & 1 deletion plugins/libplugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -1350,7 +1350,11 @@ static void memleak_check(struct plugin *plugin, struct command *cmd)
{
struct htable *memtable;

memtable = memleak_start(tmpctx, cmd, cmd);
memtable = memleak_start(tmpctx);

/* cmd in use right now */
memleak_ptr(memtable, cmd);
memleak_ignore_children(memtable, cmd);

/* Now delete plugin and anything it has pointers to. */
memleak_scan_obj(memtable, plugin);
Expand Down

0 comments on commit 701dd3d

Please sign in to comment.