2006-05-31 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / metadata / appdomain.c
index cf5922e5a9da60a2f5c305f18708f8ececb48294..6efa0690bab61862c5cd21ae576ab9d556b492bb 100644 (file)
@@ -29,8 +29,9 @@
 #include <mono/metadata/monitor.h>
 #include <mono/metadata/threadpool.h>
 #include <mono/utils/mono-uri.h>
+#include <mono/utils/mono-logger.h>
 
-#define MONO_CORLIB_VERSION 38
+#define MONO_CORLIB_VERSION 52
 
 CRITICAL_SECTION mono_delegate_section;
 
@@ -48,6 +49,10 @@ static MonoAssembly *
 mono_domain_assembly_search (MonoAssemblyName *aname,
                                                         gpointer user_data);
 
+static MonoAssembly *
+mono_domain_assembly_postload_search (MonoAssemblyName *aname,
+                                                                         gpointer user_data);
+
 static void
 mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data);
 
@@ -87,6 +92,8 @@ mono_runtime_init (MonoDomain *domain, MonoThreadStartCB start_cb,
        mono_install_assembly_refonly_preload_hook (mono_domain_assembly_preload, GUINT_TO_POINTER (TRUE));
        mono_install_assembly_search_hook (mono_domain_assembly_search, GUINT_TO_POINTER (FALSE));
        mono_install_assembly_refonly_search_hook (mono_domain_assembly_search, GUINT_TO_POINTER (TRUE));
+       mono_install_assembly_postload_search_hook (mono_domain_assembly_postload_search, GUINT_TO_POINTER (FALSE));
+       mono_install_assembly_postload_refonly_search_hook (mono_domain_assembly_postload_search, GUINT_TO_POINTER (TRUE));
        mono_install_assembly_load_hook (mono_domain_fire_assembly_load, NULL);
        mono_install_lookup_dynamic_token (mono_reflection_lookup_dynamic_token);
 
@@ -177,7 +184,13 @@ mono_context_init (MonoDomain *domain)
        domain->default_context = context;
 }
 
-/* This must not be called while there are still running threads executing
+/**
+ * mono_runtime_cleanup:
+ * @domain: unused.
+ *
+ * Internal routine.
+ *
+ * This must not be called while there are still running threads executing
  * managed code.
  */
 void
@@ -188,7 +201,11 @@ mono_runtime_cleanup (MonoDomain *domain)
        /* This ends up calling any pending pending (for at most 2 seconds) */
        mono_gc_cleanup ();
 
+       mono_thread_cleanup ();
+
        mono_network_cleanup ();
+
+       mono_marshal_cleanup ();
 }
 
 static MonoDomainFunc quit_function = NULL;
@@ -206,18 +223,40 @@ mono_runtime_quit ()
                quit_function (mono_get_root_domain (), NULL);
 }
 
+/** 
+ * mono_runtime_set_shutting_down:
+ *
+ * Invoked by System.Environment.Exit to flag that the runtime
+ * is shutting down.
+ */
 void
 mono_runtime_set_shutting_down (void)
 {
        shutting_down = TRUE;
 }
 
+/**
+ * mono_runtime_is_shutting_down:
+ *
+ * Returns whether the runtime has been flagged for shutdown.
+ *
+ * This is consumed by the P:System.Environment.HasShutdownStarted
+ * property.
+ *
+ */
 gboolean
 mono_runtime_is_shutting_down (void)
 {
        return shutting_down;
 }
 
+/**
+ * mono_domain_has_type_resolve:
+ * @domain: application domains being looked up
+ *
+ * Returns true if the AppDomain.TypeResolve field has been
+ * set.
+ */
 gboolean
 mono_domain_has_type_resolve (MonoDomain *domain)
 {
@@ -233,6 +272,19 @@ mono_domain_has_type_resolve (MonoDomain *domain)
        return o != NULL;
 }
 
