aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2012-12-28 18:26:59 +0000
committerWerner Koch <[email protected]>2013-03-20 08:50:17 +0000
commit2739834206f23833161898a73427b8a9c6d5d26d (patch)
tree03714abe221b38f91b2dc1a8df85d20f51b08c57
parentkbx: Remove unused macro. (diff)
downloadgnupg-2739834206f23833161898a73427b8a9c6d5d26d.tar.gz
gnupg-2739834206f23833161898a73427b8a9c6d5d26d.zip
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.
Diffstat (limited to '')
-rw-r--r--common/init.c47
-rw-r--r--common/init.h2
-rw-r--r--g10/kbnode.c59
3 files changed, 90 insertions, 18 deletions
diff --git a/common/init.c b/common/init.c
index e00b9b308..8a0b6a8e7 100644
--- a/common/init.c
+++ b/common/init.c
@@ -46,6 +46,21 @@
#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
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*/
+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
must be 1 or 2. If STRING is NULL flush the respective stream. */
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. */
default_errsource = errsource;
+ atexit (run_mem_cleanup);
+
/* Try to auto set the character set. */
set_native_charset (NULL);
diff --git a/common/init.h b/common/init.h
index 633ffac52..eea2eb167 100644
--- a/common/init.h
+++ b/common/init.h
@@ -36,6 +36,8 @@
# error GPG_ERR_SOURCE_DEFAULT has default value
#endif
+void register_mem_cleanup_func (void (*func)(void));
+
void _init_common_subsystems (gpg_err_source_t errsource,
int *argcp, char ***argvp);
#define init_common_subsystems(a,b) \
diff --git a/g10/kbnode.c b/g10/kbnode.c
index 1a8b91e43..d4907408b 100644
--- a/g10/kbnode.c
+++ b/g10/kbnode.c
@@ -31,35 +31,58 @@
#define USE_UNUSED_NODES 1
+static int cleanup_registered;
static KBNODE unused_nodes;
-static KBNODE
-alloc_node(void)
+#if USE_UNUSED_NODES
+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 )
- unused_nodes = n->next;
- else
- n = xmalloc( sizeof *n );
- n->next = NULL;
- n->pkt = NULL;
- n->flag = 0;
- n->private_flag=0;
- n->recno = 0;
- return n;
+
+static kbnode_t
+alloc_node (void)
+{
+ kbnode_t n;
+
+ n = unused_nodes;
+ if (n)
+ unused_nodes = n->next;
+ else
+ {
+ 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
free_node( KBNODE n )
{
- if( n ) {
+ if (n)
+ {
#if USE_UNUSED_NODES
- n->next = unused_nodes;
- unused_nodes = n;
+ n->next = unused_nodes;
+ unused_nodes = n;
#else
- xfree( n );
+ xfree (n);
#endif
}
}