Fri Jan 21 15:29:27 CET 2005 Paolo Molaro <lupus@ximian.com>
authorPaolo Molaro <lupus@oddwiz.org>
Fri, 21 Jan 2005 14:20:18 +0000 (14:20 -0000)
committerPaolo Molaro <lupus@oddwiz.org>
Fri, 21 Jan 2005 14:20:18 +0000 (14:20 -0000)
* domain.c, appdomain.c, assembly.c, image.c, metadata-internals.h,
reflection.c: properly refcount images and assemblies, many leaks fixed.

svn path=/trunk/mono/; revision=39306

mono/metadata/ChangeLog
mono/metadata/appdomain.c
mono/metadata/assembly.c
mono/metadata/domain.c
mono/metadata/image.c
mono/metadata/metadata-internals.h
mono/metadata/reflection.c

index 4bb45424a0db61ffa6d99c95aa439324018f44b8..98d8ad52a05c32c26d17ccc38d828b5f28e2d27f 100644 (file)
@@ -1,3 +1,9 @@
+
+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
index 66eb6aa938ad87fb74f82dbb0bc2bfee448d652a..20f024e93c9674877f43f5b55c6ef4b623fac81c 100644 (file)
@@ -541,6 +541,7 @@ add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass)
                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);
@@ -1388,6 +1389,7 @@ mono_domain_unload (MonoDomain *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);
 
index 1822bd8e4a2fbb61031b00aae2c8787a0475d6c7..7abd4908e971ae7348c79d3037b7381b8bab490b 100644 (file)
@@ -306,6 +306,14 @@ assemblyref_public_tok (MonoImage *image, guint32 key_index, guint32 flags)
        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)
 {
@@ -390,11 +398,14 @@ 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);
@@ -760,6 +771,7 @@ mono_assembly_load_from (MonoImage *image, const char*fname,
        ass = g_new0 (MonoAssembly, 1);
        ass->basedir = base_dir;
        ass->image = image;
+       ass->ref_count = 1;
 
        mono_assembly_fill_assembly_name (image, &ass->aname);
 
@@ -1067,6 +1079,8 @@ mono_assembly_close (MonoAssembly *assembly)
        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;
@@ -1084,7 +1098,8 @@ mono_assembly_close (MonoAssembly *assembly)
        mono_image_close (assembly->image);
 
        g_free (assembly->basedir);
-       g_free (assembly);
+       if (!assembly->dynamic)
+               g_free (assembly);
 }
 
 MonoImage*
index 6bac10a84600512b35cb6cc0e48e25406b9ff7ea..e29610ad3c4bdfb0de5a0981192f5db9808f283c 100644 (file)
@@ -753,6 +753,12 @@ remove_assembly (gpointer key, gpointer value, gpointer user_data)
        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)
 {
@@ -770,6 +776,8 @@ delete_jump_list (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;
@@ -793,14 +801,22 @@ mono_domain_free (MonoDomain *domain, gboolean force)
        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);
index 5a6f286a3ac3d8029e42cc42fb520c12d2fb91c2..81a153ff3981e6c781593e8a38f1834fb7af2fa1 100644 (file)
@@ -989,6 +989,18 @@ mono_image_addref (MonoImage *image)
        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
@@ -1004,6 +1016,8 @@ mono_image_close (MonoImage *image)
        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;
@@ -1083,9 +1097,47 @@ mono_image_close (MonoImage *image)
                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);
+               }
+       }
 }
 
 /** 
index 63b14b0d2a9bf27708310c19f050d84be23a31ca..df20c8745fef5d85b2a85331fc0f0f68c99f9a5e 100644 (file)
@@ -291,5 +291,8 @@ MonoGenericInst *
 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__ */
 
index becbe48f7b2ef4f4acc04d629fdc6c974bb927eb..0874e966a60a1c919148723b037fb0bad10f7e6f 100644 (file)
@@ -174,15 +174,6 @@ make_room_in_stream (MonoDynamicStream *stream, int size)
        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)
 {
@@ -215,18 +206,10 @@ string_heap_init (MonoDynamicStream *sh)
        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)
 {
@@ -4220,12 +4203,14 @@ create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, c
        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;
@@ -4284,6 +4269,7 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
 {
        MonoDynamicAssembly *assembly;
        MonoDynamicImage *image;
+       MonoDomain *domain = mono_object_domain (assemblyb);
        
        MONO_ARCH_SAVE_REGS;
 
@@ -4296,6 +4282,7 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
        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;
@@ -4313,6 +4300,10 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
        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);
 }
@@ -4927,10 +4918,11 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
        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 *