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