mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-02 12:01:32 +01:00
Add code to allow for late memory cleanup.
* common/init.c (mem_cleanup_item_t): New. (run_mem_cleanup): New. (_init_common_subsystems): Add an atexit for it. (register_mem_cleanup_func): New. * g10/kbnode.c (cleanup_registered): New. (release_unused_nodes): New. (alloc_node): Call register_mem_cleanup_func. -- It is often time consuming to figure out whether still allocated memory at process termination is fine (e.g. a cache) or a problem. To help for that register_mem_cleanup_func may now be used to cleanup such memory. The run time of the program will be longer; if that turns out to be a problem we can change the code to only run in debugging mode.
This commit is contained in:
parent
44159b681f
commit
2739834206
@ -46,6 +46,21 @@
|
|||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
/* This object is used to register memory cleanup functions.
|
||||||
|
Technically they are not needed but they can avoid frequent
|
||||||
|
questions about un-released memory. Note that we use the system
|
||||||
|
malloc and not any wrappers. */
|
||||||
|
struct mem_cleanup_item_s;
|
||||||
|
typedef struct mem_cleanup_item_s *mem_cleanup_item_t;
|
||||||
|
|
||||||
|
struct mem_cleanup_item_s
|
||||||
|
{
|
||||||
|
mem_cleanup_item_t next;
|
||||||
|
void (*func) (void);
|
||||||
|
};
|
||||||
|
|
||||||
|
static mem_cleanup_item_t mem_cleanup_list;
|
||||||
|
|
||||||
|
|
||||||
/* The default error source of the application. This is different
|
/* The default error source of the application. This is different
|
||||||
from GPG_ERR_SOURCE_DEFAULT in that it does not depend on the
|
from GPG_ERR_SOURCE_DEFAULT in that it does not depend on the
|
||||||
@ -65,6 +80,36 @@ sleep_on_exit (void)
|
|||||||
#endif /*HAVE_W32CE_SYSTEM*/
|
#endif /*HAVE_W32CE_SYSTEM*/
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
run_mem_cleanup (void)
|
||||||
|
{
|
||||||
|
mem_cleanup_item_t next;
|
||||||
|
|
||||||
|
while (mem_cleanup_list)
|
||||||
|
{
|
||||||
|
next = mem_cleanup_list->next;
|
||||||
|
mem_cleanup_list->func ();
|
||||||
|
free (mem_cleanup_list);
|
||||||
|
mem_cleanup_list = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
register_mem_cleanup_func (void (*func)(void))
|
||||||
|
{
|
||||||
|
mem_cleanup_item_t item;
|
||||||
|
|
||||||
|
item = malloc (sizeof *item);
|
||||||
|
if (item)
|
||||||
|
{
|
||||||
|
item->func = func;
|
||||||
|
item->next = mem_cleanup_list;
|
||||||
|
mem_cleanup_list = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* If STRING is not NULL write string to es_stdout or es_stderr. MODE
|
/* If STRING is not NULL write string to es_stdout or es_stderr. MODE
|
||||||
must be 1 or 2. If STRING is NULL flush the respective stream. */
|
must be 1 or 2. If STRING is NULL flush the respective stream. */
|
||||||
static int
|
static int
|
||||||
@ -100,6 +145,8 @@ _init_common_subsystems (gpg_err_source_t errsource, int *argcp, char ***argvp)
|
|||||||
/* Store the error source in a gloabl variable. */
|
/* Store the error source in a gloabl variable. */
|
||||||
default_errsource = errsource;
|
default_errsource = errsource;
|
||||||
|
|
||||||
|
atexit (run_mem_cleanup);
|
||||||
|
|
||||||
/* Try to auto set the character set. */
|
/* Try to auto set the character set. */
|
||||||
set_native_charset (NULL);
|
set_native_charset (NULL);
|
||||||
|
|
||||||
|
@ -36,6 +36,8 @@
|
|||||||
# error GPG_ERR_SOURCE_DEFAULT has default value
|
# error GPG_ERR_SOURCE_DEFAULT has default value
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void register_mem_cleanup_func (void (*func)(void));
|
||||||
|
|
||||||
void _init_common_subsystems (gpg_err_source_t errsource,
|
void _init_common_subsystems (gpg_err_source_t errsource,
|
||||||
int *argcp, char ***argvp);
|
int *argcp, char ***argvp);
|
||||||
#define init_common_subsystems(a,b) \
|
#define init_common_subsystems(a,b) \
|
||||||
|
59
g10/kbnode.c
59
g10/kbnode.c
@ -31,35 +31,58 @@
|
|||||||
|
|
||||||
#define USE_UNUSED_NODES 1
|
#define USE_UNUSED_NODES 1
|
||||||
|
|
||||||
|
static int cleanup_registered;
|
||||||
static KBNODE unused_nodes;
|
static KBNODE unused_nodes;
|
||||||
|
|
||||||
static KBNODE
|
#if USE_UNUSED_NODES
|
||||||
alloc_node(void)
|
static void
|
||||||
|
release_unused_nodes (void)
|
||||||
{
|
{
|
||||||
KBNODE n;
|
while (unused_nodes)
|
||||||
|
{
|
||||||
|
kbnode_t next = unused_nodes->next;
|
||||||
|
xfree (unused_nodes);
|
||||||
|
unused_nodes = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /*USE_UNUSED_NODES*/
|
||||||
|
|
||||||
n = unused_nodes;
|
|
||||||
if( n )
|
static kbnode_t
|
||||||
unused_nodes = n->next;
|
alloc_node (void)
|
||||||
else
|
{
|
||||||
n = xmalloc( sizeof *n );
|
kbnode_t n;
|
||||||
n->next = NULL;
|
|
||||||
n->pkt = NULL;
|
n = unused_nodes;
|
||||||
n->flag = 0;
|
if (n)
|
||||||
n->private_flag=0;
|
unused_nodes = n->next;
|
||||||
n->recno = 0;
|
else
|
||||||
return n;
|
{
|
||||||
|
if (!cleanup_registered)
|
||||||
|
{
|
||||||
|
cleanup_registered = 1;
|
||||||
|
register_mem_cleanup_func (release_unused_nodes);
|
||||||
|
}
|
||||||
|
n = xmalloc (sizeof *n);
|
||||||
|
}
|
||||||
|
n->next = NULL;
|
||||||
|
n->pkt = NULL;
|
||||||
|
n->flag = 0;
|
||||||
|
n->private_flag=0;
|
||||||
|
n->recno = 0;
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
free_node( KBNODE n )
|
free_node( KBNODE n )
|
||||||
{
|
{
|
||||||
if( n ) {
|
if (n)
|
||||||
|
{
|
||||||
#if USE_UNUSED_NODES
|
#if USE_UNUSED_NODES
|
||||||
n->next = unused_nodes;
|
n->next = unused_nodes;
|
||||||
unused_nodes = n;
|
unused_nodes = n;
|
||||||
#else
|
#else
|
||||||
xfree( n );
|
xfree (n);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user