diff --git a/channeld/channeld.c b/channeld/channeld.c index 6fd127839..5e20d71e7 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -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); diff --git a/closingd/closingd.c b/closingd/closingd.c index d3f0623a3..3528f5d3c 100644 --- a/closingd/closingd.c +++ b/closingd/closingd.c @@ -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]); diff --git a/common/memleak.c b/common/memleak.c index 2ad2411e3..a12b32001 100644 --- a/common/memleak.c +++ b/common/memleak.c @@ -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")) @@ -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); } } @@ -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) @@ -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); diff --git a/common/memleak.h b/common/memleak.h index c06014ea0..e28ae53bf 100644 --- a/common/memleak.h +++ b/common/memleak.h @@ -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. @@ -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. diff --git a/connectd/connectd.c b/connectd/connectd.c index 49bd268a1..debe87693 100644 --- a/connectd/connectd.c +++ b/connectd/connectd.c @@ -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); diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index 9cbbfc21d..1926c440e 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -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); diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index aae54bedd..9e3991c4e 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -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)); diff --git a/lightningd/memdump.c b/lightningd/memdump.c index f279aca8e..4c3884c9e 100644 --- a/lightningd/memdump.c +++ b/lightningd/memdump.c @@ -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); diff --git a/onchaind/onchaind.c b/onchaind/onchaind.c index 3f75dac9f..937235cd7 100644 --- a/onchaind/onchaind.c +++ b/onchaind/onchaind.c @@ -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); diff --git a/onchaind/test/run-grind_feerate-bug.c b/onchaind/test/run-grind_feerate-bug.c index 8423e972e..34917cb3a 100644 --- a/onchaind/test/run-grind_feerate-bug.c +++ b/onchaind/test/run-grind_feerate-bug.c @@ -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, ...) diff --git a/onchaind/test/run-grind_feerate.c b/onchaind/test/run-grind_feerate.c index 7e59d8fb2..057ef558c 100644 --- a/onchaind/test/run-grind_feerate.c +++ b/onchaind/test/run-grind_feerate.c @@ -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, diff --git a/openingd/dualopend.c b/openingd/dualopend.c index 79a2b29f0..8e747a140 100644 --- a/openingd/dualopend.c +++ b/openingd/dualopend.c @@ -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); diff --git a/openingd/openingd.c b/openingd/openingd.c index 27a84737d..cf3afbefd 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -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); diff --git a/plugins/libplugin.c b/plugins/libplugin.c index 0d4afafc2..5b2701b81 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -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);