pike.git / src / module.c

version» Context lines:

pike.git/src/module.c:1:   /*   || 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.50 2008/03/29 16:20:16 mast Exp $ + || $Id: module.c,v 1.51 2008/03/30 01:24:10 mast Exp $   */      #include "global.h"   #include "module.h"   #include "pike_macros.h"   #include "pike_error.h"   #include "builtin_functions.h"   #include "main.h"   #include "svalue.h"   #include "interpret.h"
pike.git/src/module.c:177: Inside #if defined(DO_PIKE_CLEANUP)
      /* The use of markers below only works after a gc run where it    * hasn't freed anything. Since we've destructed all objects in    * exit_main, nothing should be left after the run above, so only    * one more run is necessary. */    gc_keep_markers = 1;    do_gc (NULL, 1);      #define STATIC_ARRAYS &empty_array, &weak_empty_array,    - #define STATIC_TYPES string0_type_string, string_type_string, \ -  int_type_string, object_type_string, program_type_string, \ -  float_type_string, mixed_type_string, array_type_string, \ -  multiset_type_string, mapping_type_string, function_type_string, \ -  type_type_string, void_type_string, zero_type_string, any_type_string, \ -  weak_type_string, -  +    #define REPORT_LINKED_LIST_LEAKS(TYPE, START, STATICS, T_TYPE, NAME, \    PRINT_EXTRA) do { \    struct TYPE *x; \    for (x = START; x; x = x->next) { \    struct marker *m = find_marker (x); \    if (!m) { \    DO_IF_DEBUG ( \    fprintf (stderr, "Didn't find gc marker as expected for:\n"); \    describe_something (x, T_TYPE, 2, 2, 0, NULL); \    ); \    } \    else { \    int is_static = 0; \    /*static const*/ struct TYPE *statics[] = {STATICS NULL}; \    ptrdiff_t i; /* Use signed type to avoid warnings from gcc. */ \    for (i = 0; i < (ptrdiff_t) (NELEM (statics) - 1); i++) \    if (x == statics[i]) \    is_static = 1; \ -  +  /* Note: m->xrefs is always zero here since the mark pass \ +  * isn't run in gc_destruct_everything mode. */ \    if (x->refs != m->refs + is_static) { \    if (!leak_found) { \    fputs ("Leak(s) found at exit:\n", stderr); \    leak_found = 1; \    } \ -  fprintf (stderr, NAME " at %p got %d unaccounted references: ", \ -  x, x->refs - (m->refs + is_static)); \ +  fprintf (stderr, NAME " at %p got %d unaccounted refs " \ +  "(and %d accounted): ", \ +  x, x->refs - (m->refs + is_static), \ +  m->refs + is_static); \    safe_print_short_svalue (stderr, (union anything *) &x, T_TYPE); \ -  fputc ('\n', stderr); \ +     {PRINT_EXTRA;} \ -  +  fputc ('\n', stderr); \ +  /* describe (x); */ \    DO_IF_DMALLOC ( \    debug_malloc_dump_references (x, 2, 1, 0); \    fputc ('\n', stderr); \    ); \ -  +  DO_IF_DEBUG (m->flags |= GC_CLEANUP_LEAKED); \    } \    } \    } \    } while (0)       REPORT_LINKED_LIST_LEAKS (array, first_array, STATIC_ARRAYS, T_ARRAY, "Array", {});    REPORT_LINKED_LIST_LEAKS (multiset, first_multiset, NOTHING, T_MULTISET, "Multiset", {});    REPORT_LINKED_LIST_LEAKS (mapping, first_mapping, NOTHING, T_MAPPING, "Mapping", {});    REPORT_LINKED_LIST_LEAKS (    program, first_program, NOTHING, T_PROGRAM, "Program",    {    /* This kind of info is rarely useful - the output from    * print_short_svalue is usually enough to identify the program, and    * the dmalloc ref dump shows where it has been used.    DO_IF_DEBUG(    struct program *p = (struct program *)x; -  +  fputc ('\n', stderr);    if (p->parent) {    fprintf(stderr, " Parent is: %p\n",    p->parent);    dump_program_tables(p->parent, 6);    }    fprintf(stderr, " Symbol tables:\n");    dump_program_tables(p, 4);    );    */    }    );    REPORT_LINKED_LIST_LEAKS (    object, first_object, NOTHING, T_OBJECT, "Object", { -  DO_IF_DEBUG ( +     if (!x->prog) { -  +  fputs (" (destructed)", stderr); +  DO_IF_DEBUG ({    struct program *p = id_to_program (x->program_id);    if (p) { -  fputs ("Destructed object - program was: ", stderr); +  fputs ("\n Program for destructed object: ", stderr);    safe_print_short_svalue (stderr,    (union anything *) &p, T_PROGRAM); -  fputc ('\n', stderr); +     }    else -  fprintf (stderr, "Destructed object - " -  "program gone too, its id was %d\n", x->program_id); +  fprintf (stderr, "\n Program for destructed object gone too, " +  "its id was: %d", x->program_id); +  });    } -  ); +     });       {    size_t index;    for (index = 0; index < pike_type_hash_size; index++) { -  REPORT_LINKED_LIST_LEAKS(pike_type, pike_type_hash[index], STATIC_TYPES, PIKE_T_TYPE, "Type", {}); +  REPORT_LINKED_LIST_LEAKS(pike_type, pike_type_hash[index], NOTHING, PIKE_T_TYPE, "Type", {});    }    }      #undef REPORT_LINKED_LIST_LEAKS       /* Just remove the extra external refs reported above and do    * another gc so that we don't report the blocks again in the low    * level dmalloc reports. */    -  + #ifdef PIKE_DEBUG +  /* If we stumble on the real refs whose refcounts we're zapping, +  * we should try to handle it gracefully, and log all frees. */ +  gc_external_refs_zapped = 1; + #endif +    #if 1    /* It can be a good idea to disable this to leave the blocks    * around to be reported by an external memchecker like valgrind.    * Ideally we should only free the svalues inside these things but    * leave the blocks themselves. */      #define ZAP_LINKED_LIST_LEAKS(TYPE, START, STATICS) do { \    struct TYPE *x, *next; \    for (x = START; x; x = next) { \    struct marker *m = find_marker (x); \
