mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 07:04:22 +01:00
memleak: remove exclusions from memleak_start()
Add memleak_ignore_children() so callers can do exclusions themselves. Having two exclusions was always such a hack! Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -3652,7 +3652,8 @@ static void handle_dev_memleak(struct peer *peer, const u8 *msg)
|
|||||||
struct htable *memtable;
|
struct htable *memtable;
|
||||||
bool found_leak;
|
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. */
|
/* Now delete peer and things it has pointers to. */
|
||||||
memleak_scan_obj(memtable, peer);
|
memleak_scan_obj(memtable, peer);
|
||||||
|
|||||||
@@ -554,7 +554,7 @@ static void closing_dev_memleak(const tal_t *ctx,
|
|||||||
u8 *scriptpubkey[NUM_SIDES],
|
u8 *scriptpubkey[NUM_SIDES],
|
||||||
const u8 *funding_wscript)
|
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, ctx);
|
||||||
memleak_ptr(memtable, scriptpubkey[LOCAL]);
|
memleak_ptr(memtable, scriptpubkey[LOCAL]);
|
||||||
|
|||||||
@@ -71,17 +71,13 @@ bool memleak_ptr(struct htable *memtable, const void *p)
|
|||||||
return htable_del(memtable, hash_ptr(p, NULL), p);
|
return htable_del(memtable, hash_ptr(p, NULL), p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void children_into_htable(const void *exclude1, const void *exclude2,
|
static void children_into_htable(struct htable *memtable, const tal_t *p)
|
||||||
struct htable *memtable, const tal_t *p)
|
|
||||||
{
|
{
|
||||||
const tal_t *i;
|
const tal_t *i;
|
||||||
|
|
||||||
for (i = tal_first(p); i; i = tal_next(i)) {
|
for (i = tal_first(p); i; i = tal_next(i)) {
|
||||||
const char *name = tal_name(i);
|
const char *name = tal_name(i);
|
||||||
|
|
||||||
if (i == exclude1 || i == exclude2)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
/* Don't add backtrace objects. */
|
/* Don't add backtrace objects. */
|
||||||
if (streq(name, "backtrace"))
|
if (streq(name, "backtrace"))
|
||||||
@@ -108,7 +104,7 @@ static void children_into_htable(const void *exclude1, const void *exclude2,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
htable_add(memtable, hash_ptr(i, NULL), i);
|
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;
|
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() */
|
/* Handle allocations marked with helpers or notleak() */
|
||||||
static void call_memleak_helpers(struct htable *memtable, const tal_t *p)
|
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,
|
struct htable *memleak_start(const tal_t *ctx)
|
||||||
const void *exclude1,
|
|
||||||
const void *exclude2)
|
|
||||||
{
|
{
|
||||||
struct htable *memtable = tal(ctx, struct htable);
|
struct htable *memtable = tal(ctx, struct htable);
|
||||||
htable_init(memtable, hash_ptr, NULL);
|
htable_init(memtable, hash_ptr, NULL);
|
||||||
|
|
||||||
if (memleak_track) {
|
if (memleak_track) {
|
||||||
/* First, add all pointers off NULL to table. */
|
/* 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. */
|
/* Iterate and call helpers to eliminate hard-to-get references. */
|
||||||
call_memleak_helpers(memtable, NULL);
|
call_memleak_helpers(memtable, NULL);
|
||||||
|
|||||||
@@ -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
|
* memleak_start: allocate a htable with all tal objects
|
||||||
* @ctx: the context to allocate the htable from
|
* @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,
|
struct htable *memleak_start(const tal_t *ctx);
|
||||||
const void *exclude1,
|
|
||||||
const void *exclude2);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* memleak_ptr: this pointer is not a memleak.
|
* 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))
|
memleak_scan_strmap_((memtable), tcon_unwrap(strmap))
|
||||||
void memleak_scan_strmap_(struct htable *memtable, const struct strmap *m);
|
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
|
* memleak_get: get (and remove) a leak from memtable, or NULL
|
||||||
* @memtable: the memtable after all known allocations removed.
|
* @memtable: the memtable after all known allocations removed.
|
||||||
|
|||||||
@@ -1860,7 +1860,8 @@ static void dev_connect_memleak(struct daemon *daemon, const u8 *msg)
|
|||||||
struct htable *memtable;
|
struct htable *memtable;
|
||||||
bool found_leak;
|
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. */
|
/* Now delete daemon and those which it has pointers to. */
|
||||||
memleak_scan_obj(memtable, daemon);
|
memleak_scan_obj(memtable, daemon);
|
||||||
|
|||||||
@@ -807,8 +807,8 @@ static void dev_gossip_memleak(struct daemon *daemon, const u8 *msg)
|
|||||||
struct htable *memtable;
|
struct htable *memtable;
|
||||||
bool found_leak;
|
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. */
|
/* Now delete daemon and those which it has pointers to. */
|
||||||
memleak_scan_obj(memtable, daemon);
|
memleak_scan_obj(memtable, daemon);
|
||||||
|
|
||||||
|
|||||||
@@ -555,7 +555,8 @@ static struct io_plan *handle_memleak(struct io_conn *conn,
|
|||||||
bool found_leak;
|
bool found_leak;
|
||||||
u8 *reply;
|
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. */
|
/* Now note clients and anything they point to. */
|
||||||
memleak_scan_region(memtable, dbid_zero_clients, sizeof(dbid_zero_clients));
|
memleak_scan_region(memtable, dbid_zero_clients, sizeof(dbid_zero_clients));
|
||||||
|
|||||||
@@ -143,7 +143,11 @@ static void finish_report(const struct leak_detect *leaks)
|
|||||||
ld = cmd->ld;
|
ld = cmd->ld;
|
||||||
|
|
||||||
/* Enter everything, except this cmd and its jcon */
|
/* 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. */
|
/* First delete known false positives. */
|
||||||
memleak_scan_htable(memtable, &ld->topology->txwatches.raw);
|
memleak_scan_htable(memtable, &ld->topology->txwatches.raw);
|
||||||
|
|||||||
@@ -2101,7 +2101,9 @@ static bool handle_dev_memleak(struct tracked_output **outs, const u8 *msg)
|
|||||||
if (!fromwire_onchaind_dev_memleak(msg))
|
if (!fromwire_onchaind_dev_memleak(msg))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
memtable = memleak_start(tmpctx, msg, msg);
|
memtable = memleak_start(tmpctx);
|
||||||
|
memleak_ptr(memtable, msg);
|
||||||
|
|
||||||
/* Top-level context is parent of outs */
|
/* Top-level context is parent of outs */
|
||||||
memleak_remove_globals(memtable, tal_parent(outs));
|
memleak_remove_globals(memtable, tal_parent(outs));
|
||||||
memleak_scan_obj(memtable, outs);
|
memleak_scan_obj(memtable, outs);
|
||||||
|
|||||||
@@ -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)
|
void memleak_scan_region(struct htable *memtable UNNEEDED, const void *p UNNEEDED, size_t len UNNEEDED)
|
||||||
{ fprintf(stderr, "memleak_scan_region called!\n"); abort(); }
|
{ fprintf(stderr, "memleak_scan_region called!\n"); abort(); }
|
||||||
/* Generated stub for memleak_start */
|
/* Generated stub for memleak_start */
|
||||||
struct htable *memleak_start(const tal_t *ctx UNNEEDED,
|
struct htable *memleak_start(const tal_t *ctx UNNEEDED)
|
||||||
const void *exclude1 UNNEEDED,
|
|
||||||
const void *exclude2 UNNEEDED)
|
|
||||||
{ fprintf(stderr, "memleak_start called!\n"); abort(); }
|
{ fprintf(stderr, "memleak_start called!\n"); abort(); }
|
||||||
/* Generated stub for memleak_status_broken */
|
/* Generated stub for memleak_status_broken */
|
||||||
void memleak_status_broken(const char *fmt UNNEEDED, ...)
|
void memleak_status_broken(const char *fmt UNNEEDED, ...)
|
||||||
|
|||||||
@@ -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)
|
void memleak_scan_obj(struct htable *memtable UNNEEDED, const void *obj UNNEEDED)
|
||||||
{ fprintf(stderr, "memleak_scan_obj called!\n"); abort(); }
|
{ fprintf(stderr, "memleak_scan_obj called!\n"); abort(); }
|
||||||
/* Generated stub for memleak_start */
|
/* Generated stub for memleak_start */
|
||||||
struct htable *memleak_start(const tal_t *ctx UNNEEDED,
|
struct htable *memleak_start(const tal_t *ctx UNNEEDED)
|
||||||
const void *exclude1 UNNEEDED,
|
|
||||||
const void *exclude2 UNNEEDED)
|
|
||||||
{ fprintf(stderr, "memleak_start called!\n"); abort(); }
|
{ fprintf(stderr, "memleak_start called!\n"); abort(); }
|
||||||
/* Generated stub for new_coin_channel_close */
|
/* Generated stub for new_coin_channel_close */
|
||||||
struct chain_coin_mvt *new_coin_channel_close(const tal_t *ctx UNNEEDED,
|
struct chain_coin_mvt *new_coin_channel_close(const tal_t *ctx UNNEEDED,
|
||||||
|
|||||||
@@ -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
|
/* Populate a hash table with all our allocations (except msg, which
|
||||||
* is in use right now). */
|
* 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. */
|
/* Now delete state and things it has pointers to. */
|
||||||
memleak_scan_obj(memtable, state);
|
memleak_scan_obj(memtable, state);
|
||||||
|
|||||||
@@ -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
|
/* Populate a hash table with all our allocations (except msg, which
|
||||||
* is in use right now). */
|
* 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. */
|
/* Now delete state and things it has pointers to. */
|
||||||
memleak_scan_obj(memtable, state);
|
memleak_scan_obj(memtable, state);
|
||||||
|
|||||||
@@ -1350,7 +1350,11 @@ static void memleak_check(struct plugin *plugin, struct command *cmd)
|
|||||||
{
|
{
|
||||||
struct htable *memtable;
|
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. */
|
/* Now delete plugin and anything it has pointers to. */
|
||||||
memleak_scan_obj(memtable, plugin);
|
memleak_scan_obj(memtable, plugin);
|
||||||
|
|||||||
Reference in New Issue
Block a user