@ -8,54 +8,26 @@
# include <common/utils.h>
# if DEVELOPER
static const void * * notleaks ;
static bool * notleak_children ;
static bool memleak_track ;
struct memleak_notleak {
bool plus_children ;
} ;
struct memleak_helper {
void ( * cb ) ( struct htable * memtable , const tal_t * ) ;
} ;
static size_t find_notleak ( const tal_t * ptr )
{
size_t i , nleaks = tal_count ( notleaks ) ;
for ( i = 0 ; i < nleaks ; i + + )
if ( notleaks [ i ] = = ptr )
return i ;
abort ( ) ;
}
static void notleak_change ( tal_t * ctx ,
enum tal_notify_type type ,
void * info )
{
size_t i ;
if ( type = = TAL_NOTIFY_FREE ) {
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 , bool plus_children )
{
struct memleak_notleak * notleak ;
/* If we're not tracking, don't do anything. */
if ( ! notleaks )
if ( ! memleak_track )
return cast_const ( void * , ptr ) ;
tal_arr_expand ( & notleaks , ptr ) ;
tal_arr_expand ( & notleak_children , plus_children ) ;
tal_add_notifier ( ptr , TAL_NOTIFY_FREE | TAL_NOTIFY_MOVE , notleak_change ) ;
notleak = tal ( ptr , struct memleak_notleak ) ;
notleak - > plus_children = plus_children ;
return cast_const ( void * , ptr ) ;
}
@ -86,8 +58,9 @@ static void children_into_htable(const void *exclude1, const void *exclude2,
if ( streq ( name , " backtrace " ) )
continue ;
/* Don't add our own memleak_helpers */
if ( strends ( name , " struct memleak_helper " ) )
/* Don't add our own memleak_helpers or notleak() */
if ( strends ( name , " struct memleak_helper " )
| | strends ( name , " struct memleak_notleak " ) )
continue ;
/* Don't add tal_link objects */
@ -145,19 +118,8 @@ static void remove_with_children(struct htable *memtable, const tal_t *p)
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 , tal_bytelen ( root ) ) ;
memleak_scan_region ( memtable , notleaks , tal_bytelen ( notleaks ) ) ;
/* 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 ] ) ;
/* notleak_children array is not a leak */
pointer_referenced ( memtable , notleak_children ) ;
/* Remove memtable itself */
pointer_referenced ( memtable , memtable ) ;
@ -258,6 +220,7 @@ void memleak_add_helper_(const tal_t *p,
}
/* Handle allocations marked with helpers or notleak() */
static void call_memleak_helpers ( struct htable * memtable , const tal_t * p )
{
const tal_t * i ;
@ -268,6 +231,13 @@ static void call_memleak_helpers(struct htable *memtable, const tal_t *p)
if ( name & & strends ( name , " struct memleak_helper " ) ) {
const struct memleak_helper * mh = i ;
mh - > cb ( memtable , p ) ;
} else if ( name & & strends ( name , " struct memleak_notleak " ) ) {
const struct memleak_notleak * notleak = i ;
if ( notleak - > plus_children )
remove_with_children ( memtable , p ) ;
else
pointer_referenced ( memtable , p ) ;
memleak_scan_region ( memtable , p , tal_bytelen ( p ) ) ;
} else {
call_memleak_helpers ( memtable , i ) ;
}
@ -293,18 +263,10 @@ struct htable *memleak_enter_allocations(const tal_t *ctx,
void memleak_init ( void )
{
assert ( ! notleaks ) ;
notleaks = tal_arr ( NULL , const void * , 0 ) ;
notleak_children = tal_arr ( notleaks , bool , 0 ) ;
memleak_track = true ;
if ( backtrace_state )
add_backtrace_notifiers ( NULL ) ;
}
void memleak_cleanup ( void )
{
notleaks = tal_free ( notleaks ) ;
}
# else /* !DEVELOPER */
void * notleak_ ( const void * ptr , bool plus_children UNNEEDED )
{