X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fappdomain.c;h=e04b84a7253da2ddaad0d46069337cf8e7ddd81d;hb=ef7a4c06206976de7ef2e974267407347ddb75a4;hp=f92cc949b6ee5160c1931415f97aa874881eb5bf;hpb=a19175129f4f34c53a73e26d949cf89ade683a03;p=mono.git diff --git a/mono/metadata/appdomain.c b/mono/metadata/appdomain.c index f92cc949b6e..e04b84a7253 100644 --- a/mono/metadata/appdomain.c +++ b/mono/metadata/appdomain.c @@ -1,5 +1,6 @@ -/* - * appdomain.c: AppDomain functions +/** + * \file + * AppDomain functions * * Authors: * Dietmar Maurer (dietmar@ximian.com) @@ -38,7 +39,6 @@ #include #include #include "mono/metadata/metadata-internals.h" -#include #include #include #include @@ -76,19 +76,6 @@ #include #endif -/* - * This is the version number of the corlib-runtime interface. When - * making changes to this interface (by changing the layout - * of classes the runtime knows about, changing icall signature or - * semantics etc), increment this variable. Also increment the - * pair of this variable in mscorlib in: - * mcs/class/corlib/System/Environment.cs - * - * Changes which are already detected at runtime, like the addition - * of icalls, do not require an increment. - */ -#define MONO_CORLIB_VERSION 164 - typedef struct { int runtime_count; @@ -124,6 +111,9 @@ static MonoDomain * mono_domain_create_appdomain_checked (char *friendly_name, char *configuration_file, MonoError *error); +static void +mono_context_set_default_context (MonoDomain *domain); + static char * get_shadow_assembly_location_base (MonoDomain *domain, MonoError *error); @@ -202,7 +192,9 @@ create_domain_objects (MonoDomain *domain) string_vt = mono_class_vtable (domain, mono_defaults.string_class); string_empty_fld = mono_class_get_field_from_name (mono_defaults.string_class, "Empty"); g_assert (string_empty_fld); - MonoString *empty_str = mono_string_intern_checked (mono_string_new (domain, ""), &error); + MonoString *empty_str = mono_string_new_checked (domain, "", &error); + mono_error_assert_ok (&error); + empty_str = mono_string_intern_checked (empty_str, &error); mono_error_assert_ok (&error); mono_field_static_set_value (string_vt, string_empty_fld, empty_str); domain->empty_string = empty_str; @@ -210,7 +202,8 @@ create_domain_objects (MonoDomain *domain) /* * Create an instance early since we can't do it when there is no memory. */ - arg = mono_string_new (domain, "Out of memory"); + arg = mono_string_new_checked (domain, "Out of memory", &error); + mono_error_assert_ok (&error); domain->out_of_memory_ex = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "OutOfMemoryException", arg, NULL, &error); mono_error_assert_ok (&error); @@ -218,10 +211,12 @@ create_domain_objects (MonoDomain *domain) * These two are needed because the signal handlers might be executing on * an alternate stack, and Boehm GC can't handle that. */ - arg = mono_string_new (domain, "A null value was found where an object instance was required"); + arg = mono_string_new_checked (domain, "A null value was found where an object instance was required", &error); + mono_error_assert_ok (&error); domain->null_reference_ex = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "NullReferenceException", arg, NULL, &error); mono_error_assert_ok (&error); - arg = mono_string_new (domain, "The requested operation caused a stack overflow."); + arg = mono_string_new_checked (domain, "The requested operation caused a stack overflow.", &error); + mono_error_assert_ok (&error); domain->stack_overflow_ex = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "StackOverflowException", arg, NULL, &error); mono_error_assert_ok (&error); @@ -243,14 +238,14 @@ create_domain_objects (MonoDomain *domain) /** * mono_runtime_init: - * @domain: domain returned by mono_init () + * \param domain domain returned by \c mono_init * * Initialize the core AppDomain: this function will run also some * IL initialization code, so it needs the execution engine to be fully * operational. * - * AppDomain.SetupInformation is set up in mono_runtime_exec_main, where - * we know the entry_assembly. + * \c AppDomain.SetupInformation is set up in \c mono_runtime_exec_main, where + * we know the \c entry_assembly. * */ void @@ -312,7 +307,7 @@ mono_runtime_init_checked (MonoDomain *domain, MonoThreadStartCB start_cb, MonoT /* contexts use GC handles, so they must be initialized after the GC */ mono_context_init_checked (domain, error); return_if_nok (error); - mono_context_set (domain->default_context); + mono_context_set_default_context (domain); #ifndef DISABLE_SOCKETS mono_network_init (); @@ -329,6 +324,15 @@ mono_runtime_init_checked (MonoDomain *domain, MonoThreadStartCB start_cb, MonoT return; } +static void +mono_context_set_default_context (MonoDomain *domain) +{ + HANDLE_FUNCTION_ENTER (); + mono_context_set_handle (MONO_HANDLE_NEW (MonoAppContext, domain->default_context)); + HANDLE_FUNCTION_RETURN (); +} + + static int mono_get_corlib_version (void) { @@ -350,11 +354,9 @@ mono_get_corlib_version (void) } /** - * mono_check_corlib_version - * + * mono_check_corlib_version: * Checks that the corlib that is loaded matches the version of this runtime. - * - * Returns: NULL if the runtime will work with the corlib, or a g_malloc + * \returns NULL if the runtime will work with the corlib, or a \c g_malloc * allocated string with the error otherwise. */ const char* @@ -375,9 +377,8 @@ mono_check_corlib_version (void) /** * mono_context_init: - * @domain: The domain where the System.Runtime.Remoting.Context.Context is initialized - * - * Initializes the @domain's default System.Runtime.Remoting's Context. + * \param domain The domain where the \c System.Runtime.Remoting.Context.Context is initialized + * Initializes the \p domain's default \c System.Runtime.Remoting 's Context. */ void mono_context_init (MonoDomain *domain) @@ -401,13 +402,14 @@ mono_context_init_checked (MonoDomain *domain, MonoError *error) context->domain_id = domain->domain_id; context->context_id = 0; - ves_icall_System_Runtime_Remoting_Contexts_Context_RegisterContext (context); + mono_threads_register_app_context (context, error); + mono_error_assert_ok (error); domain->default_context = context; } /** * mono_runtime_cleanup: - * @domain: unused. + * \param domain unused. * * Internal routine. * @@ -436,12 +438,18 @@ mono_runtime_cleanup (MonoDomain *domain) static MonoDomainFunc quit_function = NULL; +/** + * mono_install_runtime_cleanup: + */ void mono_install_runtime_cleanup (MonoDomainFunc func) { quit_function = func; } +/** + * mono_runtime_quit: + */ void mono_runtime_quit () { @@ -451,10 +459,9 @@ mono_runtime_quit () /** * mono_domain_create_appdomain: - * @friendly_name: The friendly name of the appdomain to create - * @configuration_file: The configuration file to initialize the appdomain with - * - * Returns a MonoDomain initialized with the appdomain + * \param friendly_name The friendly name of the appdomain to create + * \param configuration_file The configuration file to initialize the appdomain with + * \returns a \c MonoDomain initialized with the appdomain */ MonoDomain * mono_domain_create_appdomain (char *friendly_name, char *configuration_file) @@ -468,11 +475,11 @@ mono_domain_create_appdomain (char *friendly_name, char *configuration_file) /** * mono_domain_create_appdomain_checked: - * @friendly_name: The friendly name of the appdomain to create - * @configuration_file: The configuration file to initialize the appdomain with - * @error: Set on error. + * \param friendly_name The friendly name of the appdomain to create + * \param configuration_file The configuration file to initialize the appdomain with + * \param error Set on error. * - * Returns a MonoDomain initialized with the appdomain. On failure sets @error and returns NULL. + * \returns a MonoDomain initialized with the appdomain. On failure sets \p error and returns NULL. */ MonoDomain * mono_domain_create_appdomain_checked (char *friendly_name, char *configuration_file, MonoError *error) @@ -506,9 +513,9 @@ leave: /** * mono_domain_set_config: - * @domain: MonoDomain initialized with the appdomain we want to change - * @base_dir: new base directory for the appdomain - * @config_file_name: path to the new configuration for the app domain + * \param domain \c MonoDomain initialized with the appdomain we want to change + * \param base_dir new base directory for the appdomain + * \param config_file_name path to the new configuration for the app domain * * Used to set the system configuration for an appdomain * @@ -519,8 +526,28 @@ leave: void mono_domain_set_config (MonoDomain *domain, const char *base_dir, const char *config_file_name) { - MONO_OBJECT_SETREF (domain->setup, application_base, mono_string_new (domain, base_dir)); - MONO_OBJECT_SETREF (domain->setup, configuration_file, mono_string_new (domain, config_file_name)); + HANDLE_FUNCTION_ENTER (); + MonoError error; + mono_domain_set_config_checked (domain, base_dir, config_file_name, &error); + mono_error_cleanup (&error); + HANDLE_FUNCTION_RETURN (); +} + +gboolean +mono_domain_set_config_checked (MonoDomain *domain, const char *base_dir, const char *config_file_name, MonoError *error) +{ + error_init (error); + MonoAppDomainSetupHandle setup = MONO_HANDLE_NEW (MonoAppDomainSetup, domain->setup); + MonoStringHandle base_dir_str = mono_string_new_handle (domain, base_dir, error); + if (!is_ok (error)) + goto leave; + MONO_HANDLE_SET (setup, application_base, base_dir_str); + MonoStringHandle config_file_name_str = mono_string_new_handle (domain, config_file_name, error); + if (!is_ok (error)) + goto leave; + MONO_HANDLE_SET (setup, configuration_file, config_file_name_str); +leave: + return is_ok (error); } static MonoAppDomainSetupHandle @@ -609,7 +636,7 @@ mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetupHa data->domain = MONO_HANDLE_RAW (ad); data->friendly_name = g_strdup (friendly_name); - mono_profiler_appdomain_name (data, data->friendly_name); + MONO_PROFILER_RAISE (domain_name, (data, data->friendly_name)); MonoStringHandle app_base = MONO_HANDLE_NEW_GET (MonoString, setup, application_base); if (MONO_HANDLE_IS_NULL (app_base)) { @@ -663,10 +690,9 @@ leave: /** * mono_domain_has_type_resolve: - * @domain: application domains being looked up + * \param domain application domain being looked up * - * Returns: TRUE if the AppDomain.TypeResolve field has been - * set. + * \returns TRUE if the \c AppDomain.TypeResolve field has been set. */ gboolean mono_domain_has_type_resolve (MonoDomain *domain) @@ -689,16 +715,16 @@ mono_domain_has_type_resolve (MonoDomain *domain) /** * 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. + * \param domain application domainwhere the name where the type is going to be resolved + * \param name the name of the type to resolve or NULL. + * \param tb A \c System.Reflection.Emit.TypeBuilder, used if name is NULL. * - * This routine invokes the internal System.AppDomain.DoTypeResolve and returns + * This routine invokes the internal \c System.AppDomain.DoTypeResolve and returns * the assembly that matches name. * - * If @name is null, the value of ((TypeBuilder)tb).FullName is used instead + * If \p name is null, the value of \c ((TypeBuilder)tb).FullName is used instead * - * Returns: A MonoReflectionAssembly or NULL if not found + * \returns A \c MonoReflectionAssembly or NULL if not found */ MonoReflectionAssembly * mono_domain_try_type_resolve (MonoDomain *domain, char *name, MonoObject *tb) @@ -729,9 +755,10 @@ mono_domain_try_type_resolve_checked (MonoDomain *domain, char *name, MonoObject } } - if (name) - *params = (MonoObject*)mono_string_new (mono_domain_get (), name); - else + if (name) { + *params = (MonoObject*)mono_string_new_checked (mono_domain_get (), name, error); + return_val_if_nok (error, NULL); + } else *params = tb; ret = (MonoReflectionAssembly *) mono_runtime_invoke_checked (method, domain->domain, params, error); @@ -742,8 +769,7 @@ mono_domain_try_type_resolve_checked (MonoDomain *domain, char *name, MonoObject /** * mono_domain_owns_vtable_slot: - * - * Returns whenever VTABLE_SLOT is inside a vtable which belongs to DOMAIN. + * \returns Whether \p vtable_slot is inside a vtable which belongs to \p domain. */ gboolean mono_domain_owns_vtable_slot (MonoDomain *domain, gpointer vtable_slot) @@ -758,15 +784,13 @@ mono_domain_owns_vtable_slot (MonoDomain *domain, gpointer vtable_slot) /** * mono_domain_set: - * @domain: domain - * @force: force setting. + * \param domain domain + * \param force force setting. * - * Set the current appdomain to @domain. If @force is set, set it even + * Set the current appdomain to \p domain. If \p force is set, set it even * if it is being unloaded. * - * Returns: - * TRUE on success; - * FALSE if the domain is unloaded + * \returns TRUE on success; FALSE if the domain is unloaded */ gboolean mono_domain_set (MonoDomain *domain, gboolean force) @@ -1124,6 +1148,7 @@ leave: MonoAssembly* mono_try_assembly_resolve_handle (MonoDomain *domain, MonoStringHandle fname, MonoAssembly *requesting, gboolean refonly, MonoError *error) { + HANDLE_FUNCTION_ENTER (); MonoAssembly *ret = NULL; MonoMethod *method; MonoBoolean isrefonly; @@ -1132,7 +1157,7 @@ mono_try_assembly_resolve_handle (MonoDomain *domain, MonoStringHandle fname, Mo error_init (error); if (mono_runtime_get_no_exec ()) - return ret; + goto leave; g_assert (domain != NULL && !MONO_HANDLE_IS_NULL (fname)); @@ -1143,14 +1168,29 @@ mono_try_assembly_resolve_handle (MonoDomain *domain, MonoStringHandle fname, Mo MonoReflectionAssemblyHandle requesting_handle; if (requesting) { requesting_handle = mono_assembly_get_object_handle (domain, requesting, error); - return_val_if_nok (error, ret); + if (!is_ok (error)) + goto leave; } params [0] = MONO_HANDLE_RAW (fname); params[1] = requesting ? MONO_HANDLE_RAW (requesting_handle) : NULL; params [2] = &isrefonly; - MonoReflectionAssemblyHandle result = MONO_HANDLE_NEW (MonoReflectionAssembly, mono_runtime_invoke_checked (method, domain->domain, params, error)); + MonoObject *exc = NULL; + MonoReflectionAssemblyHandle result = MONO_HANDLE_NEW (MonoReflectionAssembly, mono_runtime_try_invoke (method, domain->domain, params, &exc, error)); + if (!is_ok (error) || exc != NULL) { + if (is_ok (error)) + mono_error_set_exception_instance (error, (MonoException*)exc); + goto leave; + } ret = !MONO_HANDLE_IS_NULL (result) ? MONO_HANDLE_GETVAL (result, assembly) : NULL; - return ret; + + if (ret && !refonly && ret->ref_only) { + /* .NET Framework throws System.IO.FileNotFoundException in this case */ + mono_error_set_file_not_found (error, "AssemblyResolveEvent handlers cannot return Assemblies loaded for reflection only"); + ret = NULL; + goto leave; + } +leave: + HANDLE_FUNCTION_RETURN_VAL (ret); } MonoAssembly * @@ -1189,12 +1229,13 @@ add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *ht) if (!ht) { ht = g_hash_table_new (mono_aligned_addr_hash, NULL); destroy_ht = TRUE; + for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { + g_hash_table_insert (ht, tmp->data, tmp->data); + } } /* FIXME: handle lazy loaded assemblies */ - for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { - g_hash_table_insert (ht, tmp->data, tmp->data); - } + if (!g_hash_table_lookup (ht, ass)) { mono_assembly_addref (ass); g_hash_table_insert (ht, ass, ass); @@ -1203,11 +1244,12 @@ add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *ht) } if (ass->image->references) { - for (i = 0; ass->image->references [i] != NULL; i++) { - if (ass->image->references [i] != REFERENCE_MISSING) + for (i = 0; i < ass->image->nreferences; i++) { + if (ass->image->references[i] && ass->image->references [i] != REFERENCE_MISSING) { if (!g_hash_table_lookup (ht, ass->image->references [i])) { add_assemblies_to_domain (domain, ass->image->references [i], ht); } + } } } if (destroy_ht) @@ -1217,6 +1259,7 @@ add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *ht) static void mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data) { + HANDLE_FUNCTION_ENTER (); static MonoClassField *assembly_load_field; static MonoMethod *assembly_load_method; MonoError error; @@ -1227,7 +1270,7 @@ mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data) if (!domain->domain) /* This can happen during startup */ - return; + goto leave; #ifdef ASSEMBLY_LOAD_DEBUG fprintf (stderr, "Loading %s into domain %s\n", assembly->aname.name, domain->friendly_name); #endif @@ -1245,7 +1288,7 @@ mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data) mono_field_get_value ((MonoObject*) domain->domain, assembly_load_field, &load_value); if (load_value == NULL) { /* No events waiting to be triggered */ - return; + goto leave; } MonoReflectionAssemblyHandle ref_assembly = mono_assembly_get_object_handle (domain, assembly, &error); @@ -1260,6 +1303,8 @@ mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data) mono_runtime_invoke_checked (assembly_load_method, domain->domain, params, &error); mono_error_cleanup (&error); +leave: + HANDLE_FUNCTION_RETURN (); } /* @@ -1840,8 +1885,10 @@ mono_make_shadow_copy (const char *filename, MonoError *oerror) sibling_source_len = strlen (sibling_source); sibling_target = g_strconcat (shadow, ".config", NULL); sibling_target_len = strlen (sibling_target); - + copy_result = shadow_copy_sibling (sibling_source, sibling_source_len, ".mdb", sibling_target, sibling_target_len, 7); + if (copy_result) + copy_result = shadow_copy_sibling (sibling_source, sibling_source_len, ".pdb", sibling_target, sibling_target_len, 11); if (copy_result) copy_result = shadow_copy_sibling (sibling_source, sibling_source_len, ".config", sibling_target, sibling_target_len, 7); @@ -1869,6 +1916,9 @@ mono_make_shadow_copy (const char *filename, MonoError *oerror) } #endif /* DISABLE_SHADOW_COPY */ +/** + * mono_domain_from_appdomain: + */ MonoDomain * mono_domain_from_appdomain (MonoAppDomain *appdomain_raw) { @@ -1900,9 +1950,11 @@ leave: static gboolean -try_load_from (MonoAssembly **assembly, const gchar *path1, const gchar *path2, - const gchar *path3, const gchar *path4, - gboolean refonly, gboolean is_private) +try_load_from (MonoAssembly **assembly, + const gchar *path1, const gchar *path2, + const gchar *path3, const gchar *path4, + gboolean refonly, gboolean is_private, + MonoAssemblyCandidatePredicate predicate, gpointer user_data) { gchar *fullpath; gboolean found = FALSE; @@ -1921,14 +1973,14 @@ try_load_from (MonoAssembly **assembly, const gchar *path1, const gchar *path2, found = g_file_test (fullpath, G_FILE_TEST_IS_REGULAR); if (found) - *assembly = mono_assembly_open_full (fullpath, NULL, refonly); + *assembly = mono_assembly_open_predicate (fullpath, refonly, FALSE, predicate, user_data, NULL); g_free (fullpath); return (*assembly != NULL); } static MonoAssembly * -real_load (gchar **search_path, const gchar *culture, const gchar *name, gboolean refonly) +real_load (gchar **search_path, const gchar *culture, const gchar *name, gboolean refonly, MonoAssemblyCandidatePredicate predicate, gpointer user_data) { MonoAssembly *result = NULL; gchar **path; @@ -1955,22 +2007,22 @@ real_load (gchar **search_path, const gchar *culture, const gchar *name, gboolea /* See test cases in bug #58992 and bug #57710 */ /* 1st try: [culture]/[name].dll (culture may be empty) */ strcpy (filename + len - 4, ".dll"); - if (try_load_from (&result, *path, local_culture, "", filename, refonly, is_private)) + if (try_load_from (&result, *path, local_culture, "", filename, refonly, is_private, predicate, user_data)) break; /* 2nd try: [culture]/[name].exe (culture may be empty) */ strcpy (filename + len - 4, ".exe"); - if (try_load_from (&result, *path, local_culture, "", filename, refonly, is_private)) + if (try_load_from (&result, *path, local_culture, "", filename, refonly, is_private, predicate, user_data)) break; /* 3rd try: [culture]/[name]/[name].dll (culture may be empty) */ strcpy (filename + len - 4, ".dll"); - if (try_load_from (&result, *path, local_culture, name, filename, refonly, is_private)) + if (try_load_from (&result, *path, local_culture, name, filename, refonly, is_private, predicate, user_data)) break; /* 4th try: [culture]/[name]/[name].exe (culture may be empty) */ strcpy (filename + len - 4, ".exe"); - if (try_load_from (&result, *path, local_culture, name, filename, refonly, is_private)) + if (try_load_from (&result, *path, local_culture, name, filename, refonly, is_private, predicate, user_data)) break; } @@ -1995,12 +2047,28 @@ mono_domain_assembly_preload (MonoAssemblyName *aname, set_domain_search_path (domain); + MonoAssemblyCandidatePredicate predicate = NULL; + void* predicate_ud = NULL; +#if !defined(DISABLE_DESKTOP_LOADER) + if (G_LIKELY (mono_loader_get_strict_strong_names ())) { + predicate = &mono_assembly_candidate_predicate_sn_same_name; + predicate_ud = aname; + } +#endif if (domain->search_path && domain->search_path [0] != NULL) { - result = real_load (domain->search_path, aname->culture, aname->name, refonly); + if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY)) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Domain %s search path is:", domain->friendly_name); + for (int i = 0; domain->search_path [i]; i++) { + const char *p = domain->search_path[i]; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "\tpath[%d] = '%s'", i, p); + } + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "End of domain %s search path.", domain->friendly_name); + } + result = real_load (domain->search_path, aname->culture, aname->name, refonly, predicate, predicate_ud); } if (result == NULL && assemblies_path && assemblies_path [0] != NULL) { - result = real_load (assemblies_path, aname->culture, aname->name, refonly); + result = real_load (assemblies_path, aname->culture, aname->name, refonly, predicate, predicate_ud); } return result; @@ -2054,7 +2122,7 @@ ves_icall_System_Reflection_Assembly_LoadFrom (MonoStringHandle fname, MonoBoole if (!is_ok (error)) goto leave; - MonoAssembly *ass = mono_assembly_open_a_lot (filename, &status, refOnly, TRUE); + MonoAssembly *ass = mono_assembly_open_predicate (filename, refOnly, TRUE, NULL, NULL, &status); if (!ass) { if (status == MONO_IMAGE_IMAGE_INVALID) @@ -2208,11 +2276,8 @@ ves_icall_System_AppDomain_InternalUnload (gint32 domain_id, MonoError *error) * Unloading seems to cause problems when running NUnit/NAnt, hence * this workaround. */ - if (g_getenv ("MONO_NO_UNLOAD")) + if (g_hasenv ("MONO_NO_UNLOAD")) return; -#ifdef __native_client__ - return; -#endif MonoException *exc = NULL; mono_domain_try_unload (domain, (MonoObject**)&exc); @@ -2233,9 +2298,11 @@ ves_icall_System_AppDomain_InternalIsFinalizingForUnload (gint32 domain_id, Mono } void -ves_icall_System_AppDomain_DoUnhandledException (MonoException *exc) +ves_icall_System_AppDomain_DoUnhandledException (MonoExceptionHandle exc, MonoError *error) { - mono_unhandled_exception ((MonoObject*) exc); + error_init (error); + mono_unhandled_exception_checked (MONO_HANDLE_CAST (MonoObject, exc), error); + mono_error_assert_ok (error); } gint32 @@ -2333,24 +2400,27 @@ ves_icall_System_AppDomain_InternalPopDomainRef (MonoError *error) mono_thread_pop_appdomain_ref (); } -MonoAppContext * -ves_icall_System_AppDomain_InternalGetContext () +MonoAppContextHandle +ves_icall_System_AppDomain_InternalGetContext (MonoError *error) { - return mono_context_get (); + error_init (error); + return mono_context_get_handle (); } -MonoAppContext * -ves_icall_System_AppDomain_InternalGetDefaultContext () +MonoAppContextHandle +ves_icall_System_AppDomain_InternalGetDefaultContext (MonoError *error) { - return mono_domain_get ()->default_context; + error_init (error); + return MONO_HANDLE_NEW (MonoAppContext, mono_domain_get ()->default_context); } -MonoAppContext * -ves_icall_System_AppDomain_InternalSetContext (MonoAppContext *mc) +MonoAppContextHandle +ves_icall_System_AppDomain_InternalSetContext (MonoAppContextHandle mc, MonoError *error) { - MonoAppContext *old_context = mono_context_get (); + error_init (error); + MonoAppContextHandle old_context = mono_context_get_handle (); - mono_context_set (mc); + mono_context_set_handle (mc); return old_context; } @@ -2373,6 +2443,9 @@ ves_icall_System_AppDomain_InternalGetProcessGuid (MonoStringHandle newguid, Mon return newguid; } +/** + * mono_domain_is_unloading: + */ gboolean mono_domain_is_unloading (MonoDomain *domain) { @@ -2479,14 +2552,14 @@ unload_thread_main (void *arg) MonoError error; unload_data *data = (unload_data*)arg; MonoDomain *domain = data->domain; - MonoThread *thread; + MonoInternalThread *internal; int i; - /* Have to attach to the runtime so shutdown can wait for this thread */ - /* Force it to be attached to avoid racing during shutdown. */ - thread = mono_thread_attach_full (mono_get_root_domain (), TRUE); + internal = mono_thread_internal_current (); - mono_thread_set_name_internal (thread->internal_thread, mono_string_new (mono_get_root_domain (), "Domain unloader"), TRUE, FALSE, &error); + MonoString *thread_name_str = mono_string_new_checked (mono_domain_get (), "Domain unloader", &error); + if (is_ok (&error)) + mono_thread_set_name_internal (internal, thread_name_str, TRUE, FALSE, &error); if (!is_ok (&error)) { data->failure_reason = g_strdup (mono_error_get_message (&error)); mono_error_cleanup (&error); @@ -2520,7 +2593,6 @@ unload_thread_main (void *arg) mono_loader_lock (); //FIXME why do we need the loader lock here? mono_domain_lock (domain); -#ifdef HAVE_SGEN_GC /* * We need to make sure that we don't have any remsets * pointing into static data of the to-be-freed domain because @@ -2533,7 +2605,6 @@ unload_thread_main (void *arg) for (i = 0; i < domain->class_vtable_array->len; ++i) zero_static_data ((MonoVTable *)g_ptr_array_index (domain->class_vtable_array, i)); mono_gc_collect (0); -#endif for (i = 0; i < domain->class_vtable_array->len; ++i) clear_cached_vtable ((MonoVTable *)g_ptr_array_index (domain->class_vtable_array, i)); deregister_reflection_info_roots (domain); @@ -2543,8 +2614,6 @@ unload_thread_main (void *arg) mono_domain_unlock (domain); mono_loader_unlock (); - mono_threads_clear_cached_culture (domain); - domain->state = MONO_APPDOMAIN_UNLOADED; /* printf ("UNLOADED %s.\n", domain->friendly_name); */ @@ -2558,22 +2627,20 @@ unload_thread_main (void *arg) mono_atomic_store_release (&data->done, TRUE); unload_data_unref (data); - mono_thread_detach (thread); return 0; failure: mono_atomic_store_release (&data->done, TRUE); unload_data_unref (data); - mono_thread_detach (thread); return 1; } -/* +/** * mono_domain_unload: - * @domain: The domain to unload + * \param domain The domain to unload * - * Unloads an appdomain. Follows the process outlined in the comment - * for mono_domain_try_unload. + * Unloads an appdomain. Follows the process outlined in the comment + * for \c mono_domain_try_unload. */ void mono_domain_unload (MonoDomain *domain) @@ -2594,10 +2661,10 @@ guarded_wait (MonoThreadHandle *thread_handle, guint32 timeout, gboolean alertab return result; } -/* +/** * mono_domain_unload: - * @domain: The domain to unload - * @exc: Exception information + * \param domain The domain to unload + * \param exc Exception information * * Unloads an appdomain. Follows the process outlined in: * http://blogs.gotdotnet.com/cbrumme @@ -2621,7 +2688,7 @@ mono_domain_try_unload (MonoDomain *domain, MonoObject **exc) MonoAppDomainState prev_state; MonoMethod *method; unload_data *thread_data; - MonoNativeThreadId tid; + MonoInternalThread *internal; MonoDomain *caller_domain = mono_domain_get (); /* printf ("UNLOAD STARTING FOR %s (%p) IN THREAD 0x%x.\n", domain->friendly_name, domain, mono_native_thread_id_get ()); */ @@ -2678,10 +2745,15 @@ mono_domain_try_unload (MonoDomain *domain, MonoObject **exc) /* * First we create a separate thread for unloading, since * we might have to abort some threads, including the current one. + * + * Have to attach to the runtime so shutdown can wait for this thread. + * + * Force it to be attached to avoid racing during shutdown. */ - thread_handle = mono_threads_create_thread (unload_thread_main, thread_data, NULL, &tid); - if (thread_handle == NULL) - return; + internal = mono_thread_create_internal (mono_get_root_domain (), unload_thread_main, thread_data, MONO_THREAD_CREATE_FLAGS_FORCE_CREATE, &error); + mono_error_assert_ok (&error); + + thread_handle = mono_threads_open_thread_handle (internal->handle); /* Wait for the thread */ while (!thread_data->done && guarded_wait (thread_handle, MONO_INFINITE_WAIT, TRUE) == MONO_THREAD_INFO_WAIT_RET_ALERTED) {