X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fappdomain.c;h=e04b84a7253da2ddaad0d46069337cf8e7ddd81d;hb=HEAD;hp=a2c8c353fd3a1d11c502f2901f5d015198047b97;hpb=f23f72c9de0cb7d03e5db68623440af9dcb19d6c;p=mono.git diff --git a/mono/metadata/appdomain.c b/mono/metadata/appdomain.c index a2c8c353fd3..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,18 +39,17 @@ #include #include #include "mono/metadata/metadata-internals.h" -#include +#include #include #include #include #include #include -#include #include #include +#include #include #include -#include #include #include #include @@ -70,24 +70,12 @@ #include #include #include -#include +#include +#include #ifdef HOST_WIN32 #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; @@ -116,8 +104,15 @@ mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data); static void add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *hash); -static MonoAppDomain * -mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetup *setup, MonoError *error); +static MonoAppDomainHandle +mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetupHandle setup, MonoError *error); + +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); @@ -125,9 +120,18 @@ get_shadow_assembly_location_base (MonoDomain *domain, MonoError *error); static MonoLoadFunc load_function = NULL; /* Lazy class loading functions */ -static GENERATE_GET_CLASS_WITH_CACHE (assembly, System.Reflection, Assembly); +static GENERATE_GET_CLASS_WITH_CACHE (assembly, "System.Reflection", "Assembly"); + +static GENERATE_GET_CLASS_WITH_CACHE (appdomain, "System", "AppDomain"); -static GENERATE_GET_CLASS_WITH_CACHE (appdomain, System, AppDomain); +static MonoDomain * +mono_domain_from_appdomain_handle (MonoAppDomainHandle appdomain); + +static void +mono_error_set_appdomain_unloaded (MonoError *error) +{ + mono_error_set_generic_error (error, "System", "AppDomainUnloadedException", ""); +} void mono_install_runtime_load (MonoLoadFunc func) @@ -188,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; @@ -196,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); @@ -204,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); @@ -229,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 @@ -254,7 +263,7 @@ mono_runtime_init_checked (MonoDomain *domain, MonoThreadStartCB start_cb, MonoT MonoAppDomain *ad; MonoClass *klass; - mono_error_init (error); + error_init (error); mono_portability_helpers_init (); @@ -298,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 (); @@ -315,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) { @@ -336,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* @@ -361,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) @@ -379,7 +394,7 @@ mono_context_init_checked (MonoDomain *domain, MonoError *error) MonoClass *klass; MonoAppContext *context; - mono_error_init (error); + error_init (error); klass = mono_class_load_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Contexts", "Context"); context = (MonoAppContext *) mono_object_new_pinned (domain, klass, error); @@ -387,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. * @@ -422,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 () { @@ -437,40 +459,63 @@ 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) { + HANDLE_FUNCTION_ENTER (); MonoError error; - MonoAppDomain *ad; - MonoAppDomainSetup *setup; - MonoClass *klass; + MonoDomain *domain = mono_domain_create_appdomain_checked (friendly_name, configuration_file, &error); + mono_error_cleanup (&error); + HANDLE_FUNCTION_RETURN_VAL (domain); +} - klass = mono_class_load_from_name (mono_defaults.corlib, "System", "AppDomainSetup"); - setup = (MonoAppDomainSetup *) mono_object_new_checked (mono_domain_get (), klass, &error); - if (!is_ok (&error)) - goto fail; - setup->configuration_file = configuration_file != NULL ? mono_string_new (mono_domain_get (), configuration_file) : NULL; +/** + * mono_domain_create_appdomain_checked: + * \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 \p error and returns NULL. + */ +MonoDomain * +mono_domain_create_appdomain_checked (char *friendly_name, char *configuration_file, MonoError *error) +{ + HANDLE_FUNCTION_ENTER (); + error_init (error); + MonoDomain *result = NULL; - ad = mono_domain_create_appdomain_internal (friendly_name, setup, &error); - if (!is_ok (&error)) - goto fail; + MonoClass *klass = mono_class_load_from_name (mono_defaults.corlib, "System", "AppDomainSetup"); + MonoAppDomainSetupHandle setup = MONO_HANDLE_NEW (MonoAppDomainSetup, mono_object_new_checked (mono_domain_get (), klass, error)); + if (!is_ok (error)) + goto leave; + MonoStringHandle config_file; + if (configuration_file != NULL) { + config_file = mono_string_new_handle (mono_domain_get (), configuration_file, error); + if (!is_ok (error)) + goto leave; + } else { + config_file = MONO_HANDLE_NEW (MonoString, NULL); + } + MONO_HANDLE_SET (setup, configuration_file, config_file); - return mono_domain_from_appdomain (ad); -fail: - mono_error_cleanup (&error); - return NULL; + MonoAppDomainHandle ad = mono_domain_create_appdomain_internal (friendly_name, setup, error); + if (!is_ok (error)) + goto leave; + + result = mono_domain_from_appdomain_handle (ad); +leave: + HANDLE_FUNCTION_RETURN_VAL (result); } /** * 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 * @@ -481,102 +526,145 @@ fail: 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 MonoAppDomainSetup* -copy_app_domain_setup (MonoDomain *domain, MonoAppDomainSetup *setup, MonoError *error) +static MonoAppDomainSetupHandle +copy_app_domain_setup (MonoDomain *domain, MonoAppDomainSetupHandle setup, MonoError *error) { + HANDLE_FUNCTION_ENTER (); MonoDomain *caller_domain; MonoClass *ads_class; - MonoAppDomainSetup *copy; + MonoAppDomainSetupHandle result = MONO_HANDLE_NEW (MonoAppDomainSetup, NULL); - mono_error_init (error); + error_init (error); caller_domain = mono_domain_get (); ads_class = mono_class_load_from_name (mono_defaults.corlib, "System", "AppDomainSetup"); - copy = (MonoAppDomainSetup*)mono_object_new_checked (domain, ads_class, error); - return_val_if_nok (error, NULL); + MonoAppDomainSetupHandle copy = MONO_HANDLE_NEW (MonoAppDomainSetup, mono_object_new_checked (domain, ads_class, error)); + if (!is_ok (error)) + goto leave; mono_domain_set_internal (domain); -#define XCOPY_FIELD(dst,field,src,error) \ +#define XCOPY_FIELD(dst,field,src,error) \ do { \ - MonoObject *copied_val = mono_marshal_xdomain_copy_value ((MonoObject*)(src), error); \ - return_val_if_nok (error, NULL); \ - MONO_OBJECT_SETREF ((dst),field,copied_val); \ + MonoObjectHandle src_val = MONO_HANDLE_NEW_GET (MonoObject, (src), field); \ + MonoObjectHandle copied_val = mono_marshal_xdomain_copy_value_handle (src_val, error); \ + if (!is_ok (error)) \ + goto leave; \ + MONO_HANDLE_SET ((dst),field,copied_val); \ } while (0) - XCOPY_FIELD (copy, application_base, setup->application_base, error); - XCOPY_FIELD (copy, application_name, setup->application_name, error); - XCOPY_FIELD (copy, cache_path, setup->cache_path, error); - XCOPY_FIELD (copy, configuration_file, setup->configuration_file, error); - XCOPY_FIELD (copy, dynamic_base, setup->dynamic_base, error); - XCOPY_FIELD (copy, license_file, setup->license_file, error); - XCOPY_FIELD (copy, private_bin_path, setup->private_bin_path, error); - XCOPY_FIELD (copy, private_bin_path_probe, setup->private_bin_path_probe, error); - XCOPY_FIELD (copy, shadow_copy_directories, setup->shadow_copy_directories, error); - XCOPY_FIELD (copy, shadow_copy_files, setup->shadow_copy_files, error); - copy->publisher_policy = setup->publisher_policy; - copy->path_changed = setup->path_changed; - copy->loader_optimization = setup->loader_optimization; - copy->disallow_binding_redirects = setup->disallow_binding_redirects; - copy->disallow_code_downloads = setup->disallow_code_downloads; - XCOPY_FIELD (copy, domain_initializer_args, setup->domain_initializer_args, error); - copy->disallow_appbase_probe = setup->disallow_appbase_probe; - XCOPY_FIELD (copy, application_trust, setup->application_trust, error); - XCOPY_FIELD (copy, configuration_bytes, setup->configuration_bytes, error); - XCOPY_FIELD (copy, serialized_non_primitives, setup->serialized_non_primitives, error); - -#undef COPY_FIELD +#define COPY_VAL(dst,field,type,src) \ + do { \ + MONO_HANDLE_SETVAL ((dst), field, type, MONO_HANDLE_GETVAL ((src),field)); \ + } while (0) + + XCOPY_FIELD (copy, application_base, setup, error); + XCOPY_FIELD (copy, application_name, setup, error); + XCOPY_FIELD (copy, cache_path, setup, error); + XCOPY_FIELD (copy, configuration_file, setup, error); + XCOPY_FIELD (copy, dynamic_base, setup, error); + XCOPY_FIELD (copy, license_file, setup, error); + XCOPY_FIELD (copy, private_bin_path, setup, error); + XCOPY_FIELD (copy, private_bin_path_probe, setup, error); + XCOPY_FIELD (copy, shadow_copy_directories, setup, error); + XCOPY_FIELD (copy, shadow_copy_files, setup, error); + COPY_VAL (copy, publisher_policy, MonoBoolean, setup); + COPY_VAL (copy, path_changed, MonoBoolean, setup); + COPY_VAL (copy, loader_optimization, int, setup); + COPY_VAL (copy, disallow_binding_redirects, MonoBoolean, setup); + COPY_VAL (copy, disallow_code_downloads, MonoBoolean, setup); + XCOPY_FIELD (copy, domain_initializer_args, setup, error); + COPY_VAL (copy, disallow_appbase_probe, MonoBoolean, setup); + XCOPY_FIELD (copy, application_trust, setup, error); + XCOPY_FIELD (copy, configuration_bytes, setup, error); + XCOPY_FIELD (copy, serialized_non_primitives, setup, error); + +#undef XCOPY_FIELD +#undef COPY_VAL mono_domain_set_internal (caller_domain); - return copy; + MONO_HANDLE_ASSIGN (result, copy); +leave: + HANDLE_FUNCTION_RETURN_REF (MonoAppDomainSetup, result); } -static MonoAppDomain * -mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetup *setup, MonoError *error) +static MonoAppDomainHandle +mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetupHandle setup, MonoError *error) { + HANDLE_FUNCTION_ENTER (); + MonoAppDomainHandle result = MONO_HANDLE_NEW (MonoAppDomain, NULL); MonoClass *adclass; - MonoAppDomain *ad; MonoDomain *data; - char *shadow_location; - mono_error_init (error); + error_init (error); adclass = mono_class_get_appdomain_class (); /* FIXME: pin all those objects */ data = mono_domain_create(); - ad = (MonoAppDomain *) mono_object_new_checked (data, adclass, error); - return_val_if_nok (error, NULL); - ad->data = data; - data->domain = ad; + MonoAppDomainHandle ad = MONO_HANDLE_NEW (MonoAppDomain, mono_object_new_checked (data, adclass, error)); + if (!is_ok (error)) + goto leave; + MONO_HANDLE_SETVAL (ad, data, MonoDomain*, data); + 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)); - if (!setup->application_base) { + MonoStringHandle app_base = MONO_HANDLE_NEW_GET (MonoString, setup, application_base); + if (MONO_HANDLE_IS_NULL (app_base)) { /* Inherit from the root domain since MS.NET does this */ MonoDomain *root = mono_get_root_domain (); - if (root->setup->application_base) { - MonoString *s = mono_string_new_utf16_checked (data, mono_string_chars (root->setup->application_base), mono_string_length (root->setup->application_base), error); - mono_error_assert_ok (error); /* FIXME don't swallow the error */ - MONO_OBJECT_SETREF (setup, application_base, s); + MonoAppDomainSetupHandle root_setup = MONO_HANDLE_NEW (MonoAppDomainSetup, root->setup); + MonoStringHandle root_app_base = MONO_HANDLE_NEW_GET (MonoString, root_setup, application_base); + if (!MONO_HANDLE_IS_NULL (root_app_base)) { + /* N.B. new string is in the new domain */ + uint32_t gchandle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, root_app_base), TRUE); + MonoStringHandle s = mono_string_new_utf16_handle (data, mono_string_chars (MONO_HANDLE_RAW (root_app_base)), mono_string_handle_length (root_app_base), error); + mono_gchandle_free (gchandle); + if (!is_ok (error)) { + g_free (data->friendly_name); + goto leave; + } + MONO_HANDLE_SET (setup, application_base, s); } } mono_context_init_checked (data, error); - return_val_if_nok (error, NULL); + if (!is_ok (error)) + goto leave; - data->setup = copy_app_domain_setup (data, setup, error); + data->setup = MONO_HANDLE_RAW (copy_app_domain_setup (data, setup, error)); if (!mono_error_ok (error)) { g_free (data->friendly_name); - return NULL; + goto leave; } mono_domain_set_options_from_config (data); @@ -584,10 +672,10 @@ mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetup * #ifndef DISABLE_SHADOW_COPY /*FIXME, guard this for when the debugger is not running */ - shadow_location = get_shadow_assembly_location_base (data, error); + char *shadow_location = get_shadow_assembly_location_base (data, error); if (!mono_error_ok (error)) { g_free (data->friendly_name); - return NULL; + goto leave; } g_free (shadow_location); @@ -595,15 +683,16 @@ mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetup * create_domain_objects (data); - return ad; + MONO_HANDLE_ASSIGN (result, ad); +leave: + HANDLE_FUNCTION_RETURN_REF (MonoAppDomain, result); } /** * 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) @@ -626,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) @@ -654,7 +743,7 @@ mono_domain_try_type_resolve_checked (MonoDomain *domain, char *name, MonoObject MonoReflectionAssembly *ret; void *params [1]; - mono_error_init (error); + error_init (error); g_assert (domain != NULL && ((name != NULL) || (tb != NULL))); @@ -666,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); @@ -679,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) @@ -695,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) @@ -716,106 +803,113 @@ mono_domain_set (MonoDomain *domain, gboolean force) return TRUE; } -MonoObject * -ves_icall_System_AppDomain_GetData (MonoAppDomain *ad, MonoString *name) +MonoObjectHandle +ves_icall_System_AppDomain_GetData (MonoAppDomainHandle ad, MonoStringHandle name, MonoError *error) { - MonoError error; - MonoDomain *add; - MonoObject *o; - char *str; + error_init (error); - MONO_CHECK_ARG_NULL (name, NULL); + if (MONO_HANDLE_IS_NULL (name)) { + mono_error_set_argument_null (error, "name", ""); + return NULL_HANDLE; + } - g_assert (ad); - add = ad->data; + g_assert (!MONO_HANDLE_IS_NULL (ad)); + MonoDomain *add = MONO_HANDLE_GETVAL (ad, data); g_assert (add); - str = mono_string_to_utf8_checked (name, &error); - if (mono_error_set_pending_exception (&error)) - return NULL; + char *str = mono_string_handle_to_utf8 (name, error); + return_val_if_nok (error, NULL_HANDLE); mono_domain_lock (add); + MonoAppDomainSetupHandle ad_setup = MONO_HANDLE_NEW (MonoAppDomainSetup, add->setup); + MonoStringHandle o; if (!strcmp (str, "APPBASE")) - o = (MonoObject *)add->setup->application_base; + o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, application_base); else if (!strcmp (str, "APP_CONFIG_FILE")) - o = (MonoObject *)add->setup->configuration_file; + o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, configuration_file); else if (!strcmp (str, "DYNAMIC_BASE")) - o = (MonoObject *)add->setup->dynamic_base; + o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, dynamic_base); else if (!strcmp (str, "APP_NAME")) - o = (MonoObject *)add->setup->application_name; + o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, application_name); else if (!strcmp (str, "CACHE_BASE")) - o = (MonoObject *)add->setup->cache_path; + o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, cache_path); else if (!strcmp (str, "PRIVATE_BINPATH")) - o = (MonoObject *)add->setup->private_bin_path; + o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, private_bin_path); else if (!strcmp (str, "BINPATH_PROBE_ONLY")) - o = (MonoObject *)add->setup->private_bin_path_probe; + o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, private_bin_path_probe); else if (!strcmp (str, "SHADOW_COPY_DIRS")) - o = (MonoObject *)add->setup->shadow_copy_directories; + o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, shadow_copy_directories); else if (!strcmp (str, "FORCE_CACHE_INSTALL")) - o = (MonoObject *)add->setup->shadow_copy_files; + o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, shadow_copy_files); else - o = (MonoObject *)mono_g_hash_table_lookup (add->env, name); + o = MONO_HANDLE_NEW (MonoString, mono_g_hash_table_lookup (add->env, MONO_HANDLE_RAW (name))); mono_domain_unlock (add); g_free (str); - if (!o) - return NULL; - - return o; + return MONO_HANDLE_CAST (MonoObject, o); } void -ves_icall_System_AppDomain_SetData (MonoAppDomain *ad, MonoString *name, MonoObject *data) +ves_icall_System_AppDomain_SetData (MonoAppDomainHandle ad, MonoStringHandle name, MonoObjectHandle data, MonoError *error) { - MonoDomain *add; + error_init (error); - MONO_CHECK_ARG_NULL (name,); + if (MONO_HANDLE_IS_NULL (name)) { + mono_error_set_argument_null (error, "name", ""); + return; + } - g_assert (ad); - add = ad->data; + g_assert (!MONO_HANDLE_IS_NULL (ad)); + MonoDomain *add = MONO_HANDLE_GETVAL (ad, data); g_assert (add); mono_domain_lock (add); - mono_g_hash_table_insert (add->env, name, data); + mono_g_hash_table_insert (add->env, MONO_HANDLE_RAW (name), MONO_HANDLE_RAW (data)); mono_domain_unlock (add); } -MonoAppDomainSetup * -ves_icall_System_AppDomain_getSetup (MonoAppDomain *ad) +MonoAppDomainSetupHandle +ves_icall_System_AppDomain_getSetup (MonoAppDomainHandle ad, MonoError *error) { - g_assert (ad); - g_assert (ad->data); + error_init (error); + g_assert (!MONO_HANDLE_IS_NULL (ad)); + MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data); + g_assert (domain); - return ad->data->setup; + return MONO_HANDLE_NEW (MonoAppDomainSetup, domain->setup); } -MonoString * -ves_icall_System_AppDomain_getFriendlyName (MonoAppDomain *ad) +MonoStringHandle +ves_icall_System_AppDomain_getFriendlyName (MonoAppDomainHandle ad, MonoError *error) { - g_assert (ad); - g_assert (ad->data); + error_init (error); + g_assert (!MONO_HANDLE_IS_NULL (ad)); + MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data); + g_assert (domain); - return mono_string_new (ad->data, ad->data->friendly_name); + return mono_string_new_handle (domain, domain->friendly_name, error); } -MonoAppDomain * -ves_icall_System_AppDomain_getCurDomain () +MonoAppDomainHandle +ves_icall_System_AppDomain_getCurDomain (MonoError *error) { + error_init (error); MonoDomain *add = mono_domain_get (); - return add->domain; + return MONO_HANDLE_NEW (MonoAppDomain, add->domain); } -MonoAppDomain * -ves_icall_System_AppDomain_getRootDomain () +MonoAppDomainHandle +ves_icall_System_AppDomain_getRootDomain (MonoError *error) { + error_init (error); MonoDomain *root = mono_get_root_domain (); - return root->domain; + return MONO_HANDLE_NEW (MonoAppDomain, root->domain); } MonoBoolean @@ -965,26 +1059,22 @@ mono_domain_set_options_from_config (MonoDomain *domain) g_free (config_file_path); } -MonoAppDomain * -ves_icall_System_AppDomain_createDomain (MonoString *friendly_name, MonoAppDomainSetup *setup) +MonoAppDomainHandle +ves_icall_System_AppDomain_createDomain (MonoStringHandle friendly_name, MonoAppDomainSetupHandle setup, MonoError *error) { - MonoError error; - MonoAppDomain *ad = NULL; + error_init (error); + MonoAppDomainHandle ad = MONO_HANDLE_NEW (MonoAppDomain, NULL); #ifdef DISABLE_APPDOMAINS - mono_error_init (&error); - mono_error_set_not_supported (&error, "AppDomain creation is not supported on this runtime."); + mono_error_set_not_supported (error, "AppDomain creation is not supported on this runtime."); #else char *fname; - fname = mono_string_to_utf8_checked (friendly_name, &error); - if (mono_error_set_pending_exception (&error)) - return NULL; - ad = mono_domain_create_appdomain_internal (fname, setup, &error); - + fname = mono_string_handle_to_utf8 (friendly_name, error); + return_val_if_nok (error, ad); + ad = mono_domain_create_appdomain_internal (fname, setup, error); g_free (fname); #endif - mono_error_set_pending_exception (&error); return ad; } @@ -992,7 +1082,7 @@ static gboolean add_assembly_to_array (MonoDomain *domain, MonoArrayHandle dest, int dest_idx, MonoAssembly* assm, MonoError *error) { HANDLE_FUNCTION_ENTER (); - mono_error_init (error); + error_init (error); MonoReflectionAssemblyHandle assm_obj = mono_assembly_get_object_handle (domain, assm, error); if (!is_ok (error)) goto leave; @@ -1004,7 +1094,7 @@ leave: MonoArrayHandle ves_icall_System_AppDomain_GetAssemblies (MonoAppDomainHandle ad, MonoBoolean refonly, MonoError *error) { - mono_error_init (error); + error_init (error); MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data); MonoAssembly* ass; GSList *tmp; @@ -1045,7 +1135,7 @@ MonoAssembly* mono_try_assembly_resolve (MonoDomain *domain, const char *fname_raw, MonoAssembly *requesting, gboolean refonly, MonoError *error) { HANDLE_FUNCTION_ENTER (); - mono_error_init (error); + error_init (error); MonoAssembly *result = NULL; MonoStringHandle fname = mono_string_new_handle (domain, fname_raw, error); if (!is_ok (error)) @@ -1058,15 +1148,16 @@ 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; gpointer params [3]; - mono_error_init (error); + error_init (error); if (mono_runtime_get_no_exec ()) - return ret; + goto leave; g_assert (domain != NULL && !MONO_HANDLE_IS_NULL (fname)); @@ -1077,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 * @@ -1123,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); @@ -1137,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) @@ -1151,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; @@ -1161,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 @@ -1179,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); @@ -1194,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 (); } /* @@ -1389,7 +1500,7 @@ mono_is_shadow_copy_enabled (MonoDomain *domain, const gchar *dir_name) char * mono_make_shadow_copy (const char *filename, MonoError *error) { - mono_error_init (error); + error_init (error); return (char *) filename; } #else @@ -1464,7 +1575,7 @@ get_shadow_assembly_location_base (MonoDomain *domain, MonoError *error) char *userdir; char *location; - mono_error_init (error); + error_init (error); setup = domain->setup; if (setup->cache_path != NULL && setup->application_name != NULL) { @@ -1508,7 +1619,7 @@ get_shadow_assembly_location (const char *filename, MonoError *error) char *location, *tmploc; MonoDomain *domain = mono_domain_get (); - mono_error_init (error); + error_init (error); hash = get_cstring_hash (bname); hash2 = get_cstring_hash (dirname); @@ -1598,7 +1709,7 @@ shadow_copy_create_ini (const char *shadow, const char *filename) full_path = mono_path_resolve_symlinks (filename); result = mono_w32file_write (handle, full_path, strlen (full_path), &n); g_free (full_path); - CloseHandle (handle); + mono_w32file_close (handle); return result; } @@ -1693,7 +1804,7 @@ mono_make_shadow_copy (const char *filename, MonoError *oerror) char *shadow_dir; gint32 copy_error; - mono_error_init (oerror); + error_init (oerror); set_domain_search_path (domain); @@ -1762,7 +1873,7 @@ mono_make_shadow_copy (const char *filename, MonoError *oerror) g_free (shadow); /* Fix for bug #17251 - if file not found try finding assembly by other means (it is not fatal error) */ - if (GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND) + if (mono_w32error_get_last() == ERROR_FILE_NOT_FOUND || mono_w32error_get_last() == ERROR_PATH_NOT_FOUND) return NULL; /* file not found, shadow copy failed */ mono_error_set_execution_engine (oerror, "Failed to create shadow copy (mono_w32file_copy)."); @@ -1774,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); @@ -1803,24 +1916,45 @@ mono_make_shadow_copy (const char *filename, MonoError *oerror) } #endif /* DISABLE_SHADOW_COPY */ +/** + * mono_domain_from_appdomain: + */ MonoDomain * -mono_domain_from_appdomain (MonoAppDomain *appdomain) +mono_domain_from_appdomain (MonoAppDomain *appdomain_raw) { - if (appdomain == NULL) - return NULL; + HANDLE_FUNCTION_ENTER (); + MONO_HANDLE_DCL (MonoAppDomain, appdomain); + MonoDomain *result = mono_domain_from_appdomain_handle (appdomain); + HANDLE_FUNCTION_RETURN_VAL (result); +} - if (mono_object_is_transparent_proxy (&appdomain->mbr.obj)) { - MonoTransparentProxy *tp = (MonoTransparentProxy*)appdomain; - return mono_domain_get_by_id (tp->rp->target_domain_id); - } - - return appdomain->data; +MonoDomain * +mono_domain_from_appdomain_handle (MonoAppDomainHandle appdomain) +{ + HANDLE_FUNCTION_ENTER (); + MonoDomain *dom = NULL; + if (MONO_HANDLE_IS_NULL (appdomain)) + goto leave; + + if (mono_class_is_transparent_proxy (mono_handle_class (appdomain))) { + MonoTransparentProxyHandle tp = MONO_HANDLE_CAST (MonoTransparentProxy, appdomain); + MonoRealProxyHandle rp = MONO_HANDLE_NEW_GET (MonoRealProxy, tp, rp); + + dom = mono_domain_get_by_id (MONO_HANDLE_GETVAL (rp, target_domain_id)); + } else + dom = MONO_HANDLE_GETVAL (appdomain, data); + +leave: + HANDLE_FUNCTION_RETURN_VAL (dom); } + 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; @@ -1839,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; @@ -1873,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; } @@ -1913,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; @@ -1954,7 +2104,7 @@ mono_domain_assembly_search (MonoAssemblyName *aname, MonoReflectionAssemblyHandle ves_icall_System_Reflection_Assembly_LoadFrom (MonoStringHandle fname, MonoBoolean refOnly, MonoError *error) { - mono_error_init (error); + error_init (error); MonoDomain *domain = mono_domain_get (); char *name, *filename; MonoImageOpenStatus status = MONO_IMAGE_OK; @@ -1972,7 +2122,7 @@ ves_icall_System_Reflection_Assembly_LoadFrom (MonoStringHandle fname, MonoBoole if (!is_ok (error)) goto leave; - MonoAssembly *ass = mono_assembly_open_full (filename, &status, refOnly); + MonoAssembly *ass = mono_assembly_open_predicate (filename, refOnly, TRUE, NULL, NULL, &status); if (!ass) { if (status == MONO_IMAGE_IMAGE_INVALID) @@ -1996,7 +2146,7 @@ ves_icall_System_AppDomain_LoadAssemblyRaw (MonoAppDomainHandle ad, MonoBoolean refonly, MonoError *error) { - mono_error_init (error); + error_init (error); MonoAssembly *ass; MonoReflectionAssemblyHandle refass = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE); MonoDomain *domain = MONO_HANDLE_GETVAL(ad, data); @@ -2048,7 +2198,7 @@ ves_icall_System_AppDomain_LoadAssemblyRaw (MonoAppDomainHandle ad, MonoReflectionAssemblyHandle ves_icall_System_AppDomain_LoadAssembly (MonoAppDomainHandle ad, MonoStringHandle assRef, MonoObjectHandle evidence, MonoBoolean refOnly, MonoError *error) { - mono_error_init (error); + error_init (error); MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data); MonoImageOpenStatus status = MONO_IMAGE_OK; MonoAssembly *ass; @@ -2107,19 +2257,18 @@ fail: } void -ves_icall_System_AppDomain_InternalUnload (gint32 domain_id) +ves_icall_System_AppDomain_InternalUnload (gint32 domain_id, MonoError *error) { - MonoException *exc = NULL; + error_init (error); MonoDomain * domain = mono_domain_get_by_id (domain_id); if (NULL == domain) { - mono_get_exception_execution_engine ("Failed to unload domain, domain id not found"); - mono_set_pending_exception (exc); + mono_error_set_execution_engine (error, "Failed to unload domain, domain id not found"); return; } if (domain == mono_get_root_domain ()) { - mono_set_pending_exception (mono_get_exception_cannot_unload_appdomain ("The default appdomain can not be unloaded.")); + mono_error_set_generic_error (error, "System", "CannotUnloadAppDomainException", "The default appdomain can not be unloaded."); return; } @@ -2127,20 +2276,19 @@ ves_icall_System_AppDomain_InternalUnload (gint32 domain_id) * 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); if (exc) - mono_set_pending_exception (exc); + mono_error_set_exception_instance (error, exc); } gboolean -ves_icall_System_AppDomain_InternalIsFinalizingForUnload (gint32 domain_id) +ves_icall_System_AppDomain_InternalIsFinalizingForUnload (gint32 domain_id, MonoError *error) { + error_init (error); MonoDomain *domain = mono_domain_get_by_id (domain_id); if (!domain) @@ -2150,9 +2298,11 @@ ves_icall_System_AppDomain_InternalIsFinalizingForUnload (gint32 domain_id) } 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 @@ -2160,7 +2310,7 @@ ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomainHandle ad, MonoReflectionAssemblyHandle refass, MonoArrayHandle args, MonoError *error) { - mono_error_init (error); + error_init (error); MonoImage *image; MonoMethod *method; @@ -2190,42 +2340,45 @@ ves_icall_System_AppDomain_GetIDFromDomain (MonoAppDomain * ad) return ad->data->domain_id; } -MonoAppDomain * -ves_icall_System_AppDomain_InternalSetDomain (MonoAppDomain *ad) +MonoAppDomainHandle +ves_icall_System_AppDomain_InternalSetDomain (MonoAppDomainHandle ad, MonoError* error) { - MonoDomain *old_domain = mono_domain_get(); + error_init (error); + MonoDomain *old_domain = mono_domain_get (); - if (!mono_domain_set (ad->data, FALSE)) { - mono_set_pending_exception (mono_get_exception_appdomain_unloaded ()); - return NULL; + if (!mono_domain_set (MONO_HANDLE_GETVAL (ad, data), FALSE)) { + mono_error_set_appdomain_unloaded (error); + return MONO_HANDLE_CAST (MonoAppDomain, NULL_HANDLE); } - return old_domain->domain; + return MONO_HANDLE_NEW (MonoAppDomain, old_domain->domain); } -MonoAppDomain * -ves_icall_System_AppDomain_InternalSetDomainByID (gint32 domainid) +MonoAppDomainHandle +ves_icall_System_AppDomain_InternalSetDomainByID (gint32 domainid, MonoError *error) { MonoDomain *current_domain = mono_domain_get (); MonoDomain *domain = mono_domain_get_by_id (domainid); if (!domain || !mono_domain_set (domain, FALSE)) { - mono_set_pending_exception (mono_get_exception_appdomain_unloaded ()); - return NULL; + mono_error_set_appdomain_unloaded (error); + return MONO_HANDLE_CAST (MonoAppDomain, NULL_HANDLE); } - return current_domain->domain; + return MONO_HANDLE_NEW (MonoAppDomain, current_domain->domain); } void -ves_icall_System_AppDomain_InternalPushDomainRef (MonoAppDomain *ad) +ves_icall_System_AppDomain_InternalPushDomainRef (MonoAppDomainHandle ad, MonoError *error) { - mono_thread_push_appdomain_ref (ad->data); + error_init (error); + mono_thread_push_appdomain_ref (MONO_HANDLE_GETVAL (ad, data)); } void -ves_icall_System_AppDomain_InternalPushDomainRefByID (gint32 domain_id) +ves_icall_System_AppDomain_InternalPushDomainRefByID (gint32 domain_id, MonoError *error) { + error_init (error); MonoDomain *domain = mono_domain_get_by_id (domain_id); if (!domain) { @@ -2233,7 +2386,7 @@ ves_icall_System_AppDomain_InternalPushDomainRefByID (gint32 domain_id) * Raise an exception to prevent the managed code from executing a pop * later. */ - mono_set_pending_exception (mono_get_exception_appdomain_unloaded ()); + mono_error_set_appdomain_unloaded (error); return; } @@ -2241,52 +2394,58 @@ ves_icall_System_AppDomain_InternalPushDomainRefByID (gint32 domain_id) } void -ves_icall_System_AppDomain_InternalPopDomainRef (void) +ves_icall_System_AppDomain_InternalPopDomainRef (MonoError *error) { + error_init (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; } -MonoString * -ves_icall_System_AppDomain_InternalGetProcessGuid (MonoString* newguid) +MonoStringHandle +ves_icall_System_AppDomain_InternalGetProcessGuid (MonoStringHandle newguid, MonoError *error) { + error_init (error); MonoDomain* mono_root_domain = mono_get_root_domain (); mono_domain_lock (mono_root_domain); if (process_guid_set) { mono_domain_unlock (mono_root_domain); - MonoError error; - MonoString *res = NULL; - res = mono_string_new_utf16_checked (mono_domain_get (), process_guid, sizeof(process_guid)/2, &error); - mono_error_set_pending_exception (&error); - return res; + return mono_string_new_utf16_handle (mono_domain_get (), process_guid, sizeof(process_guid)/2, error); } - memcpy (process_guid, mono_string_chars(newguid), sizeof(process_guid)); + uint32_t gchandle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, newguid), TRUE); + memcpy (process_guid, mono_string_chars(MONO_HANDLE_RAW (newguid)), sizeof(process_guid)); + mono_gchandle_free (gchandle); process_guid_set = TRUE; mono_domain_unlock (mono_root_domain); return newguid; } +/** + * mono_domain_is_unloading: + */ gboolean mono_domain_is_unloading (MonoDomain *domain) { @@ -2393,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, &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); @@ -2434,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 @@ -2447,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); @@ -2457,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); */ @@ -2472,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) @@ -2508,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 @@ -2535,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 ()); */ @@ -2592,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) {