-/*
- * appdomain.c: AppDomain functions
+/**
+ * \file
+ * AppDomain functions
*
* Authors:
* Dietmar Maurer (dietmar@ximian.com)
#include <mono/metadata/appdomain-icalls.h>
#include <mono/metadata/domain-internals.h>
#include "mono/metadata/metadata-internals.h"
-#include <mono/metadata/assembly.h>
+#include <mono/metadata/assembly-internals.h>
#include <mono/metadata/exception.h>
#include <mono/metadata/exception-internals.h>
#include <mono/metadata/threads.h>
#include <mono/metadata/marshal-internals.h>
#include <mono/metadata/monitor.h>
#include <mono/metadata/mono-debug.h>
-#include <mono/metadata/mono-debug-debugger.h>
#include <mono/metadata/attach.h>
#include <mono/metadata/w32file.h>
#include <mono/metadata/lock-tracer.h>
#include <direct.h>
#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;
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);
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;
/*
* 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);
* 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);
/**
* 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
MonoAppDomain *ad;
MonoClass *klass;
- mono_error_init (error);
+ error_init (error);
mono_portability_helpers_init ();
/* 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 ();
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)
{
}
/**
- * 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*
/**
* 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)
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);
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.
*
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 ()
{
/**
* 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)
/**
* 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)
{
HANDLE_FUNCTION_ENTER ();
- mono_error_init (error);
+ error_init (error);
MonoDomain *result = NULL;
MonoClass *klass = mono_class_load_from_name (mono_defaults.corlib, "System", "AppDomainSetup");
/**
* 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
*
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
MonoClass *ads_class;
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");
MonoClass *adclass;
MonoDomain *data;
- mono_error_init (error);
+ error_init (error);
adclass = mono_class_get_appdomain_class ();
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)) {
/**
* 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)
/**
* 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)
MonoReflectionAssembly *ret;
void *params [1];
- mono_error_init (error);
+ error_init (error);
g_assert (domain != NULL && ((name != NULL) || (tb != NULL)));
}
}
- 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);
/**
* 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)
/**
* 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)
MonoObjectHandle
ves_icall_System_AppDomain_GetData (MonoAppDomainHandle ad, MonoStringHandle name, MonoError *error)
{
- mono_error_init (error);
+ error_init (error);
if (MONO_HANDLE_IS_NULL (name)) {
mono_error_set_argument_null (error, "name", "");
void
ves_icall_System_AppDomain_SetData (MonoAppDomainHandle ad, MonoStringHandle name, MonoObjectHandle data, MonoError *error)
{
- mono_error_init (error);
+ error_init (error);
if (MONO_HANDLE_IS_NULL (name)) {
mono_error_set_argument_null (error, "name", "");
MonoAppDomainSetupHandle
ves_icall_System_AppDomain_getSetup (MonoAppDomainHandle ad, MonoError *error)
{
- mono_error_init (error);
+ error_init (error);
g_assert (!MONO_HANDLE_IS_NULL (ad));
MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data);
g_assert (domain);
MonoStringHandle
ves_icall_System_AppDomain_getFriendlyName (MonoAppDomainHandle ad, MonoError *error)
{
- mono_error_init (error);
+ error_init (error);
g_assert (!MONO_HANDLE_IS_NULL (ad));
MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data);
g_assert (domain);
MonoAppDomainHandle
ves_icall_System_AppDomain_getCurDomain (MonoError *error)
{
- mono_error_init (error);
+ error_init (error);
MonoDomain *add = mono_domain_get ();
return MONO_HANDLE_NEW (MonoAppDomain, add->domain);
MonoAppDomainHandle
ves_icall_System_AppDomain_getRootDomain (MonoError *error)
{
- mono_error_init (error);
+ error_init (error);
MonoDomain *root = mono_get_root_domain ();
return MONO_HANDLE_NEW (MonoAppDomain, root->domain);
MonoAppDomainHandle
ves_icall_System_AppDomain_createDomain (MonoStringHandle friendly_name, MonoAppDomainSetupHandle setup, MonoError *error)
{
- mono_error_init (error);
+ error_init (error);
MonoAppDomainHandle ad = MONO_HANDLE_NEW (MonoAppDomain, NULL);
#ifdef DISABLE_APPDOMAINS
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;
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;
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))
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));
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 *
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);
}
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)
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;
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
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);
mono_runtime_invoke_checked (assembly_load_method, domain->domain, params, &error);
mono_error_cleanup (&error);
+leave:
+ HANDLE_FUNCTION_RETURN ();
}
/*
char *
mono_make_shadow_copy (const char *filename, MonoError *error)
{
- mono_error_init (error);
+ error_init (error);
return (char *) filename;
}
#else
char *userdir;
char *location;
- mono_error_init (error);
+ error_init (error);
setup = domain->setup;
if (setup->cache_path != NULL && setup->application_name != NULL) {
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);
char *shadow_dir;
gint32 copy_error;
- mono_error_init (oerror);
+ error_init (oerror);
set_domain_search_path (domain);
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);
}
#endif /* DISABLE_SHADOW_COPY */
+/**
+ * mono_domain_from_appdomain:
+ */
MonoDomain *
mono_domain_from_appdomain (MonoAppDomain *appdomain_raw)
{
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;
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;
/* 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;
}
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;
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;
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)
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);
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;
void
ves_icall_System_AppDomain_InternalUnload (gint32 domain_id, MonoError *error)
{
- mono_error_init (error);
+ error_init (error);
MonoDomain * domain = mono_domain_get_by_id (domain_id);
if (NULL == domain) {
* 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);
gboolean
ves_icall_System_AppDomain_InternalIsFinalizingForUnload (gint32 domain_id, MonoError *error)
{
- mono_error_init (error);
+ error_init (error);
MonoDomain *domain = mono_domain_get_by_id (domain_id);
if (!domain)
}
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
MonoReflectionAssemblyHandle refass, MonoArrayHandle args,
MonoError *error)
{
- mono_error_init (error);
+ error_init (error);
MonoImage *image;
MonoMethod *method;
MonoAppDomainHandle
ves_icall_System_AppDomain_InternalSetDomain (MonoAppDomainHandle ad, MonoError* error)
{
- mono_error_init (error);
+ error_init (error);
MonoDomain *old_domain = mono_domain_get ();
if (!mono_domain_set (MONO_HANDLE_GETVAL (ad, data), FALSE)) {
void
ves_icall_System_AppDomain_InternalPushDomainRef (MonoAppDomainHandle ad, MonoError *error)
{
- mono_error_init (error);
+ error_init (error);
mono_thread_push_appdomain_ref (MONO_HANDLE_GETVAL (ad, data));
}
void
ves_icall_System_AppDomain_InternalPushDomainRefByID (gint32 domain_id, MonoError *error)
{
- mono_error_init (error);
+ error_init (error);
MonoDomain *domain = mono_domain_get_by_id (domain_id);
if (!domain) {
void
ves_icall_System_AppDomain_InternalPopDomainRef (MonoError *error)
{
- mono_error_init (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;
}
MonoStringHandle
ves_icall_System_AppDomain_InternalGetProcessGuid (MonoStringHandle newguid, MonoError *error)
{
- mono_error_init (error);
+ error_init (error);
MonoDomain* mono_root_domain = mono_get_root_domain ();
mono_domain_lock (mono_root_domain);
if (process_guid_set) {
return newguid;
}
+/**
+ * mono_domain_is_unloading:
+ */
gboolean
mono_domain_is_unloading (MonoDomain *domain)
{
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);
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
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);
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); */
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)
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
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 ()); */
/*
* 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) {