[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
FYI: 20-gary-unrevert-memory-handling-bits-of-15-gary-cleanup-from-renam
From: |
Gary V. Vaughan |
Subject: |
FYI: 20-gary-unrevert-memory-handling-bits-of-15-gary-cleanup-from-renaming-token-data-to-symbol.patch |
Date: |
Sun, 30 Sep 2001 23:34:12 +0100 |
User-agent: |
Mutt/1.3.22.1i |
Index: ChangeLog
from Gary V. Vaughan <address@hidden>
Reinstate the memory handling improvements from the patch I just
reverted. Relevant ChangeLog entries repeated here:
* m4/module.c (m4_module_remove): New function that holds the core
of the old m4_module_unload.
(m4_module_unload): Use it.
(m4_module_unload_all): When we know the modules will never be
used again (i.e. on exit), free up as much module memory as
possible. There are still some artifacts from resident modules
living inside ltdl.c, but everything else is freed.
* m4/debug.c (m4_debug_exit): Free memory allocated in
m4_debug_init().
* m4/input.c (m4_input_exit): Ditto wrt m4_input_init().
* m4/output.c (m4_output_exit): Ditto wrt m4_output_init ().
* src/stackovf.c (stackovf_exit): Ditto wrt setup_stackovf_trap ().
* m4/m4module.h: Updated prototypes.
* m4/hash.c (m4_hash_exit): Free the nodes on the free list.
* m4/hash.h: Updated prototypes.
* src/main.c (main): Use all these new functions to clean up as
much memory as possible before exit.
Index: m4/debug.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/debug.c,v
retrieving revision 1.7
diff -u -p -u -r1.7 debug.c
--- m4/debug.c 2001/09/30 14:43:38 1.7
+++ m4/debug.c 2001/09/30 22:24:09
@@ -44,6 +44,12 @@ m4_debug_init (void)
obstack_init (&trace);
}
+void
+m4_debug_exit (void)
+{
+ obstack_free (&trace, NULL);
+}
+
/* Function to decode the debugging flags OPTS. Used by main while
Index: m4/hash.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/hash.c,v
retrieving revision 1.4
diff -u -p -u -r1.4 hash.c
--- m4/hash.c 2001/09/30 14:43:38 1.4
+++ m4/hash.c 2001/09/30 22:24:10
@@ -271,8 +271,9 @@ m4_hash_remove (m4_hash *hash, const voi
/* Return the address of the value field of the first node in
HASH that has a matching KEY. The address is returned so that
- an explicit 0 value can be distinguihed from a failed lookup
- (also 0). */
+ an explicit 0 value can be distinguished from a failed lookup
+ (also 0). Fortuitously for M4, this also means that the value
+ field can be changed `in situ' to implement a value stack. */
void **
m4_hash_lookup (m4_hash *hash, const void *key)
{
@@ -363,6 +364,17 @@ m4_hash_bucket_insert (m4_hash *hash, m4
while (bucket);
}
+void
+m4_hash_exit (void)
+{
+ while (m4_hash_node_free_list)
+ {
+ m4_hash_node *stale = m4_hash_node_free_list;
+ m4_hash_node_free_list = M4_HASH_NODE_NEXT (stale);
+ xfree (stale);
+ }
+}
+
struct m4_hash_iterator
Index: m4/hash.h
===================================================================
RCS file: /cvsroot/m4/m4/m4/hash.h,v
retrieving revision 1.3
diff -u -p -u -r1.3 hash.h
--- m4/hash.h 2001/09/30 14:43:38 1.3
+++ m4/hash.h 2001/09/30 22:24:10
@@ -44,6 +44,7 @@ void m4_hash_insert (m4_hash *hash, con
void * m4_hash_remove (m4_hash *hash, const void *key);
void ** m4_hash_lookup (m4_hash *hash, const void *key);
size_t m4_hash_length (m4_hash *hash);
+void m4_hash_exit (void);
Index: m4/input.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/input.c,v
retrieving revision 1.12
diff -u -p -u -r1.12 input.c
--- m4/input.c 2001/09/30 14:43:38 1.12
+++ m4/input.c 2001/09/30 22:24:13
@@ -793,6 +793,18 @@ m4_input_init (void)
use_macro_escape = FALSE;
}
+ void
+m4_input_exit (void)
+{
+ XFREE (lquote.string);
+ XFREE (rquote.string);
+ XFREE (bcomm.string);
+ XFREE (ecomm.string);
+ obstack_free (&wrapup_stack, NULL);
+ obstack_free (&input_stack, NULL);
+ obstack_free (&token_stack, NULL);
+}
+
void
m4_syntax_init (void)
{
Index: m4/m4module.h
===================================================================
RCS file: /cvsroot/m4/m4/m4/m4module.h,v
retrieving revision 1.31
diff -u -p -u -r1.31 m4module.h
--- m4/m4module.h 2001/09/30 14:43:38 1.31
+++ m4/m4module.h 2001/09/30 22:24:14
@@ -94,6 +94,7 @@ extern m4_hash *m4_symtab;
extern void m4_symtab_init (void);
extern int m4_symtab_apply (m4_symtab_apply_func *, void *);
extern void m4_symtab_remove_module_references (lt_dlhandle);
+extern void m4_symtab_exit (void);
extern m4_symbol *m4_symbol_lookup (const char *);
extern m4_symbol *m4_symbol_pushdef (const char *);
@@ -291,6 +292,7 @@ FILE *m4_debug;
while (0)
void m4_debug_init (void);
+void m4_debug_exit (void);
int m4_debug_decode (const char *);
void m4_debug_flush_files (void);
boolean m4_debug_set_output (const char *);
@@ -375,6 +377,7 @@ int m4_current_line;
extern int m4_syntax_code (char ch);
extern void m4_input_init (void);
+extern void m4_input_exit (void);
extern void m4_syntax_init (void);
extern int m4_peek_input (void);
extern m4_token_t m4_next_token (m4_token_data *);
@@ -399,6 +402,7 @@ int m4_current_diversion;
int m4_output_current_line;
extern void m4_output_init (void);
+extern void m4_output_exit (void);
extern void m4_shipout_text (struct obstack *, const char *, int);
extern void m4_make_diversion (int);
extern void m4_insert_diversion (int);
Index: m4/m4private.h
===================================================================
RCS file: /cvsroot/m4/m4/m4/m4private.h,v
retrieving revision 1.11
diff -u -p -u -r1.11 m4private.h
--- m4/m4private.h 2001/09/30 14:43:38 1.11
+++ m4/m4private.h 2001/09/30 22:24:14
@@ -79,9 +79,14 @@ struct m4_symbol
/* Debugging the memory allocator. */
#if WITH_DMALLOC
-# define DMALLOC_FUNC_CHECK
-# include <dmalloc.h>
-#endif
+# define DMALLOC_FUNC_CHECK
+# include <dmalloc.h>
+
+/* Dmalloc expects us to use a void returning xfree. */
+# undef XFREE
+# define XFREE(p) if (p) xfree (p)
+
+#endif /* WITH_DMALLOC */
/* Other debug stuff. */
Index: m4/module.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/module.c,v
retrieving revision 1.13
diff -u -p -u -r1.13 module.c
--- m4/module.c 2001/09/30 14:43:38 1.13
+++ m4/module.c 2001/09/30 22:24:17
@@ -83,6 +83,8 @@
#define M4_FINISH_SYMBOL "m4_finish_module"
static const char* m4_module_dlerror (void);
+static int m4_module_remove (lt_dlhandle handle,
+ struct obstack *obs);
static lt_dlcaller_id m4_caller_id = 0;
@@ -177,9 +179,11 @@ m4_module_init (void)
return;
}
+#if !WITH_DMALLOC
/* initialise libltdl's memory management. */
lt_dlmalloc = xmalloc;
lt_dlfree = (void (*)(void*)) xfree;
+#endif
errors = lt_dlinit ();
@@ -323,11 +327,11 @@ void
m4_module_close (lt_dlhandle handle, struct obstack *obs)
{
m4_module_finish_func *finish_func = 0;
- const char *name = 0;
+ char *name = 0;
int errors = 0;
-
+
assert (handle);
- name = m4_module_name (handle);
+ name = xstrdup (m4_module_name (handle));
/* Run any finishing function for the opened module. */
finish_func = (m4_module_finish_func *) lt_dlsym (handle, M4_FINISH_SYMBOL);
@@ -343,18 +347,16 @@ m4_module_close (lt_dlhandle handle, str
if (!lt_dlisresident (handle))
{
- {
- const lt_dlinfo *info = lt_dlgetinfo (handle);
+ const lt_dlinfo *info = lt_dlgetinfo (handle);
- /* When we are about to unload the module for the final
- time, be sure to release any client data memory. */
- if (info && (info->ref_count == 1))
- {
- m4_module_data *stale
- = lt_dlcaller_set_data (m4_caller_id, handle, 0);
- xfree (stale);
- }
- }
+ /* When we are about to unload the module for the final
+ time, be sure to release any client data memory. */
+ if (info && (info->ref_count == 1))
+ {
+ m4_module_data *stale
+ = lt_dlcaller_set_data (m4_caller_id, handle, 0);
+ XFREE (stale);
+ }
errors = lt_dlclose (handle);
if (!errors)
@@ -364,6 +366,10 @@ m4_module_close (lt_dlhandle handle, str
#endif /* DEBUG_MODULES */
}
}
+#ifdef DEBUG_MODULES
+ else
+ M4_DEBUG_MESSAGE1("module %s: resident module not closed", name);
+#endif /* DEBUG_MODULES */
if (errors)
{
@@ -371,6 +377,8 @@ m4_module_close (lt_dlhandle handle, str
_("ERROR: cannot close module `%s': %s"),
name, m4_module_dlerror ()));
}
+
+ xfree (name);
}
void
@@ -384,6 +392,10 @@ m4_module_close_all (struct obstack *obs
closed, even to find the address of the next handle. */
lt_dlhandle pending = handle;
handle = lt_dlhandle_next (handle);
+#ifdef DEBUG_MODULES
+ M4_DEBUG_MESSAGE1("module %s: attempting module close",
+ m4_module_name (pending));
+#endif /* DEBUG_MODULES */
m4_module_close (pending, obs);
}
@@ -438,6 +450,46 @@ m4_module_load (const char *name, struct
return handle;
}
+int
+m4_module_remove (lt_dlhandle handle, struct obstack *obs)
+{
+ const lt_dlinfo *info = 0;
+ int errors = 0;
+
+ assert (handle);
+
+ info = lt_dlgetinfo (handle);
+
+ /* Only do the actual close when the number of calls to close this
+ module is equal to the number of times it was opened. */
+#ifdef DEBUG_MODULES
+ if (info->ref_count > 1)
+ {
+ M4_DEBUG_MESSAGE2("module %s: now has %d references.",
+ m4_module_name (handle), info->ref_count -1);
+ }
+#endif /* DEBUG_MODULES */
+
+ if (info->ref_count == 1)
+ {
+ /* Remove the table references only when ref_count is *exactly*
+ equal to 1. If m4_module_close is called again on a
+ resident module after the references have already been
+ removed, we needn't try to remove them again! */
+ m4_symtab_remove_module_references (handle);
+
+#ifdef DEBUG_MODULES
+ M4_DEBUG_MESSAGE1("module %s: symbols unloaded",
+ m4_module_name (handle));
+#endif /* DEBUG_MODULES */
+ }
+
+ if (!errors)
+ m4_module_close (handle, obs);
+
+ return errors;
+}
+
/* Unload a module. */
void
m4_module_unload (const char *name, struct obstack *obs)
@@ -460,40 +512,51 @@ m4_module_unload (const char *name, stru
++errors;
}
else
+ errors = m4_module_remove (handle, obs);
+
+ if (errors)
{
- const lt_dlinfo *info = lt_dlgetinfo (handle);
+ M4ERROR ((EXIT_FAILURE, 0,
+ _("ERROR: cannot unload module `%s': %s"),
+ name, m4_module_dlerror ()));
+ }
+}
+
+void
+m4_module_unload_all (void)
+{
+ lt_dlhandle handle = lt_dlhandle_next (0);
+ int errors = 0;
+
+ while (handle && !errors)
+ {
+ lt_dlhandle pending = handle;
+ const lt_dlinfo *info = lt_dlgetinfo (pending);
- /* Only do the actual close when the number of calls to close this
- module is equal to the number of times it was opened. */
- if (info->ref_count > 1)
+ /* We are *really* shutting down here, so freeing the module
+ data is required. */
+ if (info)
{
-#ifdef DEBUG_MODULES
- M4_DEBUG_MESSAGE2("module %s: now has %d references.",
- name, info->ref_count -1);
-#endif /* DEBUG_MODULES */
+ m4_module_data *stale
+ = lt_dlcaller_set_data (m4_caller_id, handle, 0);
+ XFREE (stale);
}
- if (info->ref_count == 1)
- {
- /* Remove the table references only when ref_count is *exactly*
- equal to 1. If m4_module_close is called again on a
- resident module after the references have already been
- removed, we needn't try to remove them again! */
- m4_symtab_remove_module_references (handle);
+ /* If we are about to unload the final reference, move on to the
+ next handle before we unload the current one. */
+ if (info->ref_count <= 1)
+ handle = lt_dlhandle_next (pending);
-#ifdef DEBUG_MODULES
- M4_DEBUG_MESSAGE1("module %s: symbols unloaded", name);
-#endif /* DEBUG_MODULES */
- }
+ errors = m4_module_remove (pending, 0);
}
if (!errors)
- m4_module_close (handle, obs);
+ errors = lt_dlexit();
if (errors)
{
M4ERROR ((EXIT_FAILURE, 0,
- _("ERROR: cannot unload module `%s': %s"),
- name, m4_module_dlerror ()));
+ _("ERROR: cannot unload all modules: %s"),
+ m4_module_dlerror ()));
}
}
Index: m4/output.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/output.c,v
retrieving revision 1.7
diff -u -p -u -r1.7 output.c
--- m4/output.c 2001/09/30 14:43:38 1.7
+++ m4/output.c 2001/09/30 22:24:19
@@ -105,7 +105,7 @@ int m4_output_current_line;
void
m4_output_init (void)
{
- diversion_table = (struct diversion *) xmalloc (sizeof (struct diversion));
+ diversion_table = XMALLOC (struct diversion, 1);
diversions = 1;
diversion_table[0].file = stdout;
diversion_table[0].buffer = NULL;
@@ -120,6 +120,14 @@ m4_output_init (void)
output_unused = 0;
}
+void
+m4_output_exit (void)
+{
+ assert (diversions = 1);
+ XFREE (diversion_table);
+}
+
+
#ifdef HAVE_MKTEMP
#ifndef HAVE_MKSTEMP
@@ -683,4 +691,3 @@ m4_freeze_diversions (file)
if (saved_number != last_inserted)
fprintf (file, "D%d,0\n\n", saved_number);
}
-
Index: m4/symtab.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/symtab.c,v
retrieving revision 1.23
diff -u -p -u -r1.23 symtab.c
--- m4/symtab.c 2001/09/30 14:43:38 1.23
+++ m4/symtab.c 2001/09/30 22:24:19
@@ -18,6 +18,11 @@
02111-1307 USA
*/
+#include "m4private.h"
+
+#define DEBUG_SYM /* Define this to see runtime debug info. */
+#undef DEBUG_SYM
+
/* This file handles all the low level work around the symbol table. The
symbol table is an abstract hash table type implemented in hash.c. Each
symbol is represented by `struct m4_symbol', which is stored in the hash
@@ -27,13 +32,13 @@
simply ordered on the stack by age. The most recently pushed definition
will then always be the first found. */
-#include "m4private.h"
-
static size_t m4_symtab_hash (const void *key);
static int m4_symtab_cmp (const void *key, const void *try);
static void m4_token_data_delete (m4_token_data *data);
static void m4_symbol_pop (m4_symbol *symbol);
static void m4_symbol_del (m4_symbol *symbol);
+static int m4_symbol_destroy (const char *name, m4_symbol *symbol,
+ void *data);
/* Pointer to symbol table. */
@@ -47,8 +52,23 @@ m4_symtab_init (void)
m4_symtab = m4_hash_new (m4_symtab_hash, m4_symtab_cmp);
}
+int
+m4_symbol_destroy (const char *name, m4_symbol *symbol, void *data)
+{
+ m4_symbol_delete (name);
+ return 0;
+}
+
+void
+m4_symtab_exit (void)
+{
+ m4_symtab_apply (m4_symbol_destroy, NULL);
+ m4_hash_delete (m4_symtab);
+ m4_hash_exit ();
+}
+
/* Return a hashvalue for a string, from GNU-emacs. */
-size_t
+static size_t
m4_symtab_hash (const void *key)
{
int val = 0;
@@ -65,7 +85,7 @@ m4_symtab_hash (const void *key)
return val;
}
-int
+static int
m4_symtab_cmp (const void *key, const void *try)
{
return (strcmp ((const char *) key, (const char *) try));
@@ -73,7 +93,7 @@ m4_symtab_cmp (const void *key, const vo
-void
+static void
m4_token_data_delete (m4_token_data *data)
{
assert (data);
@@ -167,11 +187,11 @@ m4_symbol_pushdef (const char *name)
m4_symbol *
m4_symbol_define (const char *name)
{
- m4_symbol *res = m4_symbol_lookup (name);
- if (res)
- return res;
+ m4_symbol **psymbol = (m4_symbol **) m4_hash_lookup (m4_symtab, name);
+ if (psymbol)
+ return *psymbol;
else
- m4_symbol_pushdef (name);
+ return m4_symbol_pushdef (name);
}
@@ -200,6 +220,11 @@ m4_symbol_delete (const char *name)
m4_symbol **psymbol = (m4_symbol **) m4_hash_lookup (m4_symtab, name);
assert (psymbol);
+
+#ifdef DEBUG_SYM
+ M4_DEBUG_MESSAGE1("symbol %s recycled.", name);
+#endif
+
xfree (m4_hash_remove (m4_symtab, name));
m4_symbol_del (*psymbol);
}
@@ -253,6 +278,7 @@ m4_symtab_remove_module_references (lt_d
assert (handle);
+ /* Traverse each symbol name in the hash table. */
while ((place = m4_hash_iterator_next (m4_symtab, place)))
{
m4_symbol *symbol = (m4_symbol *) m4_hash_iterator_value (place);
@@ -286,9 +312,9 @@ m4_symtab_remove_module_references (lt_d
}
}
-/* The following function is used for the cases, where we want to do
+/* The following function is used for the cases where we want to do
something to each and every symbol in the table. The function
- hack_all_symbols () traverses the symbol table, and calls a specified
+ m4_symtab_apply () traverses the symbol table, and calls a specified
function FUNC for each symbol in the table. FUNC is called with a
pointer to the symbol, and the DATA argument. */
int
@@ -327,7 +353,7 @@ symtab_debug (void)
m4_symbol *s;
int delete;
- while ((t = m4_next_token (&td)) != NULL)
+ while ((t = m4_next_token (&td)) != M4_TOKEN_EOF)
{
if (t != M4_TOKEN_WORD)
continue;
Index: src/freeze.c
===================================================================
RCS file: /cvsroot/m4/m4/src/freeze.c,v
retrieving revision 1.18
diff -u -p -u -r1.18 freeze.c
--- src/freeze.c 2001/09/30 14:43:38 1.18
+++ src/freeze.c 2001/09/30 22:24:21
@@ -128,7 +128,7 @@ produce_symbol_dump (FILE *file, m4_hash
while ((place = m4_hash_iterator_next (hash, place)))
{
- const char *symbol_name = m4_hash_iterator_key (place);
+ const char *symbol_name = (const char *) m4_hash_iterator_key
(place);
m4_symbol *symbol = m4_hash_iterator_value (place);
lt_dlhandle handle = M4_SYMBOL_HANDLE (symbol);
const char *module_name = handle ? m4_module_name (handle) :
NULL;
Index: src/m4.h
===================================================================
RCS file: /cvsroot/m4/m4/src/m4.h,v
retrieving revision 1.10
diff -u -p -u -r1.10 m4.h
--- src/m4.h 2001/09/30 14:43:38 1.10
+++ src/m4.h 2001/09/30 22:24:21
@@ -99,6 +99,7 @@ char *mktemp ();
#ifdef USE_STACKOVF
void setup_stackovf_trap (char *const *, char *const *,
void (*handler) (void));
+void stackovf_exit (void);
#endif
Index: src/main.c
===================================================================
RCS file: /cvsroot/m4/m4/src/main.c,v
retrieving revision 1.26
diff -u -p -u -r1.26 main.c
--- src/main.c 2001/09/30 14:43:38 1.26
+++ src/main.c 2001/09/30 22:24:22
@@ -516,10 +516,21 @@ warranty; not even for MERCHANTABILITY o
m4_undivert_all ();
}
- {
- struct obstack *obs = 0;
- m4_module_close_all (obs);
- }
+ m4_module_unload_all ();
+
+ /* The remaining cleanup functions systematically free all of the
+ memory we still have pointers to. By definition, if there is
+ anything left when we're done: it was caused by a memory leak.
+ Strictly, we don't need to do this, but it makes leak detection
+ a whole lot easier! */
+ m4_symtab_exit ();
+ m4_output_exit ();
+ m4_input_exit ();
+ m4_debug_exit ();
+
+#ifdef USE_STACKOVF
+ stackovf_exit ();
+#endif
exit (exit_status);
}
Index: src/stackovf.c
===================================================================
RCS file: /cvsroot/m4/m4/src/stackovf.c,v
retrieving revision 1.8
diff -u -p -u -r1.8 stackovf.c
--- src/stackovf.c 2001/09/30 14:43:38 1.8
+++ src/stackovf.c 2001/09/30 22:24:23
@@ -118,6 +118,7 @@ extern int sigstack (struct sigstack *,
extern int sigvec (int, struct sigvec *, struct sigvec *);
#endif
+static const char *stackbuf;
static const char *stackbot;
static const char *stackend;
static const char *arg0;
@@ -335,12 +336,14 @@ setup_stackovf_trap (char *const *argv,
{
stack_t ss;
+ stackbuf = (char *) xmalloc (SIGSTKSZ);
+
ss.ss_size = SIGSTKSZ;
- ss.ss_sp = xmalloc (ss.ss_size);
+ ss.ss_sp = (void *) stackbuf;
ss.ss_flags = 0;
if (sigaltstack (&ss, (stack_t *) 0) < 0)
{
- xfree (ss.ss_sp);
+ xfree (stackbuf);
error (1, errno, "sigaltstack");
}
}
@@ -350,7 +353,7 @@ setup_stackovf_trap (char *const *argv,
{
struct sigstack ss;
- char *stackbuf = xmalloc (2 * SIGSTKSZ);
+ stackbuf = (char *) xmalloc (2 * SIGSTKSZ);
ss.ss_sp = stackbuf + SIGSTKSZ;
ss.ss_onstack = 0;
@@ -406,6 +409,12 @@ Error - Do not know how to catch signals
#endif /* HAVE_SIGVEC && defined(SV_ONSTACK) */
#endif /* HAVE_SIGALTSTACK && defined(SA_ONSTACK) */
+}
+
+void
+stackovf_exit (void)
+{
+ XFREE (stackbuf);
}
#endif /* USE_STACKOVF */
--
())_. Gary V. Vaughan gary@(oranda.demon.co.uk|gnu.org)
( '/ Research Scientist http://www.oranda.demon.co.uk ,_())____
/ )= GNU Hacker http://www.gnu.org/software/libtool \' `&
`(_~)_ Tech' Author http://sources.redhat.com/autobook =`---d__/
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- FYI: 20-gary-unrevert-memory-handling-bits-of-15-gary-cleanup-from-renaming-token-data-to-symbol.patch,
Gary V. Vaughan <=