X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fappdomain.c;h=a57df66f8b6d1710c68312580d9f9af4746df655;hb=57cd4050c4c46d4e39717dadeae9516f147af7f6;hp=20e4521e7b6df8e4fe084c594a4d8da85277af30;hpb=07ec1253c277856bdbb74213e2defc8ed23cf8e3;p=mono.git diff --git a/mono/metadata/appdomain.c b/mono/metadata/appdomain.c index 20e4521e7b6..a57df66f8b6 100644 --- a/mono/metadata/appdomain.c +++ b/mono/metadata/appdomain.c @@ -12,10 +12,21 @@ #include #include #include +#ifdef HAVE_UNISTD_H #include +#endif +#include +#include +#include +#ifdef HAVE_UTIME_H +#include +#else +#ifdef HAVE_SYS_UTIME_H +#include +#endif +#endif -#include - +#include #include #include #include "mono/metadata/metadata-internals.h" @@ -34,8 +45,30 @@ #include #include #include +#include +#ifdef PLATFORM_WIN32 +#include +#endif -#define MONO_CORLIB_VERSION 54 +/* + * 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/mscorlib/System/Environment.cs + * + * Changes which are already detected at runtime, like the addition + * of icalls, do not require an increment. + */ +#define MONO_CORLIB_VERSION 68 + +typedef struct +{ + int runtime_count; + int assemblybinding_count; + MonoDomain *domain; +} RuntimeConfig; CRITICAL_SECTION mono_delegate_section; @@ -66,6 +99,21 @@ add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *has static void mono_domain_unload (MonoDomain *domain); +static MonoLoadFunc load_function = NULL; + +void +mono_install_runtime_load (MonoLoadFunc func) +{ + load_function = func; +} + +MonoDomain* +mono_runtime_load (const char *filename, const char *runtime_version) +{ + g_assert (load_function); + return load_function (filename, runtime_version); +} + /** * mono_runtime_init: * @domain: domain returned by mono_init () @@ -86,8 +134,10 @@ mono_runtime_init (MonoDomain *domain, MonoThreadStartCB start_cb, MonoAppDomain *ad; MonoClass *class; MonoString *arg; + + mono_portability_helpers_init (); - MONO_GC_PRE_INIT (); + mono_gc_base_init (); mono_monitor_init (); mono_thread_pool_init (); mono_marshal_init (); @@ -143,7 +193,7 @@ mono_runtime_init (MonoDomain *domain, MonoThreadStartCB start_cb, /* mscorlib is loaded before we install the load hook */ mono_domain_fire_assembly_load (mono_defaults.corlib->assembly, NULL); - + return; } @@ -214,6 +264,10 @@ mono_runtime_cleanup (MonoDomain *domain) mono_type_initialization_cleanup (); mono_monitor_cleanup (); + +#ifndef PLATFORM_WIN32 + _wapi_cleanup (); +#endif } static MonoDomainFunc quit_function = NULL; @@ -472,6 +526,111 @@ ves_icall_System_AppDomain_getRootDomain () return root->domain; } +static char* +get_attribute_value (const gchar **attribute_names, + const gchar **attribute_values, + const char *att_name) +{ + int n; + for (n = 0; attribute_names [n] != NULL; n++) { + if (strcmp (attribute_names [n], att_name) == 0) + return g_strdup (attribute_values [n]); + } + return NULL; +} + +static void +start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + RuntimeConfig *runtime_config = user_data; + + if (strcmp (element_name, "runtime") == 0) { + runtime_config->runtime_count++; + return; + } + + if (strcmp (element_name, "assemblyBinding") == 0) { + runtime_config->assemblybinding_count++; + return; + } + + if (runtime_config->runtime_count != 1 || runtime_config->assemblybinding_count != 1) + return; + + if (strcmp (element_name, "probing") != 0) + return; + + g_free (runtime_config->domain->private_bin_path); + runtime_config->domain->private_bin_path = get_attribute_value (attribute_names, attribute_values, "privatePath"); + if (runtime_config->domain->private_bin_path && !runtime_config->domain->private_bin_path [0]) { + g_free (runtime_config->domain->private_bin_path); + runtime_config->domain->private_bin_path = NULL; + return; + } +} + +static void +end_element (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error) +{ + RuntimeConfig *runtime_config = user_data; + if (strcmp (element_name, "runtime") == 0) + runtime_config->runtime_count--; + else if (strcmp (element_name, "assemblyBinding") == 0) + runtime_config->assemblybinding_count--; +} + +static const GMarkupParser +mono_parser = { + start_element, + end_element, + NULL, + NULL, + NULL +}; + +static void +mono_set_private_bin_path_from_config (MonoDomain *domain) +{ + gchar *config_file, *text; + gsize len; + struct stat sbuf; + GMarkupParseContext *context; + RuntimeConfig runtime_config; + + if (!domain || !domain->setup || !domain->setup->configuration_file) + return; + + config_file = mono_string_to_utf8 (domain->setup->configuration_file); + if (stat (config_file, &sbuf) != 0) { + g_free (config_file); + return; + } + + if (!g_file_get_contents (config_file, &text, &len, NULL)) { + g_free (config_file); + return; + } + g_free (config_file); + + runtime_config.runtime_count = 0; + runtime_config.assemblybinding_count = 0; + runtime_config.domain = domain; + + context = g_markup_parse_context_new (&mono_parser, 0, &runtime_config, NULL); + if (g_markup_parse_context_parse (context, text, len, NULL)) + g_markup_parse_context_end_parse (context, NULL); + g_markup_parse_context_free (context); + g_free (text); +} + MonoAppDomain * ves_icall_System_AppDomain_createDomain (MonoString *friendly_name, MonoAppDomainSetup *setup) { @@ -491,6 +650,8 @@ ves_icall_System_AppDomain_createDomain (MonoString *friendly_name, MonoAppDomai data->domain = ad; data->setup = setup; data->friendly_name = mono_string_to_utf8 (friendly_name); + // FIXME: The ctor runs in the current domain + // FIXME: Initialize null_reference_ex and stack_overflow_ex data->out_of_memory_ex = mono_exception_from_name_domain (data, mono_defaults.corlib, "System", "OutOfMemoryException"); if (!setup->application_base) { @@ -500,6 +661,8 @@ ves_icall_System_AppDomain_createDomain (MonoString *friendly_name, MonoAppDomai MONO_OBJECT_SETREF (setup, application_base, mono_string_new_utf16 (data, mono_string_chars (root->setup->application_base), mono_string_length (root->setup->application_base))); } + mono_set_private_bin_path_from_config (data); + mono_context_init (data); add_assemblies_to_domain (data, mono_defaults.corlib->assembly, NULL); @@ -515,42 +678,45 @@ ves_icall_System_AppDomain_GetAssemblies (MonoAppDomain *ad, MonoBoolean refonly static MonoClass *System_Reflection_Assembly; MonoArray *res; GSList *tmp; - int i, count; - + int i; + GPtrArray *assemblies; + MONO_ARCH_SAVE_REGS; if (!System_Reflection_Assembly) System_Reflection_Assembly = mono_class_from_name ( mono_defaults.corlib, "System.Reflection", "Assembly"); - count = 0; + /* + * Make a copy of the list of assemblies because we can't hold the assemblies + * lock while creating objects etc. + */ + assemblies = g_ptr_array_new (); /* Need to skip internal assembly builders created by remoting */ mono_domain_assemblies_lock (domain); - for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { - ass = tmp->data; - if (refonly && !ass->ref_only) - continue; - if (!ass->corlib_internal) - count++; - } - res = mono_array_new (domain, System_Reflection_Assembly, count); - i = 0; for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { ass = tmp->data; if (refonly && !ass->ref_only) continue; if (ass->corlib_internal) continue; - mono_array_setref (res, i, mono_assembly_get_object (domain, ass)); - ++i; + g_ptr_array_add (assemblies, ass); } mono_domain_assemblies_unlock (domain); + res = mono_array_new (domain, System_Reflection_Assembly, assemblies->len); + for (i = 0; i < assemblies->len; ++i) { + ass = g_ptr_array_index (assemblies, i); + mono_array_setref (res, i, mono_assembly_get_object (domain, ass)); + } + + g_ptr_array_free (assemblies, TRUE); + return res; } -static MonoReflectionAssembly * -try_assembly_resolve (MonoDomain *domain, MonoString *fname, gboolean refonly) +MonoReflectionAssembly * +mono_try_assembly_resolve (MonoDomain *domain, MonoString *fname, gboolean refonly) { MonoClass *klass; MonoMethod *method; @@ -586,7 +752,7 @@ mono_domain_assembly_postload_search (MonoAssemblyName *aname, aname_str = mono_stringify_assembly_name (aname); /* FIXME: We invoke managed code here, so there is a potential for deadlocks */ - assembly = try_assembly_resolve (domain, mono_string_new (domain, aname_str), refonly); + assembly = mono_try_assembly_resolve (domain, mono_string_new (domain, aname_str), refonly); g_free (aname_str); @@ -627,9 +793,10 @@ add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *ht) if (ass->image->references) { for (i = 0; ass->image->references [i] != NULL; i++) { - if (!g_hash_table_lookup (ht, ass->image->references [i])) { - add_assemblies_to_domain (domain, ass->image->references [i], ht); - } + if (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) @@ -682,32 +849,80 @@ mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data) mono_runtime_invoke (assembly_load_method, domain->domain, params, NULL); } +/* + * LOCKING: Acquires the domain assemblies lock. + */ static void set_domain_search_path (MonoDomain *domain) { MonoAppDomainSetup *setup; gchar **tmp; - gchar *utf8; + gchar *search_path = NULL; gint i; gint npaths = 0; gchar **pvt_split = NULL; GError *error = NULL; gint appbaselen = -1; - if ((domain->search_path != NULL) && !domain->setup->path_changed) + /* + * We use the low-level domain assemblies lock, since this is called from + * assembly loads hooks, which means this thread might hold the loader lock. + */ + mono_domain_assemblies_lock (domain); + + if ((domain->search_path != NULL) && !domain->setup->path_changed) { + mono_domain_assemblies_unlock (domain); return; - if (!domain->setup) + } + if (!domain->setup) { + mono_domain_assemblies_unlock (domain); return; + } setup = domain->setup; - if (!setup->application_base) + if (!setup->application_base) { + mono_domain_assemblies_unlock (domain); return; /* Must set application base to get private path working */ + } npaths++; - if (setup->private_bin_path) { - utf8 = mono_string_to_utf8 (setup->private_bin_path); - pvt_split = g_strsplit (utf8, G_SEARCHPATH_SEPARATOR_S, 1000); - g_free (utf8); + + if (setup->private_bin_path) + search_path = mono_string_to_utf8 (setup->private_bin_path); + + if (domain->private_bin_path) { + if (search_path == NULL) + search_path = domain->private_bin_path; + else { + gchar *tmp2 = search_path; + search_path = g_strjoin (";", search_path, domain->private_bin_path, NULL); + g_free (tmp2); + } + } + + if (search_path) { + /* + * As per MSDN documentation, AppDomainSetup.PrivateBinPath contains a list of + * directories relative to ApplicationBase separated by semicolons (see + * http://msdn2.microsoft.com/en-us/library/system.appdomainsetup.privatebinpath.aspx) + * The loop below copes with the fact that some Unix applications may use ':' (or + * System.IO.Path.PathSeparator) as the path search separator. We replace it with + * ';' for the subsequent split. + * + * The issue was reported in bug #81446 + */ + +#ifndef PLATFORM_WIN32 + gint slen; + + slen = strlen (search_path); + for (i = 0; i < slen; i++) + if (search_path [i] == ':') + search_path [i] = ';'; +#endif + + pvt_split = g_strsplit (search_path, ";", 1000); + g_free (search_path); for (tmp = pvt_split; *tmp; tmp++, npaths++); } @@ -721,6 +936,7 @@ set_domain_search_path (MonoDomain *domain) * domain->search_path = g_malloc (sizeof (char *)); * domain->search_path [0] = NULL; */ + mono_domain_assemblies_unlock (domain); return; } @@ -794,43 +1010,280 @@ set_domain_search_path (MonoDomain *domain) domain->setup->path_changed = FALSE; g_strfreev (pvt_split); + + mono_domain_assemblies_unlock (domain); } -static char * -make_shadow_copy (const char *filename) +static gboolean +shadow_copy_sibling (gchar *src, gint srclen, const char *extension, gchar *target, gint targetlen, gint tail_len) { - gchar *tmp; guint16 *orig, *dest; + gboolean copy_result; + + strcpy (src + srclen - tail_len, extension); + if (!g_file_test (src, G_FILE_TEST_IS_REGULAR)) + return TRUE; + orig = g_utf8_to_utf16 (src, strlen (src), NULL, NULL, NULL); + + strcpy (target + targetlen - tail_len, extension); + dest = g_utf8_to_utf16 (target, strlen (target), NULL, NULL, NULL); + + DeleteFile (dest); + copy_result = CopyFile (orig, dest, FALSE); + g_free (orig); + g_free (dest); + + return copy_result; +} + +static gint32 +get_cstring_hash (const char *str) +{ + int len, i; + const char *p; + gint32 h = 0; + + if (!str || !str [0]) + return 0; + + len = strlen (str); + p = str; + for (i = 0; i < len; i++) { + h = (h << 5) - h + *p; + p++; + } + + return h; +} + +static char * +get_shadow_assembly_location (const char *filename) +{ + gint32 hash = 0, hash2 = 0; + char name_hash [9]; + char path_hash [30]; + char *bname = g_path_get_basename (filename); + char *dirname = g_path_get_dirname (filename); + char *location, *dyn_base; MonoDomain *domain = mono_domain_get (); - char *db; - int fd; + + hash = get_cstring_hash (bname); + hash2 = get_cstring_hash (dirname); + g_snprintf (name_hash, sizeof (name_hash), "%08x", hash); + g_snprintf (path_hash, sizeof (path_hash), "%08x_%08x_%08x", hash ^ hash2, hash2, domain->shadow_serial); + dyn_base = mono_string_to_utf8 (domain->setup->dynamic_base); + location = g_build_filename (dyn_base, "assembly", "shadow", name_hash, path_hash, bname, NULL); + g_free (dyn_base); + g_free (bname); + g_free (dirname); + return location; +} + +static gboolean +ensure_directory_exists (const char *filename) +{ +#ifdef PLATFORM_WIN32 + gchar *dir_utf8 = g_path_get_dirname (filename); + gunichar2 *p; + gunichar2 *dir_utf16 = NULL; + int retval; + + if (!dir_utf8 || !dir_utf8 [0]) + return FALSE; + + dir_utf16 = g_utf8_to_utf16 (dir_utf8, strlen (dir_utf8), NULL, NULL, NULL); + g_free (dir_utf8); + + if (!dir_utf16) + return FALSE; + + p = dir_utf16; + + /* make life easy and only use one directory seperator */ + while (*p != '\0') + { + if (*p == '/') + *p = '\\'; + p++; + } + + p = dir_utf16; + + /* get past C:\ )*/ + while (*p++ != '\\') + { + } + + while (1) { + BOOL bRet = FALSE; + p = wcschr (p, '\\'); + if (p) + *p = '\0'; + retval = _wmkdir (dir_utf16); + if (retval != 0 && errno != EEXIST) { + g_free (dir_utf16); + return FALSE; + } + if (!p) + break; + *p++ = '\\'; + } + + g_free (dir_utf16); + return TRUE; +#else + char *p; + gchar *dir = g_path_get_dirname (filename); + int retval; + struct stat sbuf; + + if (!dir || !dir [0]) { + g_free (dir); + return FALSE; + } + + if (stat (dir, &sbuf) == 0 && S_ISDIR (sbuf.st_mode)) { + g_free (dir); + return TRUE; + } + + p = dir; + while (*p == '/') + p++; + + while (1) { + p = strchr (p, '/'); + if (p) + *p = '\0'; + retval = mkdir (dir, 0777); + if (retval != 0 && errno != EEXIST) { + g_free (dir); + return FALSE; + } + if (!p) + break; + *p++ = '/'; + } + + g_free (dir); + return TRUE; +#endif +} + +static gboolean +private_file_needs_copying (const char *src, struct stat *sbuf_src, char *dest) +{ + struct stat sbuf_dest; + + if (stat (src, sbuf_src) == -1 || stat (dest, &sbuf_dest) == -1) + return TRUE; + + if (sbuf_src->st_mode == sbuf_dest.st_mode && + sbuf_src->st_size == sbuf_dest.st_size && + sbuf_src->st_mtime == sbuf_dest.st_mtime) + return FALSE; + + return TRUE; +} + +char * +mono_make_shadow_copy (const char *filename) +{ + gchar *sibling_source, *sibling_target; + gint sibling_source_len, sibling_target_len; + guint16 *orig, *dest; + char *shadow; gboolean copy_result; + gboolean is_private = FALSE; + gboolean do_copy = FALSE; MonoException *exc; + gchar **path; + struct stat src_sbuf; + struct utimbuf utbuf; + char *dir_name = g_path_get_dirname (filename); + MonoDomain *domain = mono_domain_get (); + set_domain_search_path (domain); - db = mono_string_to_utf8 (domain->setup->dynamic_base); - tmp = g_build_filename (db, "shadow-XXXXXX", NULL); - fd = mono_mkstemp (tmp); - if (fd == -1) { - exc = mono_get_exception_execution_engine ("Failed to create shadow copy (mkstemp)."); - g_free (tmp); - g_free (db); - mono_raise_exception (exc); + if (!domain->search_path) { + g_free (dir_name); + return (char*) filename; + } + + for (path = domain->search_path; *path; path++) { + if (**path == '\0') { + is_private = TRUE; + continue; + } + + if (!is_private) + continue; + + if (strstr (dir_name, *path) == dir_name) { + do_copy = TRUE; + break; + } } - close (fd); - remove (tmp); + g_free (dir_name); + + if (!do_copy) + return (char*) filename; + + shadow = get_shadow_assembly_location (filename); + if (ensure_directory_exists (shadow) == FALSE) { + exc = mono_get_exception_execution_engine ("Failed to create shadow copy (ensure directory exists)."); + mono_raise_exception (exc); + } + + if (!private_file_needs_copying (filename, &src_sbuf, shadow)) + return (char*) shadow; + orig = g_utf8_to_utf16 (filename, strlen (filename), NULL, NULL, NULL); - dest = g_utf8_to_utf16 (tmp, strlen (tmp), NULL, NULL, NULL); - copy_result = CopyFile (orig, dest, TRUE); + dest = g_utf8_to_utf16 (shadow, strlen (shadow), NULL, NULL, NULL); + DeleteFile (dest); + copy_result = CopyFile (orig, dest, FALSE); g_free (dest); g_free (orig); - g_free (db); if (copy_result == FALSE) { - g_free (tmp); + g_free (shadow); exc = mono_get_exception_execution_engine ("Failed to create shadow copy (CopyFile)."); mono_raise_exception (exc); } - return tmp; + + /* attempt to copy .mdb, .config if they exist */ + sibling_source = g_strconcat (filename, ".config", NULL); + 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 == TRUE) + copy_result = shadow_copy_sibling (sibling_source, sibling_source_len, ".config", sibling_target, sibling_target_len, 7); + + g_free (sibling_source); + g_free (sibling_target); + + if (copy_result == FALSE) { + g_free (shadow); + exc = mono_get_exception_execution_engine ("Failed to create shadow copy of sibling data (CopyFile)."); + mono_raise_exception (exc); + } + + utbuf.actime = src_sbuf.st_atime; + utbuf.modtime = src_sbuf.st_mtime; + utime (shadow, &utbuf); + + return shadow; +} + + +MonoDomain * +mono_domain_from_appdomain (MonoAppDomain *appdomain) +{ + if (appdomain == NULL) + return NULL; + + return appdomain->data; } static gboolean @@ -838,20 +1291,24 @@ try_load_from (MonoAssembly **assembly, const gchar *path1, const gchar *path2, const gchar *path3, const gchar *path4, gboolean refonly, gboolean is_private) { - gchar *fullpath; - + gboolean found = FALSE; + *assembly = NULL; fullpath = g_build_filename (path1, path2, path3, path4, NULL); - if (g_file_test (fullpath, G_FILE_TEST_IS_REGULAR)) { - if (is_private) { - char *new_path = make_shadow_copy (fullpath); + + if (IS_PORTABILITY_SET) { + gchar *new_fullpath = mono_portability_find_file (fullpath, TRUE); + if (new_fullpath) { g_free (fullpath); - fullpath = new_path; + fullpath = new_fullpath; + found = TRUE; } - + } else + found = g_file_test (fullpath, G_FILE_TEST_IS_REGULAR); + + if (found) *assembly = mono_assembly_open_full (fullpath, NULL, refonly); - } g_free (fullpath); return (*assembly != NULL); @@ -911,6 +1368,8 @@ real_load (gchar **search_path, const gchar *culture, const gchar *name, gboolea /* * Try loading the assembly from ApplicationBase and PrivateBinPath * and then from assemblies_path if any. + * LOCKING: This is called from the assembly loading code, which means the caller + * might hold the loader lock. Thus, this function must not acquire the domain lock. */ static MonoAssembly * mono_domain_assembly_preload (MonoAssemblyName *aname, @@ -977,14 +1436,14 @@ ves_icall_System_Reflection_Assembly_LoadFrom (MonoString *fname, MonoBoolean re } name = filename = mono_string_to_utf8 (fname); - + ass = mono_assembly_open_full (filename, &status, refOnly); if (!ass){ MonoException *exc; if (status == MONO_IMAGE_IMAGE_INVALID) - exc = mono_get_exception_bad_image_format (name); + exc = mono_get_exception_bad_image_format2 (NULL, fname); else exc = mono_get_exception_file_not_found2 (NULL, fname); g_free (name); @@ -998,9 +1457,9 @@ ves_icall_System_Reflection_Assembly_LoadFrom (MonoString *fname, MonoBoolean re MonoReflectionAssembly * ves_icall_System_AppDomain_LoadAssemblyRaw (MonoAppDomain *ad, - MonoArray *raw_assembly, - MonoArray *raw_symbol_store, MonoObject *evidence, - MonoBoolean refonly) + MonoArray *raw_assembly, + MonoArray *raw_symbol_store, MonoObject *evidence, + MonoBoolean refonly) { MonoAssembly *ass; MonoReflectionAssembly *refass = NULL; @@ -1015,7 +1474,7 @@ ves_icall_System_AppDomain_LoadAssemblyRaw (MonoAppDomain *ad, } if (raw_symbol_store != NULL) - mono_debug_init_2_memory (image, mono_array_addr (raw_symbol_store, guint8, 0), mono_array_length (raw_symbol_store)); + mono_debug_open_image_from_memory (image, mono_array_addr (raw_symbol_store, guint8, 0), mono_array_length (raw_symbol_store)); ass = mono_assembly_load_from_full (image, "", &status, refonly); @@ -1058,13 +1517,20 @@ ves_icall_System_AppDomain_LoadAssembly (MonoAppDomain *ad, MonoString *assRef, mono_raise_exception (exc); } - ass = mono_assembly_load_full (&aname, NULL, &status, refOnly); + ass = mono_assembly_load_full_nosearch (&aname, NULL, &status, refOnly); mono_assembly_name_free (&aname); - if (!ass && (refass = try_assembly_resolve (domain, assRef, refOnly)) == NULL){ - /* FIXME: it doesn't make much sense since we really don't have a filename ... */ - MonoException *exc = mono_get_exception_file_not_found2 (NULL, assRef); - mono_raise_exception (exc); + if (!ass) { + /* MS.NET doesn't seem to call the assembly resolve handler for refonly assemblies */ + if (!refOnly) + refass = mono_try_assembly_resolve (domain, assRef, refOnly); + else + refass = NULL; + if (!refass) { + /* FIXME: it doesn't make much sense since we really don't have a filename ... */ + MonoException *exc = mono_get_exception_file_not_found2 (NULL, assRef); + mono_raise_exception (exc); + } } if (refass == NULL) @@ -1113,26 +1579,17 @@ ves_icall_System_AppDomain_InternalIsFinalizingForUnload (gint32 domain_id) } gint32 -ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomain *ad, MonoString *file, - MonoObject *evidence, MonoArray *args) +ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomain *ad, + MonoReflectionAssembly *refass, MonoArray *args) { - MonoAssembly *assembly; MonoImage *image; MonoMethod *method; - char *filename; - gint32 res; - MonoReflectionAssembly *refass; MONO_ARCH_SAVE_REGS; - filename = mono_string_to_utf8 (file); - assembly = mono_assembly_open (filename, NULL); - g_free (filename); - - if (!assembly) - mono_raise_exception (mono_get_exception_file_not_found2 (NULL, file)); - - image = assembly->image; + g_assert (refass); + image = refass->assembly->image; + g_assert (image); method = mono_get_method (image, mono_image_get_entry_point (image), NULL); @@ -1142,12 +1599,7 @@ ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomain *ad, MonoString *file, if (!args) args = (MonoArray *) mono_array_new (ad->data, mono_defaults.string_class, 0); - refass = mono_assembly_get_object (ad->data, assembly); - MONO_OBJECT_SETREF (refass, evidence, evidence); - - res = mono_runtime_exec_main (method, (MonoArray *)args, NULL); - - return res; + return mono_runtime_exec_main (method, (MonoArray *)args, NULL); } gint32 @@ -1297,13 +1749,13 @@ unload_thread_main (void *arg) * FIXME: Abort our parent thread last, so we can return a failure * indication if aborting times out. */ - if (!mono_threads_abort_appdomain_threads (domain, 10000)) { + if (!mono_threads_abort_appdomain_threads (domain, -1)) { data->failure_reason = g_strdup_printf ("Aborting of threads in domain %s timed out.", domain->friendly_name); return 1; } /* Finalize all finalizable objects in the doomed appdomain */ - if (!mono_domain_finalize (domain, 10000)) { + if (!mono_domain_finalize (domain, -1)) { data->failure_reason = g_strdup_printf ("Finalization of domain %s timed out.", domain->friendly_name); return 1; } @@ -1403,6 +1855,9 @@ mono_domain_unload (MonoDomain *domain) thread_handle = CreateThread (NULL, 0, unload_thread_main, &thread_data, 0, &tid); #else thread_handle = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)unload_thread_main, &thread_data, CREATE_SUSPENDED, &tid); + if (thread_handle == NULL) { + return; + } ResumeThread (thread_handle); #endif