e576bb2002-10-11Martin Nilsson /* || 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. */
aedfb12002-10-09Martin Nilsson 
db3e131997-02-06Fredrik Hübinette (Hubbe) #include "global.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "module.h"
f08c182017-02-05Henrik Grubbström (Grubba) #include "pike_compiler.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
db3e131997-02-06Fredrik Hübinette (Hubbe) #include "builtin_functions.h" #include "main.h" #include "svalue.h" #include "interpret.h" #include "stralloc.h" #include "object.h" #include "mapping.h"
992e662000-07-06Fredrik Hübinette (Hubbe) #include "program_id.h"
37b0222002-01-31Marcus Comstedt #include "lex.h"
a6b1142004-12-29Henrik Grubbström (Grubba) #include "cpp.h" #include "backend.h" #include "threads.h" #include "operators.h" #include "signal_handler.h" #include "dynamic_load.h"
faf7fb2004-12-29Henrik Grubbström (Grubba) #include "gc.h" #include "multiset.h" #include "pike_types.h" #include "constants.h"
22c0842005-03-28Martin Nilsson #include "bignum.h" #include "module_support.h"
9d1f542017-01-25Henrik Grubbström (Grubba) #include "sprintf.h"
5081932018-01-18Martin Nilsson #include "pike_search.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) 
db3e131997-02-06Fredrik Hübinette (Hubbe) #include "modules/modlist_headers.h"
9eab532006-02-27Martin Stjernholm #ifndef PRE_PIKE
f173082001-02-01Fredrik Hübinette (Hubbe) #include "post_modules/modlist_headers.h"
9eab532006-02-27Martin Stjernholm #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) 
48073c2003-02-05Henrik Grubbström (Grubba) /* Define this to trace the initialization and cleanup of static modules. */ /* #define TRACE_MODULE */
59f8eb2007-05-18Henrik Grubbström (Grubba) #ifdef PIKE_EXTRA_DEBUG #define TRACE_MAIN #define TRACE_MODULE #endif
48073c2003-02-05Henrik Grubbström (Grubba) #if defined(TRACE_MAIN) || defined(TRACE_MODULE)
a91d9a2016-01-11Martin Nilsson #define TRACE(...) fprintf(stderr, __VA_ARGS__)
48073c2003-02-05Henrik Grubbström (Grubba) #else /* !TRACE_MAIN */
a91d9a2016-01-11Martin Nilsson #define TRACE(...)
48073c2003-02-05Henrik Grubbström (Grubba) #endif /* TRACE_MAIN */
24ddc71998-03-28Henrik Grubbström (Grubba) 
6c46a72004-12-29Henrik Grubbström (Grubba) static void init_builtin_modules(void) { void init_iterators(void);
d18ea62010-07-19Martin Stjernholm #ifdef DEBUG_MALLOC /* Make some statically allocated structs known to dmalloc. These * will still show up in the DO_PIKE_CLEANUP leak report if they * leak, in spite of dmalloc_accept_leak. */ dmalloc_register (&empty_array, sizeof (empty_array), DMALLOC_LOCATION()); dmalloc_accept_leak (&empty_array); dmalloc_register (&weak_empty_array, sizeof (weak_empty_array), DMALLOC_LOCATION()); dmalloc_accept_leak (&weak_empty_array); #endif
5863142018-02-05Henrik Grubbström (Grubba)  TRACE("Init String.Buffer...\n"); init_string_buffer();
a91d9a2016-01-11Martin Nilsson  TRACE("Init cpp...\n");
6c46a72004-12-29Henrik Grubbström (Grubba)  init_cpp();
e6e4432007-05-18Henrik Grubbström (Grubba) 
a91d9a2016-01-11Martin Nilsson  TRACE("Init memory counter...\n");
3e3fb42015-07-30Henrik Grubbström (Grubba)  init_mc();
a91d9a2016-01-11Martin Nilsson  TRACE("Init backend...\n");
6c46a72004-12-29Henrik Grubbström (Grubba)  init_backend();
e6e4432007-05-18Henrik Grubbström (Grubba) 
a91d9a2016-01-11Martin Nilsson  TRACE("Init iterators...\n");
6c46a72004-12-29Henrik Grubbström (Grubba)  init_iterators();
e6e4432007-05-18Henrik Grubbström (Grubba) 
a91d9a2016-01-11Martin Nilsson  TRACE("Init searching...\n");
6c46a72004-12-29Henrik Grubbström (Grubba)  init_pike_searching();
e6e4432007-05-18Henrik Grubbström (Grubba) 
a91d9a2016-01-11Martin Nilsson  TRACE("Init error handling...\n");
6c46a72004-12-29Henrik Grubbström (Grubba)  init_error();
e6e4432007-05-18Henrik Grubbström (Grubba) 
a91d9a2016-01-11Martin Nilsson  TRACE("Init threads...\n");
6c46a72004-12-29Henrik Grubbström (Grubba)  th_init();
e6e4432007-05-18Henrik Grubbström (Grubba) 
a91d9a2016-01-11Martin Nilsson  TRACE("Init operators...\n");
6c46a72004-12-29Henrik Grubbström (Grubba)  init_operators();
a91d9a2016-01-11Martin Nilsson  TRACE("Init builtin...\n");
6c46a72004-12-29Henrik Grubbström (Grubba)  init_builtin();
a91d9a2016-01-11Martin Nilsson  TRACE("Init efuns...\n");
6c46a72004-12-29Henrik Grubbström (Grubba)  init_builtin_efuns();
e6e4432007-05-18Henrik Grubbström (Grubba) 
a91d9a2016-01-11Martin Nilsson  TRACE("Init signal handling...\n");
6c46a72004-12-29Henrik Grubbström (Grubba)  init_signals();
e6e4432007-05-18Henrik Grubbström (Grubba) 
a91d9a2016-01-11Martin Nilsson  TRACE("Init dynamic loading...\n");
6c46a72004-12-29Henrik Grubbström (Grubba)  init_dynamic_load();
d980002013-05-27Martin Nilsson 
a91d9a2016-01-11Martin Nilsson  TRACE("Init sprintf...\n");
d980002013-05-27Martin Nilsson  init_sprintf();
6c46a72004-12-29Henrik Grubbström (Grubba) } static void exit_builtin_modules(void) { #ifdef DO_PIKE_CLEANUP void exit_iterators(void); /* Clear various global references. */
d980002013-05-27Martin Nilsson  exit_sprintf();
6c46a72004-12-29Henrik Grubbström (Grubba)  exit_pike_searching(); exit_object(); exit_signals();
4664532010-05-31Henrik Grubbström (Grubba)  exit_builtin_efuns();
6c46a72004-12-29Henrik Grubbström (Grubba)  exit_builtin(); exit_cpp();
5863142018-02-05Henrik Grubbström (Grubba)  exit_string_buffer();
6c46a72004-12-29Henrik Grubbström (Grubba)  cleanup_interpret(); exit_builtin_constants(); cleanup_module_support(); exit_operators(); exit_iterators();
a36dea2018-02-26Henrik Grubbström (Grubba)  exit_mc();
6c46a72004-12-29Henrik Grubbström (Grubba)  cleanup_program(); cleanup_error(); exit_backend(); cleanup_gc(); cleanup_pike_types();
09a5732008-08-05Martin Stjernholm #ifdef PIKE_THREADS
6c46a72004-12-29Henrik Grubbström (Grubba)  /* This zaps Pike_interpreter.thread_state among other things, so * THREADS_ALLOW/DISALLOW are NOPs beyond this point. */ th_cleanup();
09a5732008-08-05Martin Stjernholm #endif
c1f4762008-11-02Henrik Grubbström (Grubba)  free_all_pike_list_node_blocks();
6c46a72004-12-29Henrik Grubbström (Grubba)  free_svalue(& throw_value);
1ab4ac2008-01-26Martin Stjernholm  mark_free_svalue (&throw_value);
6c46a72004-12-29Henrik Grubbström (Grubba)  do_gc(NULL, 1); if (exit_with_cleanup) { int leak_found = 0;
09a5732008-08-05Martin Stjernholm #ifdef PIKE_THREADS
f8a04f2008-08-05Martin Stjernholm  if(count_pike_threads())
6c46a72004-12-29Henrik Grubbström (Grubba)  {
4aa6b52008-08-05Martin Stjernholm  fprintf(stderr,"Cleanup-on-exit aborted " "because %d thread(s) still are running.\n", count_pike_threads());
6c46a72004-12-29Henrik Grubbström (Grubba)  exit_with_cleanup = 0; return; } #endif #ifdef DEBUG_MALLOC search_all_memheaders_for_references(); #endif /* The use of markers below only works after a gc run where it
b245af2008-06-23Martin Stjernholm  * hasn't freed anything. Since we've destructed all live objects * in exit_modules, nothing should be left after the run above, so * only one more run is necessary. */
6c46a72004-12-29Henrik Grubbström (Grubba)  gc_keep_markers = 1; do_gc (NULL, 1);
b733792006-07-04Martin Stjernholm #define STATIC_ARRAYS &empty_array, &weak_empty_array,
6c46a72004-12-29Henrik Grubbström (Grubba) 
cd9dfa2008-03-29Martin Stjernholm #define REPORT_LINKED_LIST_LEAKS(TYPE, START, STATICS, T_TYPE, NAME, \ PRINT_EXTRA) do { \
6c46a72004-12-29Henrik Grubbström (Grubba)  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; \
59f8eb2007-05-18Henrik Grubbström (Grubba)  /*static const*/ struct TYPE *statics[] = {STATICS NULL}; \
6c46a72004-12-29Henrik Grubbström (Grubba)  ptrdiff_t i; /* Use signed type to avoid warnings from gcc. */ \
b733792006-07-04Martin Stjernholm  for (i = 0; i < (ptrdiff_t) (NELEM (statics) - 1); i++) \
6c46a72004-12-29Henrik Grubbström (Grubba)  if (x == statics[i]) \ is_static = 1; \
97a7332008-03-30Martin Stjernholm  /* Note: m->xrefs is always zero here since the mark pass \ * isn't run in gc_destruct_everything mode. */ \
6c46a72004-12-29Henrik Grubbström (Grubba)  if (x->refs != m->refs + is_static) { \ if (!leak_found) { \ fputs ("Leak(s) found at exit:\n", stderr); \ leak_found = 1; \ } \
97a7332008-03-30Martin Stjernholm  fprintf (stderr, NAME " at %p got %d unaccounted refs " \ "(and %d accounted): ", \ x, x->refs - (m->refs + is_static), \ m->refs + is_static); \
cd9dfa2008-03-29Martin Stjernholm  safe_print_short_svalue (stderr, (union anything *) &x, T_TYPE); \ {PRINT_EXTRA;} \
97a7332008-03-30Martin Stjernholm  fputc ('\n', stderr); \ /* describe (x); */ \
cd9dfa2008-03-29Martin Stjernholm  DO_IF_DMALLOC ( \ debug_malloc_dump_references (x, 2, 1, 0); \ fputc ('\n', stderr); \ ); \
97a7332008-03-30Martin Stjernholm  DO_IF_DEBUG (m->flags |= GC_CLEANUP_LEAKED); \
6c46a72004-12-29Henrik Grubbström (Grubba)  } \ } \ } \ } while (0)
cd9dfa2008-03-29Martin Stjernholm  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;
97a7332008-03-30Martin Stjernholm  fputc ('\n', stderr);
cd9dfa2008-03-29Martin Stjernholm  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", {
97a7332008-03-30Martin Stjernholm  if (!x->prog) { fputs (" (destructed)", stderr); DO_IF_DEBUG ({ struct program *p = id_to_program (x->program_id); if (p) { fputs ("\n Program for destructed object: ", stderr); safe_print_short_svalue (stderr, (union anything *) &p, T_PROGRAM); } else fprintf (stderr, "\n Program for destructed object gone too, " "its id was: %d", x->program_id); }); }
cd9dfa2008-03-29Martin Stjernholm  });
6c46a72004-12-29Henrik Grubbström (Grubba) 
59f8eb2007-05-18Henrik Grubbström (Grubba)  { size_t index;
db8ba12017-08-19Henrik Grubbström (Grubba)  for (index = 0; index <= pike_type_hash_size; index++) {
97a7332008-03-30Martin Stjernholm  REPORT_LINKED_LIST_LEAKS(pike_type, pike_type_hash[index], NOTHING, PIKE_T_TYPE, "Type", {});
59f8eb2007-05-18Henrik Grubbström (Grubba)  } }
6c46a72004-12-29Henrik Grubbström (Grubba) #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. */
97a7332008-03-30Martin Stjernholm #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
3fd1ea2008-06-02Martin Stjernholm #ifdef VALGRIND_DO_LEAK_CHECK /* Let valgrind print a leak report before we free the leaked * blocks. Ideally we should only free the svalues inside them * below and make the report afterwards. */ VALGRIND_DO_LEAK_CHECK; #endif
6c46a72004-12-29Henrik Grubbström (Grubba)  #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); \ next = x->next; \ if (m) { \ int is_static = 0; \
b733792006-07-04Martin Stjernholm  static const struct TYPE *statics[] = {STATICS NULL}; \
6c46a72004-12-29Henrik Grubbström (Grubba)  ptrdiff_t i; /* Use signed type to avoid warnings from gcc. */ \ INT32 refs; \
b733792006-07-04Martin Stjernholm  for (i = 0; i < (ptrdiff_t) (NELEM (statics) - 1); i++) \
6c46a72004-12-29Henrik Grubbström (Grubba)  if (x == statics[i]) \ is_static = 1; \ refs = x->refs; \ while (refs > m->refs + is_static) { \ PIKE_CONCAT(free_, TYPE) (x); \ refs--; \ } \ } \ } \ } while (0) ZAP_LINKED_LIST_LEAKS (array, first_array, STATIC_ARRAYS);
b733792006-07-04Martin Stjernholm  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);
6c46a72004-12-29Henrik Grubbström (Grubba) 
97a7332008-03-30Martin Stjernholm  { size_t index;
db8ba12017-08-19Henrik Grubbström (Grubba)  for (index = 0; index <= pike_type_hash_size; index++) {
97a7332008-03-30Martin Stjernholm  ZAP_LINKED_LIST_LEAKS(pike_type, pike_type_hash[index], NOTHING); } }
6c46a72004-12-29Henrik Grubbström (Grubba) 
97a7332008-03-30Martin Stjernholm #undef ZAP_LINKED_LIST_LEAKS
6c46a72004-12-29Henrik Grubbström (Grubba)  do_gc (NULL, 1); gc_keep_markers = 0; exit_gc(); } destruct_objects_to_destruct_cb(); /* Now there are no arrays/objects/programs/anything left. */ really_clean_up_interpret();
74e3df2014-05-25Henrik Grubbström (Grubba)  late_exit_object();
6c46a72004-12-29Henrik Grubbström (Grubba)  cleanup_callbacks(); free_all_callable_blocks(); cleanup_pike_type_table(); cleanup_shared_string_table(); free_dynamic_load(); first_mapping=0; free_all_mapping_blocks(); first_object=0; free_all_object_blocks(); first_program=0; free_all_program_blocks(); exit_multiset();
b24c9e2008-06-29Martin Nilsson #endif /* DO_PIKE_CLEANUP */
6c46a72004-12-29Henrik Grubbström (Grubba) }
db3e131997-02-06Fredrik Hübinette (Hubbe) typedef void (*modfun)(void);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
db3e131997-02-06Fredrik Hübinette (Hubbe) struct static_module
5267b71995-08-09Fredrik Hübinette (Hubbe) {
db3e131997-02-06Fredrik Hübinette (Hubbe)  char *name; modfun init; modfun exit;
859fc32014-01-06Henrik Grubbström (Grubba)  int semidynamic;
db3e131997-02-06Fredrik Hübinette (Hubbe) };
5267b71995-08-09Fredrik Hübinette (Hubbe) 
5a59872004-09-19Martin Nilsson static const struct static_module module_list[] = {
859fc32014-01-06Henrik Grubbström (Grubba)  { "Builtin", init_builtin_modules, exit_builtin_modules, 0 }
db3e131997-02-06Fredrik Hübinette (Hubbe) #include "modules/modlist.h"
9eab532006-02-27Martin Stjernholm #ifndef PRE_PIKE
f173082001-02-01Fredrik Hübinette (Hubbe) #include "post_modules/modlist.h"
9eab532006-02-27Martin Stjernholm #endif
db3e131997-02-06Fredrik Hübinette (Hubbe) };
859fc32014-01-06Henrik Grubbström (Grubba) /* The follwing are used to simulate dlopen() et al. */ const struct static_module *find_semidynamic_module(const char *name, int namelen) { unsigned int e; for(e=0;e<NELEM(module_list);e++) { if (module_list[e].semidynamic && !strncmp(module_list[e].name, name, namelen) && !module_list[e].name[namelen]) {
a91d9a2016-01-11Martin Nilsson  TRACE("Found semidynamic module #%d: \"%s\"...\n", e, module_list[e].name);
859fc32014-01-06Henrik Grubbström (Grubba)  return module_list+e; } } return NULL; } void *get_semidynamic_init_fun(const struct static_module *sm) { if (!sm) return NULL; return sm->init; } void *get_semidynamic_exit_fun(const struct static_module *sm) { if (!sm) return NULL; return sm->exit; }
6c3a6f2013-11-20Henrik Grubbström (Grubba) /*! @decl object _static_modules *! *! This is an object containing the classes for all static *! (ie non-dynamic) C-modules. *! *! In a typic Pike with support for dynamic modules the contained *! module classes are: *! @dl *! @item @[Builtin] *! @item @[Gmp] *! @item @[_Stdio] *! @item @[_math] *! @item @[_system] *! @enddl *! *! If the Pike binary lacks support for dynamic modules, all C-modules *! will show up here. */
db3e131997-02-06Fredrik Hübinette (Hubbe) void init_modules(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
1cb5d52004-04-14Henrik Grubbström (Grubba)  struct program *p = NULL;
766bc82004-10-16Marcus Agehall  volatile unsigned int e;
37b0222002-01-31Marcus Comstedt 
e021fe2008-04-14Henrik Grubbström (Grubba)  enter_compiler(NULL, 1);
c712e71998-04-23Fredrik Hübinette (Hubbe)  start_new_program();
992e662000-07-06Fredrik Hübinette (Hubbe)  Pike_compiler->new_program->id=PROG___BUILTIN_ID;
db3e131997-02-06Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  for(e=0;e<NELEM(module_list);e++) {
37b0222002-01-31Marcus Comstedt  JMP_BUF recovery;
1cb5d52004-04-14Henrik Grubbström (Grubba)  if (!p) { start_new_program();
75876b2004-04-14Henrik Grubbström (Grubba)  p = Pike_compiler->new_program;
1cb5d52004-04-14Henrik Grubbström (Grubba)  }
859fc32014-01-06Henrik Grubbström (Grubba)  if (module_list[e].semidynamic) continue;
37b0222002-01-31Marcus Comstedt  if(SETJMP(recovery)) {
1cb5d52004-04-14Henrik Grubbström (Grubba)  /* FIXME: We could loop here until we find p. */
37b0222002-01-31Marcus Comstedt  free_program(end_program());
1cb5d52004-04-14Henrik Grubbström (Grubba)  p = NULL;
37b0222002-01-31Marcus Comstedt  call_handle_error(); } else {
a91d9a2016-01-11Martin Nilsson  TRACE("Initializing static module #%d: \"%s\"...\n", e, module_list[e].name);
37b0222002-01-31Marcus Comstedt  module_list[e].init();
0bd1472004-04-15Henrik Grubbström (Grubba)  if ( #if 0 Pike_compiler->new_program->num_identifier_references #else /* !0 */ 1 #endif /* 0 */ ) {
1cb5d52004-04-14Henrik Grubbström (Grubba)  debug_end_class(module_list[e].name,strlen(module_list[e].name),0); p = NULL; } else { /* No identifier references -- Disabled module. */ }
37b0222002-01-31Marcus Comstedt  } UNSETJMP(recovery);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
1cb5d52004-04-14Henrik Grubbström (Grubba)  if (p) free_program(end_program());
75367d2014-08-22Arne Goedeke  push_static_text("_static_modules");
c712e71998-04-23Fredrik Hübinette (Hubbe)  push_object(low_clone(p=end_program())); f_add_constant(2); free_program(p);
e021fe2008-04-14Henrik Grubbström (Grubba)  exit_compiler();
5267b71995-08-09Fredrik Hübinette (Hubbe) }
db3e131997-02-06Fredrik Hübinette (Hubbe) void exit_modules(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
37b0222002-01-31Marcus Comstedt  JMP_BUF recovery;
766bc82004-10-16Marcus Agehall  volatile int e;
00538d2003-03-26Martin Nilsson 
bd18892005-01-01Henrik Grubbström (Grubba) #ifdef DO_PIKE_CLEANUP size_t count; if (exit_with_cleanup) {
09a5732008-08-05Martin Stjernholm  /* Kill the threads and destruct all remaining objects while we * have a proper execution environment. The downside is that the * leak report below will always report destructed objects. We use * the gc in a special mode for this to get a reasonably sane * destruct order. */ #ifdef PIKE_THREADS cleanup_all_other_threads(); #endif
bd18892005-01-01Henrik Grubbström (Grubba)  gc_destruct_everything = 1; count = do_gc (NULL, 1); while (count) { size_t new_count = do_gc (NULL, 1); if (new_count >= count) {
f76ace2017-11-05Henrik Grubbström (Grubba)  fprintf (stderr, "Some _destruct function is creating new objects "
bd18892005-01-01Henrik Grubbström (Grubba)  "during final cleanup - can't exit cleanly.\n"); break; } count = new_count; }
14a89b2007-05-13Martin Stjernholm #ifdef PIKE_DEBUG if (!count) { struct object *o; for (o = first_object; o; o = o->next)
5c4fc12007-05-13Martin Stjernholm  if (gc_object_is_live (o))
14a89b2007-05-13Martin Stjernholm  gc_fatal (o, 0, "Object missed in gc_destruct_everything mode.\n"); for (o = objects_to_destruct; o; o = o->next)
5c4fc12007-05-13Martin Stjernholm  if (gc_object_is_live (o))
14a89b2007-05-13Martin Stjernholm  gc_fatal (o, 0, "Object missed in gc_destruct_everything mode" " (is on objects_to_destruct list).\n"); }
b24c9e2008-06-29Martin Nilsson #endif /* PIKE_DEBUG */
bd18892005-01-01Henrik Grubbström (Grubba)  gc_destruct_everything = 0;
ac9b152006-01-25Martin Stjernholm  exit_cleanup_in_progress = 1; /* Warn about object creation from now on. */
bd18892005-01-01Henrik Grubbström (Grubba)  } /* Unload dynamic modules before static ones. */ exit_dynamic_load();
b24c9e2008-06-29Martin Nilsson #endif /* DO_PIKE_CLEANUP */
00538d2003-03-26Martin Nilsson 
db3e131997-02-06Fredrik Hübinette (Hubbe)  for(e=NELEM(module_list)-1;e>=0;e--)
37b0222002-01-31Marcus Comstedt  {
859fc32014-01-06Henrik Grubbström (Grubba)  if (module_list[e].semidynamic) continue;
37b0222002-01-31Marcus Comstedt  if(SETJMP(recovery)) call_handle_error();
48073c2003-02-05Henrik Grubbström (Grubba)  else {
a91d9a2016-01-11Martin Nilsson  TRACE("Exiting static module #%d: \"%s\"...\n", e, module_list[e].name);
37b0222002-01-31Marcus Comstedt  module_list[e].exit();
48073c2003-02-05Henrik Grubbström (Grubba)  }
37b0222002-01-31Marcus Comstedt  UNSETJMP(recovery); }
5267b71995-08-09Fredrik Hübinette (Hubbe) }