+
+Fri Jan 21 15:29:27 CET 2005 Paolo Molaro <lupus@ximian.com>
+
+ * domain.c, appdomain.c, assembly.c, image.c, metadata-internals.h,
+ reflection.c: properly refcount images and assemblies, many leaks fixed.
+
2005-01-20 Gonzalo Paniagua Javier <gonzalo@ximian.com>
* threadpool.c: increase the timeout for threads in the thread pool to
return; /* This is ok while no lazy loading of assemblies */
}
+ mono_assembly_addref (ass);
g_hash_table_insert (domain->assemblies_by_name, (gpointer) ass->aname.name, ass);
domain->assemblies = g_list_prepend (domain->assemblies, ass);
mono_domain_unlock (domain);
g_warning (thread_data.failure_reason);
g_free (thread_data.failure_reason);
+ thread_data.failure_reason = NULL;
ex = mono_get_exception_cannot_unload_appdomain (thread_data.failure_reason);
return encode_public_tok (public_tok, len);
}
+void
+mono_assembly_addref (MonoAssembly *assembly)
+{
+ EnterCriticalSection (&assemblies_mutex);
+ assembly->ref_count++;
+ LeaveCriticalSection (&assemblies_mutex);
+}
+
void
mono_assembly_load_reference (MonoImage *image, int index)
{
}
}
- if (reference == NULL)
+ EnterCriticalSection (&assemblies_mutex);
+ if (reference == NULL) {
/* Flag as not found */
reference = (gpointer)-1;
+ } else {
+ reference->ref_count++;
+ }
- EnterCriticalSection (&assemblies_mutex);
if (!image->references [index])
image->references [index] = reference;
LeaveCriticalSection (&assemblies_mutex);
ass = g_new0 (MonoAssembly, 1);
ass->basedir = base_dir;
ass->image = image;
+ ass->ref_count = 1;
mono_assembly_fill_assembly_name (image, &ass->aname);
g_return_if_fail (assembly != NULL);
EnterCriticalSection (&assemblies_mutex);
+ /*g_print ("destroy assembly %p %d (%s)\n", assembly, assembly->ref_count, assembly->image->name);*/
+ g_assert (assembly->ref_count > 0);
if (--assembly->ref_count != 0) {
LeaveCriticalSection (&assemblies_mutex);
return;
mono_image_close (assembly->image);
g_free (assembly->basedir);
- g_free (assembly);
+ if (!assembly->dynamic)
+ g_free (assembly);
}
MonoImage*
mono_assembly_close ((MonoAssembly *)value);
}
+static void
+add_assembly (gpointer key, gpointer value, gpointer user_data)
+{
+ g_hash_table_insert ((GHashTable*)user_data, value, value);
+}
+
static void
dynamic_method_info_free (gpointer key, gpointer value, gpointer user_data)
{
void
mono_domain_free (MonoDomain *domain, gboolean force)
{
+ GHashTable *unique_assemblies;
+ GList *tmp;
if ((domain == mono_root_domain) && !force) {
g_warning ("cant unload root domain");
return;
domain->entry_assembly = NULL;
g_free (domain->friendly_name);
domain->friendly_name = NULL;
- g_hash_table_foreach (domain->assemblies_by_name, remove_assembly, NULL);
-
- mono_g_hash_table_destroy (domain->env);
- domain->env = NULL;
+ /* some assemblies are in domain->assemblies_by_name and some only in domain->assemblies:
+ * collect them in unique_assemblies so we don't free them twice.
+ */
+ unique_assemblies = g_hash_table_new (NULL, NULL);
+ g_hash_table_foreach (domain->assemblies_by_name, add_assembly, unique_assemblies);
+ for (tmp = domain->assemblies; tmp; tmp = tmp->next)
+ g_hash_table_insert (unique_assemblies, tmp->data, tmp->data);
+ g_hash_table_foreach (unique_assemblies, remove_assembly, NULL);
+ g_hash_table_destroy (unique_assemblies);
g_hash_table_destroy (domain->assemblies_by_name);
domain->assemblies_by_name = NULL;
g_list_free (domain->assemblies);
domain->assemblies = NULL;
+
+ mono_g_hash_table_destroy (domain->env);
+ domain->env = NULL;
g_hash_table_destroy (domain->class_vtable_hash);
domain->class_vtable_hash = NULL;
mono_g_hash_table_destroy (domain->proxy_vtable_hash);
InterlockedIncrement (&image->ref_count);
}
+void
+mono_dynamic_stream_reset (MonoDynamicStream* stream)
+{
+ stream->alloc_size = stream->index = stream->offset = 0;
+ g_free (stream->data);
+ stream->data = NULL;
+ if (stream->hash) {
+ g_hash_table_destroy (stream->hash);
+ stream->hash = NULL;
+ }
+}
+
/**
* mono_image_close:
* @image: The image file we wish to close
g_return_if_fail (image != NULL);
EnterCriticalSection (&images_mutex);
+ /*g_print ("destroy image %p (dynamic: %d) refcount: %d\n", image, image->dynamic, image->ref_count);*/
+ g_assert (image->ref_count > 0);
if (--image->ref_count) {
LeaveCriticalSection (&images_mutex);
return;
g_free (image->image_info);
}
- if (!image->dynamic)
- /* Dynamic images are GC_MALLOCed */
+ /*g_print ("destroy image %p (dynamic: %d)\n", image, image->dynamic);*/
+ if (!image->dynamic) {
g_free (image);
+ } else {
+ /* Dynamic images are GC_MALLOCed */
+ struct _MonoDynamicImage *di = (struct _MonoDynamicImage*)image;
+ int i;
+ if (di->typespec)
+ g_hash_table_destroy (di->typespec);
+ if (di->typeref)
+ g_hash_table_destroy (di->typeref);
+ if (di->handleref)
+ g_hash_table_destroy (di->handleref);
+ if (di->tokens)
+ mono_g_hash_table_destroy (di->tokens);
+ if (di->blob_cache)
+ g_hash_table_destroy (di->blob_cache);
+ g_list_free (di->array_methods);
+ if (di->gen_params)
+ g_ptr_array_free (di->gen_params, TRUE);
+ if (di->token_fixups)
+ mono_g_hash_table_destroy (di->token_fixups);
+ if (di->method_to_table_idx)
+ g_hash_table_destroy (di->method_to_table_idx);
+ if (di->field_to_table_idx)
+ g_hash_table_destroy (di->field_to_table_idx);
+ if (di->method_aux_hash)
+ g_hash_table_destroy (di->method_aux_hash);
+ g_free (di->strong_name);
+ g_free (di->win32_res);
+ mono_dynamic_stream_reset (&di->sheap);
+ mono_dynamic_stream_reset (&di->code);
+ mono_dynamic_stream_reset (&di->resources);
+ mono_dynamic_stream_reset (&di->us);
+ mono_dynamic_stream_reset (&di->blob);
+ mono_dynamic_stream_reset (&di->tstream);
+ mono_dynamic_stream_reset (&di->guid);
+ for (i = 0; i < MONO_TABLE_NUM; ++i) {
+ g_free (di->tables [i].values);
+ }
+ }
}
/**
mono_metadata_inflate_generic_inst (MonoGenericInst *ginst,
MonoGenericContext *context);
+void mono_dynamic_stream_reset (MonoDynamicStream* stream);
+void mono_assembly_addref (MonoAssembly *assembly);
+
#endif /* __MONO_METADATA_INTERNALS_H__ */
stream->data = g_realloc (stream->data, stream->alloc_size);
}
-static void
-mono_dynamic_stream_reset (MonoDynamicStream* stream)
-{
- stream->alloc_size = stream->index = stream->offset = 0;
- g_free (stream->data);
- if (stream->hash)
- g_hash_table_destroy (stream->hash);
-}
-
static guint32
string_heap_insert (MonoDynamicStream *sh, const char *str)
{
sh->index = 0;
sh->alloc_size = 4096;
sh->data = g_malloc (4096);
- sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
+ sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
string_heap_insert (sh, "");
}
-static void
-string_heap_free (MonoDynamicStream *sh)
-{
- g_free (sh->data);
- g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
- g_hash_table_destroy (sh->hash);
-}
-
static guint32
mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
{
image = g_new0 (MonoDynamicImage, 1);
#endif
+ /*g_print ("created image %p\n", image);*/
/* keep in sync with image.c */
image->image.name = assembly_name;
image->image.assembly_name = image->image.name; /* they may be different */
image->image.module_name = module_name;
image->image.version = g_strdup (version);
image->image.dynamic = TRUE;
+ image->image.ref_count = 1;
image->image.references = g_new0 (MonoAssembly*, 1);
image->image.references [0] = NULL;
{
MonoDynamicAssembly *assembly;
MonoDynamicImage *image;
+ MonoDomain *domain = mono_object_domain (assemblyb);
MONO_ARCH_SAVE_REGS;
assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
#endif
+ assembly->assembly.ref_count = 1;
assembly->assembly.dynamic = TRUE;
assembly->assembly.corlib_internal = assemblyb->corlib_internal;
assemblyb->assembly.assembly = (MonoAssembly*)assembly;
assembly->assembly.aname.name = image->image.name;
assembly->assembly.image = &image->image;
+ mono_domain_lock (domain);
+ domain->assemblies = g_list_prepend (domain->assemblies, assembly);
+ mono_domain_unlock (domain);
+
register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
}
mono_dynamic_stream_reset (&assembly->us);
mono_dynamic_stream_reset (&assembly->blob);
mono_dynamic_stream_reset (&assembly->guid);
- string_heap_free (&assembly->sheap);
+ mono_dynamic_stream_reset (&assembly->sheap);
g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
g_hash_table_destroy (assembly->blob_cache);
+ assembly->blob_cache = NULL;
}
MonoReflectionModule *