diff --git a/src/array.h b/src/array.h index ba67be304f55ef1709988793ccd5c6c1d39fe829..95d54b1b9ec80048a9397595d7a432f48df3002c 100644 --- a/src/array.h +++ b/src/array.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: array.h,v 1.58 2004/03/17 15:27:26 grubba Exp $ +|| $Id: array.h,v 1.59 2004/04/18 02:16:05 mast Exp $ */ #ifndef ARRAY_H @@ -68,7 +68,16 @@ extern struct array *gc_internal_array; #define PIKE_ARRAY_OP_SUB PIKE_MINTERM(PIKE_ARRAY_OP_TAKE_A,PIKE_ARRAY_OP_SKIP_A ,PIKE_ARRAY_OP_SKIP_B) -#define free_array(V) do{ struct array *v_=(V); debug_malloc_touch(v_); if(!sub_ref(v_)) really_free_array(v_); }while(0) +#define free_array(V) do{ \ + struct array *v_=(V); \ + debug_malloc_touch(v_); \ + DO_IF_PIKE_CLEANUP ( \ + if (gc_external_refs_zapped) \ + gc_check_zapped (v_, PIKE_T_ARRAY, __FILE__, __LINE__); \ + ); \ + if(!sub_ref(v_)) \ + really_free_array(v_); \ + }while(0) #define allocate_array(X) low_allocate_array((X),0) #define allocate_array_no_init(X,Y) low_allocate_array((X),(Y)) diff --git a/src/dmalloc.h b/src/dmalloc.h index 0149c073f8741a52ba720d79fbf80aece4a4db07..ae0260296fe26bd0a949a880568d3e53b13b7c9e 100644 --- a/src/dmalloc.h +++ b/src/dmalloc.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: dmalloc.h,v 1.49 2004/04/03 18:24:24 mast Exp $ +|| $Id: dmalloc.h,v 1.50 2004/04/18 02:16:05 mast Exp $ */ #ifndef DMALLOC_H @@ -35,6 +35,8 @@ extern size_t dmalloc_tracelogptr; #if defined (PIKE_DEBUG) && defined (DO_PIKE_CLEANUP) extern int verbose_debug_exit; +extern int gc_external_refs_zapped; +void gc_check_zapped (void *a, TYPE_T type, const char *file, int line); #endif #ifdef DO_PIKE_CLEANUP diff --git a/src/gc.c b/src/gc.c index 6f92fe31696d7292950e68f26c71447a21103f56..6daa608ae7364c2e324302dfa867e1693927e820 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.252 2004/04/17 23:35:53 mast Exp $ +|| $Id: gc.c,v 1.253 2004/04/18 02:16:05 mast Exp $ */ #include "global.h" @@ -33,7 +33,7 @@ struct callback *gc_evaluator_callback=0; #include "block_alloc.h" -RCSID("$Id: gc.c,v 1.252 2004/04/17 23:35:53 mast Exp $"); +RCSID("$Id: gc.c,v 1.253 2004/04/18 02:16:05 mast Exp $"); int gc_enabled = 1; @@ -321,10 +321,11 @@ int attempt_to_identify(void *something, void **inblock) if(safe_debug_findstring((struct pike_string *)something)) return T_STRING; - for (i = 0; i < pike_type_hash_size; i++) - for (t = pike_type_hash[i]; t; t = t->next) - if (t == (struct pike_type *) something) - return T_TYPE; + if (pike_type_hash) + for (i = 0; i < pike_type_hash_size; i++) + for (t = pike_type_hash[i]; t; t = t->next) + if (t == (struct pike_type *) something) + return T_TYPE; for (c = first_callable; c; c = c->next) if (c == (struct callable *) something) @@ -1528,7 +1529,22 @@ static void cleanup_markers (void) { #ifdef DO_PIKE_CLEANUP size_t e=0; - struct marker *h; + + if (gc_keep_markers) { + /* Carry over any GC_CLEANUP_FREED flags but reinitialize them + * otherwise. */ + for(e=0;e<marker_hash_table_size;e++) { + struct marker *m; + for (m = marker_hash_table[e]; m; m = m->next) { + m->flags &= GC_CLEANUP_FREED; + m->refs = m->weak_refs = m->xrefs = 0; + m->saved_refs = -1; + m->frame = 0; + } + } + return; + } + for(e=0;e<marker_hash_table_size;e++) while(marker_hash_table[e]) remove_marker(marker_hash_table[e]->data); @@ -1536,7 +1552,6 @@ static void cleanup_markers (void) exit_marker_hash(); } - static void init_gc(void) { #ifdef PIKE_DEBUG @@ -1544,16 +1559,16 @@ static void init_gc(void) /* The marker hash table is left around after a previous gc if * gc_keep_markers is set. */ if (marker_hash_table) cleanup_markers(); + if (!marker_hash_table) #endif - - low_init_marker_hash(num_objects); + low_init_marker_hash(num_objects); get_marker(rec_list.data); /* Used to simplify fencepost conditions. */ #ifdef PIKE_DEBUG } #endif } -static void exit_gc(void) +void exit_gc(void) { if (gc_evaluator_callback) { remove_callback(gc_evaluator_callback); @@ -1764,6 +1779,16 @@ int gc_mark_external (void *a, const char *place) return 0; } +#ifdef DO_PIKE_CLEANUP +void gc_check_zapped (void *a, TYPE_T type, const char *file, int line) +{ + struct marker *m = find_marker (a); + if (m && (m->flags & GC_CLEANUP_FREED)) + fprintf (stderr, "Free of leaked %s %p from %s:%d, %d refs remaining\n", + get_name_of_type (type), a, file, line, *(INT32 *)a - 1); +} +#endif + void debug_really_free_gc_frame(struct gc_frame *l) { if (l->frameflags & GC_LINK_FREED) diff --git a/src/gc.h b/src/gc.h index f773cf9a8290114c855d72915479ced6f261e629..3c3307e66750c4a8b415f821027d52be9f4a13ab 100644 --- a/src/gc.h +++ b/src/gc.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: gc.h,v 1.111 2004/03/19 02:23:26 mast Exp $ +|| $Id: gc.h,v 1.112 2004/04/18 02:16:05 mast Exp $ */ #ifndef GC_H @@ -87,7 +87,6 @@ extern int gc_destruct_everything; #if defined (PIKE_DEBUG) && defined (DO_PIKE_CLEANUP) extern int gc_keep_markers; -extern int gc_external_refs_zapped; #else #define gc_keep_markers 0 #endif @@ -242,6 +241,9 @@ struct marker /* The thing has been visited by gc_checked_as_weak(). */ #define GC_WATCHED 0x01000000 /* The thing has been set under watch by gc_watch(). */ +#define GC_CLEANUP_FREED 0x02000000 +/* The thing was freed by the cleanup code under the assumption that + * references were lost. */ #endif #ifdef PIKE_DEBUG @@ -290,6 +292,7 @@ void gc_watch(void *a); void debug_gc_touch(void *a); PMOD_EXPORT int real_gc_check(void *a); int real_gc_check_weak(void *a); +void exit_gc(void); void locate_references(void *a); void debug_gc_add_extra_ref(void *a); void debug_gc_free_extra_ref(void *a); diff --git a/src/main.c b/src/main.c index e152cf19b92f511782251e1b4e8f8ed8b7959bdb..1b5549bf7951cbb9f4175ee531d38ce651ce956c 100644 --- a/src/main.c +++ b/src/main.c @@ -2,11 +2,11 @@ || 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: main.c,v 1.199 2004/04/06 15:37:55 nilsson Exp $ +|| $Id: main.c,v 1.200 2004/04/18 02:16:05 mast Exp $ */ #include "global.h" -RCSID("$Id: main.c,v 1.199 2004/04/06 15:37:55 nilsson Exp $"); +RCSID("$Id: main.c,v 1.200 2004/04/18 02:16:05 mast Exp $"); #include "fdlib.h" #include "backend.h" #include "module.h" @@ -1066,8 +1066,10 @@ void low_exit_main(void) for (i = 0; i < (ptrdiff_t) NELEM (statics); i++) \ if (x == statics[i]) \ is_static = 1; \ - while (x->refs > m->refs + is_static) \ + while (x->refs > m->refs + is_static) { \ + m->flags |= GC_CLEANUP_FREED; \ PIKE_CONCAT(free_, TYPE) (x); \ + } \ } \ } \ } while (0) @@ -1084,9 +1086,11 @@ void low_exit_main(void) * above we should try to handle it gracefully. */ gc_external_refs_zapped = 1; - gc_keep_markers = 0; do_gc (NULL, 1); + gc_keep_markers = 0; + exit_gc(); + #ifdef DEBUG_MALLOC { INT32 num, size; diff --git a/src/mapping.h b/src/mapping.h index c71565e5405cb4138e70ddd2ac878395752a9e98..21009355045e3e2be3be75b6c30247deb5a27dab 100644 --- a/src/mapping.h +++ b/src/mapping.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: mapping.h,v 1.53 2004/03/22 19:35:44 mast Exp $ +|| $Id: mapping.h,v 1.54 2004/04/18 02:16:06 mast Exp $ */ #ifndef MAPPING_H @@ -82,7 +82,16 @@ extern struct mapping *gc_internal_mapping; for(((k = MD_KEYPAIRS((m)->data, (m)->data->hashsize)), e=0) DO_IF_DMALLOC( ?0:(debug_malloc_touch(m),debug_malloc_touch((m)->data)) ) ; e<(m)->data->size; e++,k++) #endif /* PIKE_MAPPING_KEYPAIR_LOOP */ -#define free_mapping(M) do{ struct mapping *m_=(M); debug_malloc_touch(m_); if(!sub_ref(m_)) really_free_mapping(m_); }while(0) +#define free_mapping(M) do{ \ + struct mapping *m_=(M); \ + debug_malloc_touch(m_); \ + DO_IF_PIKE_CLEANUP ( \ + if (gc_external_refs_zapped) \ + gc_check_zapped (m_, PIKE_T_MAPPING, __FILE__, __LINE__); \ + ); \ + if(!sub_ref(m_)) \ + really_free_mapping(m_); \ + }while(0) #define free_mapping_data(M) do{ \ struct mapping_data *md_=(M); \ diff --git a/src/multiset.h b/src/multiset.h index b7c8206834378acbaed8edb9fae94f9d2f4b4378..561f4e5a1b21b594be767abade68e3cf271df150 100644 --- a/src/multiset.h +++ b/src/multiset.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: multiset.h,v 1.33 2004/04/06 15:37:55 nilsson Exp $ +|| $Id: multiset.h,v 1.34 2004/04/18 02:16:06 mast Exp $ */ #ifndef MULTISET_H @@ -224,6 +224,10 @@ PMOD_PROTO void really_free_multiset (struct multiset *l); #define free_multiset(L) do { \ struct multiset *_ms_ = (L); \ debug_malloc_touch (_ms_); \ + DO_IF_PIKE_CLEANUP ( \ + if (gc_external_refs_zapped) \ + gc_check_zapped (_ms_, PIKE_T_MULTISET, __FILE__, __LINE__); \ + ); \ if (!sub_ref (_ms_)) really_free_multiset (_ms_); \ } while (0) diff --git a/src/object.h b/src/object.h index e6f97a67f1a3f2b6aec64a00e03c3725dd5b3a07..d9817071077d194cc6b1ed03f00b8739143b6615 100644 --- a/src/object.h +++ b/src/object.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: object.h,v 1.81 2004/03/15 22:47:15 mast Exp $ +|| $Id: object.h,v 1.82 2004/04/18 02:16:06 mast Exp $ */ #ifndef OBJECT_H @@ -38,7 +38,17 @@ extern struct program *magic_set_index_program; extern struct program *magic_indices_program; extern struct program *magic_values_program; -#define free_object(O) do{ struct object *o_=(O); debug_malloc_touch(o_); debug_malloc_touch(o_->storage); if(!sub_ref(o_)) schedule_really_free_object(o_); }while(0) +#define free_object(O) do{ \ + struct object *o_=(O); \ + debug_malloc_touch(o_); \ + debug_malloc_touch(o_->storage); \ + DO_IF_PIKE_CLEANUP ( \ + if (gc_external_refs_zapped) \ + gc_check_zapped (o_, PIKE_T_OBJECT, __FILE__, __LINE__); \ + ); \ + if(!sub_ref(o_)) \ + schedule_really_free_object(o_); \ + }while(0) #ifdef DEBUG_MALLOC #define PIKE_OBJ_STORAGE(O) ((char *)debug_malloc_pass( (O)->storage )) diff --git a/src/program.c b/src/program.c index 618fb671da8cdcf48304ae3755a65729209b2565..e5967e378abac6c766dfd62dab5694fc4d9cf365 100644 --- a/src/program.c +++ b/src/program.c @@ -2,11 +2,11 @@ || 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: program.c,v 1.562 2004/04/17 15:18:52 marcus Exp $ +|| $Id: program.c,v 1.563 2004/04/18 02:16:06 mast Exp $ */ #include "global.h" -RCSID("$Id: program.c,v 1.562 2004/04/17 15:18:52 marcus Exp $"); +RCSID("$Id: program.c,v 1.563 2004/04/18 02:16:06 mast Exp $"); #include "program.h" #include "object.h" #include "dynamic_buffer.h" @@ -2340,6 +2340,7 @@ static void exit_program_struct(struct program *p) #ifdef PIKE_DEBUG if (p->refs) { #ifdef DEBUG_MALLOC + fprintf (stderr, "Program to be freed still got %d references:\n", p->refs); describe_something(p, T_PROGRAM, 0,2,0, NULL); #endif Pike_fatal("Program to be freed still got %d references.\n", p->refs); diff --git a/src/program.h b/src/program.h index 12cdc0f965800072f88c4ab40dd2e6db25f3aa40..fbc0e413afbfb7c4b86a3d2c436563eeab829266 100644 --- a/src/program.h +++ b/src/program.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: program.h,v 1.201 2004/03/16 12:46:51 grubba Exp $ +|| $Id: program.h,v 1.202 2004/04/18 02:16:06 mast Exp $ */ #ifndef PROGRAM_H @@ -564,7 +564,16 @@ static inline int CHECK_IDREF_RANGE (int x, const struct program *p) #define FIND_LFUN(P,N) ( dmalloc_touch(struct program *,(P))->flags & PROGRAM_FIXED?((P)->lfuns[(N)]):low_find_lfun((P), (N)) ) #define QUICK_FIND_LFUN(P,N) (dmalloc_touch(struct program *,(P))->lfuns[N]) -#define free_program(p) do{ struct program *_=(p); debug_malloc_touch(_); if(!sub_ref(_)) really_free_program(_); }while(0) +#define free_program(p) do{ \ + struct program *_=(p); \ + debug_malloc_touch(_); \ + DO_IF_PIKE_CLEANUP ( \ + if (gc_external_refs_zapped) \ + gc_check_zapped (_, PIKE_T_PROGRAM, __FILE__, __LINE__); \ + ); \ + if(!sub_ref(_)) \ + really_free_program(_); \ + }while(0) BLOCK_ALLOC_FILL_PAGES(program, n/a)