From fec15ecb62fe38bd4a2ac479abeb91afd649842b Mon Sep 17 00:00:00 2001 From: Martin Stjernholm <mast@lysator.liu.se> Date: Wed, 25 Apr 2007 23:58:33 +0200 Subject: [PATCH] Improved leak reports for types. Rev: src/gc.c:1.280 Rev: src/module.c:1.41 Rev: src/pike_types.c:1.296 Rev: src/pike_types.h:1.106 --- src/gc.c | 11 ++-- src/module.c | 16 ++---- src/pike_types.c | 136 ++++++++++++++++++++++++++++++++++++++++------- src/pike_types.h | 6 ++- 4 files changed, 132 insertions(+), 37 deletions(-) diff --git a/src/gc.c b/src/gc.c index c98b2b4d83..dc523bcb8e 100644 --- a/src/gc.c +++ b/src/gc.c @@ -2,7 +2,7 @@ || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. -|| $Id: gc.c,v 1.279 2007/03/31 21:41:34 grubba Exp $ +|| $Id: gc.c,v 1.280 2007/04/25 21:58:33 mast Exp $ */ #include "global.h" @@ -1778,6 +1778,9 @@ void locate_references(void *a) gc_check_all_mappings(); gc_check_all_programs(); gc_check_all_objects(); +#if defined (PIKE_DEBUG) || defined (DO_PIKE_CLEANUP) + debug_gc_check_all_types(); +#endif } GC_LEAVE; #ifdef DEBUG_MALLOC @@ -2939,9 +2942,6 @@ size_t do_gc(void *ignored, int explicit_call) n += gc_touch_all_programs(); n += gc_touch_all_objects(); #ifdef PIKE_DEBUG -#if 0 - gc_touch_all_types(); -#endif gc_touch_all_strings(); #endif if (n != (unsigned) num_objects) @@ -2964,6 +2964,9 @@ size_t do_gc(void *ignored, int explicit_call) gc_check_all_mappings(); gc_check_all_programs(); gc_check_all_objects(); +#if defined (PIKE_DEBUG) || defined (DO_PIKE_CLEANUP) + debug_gc_check_all_types(); +#endif } END_ACCEPT_UNFINISHED_TYPE_FIELDS; GC_VERBOSE_DO(fprintf(stderr, "| check: %u references in %d things, " diff --git a/src/module.c b/src/module.c index fc93a3bec2..377d3a8617 100644 --- a/src/module.c +++ b/src/module.c @@ -2,7 +2,7 @@ || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. -|| $Id: module.c,v 1.40 2006/07/04 21:31:30 mast Exp $ +|| $Id: module.c,v 1.41 2007/04/25 21:58:33 mast Exp $ */ #include "global.h" @@ -171,7 +171,7 @@ static void exit_builtin_modules(void) x->refs - (m->refs + is_static)); \ print_short_svalue (stderr, (union anything *) &x, T_TYPE); \ fputc ('\n', stderr); \ - DO_IF_DMALLOC (debug_malloc_dump_references (x, 0, 1, 0)); \ + DO_IF_DMALLOC (debug_malloc_dump_references (x, 2, 1, 0)); \ } \ } \ } \ @@ -182,6 +182,7 @@ static void exit_builtin_modules(void) REPORT_LINKED_LIST_LEAKS (mapping, first_mapping, NOTHING, T_MAPPING, "Mapping"); REPORT_LINKED_LIST_LEAKS (program, first_program, NOTHING, T_PROGRAM, "Program"); REPORT_LINKED_LIST_LEAKS (object, first_object, NOTHING, T_OBJECT, "Object"); + report_all_type_leaks(); #undef REPORT_LINKED_LIST_LEAKS @@ -223,6 +224,7 @@ static void exit_builtin_modules(void) ZAP_LINKED_LIST_LEAKS (mapping, first_mapping, NOTHING); ZAP_LINKED_LIST_LEAKS (program, first_program, NOTHING); ZAP_LINKED_LIST_LEAKS (object, first_object, NOTHING); + free_all_leaked_types(); #undef ZAP_LINKED_LIST_LEAKS @@ -238,16 +240,6 @@ static void exit_builtin_modules(void) gc_keep_markers = 0; exit_gc(); - -#ifdef DEBUG_MALLOC - { - INT32 num, size; - count_memory_in_pike_types(&num, &size); - if (num) - fprintf(stderr, "Types left: %d (%d bytes)\n", num, size); - describe_all_types(); - } -#endif } destruct_objects_to_destruct_cb(); diff --git a/src/pike_types.c b/src/pike_types.c index 5d8fdf80df..b6d22b67b5 100644 --- a/src/pike_types.c +++ b/src/pike_types.c @@ -2,7 +2,7 @@ || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. -|| $Id: pike_types.c,v 1.295 2007/04/25 16:01:22 grubba Exp $ +|| $Id: pike_types.c,v 1.296 2007/04/25 21:58:33 mast Exp $ */ #include "global.h" @@ -1923,24 +1923,6 @@ void simple_describe_type(struct pike_type *s) } } -#ifdef DEBUG_MALLOC -void describe_all_types(void) -{ - unsigned INT32 index; - - for(index = 0; index < pike_type_hash_size; index++) { - struct pike_type *t; - for (t = pike_type_hash[index]; t; t = t->next) { - if (t->refs) { - fprintf(stderr, "Type at 0x%p: ", t); - simple_describe_type(t); - fprintf(stderr, " (refs:%ld)\n", (long)t->refs); - } - } - } -} -#endif /* DEBUG_MALLOC */ - static void low_describe_type(struct pike_type *t) { char buffer[100]; @@ -2224,6 +2206,122 @@ struct pike_string *describe_type(struct pike_type *type) return free_buf(&save_buf); } +#if defined (PIKE_DEBUG) || defined (DO_PIKE_CLEANUP) + +void debug_gc_check_all_types (void) +{ + if (gc_keep_markers || Pike_in_gc == GC_PASS_LOCATE) { + unsigned INT32 index; + for (index = 0; index < pike_type_hash_size; index++) { + struct pike_type *t; + for (t = pike_type_hash[index]; t; t = t->next) { + GC_ENTER (t, T_TYPE) { + switch (t->type) { + case T_FUNCTION: + case T_MANY: + case T_TUPLE: + case T_MAPPING: + case T_OR: + case T_AND: + case PIKE_T_RING: + case PIKE_T_ATTRIBUTE: + case PIKE_T_NAME: + debug_gc_check (t->car, " as car in a type"); + debug_gc_check (t->cdr, " as cdr in a type"); + break; + case T_ARRAY: + case T_MULTISET: + case T_NOT: + case T_TYPE: + case T_PROGRAM: + debug_gc_check (t->car, " as car in a type"); + break; + case T_SCOPE: + case T_ASSIGN: + debug_gc_check (t->cdr, " as cdr in a type"); + break; +#ifdef PIKE_DEBUG + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case T_FLOAT: + case T_STRING: + case T_MIXED: + case T_VOID: + case T_ZERO: + case PIKE_T_UNKNOWN: + case T_INT: + case T_OBJECT: + break; + default: + Pike_fatal("debug_gc_check_all_types: " + "Unhandled type-node: %d\n", t->type); + break; +#endif /* PIKE_DEBUG */ + } + } GC_LEAVE; + } + } + } +} + +/* Leak reporting similar to the exit_with_cleanup code in + * exit_builtin_modules. */ + +void report_all_type_leaks (void) +{ + unsigned INT32 index; + if (!gc_keep_markers) + Pike_fatal ("Should only be called in final cleanup.\n"); + for (index = 0; index < pike_type_hash_size; index++) { + struct pike_type *t; + for (t = pike_type_hash[index]; t; t = t->next) { + struct marker *m = find_marker (t); + /* We aren't hooked in to the gc mark pass so we don't have + * markers for types with only external references. */ + INT32 m_refs = m ? m->refs : 0; + if (t->refs != m_refs) { + fprintf (stderr, "Type at %p got %d unaccounted refs: ", + t, t->refs - m_refs); + simple_describe_type (t); + fputc ('\n', stderr); +#ifdef DEBUG_MALLOC + debug_malloc_dump_references (t, 2, 1, 0); +#endif + } + } + } +} + +void free_all_leaked_types (void) +{ + unsigned INT32 index; + if (!gc_keep_markers) + Pike_fatal ("Should only be called in final cleanup.\n"); + for (index = 0; index < pike_type_hash_size; index++) { + struct pike_type *t; + for (t = pike_type_hash[index]; t; t = t->next) { + struct marker *m = find_marker (t); + INT32 m_refs = m ? m->refs : 0; + INT32 refs = t->refs; + while (refs > m_refs) { + if (m) m->flags |= GC_CLEANUP_FREED; + free_type (t); + refs--; + } + } + } +} + +#endif /* PIKE_DEBUG || DO_PIKE_CLEANUP */ + /******/ diff --git a/src/pike_types.h b/src/pike_types.h index 3657abf5d6..f55ed81549 100644 --- a/src/pike_types.h +++ b/src/pike_types.h @@ -2,7 +2,7 @@ || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. -|| $Id: pike_types.h,v 1.105 2007/04/21 20:08:26 grubba Exp $ +|| $Id: pike_types.h,v 1.106 2007/04/25 21:58:33 mast Exp $ */ #ifndef PIKE_TYPES_H @@ -213,6 +213,9 @@ void stupid_describe_type(char *a, ptrdiff_t len); void simple_describe_type(struct pike_type *s); void my_describe_type(struct pike_type *type); struct pike_string *describe_type(struct pike_type *type); +void debug_gc_check_all_types (void); +void report_all_type_leaks (void); +void free_all_leaked_types (void); TYPE_T compile_type_to_runtime_type(struct pike_type *s); struct pike_type *or_pike_types(struct pike_type *a, struct pike_type *b, @@ -330,7 +333,6 @@ void register_attribute_handler(struct pike_string *attr, #endif /* 0 */ #ifdef DEBUG_MALLOC -void describe_all_types(void); #define pop_type() ((struct pike_type *)debug_malloc_pass(debug_pop_type())) #define compiler_pop_type() ((struct pike_type *)debug_malloc_pass(debug_compiler_pop_type())) #define pop_unfinished_type() \ -- GitLab