+/**
+ * mono_domain_try_type_resolve:
+ * @domain: application domainwhere the name where the type is going to be resolved
+ * @name: the name of the type to resolve or NULL.
+ * @tb: A System.Reflection.Emit.TypeBuilder, used if name is NULL.
+ *
+ * This routine invokes the internal System.AppDomain.DoTypeResolve and returns
+ * the assembly that matches name.
+ *
+ * If @name is null, the value of ((TypeBuilder)tb).FullName is used instead
+ *
+ * Returns: A MonoReflectionAssembly or NULL if not found
+ */
 MonoReflectionAssembly *
 mono_domain_try_type_resolve (MonoDomain *domain, char *name, MonoObject *tb)
 {
@@ -263,7 +315,7 @@ mono_domain_try_type_resolve (MonoDomain *domain, char *name, MonoObject *tb)
 /**
  * mono_domain_owns_vtable_slot:
  *
- *   Returns whenever VTABLE_SLOT is inside a vtable which belongs to DOMAIN.
+ *  Returns whenever VTABLE_SLOT is inside a vtable which belongs to DOMAIN.
  */
 gboolean
 mono_domain_owns_vtable_slot (MonoDomain *domain, gpointer vtable_slot)
@@ -281,7 +333,7 @@ mono_domain_owns_vtable_slot (MonoDomain *domain, gpointer vtable_slot)
  * @domain: domain
  * @force: force setting.
  *
- *   Set the current appdomain to @domain. If @force is set, set it even
+ * Set the current appdomain to @domain. If @force is set, set it even
  * if it is being unloaded.
  *
  * Returns:
@@ -302,13 +354,15 @@ mono_domain_set (MonoDomain *domain, gboolean force)
 MonoObject *
 ves_icall_System_AppDomain_GetData (MonoAppDomain *ad, MonoString *name)
 {
-       MonoDomain *add = ad->data;
+       MonoDomain *add;
        MonoObject *o;
        char *str;
 
        MONO_ARCH_SAVE_REGS;
 
        g_assert (ad != NULL);
+       add = ad->data;
+       g_assert (add != NULL);
 
        if (name == NULL)
                mono_raise_exception (mono_get_exception_argument_null ("name"));
@@ -350,11 +404,13 @@ ves_icall_System_AppDomain_GetData (MonoAppDomain *ad, MonoString *name)
 void
 ves_icall_System_AppDomain_SetData (MonoAppDomain *ad, MonoString *name, MonoObject *data)
 {
-       MonoDomain *add = ad->data;
+       MonoDomain *add;
 
        MONO_ARCH_SAVE_REGS;
 
        g_assert (ad != NULL);
+       add = ad->data;
+       g_assert (add != NULL);
 
        if (name == NULL)
                mono_raise_exception (mono_get_exception_argument_null ("name"));
@@ -434,7 +490,8 @@ ves_icall_System_AppDomain_createDomain (MonoString *friendly_name, MonoAppDomai
        if (!setup->application_base) {
                /* Inherit from the root domain since MS.NET does this */
                MonoDomain *root = mono_get_root_domain ();
-               setup->application_base = mono_string_new_utf16 (data, mono_string_chars (root->setup->application_base), mono_string_length (root->setup->application_base));
+               if (root->setup->application_base)
+                       MONO_OBJECT_SETREF (setup, application_base, mono_string_new_utf16 (data, mono_string_chars (root->setup->application_base), mono_string_length (root->setup->application_base)));
        }
 
        mono_context_init (data);
@@ -483,7 +540,7 @@ ves_icall_System_AppDomain_GetAssemblies (MonoAppDomain *ad, MonoBoolean refonly
                        continue;
                if (ass->corlib_internal)
                        continue;
-               mono_array_set (res, gpointer, i, mono_assembly_get_object (domain, ass));
+               mono_array_setref (res, i, mono_assembly_get_object (domain, ass));
                ++i;
        }
        mono_domain_assemblies_unlock (domain);
@@ -516,6 +573,28 @@ try_assembly_resolve (MonoDomain *domain, MonoString *fname, gboolean refonly)
        return (MonoReflectionAssembly *) mono_runtime_invoke (method, domain->domain, params, NULL);
 }
 
+static MonoAssembly *
+mono_domain_assembly_postload_search (MonoAssemblyName *aname,
+                                                                         gpointer user_data)
+{
+       gboolean refonly = GPOINTER_TO_UINT (user_data);
+       MonoReflectionAssembly *assembly;
+       MonoDomain *domain = mono_domain_get ();
+       char *aname_str;
+
+       aname_str = mono_stringify_assembly_name (aname);
+
+       /* FIXME: We invoke managed code here, so there is a potential for deadlocks */
+       assembly = try_assembly_resolve (domain, mono_string_new (domain, aname_str), refonly);
+
+       g_free (aname_str);
+
+       if (assembly)
+               return assembly->assembly;
+       else
+               return NULL;
+}
+       
 /*
  * LOCKING: assumes assemblies_lock in the domain is already locked.
  */
@@ -542,6 +621,7 @@ add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *ht)
                mono_assembly_addref (ass);
                g_hash_table_insert (ht, ass, ass);
                domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, ass);
+               mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Assembly %s %p added to domain %s, ref_count=%d\n", ass->aname.name, ass, domain->friendly_name, ass->ref_count);
        }
 
        if (ass->image->references) {
@@ -898,13 +978,19 @@ ves_icall_System_Reflection_Assembly_LoadFrom (MonoString *fname, MonoBoolean re
 
        ass = mono_assembly_open_full (filename, &status, refOnly);
        
-       g_free (name);
-
        if (!ass){
-               MonoException *exc = mono_get_exception_file_not_found (fname);
+               MonoException *exc;
+
+               if (status == MONO_IMAGE_IMAGE_INVALID)
+                       exc = mono_get_exception_bad_image_format (name);
+               else
+                       exc = mono_get_exception_file_not_found (fname);
+               g_free (name);
                mono_raise_exception (exc);
        }
 
+       g_free (name);
+
        return mono_assembly_get_object (domain, ass);
 }
 
@@ -919,7 +1005,7 @@ ves_icall_System_AppDomain_LoadAssemblyRaw (MonoAppDomain *ad,
        MonoDomain *domain = ad->data;
        MonoImageOpenStatus status;
        guint32 raw_assembly_len = mono_array_length (raw_assembly);
-       MonoImage *image = mono_image_open_from_data (mono_array_addr (raw_assembly, gchar, 0), raw_assembly_len, TRUE, NULL);
+       MonoImage *image = mono_image_open_from_data_full (mono_array_addr (raw_assembly, gchar, 0), raw_assembly_len, TRUE, NULL, refonly);
 
        if (raw_symbol_store)
                mono_raise_exception (mono_get_exception_not_implemented ("LoadAssemblyRaw: Raw Symbol Store not Implemented"));
@@ -938,7 +1024,7 @@ ves_icall_System_AppDomain_LoadAssemblyRaw (MonoAppDomain *ad,
        }
 
        refass = mono_assembly_get_object (domain, ass);
-       refass->evidence = evidence;
+       MONO_OBJECT_SETREF (refass, evidence, evidence);
        return refass;
 }
 
@@ -981,7 +1067,7 @@ ves_icall_System_AppDomain_LoadAssembly (MonoAppDomain *ad,  MonoString *assRef,
        if (refass == NULL)
                refass = mono_assembly_get_object (domain, ass);
 
-       refass->evidence = evidence;
+       MONO_OBJECT_SETREF (refass, evidence, evidence);
        return refass;
 }
 
@@ -1054,7 +1140,7 @@ ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomain *ad, MonoString *file,
                args = (MonoArray *) mono_array_new (ad->data, mono_defaults.string_class, 0);
 
        refass = mono_assembly_get_object (ad->data, assembly);
-       refass->evidence = evidence;
+       MONO_OBJECT_SETREF (refass, evidence, evidence);
 
        res = mono_runtime_exec_main (method, (MonoArray *)args, NULL);
 
@@ -1244,9 +1330,11 @@ unload_thread_main (void *arg)
 
 /*
  * mono_domain_unload:
+ * @domain: The domain to unload
  *
  *  Unloads an appdomain. Follows the process outlined in:
  *  http://blogs.gotdotnet.com/cbrumme
+ *
  *  If doing things the 'right' way is too hard or complex, we do it the 
  *  'simple' way, which means do everything needed to avoid crashes and
  *  memory leaks, but not much else.
@@ -1255,7 +1343,8 @@ static void
 mono_domain_unload (MonoDomain *domain)
 {
        HANDLE thread_handle;
-       guint32 tid, res;
+       gsize tid;
+       guint32 res;
        MonoAppDomainState prev_state;
        MonoMethod *method;
        MonoObject *exc;
@@ -1329,11 +1418,11 @@ mono_domain_unload (MonoDomain *domain)
 
                g_warning (thread_data.failure_reason);
 
+               ex = mono_get_exception_cannot_unload_appdomain (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);
-
                mono_raise_exception (ex);
        }
 }