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 <equinox@diac24.net>
This commit is contained in:
David Lamparter 2019-12-02 16:20:00 +01:00
parent 0bdeb5e58d
commit 767439c558
3 changed files with 26 additions and 7 deletions

View file

@ -163,6 +163,7 @@ static int qmem_exit_walker(void *arg, struct memgroup *mg, struct memtype *mt)
} else if (mt->n_alloc) { } else if (mt->n_alloc) {
char size[32]; char size[32];
if (!mg->active_at_exit)
eda->error++; eda->error++;
snprintf(size, sizeof(size), "%10zu", mt->size); snprintf(size, sizeof(size), "%10zu", mt->size);
fprintf(eda->fp, "%s: memstats: %-30s: %6zu * %s\n", fprintf(eda->fp, "%s: memstats: %-30s: %6zu * %s\n",

View file

@ -17,6 +17,7 @@
#ifndef _QUAGGA_MEMORY_H #ifndef _QUAGGA_MEMORY_H
#define _QUAGGA_MEMORY_H #define _QUAGGA_MEMORY_H
#include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <frratomic.h> #include <frratomic.h>
@ -48,6 +49,8 @@ struct memgroup {
struct memgroup *next, **ref; struct memgroup *next, **ref;
struct memtype *types, **insert; struct memtype *types, **insert;
const char *name; const char *name;
/* ignore group on dumping memleaks at exit */
bool active_at_exit;
}; };
/* macro usage: /* macro usage:
@ -76,7 +79,7 @@ struct memgroup {
*/ */
#define DECLARE_MGROUP(name) extern struct memgroup _mg_##name; #define DECLARE_MGROUP(name) extern struct memgroup _mg_##name;
#define DEFINE_MGROUP(mname, desc) \ #define _DEFINE_MGROUP(mname, desc, ...) \
struct memgroup _mg_##mname \ struct memgroup _mg_##mname \
__attribute__((section(".data.mgroups"))) = { \ __attribute__((section(".data.mgroups"))) = { \
.name = desc, \ .name = desc, \
@ -84,6 +87,7 @@ struct memgroup {
.next = NULL, \ .next = NULL, \
.insert = NULL, \ .insert = NULL, \
.ref = NULL, \ .ref = NULL, \
__VA_ARGS__ \
}; \ }; \
static void _mginit_##mname(void) __attribute__((_CONSTRUCTOR(1000))); \ static void _mginit_##mname(void) __attribute__((_CONSTRUCTOR(1000))); \
static void _mginit_##mname(void) \ static void _mginit_##mname(void) \
@ -99,7 +103,13 @@ struct memgroup {
if (_mg_##mname.next) \ if (_mg_##mname.next) \
_mg_##mname.next->ref = _mg_##mname.ref; \ _mg_##mname.next->ref = _mg_##mname.ref; \
*_mg_##mname.ref = _mg_##mname.next; \ *_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) \ #define DECLARE_MTYPE(name) \
extern struct memtype MTYPE_##name[1]; \ extern struct memtype MTYPE_##name[1]; \

View file

@ -26,10 +26,18 @@
#include "zlog.h" #include "zlog.h"
#include "zlog_targets.h" #include "zlog_targets.h"
DEFINE_MTYPE_STATIC(LIB, LOG_FD, "log file target") /* these allocations are intentionally left active even when doing full exit
DEFINE_MTYPE_STATIC(LIB, LOG_FD_NAME, "log file name") * cleanup, in order to keep the logging subsystem fully functional until the
DEFINE_MTYPE_STATIC(LIB, LOG_FD_ROTATE, "log file rotate helper") * absolute end.
DEFINE_MTYPE_STATIC(LIB, LOG_SYSL, "syslog target") */
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 zlt_fd {
struct zlog_target zt; struct zlog_target zt;