pike.git/src/module.c:295:    if (m) { \    int is_static = 0; \    static const struct TYPE *statics[] = {STATICS NULL}; \    ptrdiff_t i; /* Use signed type to avoid warnings from gcc. */ \    INT32 refs; \    for (i = 0; i < (ptrdiff_t) (NELEM (statics) - 1); i++) \    if (x == statics[i]) \    is_static = 1; \    refs = x->refs; \    while (refs > m->refs + is_static) { \ -  DO_IF_DEBUG (m->flags |= GC_CLEANUP_FREED); \ +     PIKE_CONCAT(free_, TYPE) (x); \    refs--; \    } \    } \    } \    } while (0)       ZAP_LINKED_LIST_LEAKS (array, first_array, STATIC_ARRAYS);    ZAP_LINKED_LIST_LEAKS (multiset, first_multiset, NOTHING);    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(); +     -  +  { +  size_t index; +  for (index = 0; index < pike_type_hash_size; index++) { +  ZAP_LINKED_LIST_LEAKS(pike_type, pike_type_hash[index], NOTHING); +  } +  } +    #undef ZAP_LINKED_LIST_LEAKS    - #ifdef PIKE_DEBUG -  /* If we stumble on the real refs whose refcounts we've zapped -  * above we should try to handle it gracefully. */ -  gc_external_refs_zapped = 1; - #endif + #endif /* 1 */    - #endif -  +     do_gc (NULL, 1);       gc_keep_markers = 0;    exit_gc();    }       destruct_objects_to_destruct_cb();       /* Now there are no arrays/objects/programs/anything left. */