From 767439c55858d65bf6f5776b7fcd36cc1132565c Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 2 Dec 2019 16:20:00 +0100 Subject: [PATCH] lib: mark some allocations as "active at exit" In some cases we really don't want to clean up things even when exiting (i.e. to keep the logging subsystem going.) This adds a flag on MGROUPs to indicate that. [v2: add "(active at exit)" marker text to debug memstats-at-exit] Signed-off-by: David Lamparter --- lib/memory.c | 3 ++- lib/memory.h | 14 ++++++++++++-- lib/zlog_targets.c | 16 ++++++++++++---- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/lib/memory.c b/lib/memory.c index 149e294d50..3a29404827 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -163,7 +163,8 @@ static int qmem_exit_walker(void *arg, struct memgroup *mg, struct memtype *mt) } else if (mt->n_alloc) { char size[32]; - eda->error++; + if (!mg->active_at_exit) + eda->error++; snprintf(size, sizeof(size), "%10zu", mt->size); fprintf(eda->fp, "%s: memstats: %-30s: %6zu * %s\n", eda->prefix, mt->name, mt->n_alloc, diff --git a/lib/memory.h b/lib/memory.h index e4e05faa4f..13f2f9b11a 100644 --- a/lib/memory.h +++ b/lib/memory.h @@ -17,6 +17,7 @@ #ifndef _QUAGGA_MEMORY_H #define _QUAGGA_MEMORY_H +#include #include #include #include @@ -48,6 +49,8 @@ struct memgroup { struct memgroup *next, **ref; struct memtype *types, **insert; const char *name; + /* ignore group on dumping memleaks at exit */ + bool active_at_exit; }; /* macro usage: @@ -76,7 +79,7 @@ struct memgroup { */ #define DECLARE_MGROUP(name) extern struct memgroup _mg_##name; -#define DEFINE_MGROUP(mname, desc) \ +#define _DEFINE_MGROUP(mname, desc, ...) \ struct memgroup _mg_##mname \ __attribute__((section(".data.mgroups"))) = { \ .name = desc, \ @@ -84,6 +87,7 @@ struct memgroup { .next = NULL, \ .insert = NULL, \ .ref = NULL, \ + __VA_ARGS__ \ }; \ static void _mginit_##mname(void) __attribute__((_CONSTRUCTOR(1000))); \ static void _mginit_##mname(void) \ @@ -99,7 +103,13 @@ struct memgroup { if (_mg_##mname.next) \ _mg_##mname.next->ref = _mg_##mname.ref; \ *_mg_##mname.ref = _mg_##mname.next; \ - } + } \ + /* end */ + +#define DEFINE_MGROUP(mname, desc) \ + _DEFINE_MGROUP(mname, desc, ) +#define DEFINE_MGROUP_ACTIVEATEXIT(mname, desc) \ + _DEFINE_MGROUP(mname, desc, .active_at_exit = true) #define DECLARE_MTYPE(name) \ extern struct memtype MTYPE_##name[1]; \ diff --git a/lib/zlog_targets.c b/lib/zlog_targets.c index ff9cd1e5fe..85991b0dde 100644 --- a/lib/zlog_targets.c +++ b/lib/zlog_targets.c @@ -26,10 +26,18 @@ #include "zlog.h" #include "zlog_targets.h" -DEFINE_MTYPE_STATIC(LIB, LOG_FD, "log file target") -DEFINE_MTYPE_STATIC(LIB, LOG_FD_NAME, "log file name") -DEFINE_MTYPE_STATIC(LIB, LOG_FD_ROTATE, "log file rotate helper") -DEFINE_MTYPE_STATIC(LIB, LOG_SYSL, "syslog target") +/* these allocations are intentionally left active even when doing full exit + * cleanup, in order to keep the logging subsystem fully functional until the + * absolute end. + */ + +DECLARE_MGROUP(LOG) +DEFINE_MGROUP_ACTIVEATEXIT(LOG, "logging subsystem") + +DEFINE_MTYPE_STATIC(LOG, LOG_FD, "log file target") +DEFINE_MTYPE_STATIC(LOG, LOG_FD_NAME, "log file name") +DEFINE_MTYPE_STATIC(LOG, LOG_FD_ROTATE, "log file rotate helper") +DEFINE_MTYPE_STATIC(LOG, LOG_SYSL, "syslog target") struct zlt_fd { struct zlog_target zt;