6 * Dietmar Maurer (dietmar@ximian.com)
8 * Gonzalo Paniagua Javier (gonzalo@ximian.com)
10 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
11 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12 * Copyright 2012 Xamarin Inc
13 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
21 #include <sys/types.h>
23 #ifdef HAVE_SYS_TIME_H
32 #ifdef HAVE_SYS_UTIME_H
33 #include <sys/utime.h>
37 #include <mono/metadata/gc-internals.h>
38 #include <mono/metadata/object.h>
39 #include <mono/metadata/appdomain-icalls.h>
40 #include <mono/metadata/class-init.h>
41 #include <mono/metadata/domain-internals.h>
42 #include "mono/metadata/metadata-internals.h"
43 #include <mono/metadata/assembly-internals.h>
44 #include <mono/metadata/exception.h>
45 #include <mono/metadata/exception-internals.h>
46 #include <mono/metadata/threads.h>
47 #include <mono/metadata/threadpool.h>
48 #include <mono/metadata/tabledefs.h>
49 #include <mono/metadata/mono-gc.h>
50 #include <mono/metadata/mono-hash-internals.h>
51 #include <mono/metadata/marshal.h>
52 #include <mono/metadata/marshal-internals.h>
53 #include <mono/metadata/monitor.h>
54 #include <mono/metadata/mono-debug.h>
55 #include <mono/metadata/attach.h>
56 #include <mono/metadata/w32file.h>
57 #include <mono/metadata/lock-tracer.h>
58 #include <mono/metadata/console-io.h>
59 #include <mono/metadata/threads-types.h>
60 #include <mono/metadata/tokentype.h>
61 #include <mono/metadata/profiler-private.h>
62 #include <mono/metadata/reflection-internals.h>
63 #include <mono/metadata/abi-details.h>
64 #include <mono/metadata/w32socket.h>
65 #include <mono/utils/mono-uri.h>
66 #include <mono/utils/mono-logger-internals.h>
67 #include <mono/utils/mono-path.h>
68 #include <mono/utils/mono-stdlib.h>
69 #include <mono/utils/mono-io-portability.h>
70 #include <mono/utils/mono-error-internals.h>
71 #include <mono/utils/atomic.h>
72 #include <mono/utils/mono-memory-model.h>
73 #include <mono/utils/mono-threads.h>
74 #include <mono/metadata/w32handle.h>
75 #include <mono/metadata/w32error.h>
76 #include <mono/utils/w32api.h>
80 #include "object-internals.h"
81 #include "icall-decl.h"
86 int assemblybinding_count
;
91 #ifndef ENABLE_NETCORE
92 static gunichar2 process_guid
[36];
93 static gboolean process_guid_set
= FALSE
;
96 static gboolean no_exec
= FALSE
;
99 static int n_appctx_props
;
100 static gunichar2
**appctx_keys
;
101 static gunichar2
**appctx_values
;
105 mono_check_corlib_version_internal (void);
107 static MonoAssembly
*
108 mono_domain_assembly_preload (MonoAssemblyLoadContext
*alc
,
109 MonoAssemblyName
*aname
,
110 gchar
**assemblies_path
,
115 static MonoAssembly
*
116 mono_domain_assembly_search (MonoAssemblyLoadContext
*alc
, MonoAssembly
*requesting
,
117 MonoAssemblyName
*aname
,
125 mono_domain_fire_assembly_load (MonoAssemblyLoadContext
*alc
, MonoAssembly
*assembly
, gpointer user_data
, MonoError
*error_out
);
128 mono_domain_asmctx_from_path (const char *fname
, MonoAssembly
*requesting_assembly
, gpointer user_data
, MonoAssemblyContextKind
*out_asmctx
);
131 add_assemblies_to_domain (MonoDomain
*domain
, MonoAssembly
*ass
, GHashTable
*hash
);
136 add_assembly_to_alc (MonoAssemblyLoadContext
*alc
, MonoAssembly
*ass
);
140 static MonoAppDomainHandle
141 mono_domain_create_appdomain_internal (char *friendly_name
, MonoAppDomainSetupHandle setup
, MonoError
*error
);
144 mono_domain_create_appdomain_checked (char *friendly_name
, char *configuration_file
, MonoError
*error
);
148 mono_context_set_default_context (MonoDomain
*domain
);
151 get_shadow_assembly_location_base (MonoDomain
*domain
, MonoError
*error
);
153 static MonoLoadFunc load_function
= NULL
;
155 /* Lazy class loading functions */
156 static GENERATE_GET_CLASS_WITH_CACHE (assembly
, "System.Reflection", "Assembly");
157 static GENERATE_GET_CLASS_WITH_CACHE (app_context
, "System", "AppContext");
159 GENERATE_GET_CLASS_WITH_CACHE (appdomain
, MONO_APPDOMAIN_CLASS_NAME_SPACE
, MONO_APPDOMAIN_CLASS_NAME
);
160 GENERATE_GET_CLASS_WITH_CACHE (appdomain_setup
, MONO_APPDOMAIN_SETUP_CLASS_NAME_SPACE
, MONO_APPDOMAIN_SETUP_CLASS_NAME
);
163 mono_domain_from_appdomain_handle (MonoAppDomainHandle appdomain
);
166 mono_error_set_appdomain_unloaded (MonoError
*error
)
168 mono_error_set_generic_error (error
, "System", "AppDomainUnloadedException", "");
172 mono_install_runtime_load (MonoLoadFunc func
)
174 load_function
= func
;
178 mono_runtime_load (const char *filename
, const char *runtime_version
)
180 g_assert (load_function
);
181 return load_function (filename
, runtime_version
);
185 * mono_runtime_set_no_exec:
187 * Instructs the runtime to operate in static mode, i.e. avoid/do not
188 * allow managed code execution. This is useful for running the AOT
189 * compiler on platforms which allow full-aot execution only. This
190 * should be called before mono_runtime_init ().
193 mono_runtime_set_no_exec (gboolean val
)
199 * mono_runtime_get_no_exec:
201 * If true, then the runtime will not allow managed code execution.
204 mono_runtime_get_no_exec (void)
210 create_domain_objects (MonoDomain
*domain
)
212 HANDLE_FUNCTION_ENTER ();
215 MonoDomain
*old_domain
= mono_domain_get ();
216 MonoStringHandle arg
;
217 MonoVTable
*string_vt
;
218 MonoClassField
*string_empty_fld
;
220 if (domain
!= old_domain
) {
221 mono_thread_push_appdomain_ref (domain
);
222 mono_domain_set_internal_with_options (domain
, FALSE
);
226 * Initialize String.Empty. This enables the removal of
227 * the static cctor of the String class.
229 string_vt
= mono_class_vtable_checked (domain
, mono_defaults
.string_class
, error
);
230 mono_error_assert_ok (error
);
231 string_empty_fld
= mono_class_get_field_from_name_full (mono_defaults
.string_class
, "Empty", NULL
);
232 g_assert (string_empty_fld
);
233 MonoStringHandle empty_str
= mono_string_new_handle (domain
, "", error
);
234 mono_error_assert_ok (error
);
235 empty_str
= mono_string_intern_checked (empty_str
, error
);
236 mono_error_assert_ok (error
);
237 mono_field_static_set_value_internal (string_vt
, string_empty_fld
, MONO_HANDLE_RAW (empty_str
));
238 domain
->empty_string
= MONO_HANDLE_RAW (empty_str
);
241 * Create an instance early since we can't do it when there is no memory.
243 arg
= mono_string_new_handle (domain
, "Out of memory", error
);
244 mono_error_assert_ok (error
);
245 domain
->out_of_memory_ex
= MONO_HANDLE_RAW (mono_exception_from_name_two_strings_checked (mono_defaults
.corlib
, "System", "OutOfMemoryException", arg
, NULL_HANDLE_STRING
, error
));
246 mono_error_assert_ok (error
);
249 * These two are needed because the signal handlers might be executing on
250 * an alternate stack, and Boehm GC can't handle that.
252 arg
= mono_string_new_handle (domain
, "A null value was found where an object instance was required", error
);
253 mono_error_assert_ok (error
);
254 domain
->null_reference_ex
= MONO_HANDLE_RAW (mono_exception_from_name_two_strings_checked (mono_defaults
.corlib
, "System", "NullReferenceException", arg
, NULL_HANDLE_STRING
, error
));
255 mono_error_assert_ok (error
);
256 arg
= mono_string_new_handle (domain
, "The requested operation caused a stack overflow.", error
);
257 mono_error_assert_ok (error
);
258 domain
->stack_overflow_ex
= MONO_HANDLE_RAW (mono_exception_from_name_two_strings_checked (mono_defaults
.corlib
, "System", "StackOverflowException", arg
, NULL_HANDLE_STRING
, error
));
259 mono_error_assert_ok (error
);
261 /*The ephemeron tombstone i*/
262 domain
->ephemeron_tombstone
= MONO_HANDLE_RAW (mono_object_new_handle (domain
, mono_defaults
.object_class
, error
));
263 mono_error_assert_ok (error
);
265 if (domain
!= old_domain
) {
266 mono_thread_pop_appdomain_ref ();
267 mono_domain_set_internal_with_options (old_domain
, FALSE
);
271 * This class is used during exception handling, so initialize it here, to prevent
272 * stack overflows while handling stack overflows.
274 mono_class_init_internal (mono_class_create_array (mono_defaults
.int_class
, 1));
275 HANDLE_FUNCTION_RETURN ();
280 * \param domain domain returned by \c mono_init
282 * Initialize the core AppDomain: this function will run also some
283 * IL initialization code, so it needs the execution engine to be fully
286 * \c AppDomain.SetupInformation is set up in \c mono_runtime_exec_main, where
287 * we know the \c entry_assembly.
291 mono_runtime_init (MonoDomain
*domain
, MonoThreadStartCB start_cb
, MonoThreadAttachCB attach_cb
)
294 mono_runtime_init_checked (domain
, start_cb
, attach_cb
, error
);
295 mono_error_cleanup (error
);
299 mono_runtime_init_checked (MonoDomain
*domain
, MonoThreadStartCB start_cb
, MonoThreadAttachCB attach_cb
, MonoError
*error
)
301 HANDLE_FUNCTION_ENTER ();
303 MonoAppDomainSetupHandle setup
;
304 MonoAppDomainHandle ad
;
308 mono_portability_helpers_init ();
310 mono_gc_base_init ();
311 mono_monitor_init ();
312 mono_marshal_init ();
313 mono_gc_init_icalls ();
315 mono_install_assembly_preload_hook_v2 (mono_domain_assembly_preload
, GUINT_TO_POINTER (FALSE
), FALSE
);
316 mono_install_assembly_search_hook_v2 (mono_domain_assembly_search
, GUINT_TO_POINTER (FALSE
), FALSE
, FALSE
);
317 mono_install_assembly_search_hook_v2 (mono_domain_assembly_postload_search
, GUINT_TO_POINTER (FALSE
), FALSE
, TRUE
);
318 mono_install_assembly_load_hook_v2 (mono_domain_fire_assembly_load
, NULL
);
320 #ifndef ENABLE_NETCORE // refonly hooks
321 mono_install_assembly_preload_hook_v2 (mono_domain_assembly_preload
, GUINT_TO_POINTER (TRUE
), TRUE
);
322 mono_install_assembly_search_hook_v2 (mono_domain_assembly_search
, GUINT_TO_POINTER (TRUE
), TRUE
, FALSE
);
323 mono_install_assembly_search_hook_v2 (mono_domain_assembly_postload_search
, GUINT_TO_POINTER (TRUE
), TRUE
, TRUE
);
324 mono_install_assembly_asmctx_from_path_hook (mono_domain_asmctx_from_path
, NULL
);
327 mono_thread_init (start_cb
, attach_cb
);
329 if (!mono_runtime_get_no_exec ()) {
330 MonoClass
*klass
= mono_class_get_appdomain_setup_class ();
331 setup
= MONO_HANDLE_CAST (MonoAppDomainSetup
, mono_object_new_pinned_handle (domain
, klass
, error
));
332 goto_if_nok (error
, exit
);
334 klass
= mono_class_get_appdomain_class ();
336 ad
= MONO_HANDLE_CAST (MonoAppDomain
, mono_object_new_pinned_handle (domain
, klass
, error
));
337 goto_if_nok (error
, exit
);
339 MONO_HANDLE_SETVAL (ad
, data
, MonoDomain
*, domain
);
340 domain
->domain
= MONO_HANDLE_RAW (ad
);
341 domain
->setup
= MONO_HANDLE_RAW (setup
);
344 mono_thread_attach (domain
);
346 mono_type_initialization_init ();
348 if (!mono_runtime_get_no_exec ())
349 create_domain_objects (domain
);
351 /* GC init has to happen after thread init */
354 /* contexts use GC handles, so they must be initialized after the GC */
355 #ifndef ENABLE_NETCORE
356 mono_context_init_checked (domain
, error
);
357 goto_if_nok (error
, exit
);
358 mono_context_set_default_context (domain
);
361 #ifdef ENABLE_NETCORE
362 if (!mono_runtime_get_no_exec ())
363 mono_runtime_install_appctx_properties ();
366 mono_network_init ();
367 mono_console_init ();
370 mono_locks_tracer_init ();
372 /* mscorlib is loaded before we install the load hook */
373 mono_domain_fire_assembly_load (mono_domain_default_alc (domain
), mono_defaults
.corlib
->assembly
, NULL
, error
);
374 goto_if_nok (error
, exit
);
377 HANDLE_FUNCTION_RETURN ();
381 mono_context_set_default_context (MonoDomain
*domain
)
383 if (mono_runtime_get_no_exec ())
386 HANDLE_FUNCTION_ENTER ();
387 mono_context_set_handle (MONO_HANDLE_NEW (MonoAppContext
, domain
->default_context
));
388 HANDLE_FUNCTION_RETURN ();
392 mono_get_corlib_version (void)
397 MonoClassField
*field
;
399 klass
= mono_class_load_from_name (mono_defaults
.corlib
, "System", "Environment");
400 mono_class_init_internal (klass
);
401 field
= mono_class_get_field_from_name_full (klass
, "mono_corlib_version", NULL
);
405 if (! (field
->type
->attrs
& (FIELD_ATTRIBUTE_STATIC
| FIELD_ATTRIBUTE_LITERAL
)))
409 MonoTypeEnum field_type
;
410 const char *data
= mono_class_get_field_default_value (field
, &field_type
);
411 if (field_type
!= MONO_TYPE_STRING
)
413 mono_metadata_read_constant_value (data
, field_type
, &value
, error
);
414 mono_error_assert_ok (error
);
416 char *res
= mono_string_from_blob (value
, error
);
417 mono_error_assert_ok (error
);
423 * mono_check_corlib_version:
424 * Checks that the corlib that is loaded matches the version of this runtime.
425 * \returns NULL if the runtime will work with the corlib, or a \c g_malloc
426 * allocated string with the error otherwise.
429 mono_check_corlib_version (void)
432 MONO_ENTER_GC_UNSAFE
;
433 res
= mono_check_corlib_version_internal ();
439 mono_check_corlib_version_internal (void)
441 #if defined(MONO_CROSS_COMPILE)
442 /* Can't read the corlib version because we only have the target class layouts */
446 char *version
= mono_get_corlib_version ();
448 result
= g_strdup_printf ("expected corlib string (%s) but not found or not string", MONO_CORLIB_VERSION
);
451 if (strcmp (version
, MONO_CORLIB_VERSION
) != 0) {
452 result
= g_strdup_printf ("The runtime did not find the mscorlib.dll it expected. "
453 "Expected interface version %s but found %s. Check that "
454 "your runtime and class libraries are matching.",
455 MONO_CORLIB_VERSION
, version
);
459 /* Check that the managed and unmanaged layout of MonoInternalThread matches */
460 guint32 native_offset
;
461 guint32 managed_offset
;
462 native_offset
= (guint32
) MONO_STRUCT_OFFSET (MonoInternalThread
, last
);
463 managed_offset
= mono_field_get_offset (mono_class_get_field_from_name_full (mono_defaults
.internal_thread_class
, "last", NULL
));
464 if (native_offset
!= managed_offset
)
465 result
= g_strdup_printf ("expected InternalThread.last field offset %u, found %u. See InternalThread.last comment", native_offset
, managed_offset
);
474 * \param domain The domain where the \c System.Runtime.Remoting.Context.Context is initialized
475 * Initializes the \p domain's default \c System.Runtime.Remoting 's Context.
478 mono_context_init (MonoDomain
*domain
)
481 mono_context_init_checked (domain
, error
);
482 mono_error_cleanup (error
);
486 mono_context_init_checked (MonoDomain
*domain
, MonoError
*error
)
488 HANDLE_FUNCTION_ENTER ();
491 MonoAppContextHandle context
;
494 if (mono_runtime_get_no_exec ())
497 klass
= mono_class_load_from_name (mono_defaults
.corlib
, "System.Runtime.Remoting.Contexts", "Context");
498 context
= MONO_HANDLE_CAST (MonoAppContext
, mono_object_new_pinned_handle (domain
, klass
, error
));
499 goto_if_nok (error
, exit
);
501 MONO_HANDLE_SETVAL (context
, domain_id
, gint32
, domain
->domain_id
);
502 MONO_HANDLE_SETVAL (context
, context_id
, gint32
, 0);
503 mono_threads_register_app_context (context
, error
);
504 mono_error_assert_ok (error
);
505 domain
->default_context
= MONO_HANDLE_RAW (context
);
507 HANDLE_FUNCTION_RETURN ();
511 * mono_runtime_cleanup:
512 * \param domain unused.
516 * This must not be called while there are still running threads executing
520 mono_runtime_cleanup (MonoDomain
*domain
)
522 mono_attach_cleanup ();
524 /* This ends up calling any pending pending (for at most 2 seconds) */
527 mono_thread_cleanup ();
528 mono_network_cleanup ();
529 mono_marshal_cleanup ();
531 mono_type_initialization_cleanup ();
533 mono_monitor_cleanup ();
536 static MonoDomainFunc quit_function
= NULL
;
539 * mono_install_runtime_cleanup:
542 mono_install_runtime_cleanup (MonoDomainFunc func
)
544 quit_function
= func
;
551 mono_runtime_quit (void)
553 MONO_STACKDATA (dummy
);
554 (void) mono_threads_enter_gc_unsafe_region_unbalanced_internal (&dummy
);
555 // after quit_function (in particular, mini_cleanup) everything is
556 // cleaned up so MONO_EXIT_GC_UNSAFE can't work and doesn't make sense.
558 mono_runtime_quit_internal ();
562 * mono_runtime_quit_internal:
565 mono_runtime_quit_internal (void)
567 MONO_REQ_GC_UNSAFE_MODE
;
568 // but note that when we return, we're not in GC Unsafe mode anymore.
569 // After clean up threads don't _have_ a thread state anymore.
571 if (quit_function
!= NULL
)
572 quit_function (mono_get_root_domain (), NULL
);
576 * mono_domain_create_appdomain:
577 * \param friendly_name The friendly name of the appdomain to create
578 * \param configuration_file The configuration file to initialize the appdomain with
579 * \returns a \c MonoDomain initialized with the appdomain
582 mono_domain_create_appdomain (char *friendly_name
, char *configuration_file
)
584 HANDLE_FUNCTION_ENTER ();
586 MONO_ENTER_GC_UNSAFE
;
588 domain
= mono_domain_create_appdomain_checked (friendly_name
, configuration_file
, error
);
589 mono_error_cleanup (error
);
591 HANDLE_FUNCTION_RETURN_VAL (domain
);
595 * mono_domain_create_appdomain_checked:
596 * \param friendly_name The friendly name of the appdomain to create
597 * \param configuration_file The configuration file to initialize the appdomain with
598 * \param error Set on error.
600 * \returns a MonoDomain initialized with the appdomain. On failure sets \p error and returns NULL.
603 mono_domain_create_appdomain_checked (char *friendly_name
, char *configuration_file
, MonoError
*error
)
605 HANDLE_FUNCTION_ENTER ();
607 MonoDomain
*result
= NULL
;
609 MonoClass
*klass
= mono_class_get_appdomain_setup_class ();
610 MonoAppDomainSetupHandle setup
= MONO_HANDLE_CAST (MonoAppDomainSetup
, mono_object_new_handle (mono_domain_get (), klass
, error
));
611 goto_if_nok (error
, leave
);
612 MonoStringHandle config_file
;
613 if (configuration_file
!= NULL
) {
614 config_file
= mono_string_new_handle (mono_domain_get (), configuration_file
, error
);
615 goto_if_nok (error
, leave
);
617 config_file
= MONO_HANDLE_NEW (MonoString
, NULL
);
619 MONO_HANDLE_SET (setup
, configuration_file
, config_file
);
621 MonoAppDomainHandle ad
;
622 ad
= mono_domain_create_appdomain_internal (friendly_name
, setup
, error
);
623 goto_if_nok (error
, leave
);
625 result
= mono_domain_from_appdomain_handle (ad
);
627 HANDLE_FUNCTION_RETURN_VAL (result
);
631 * mono_domain_set_config:
632 * \param domain \c MonoDomain initialized with the appdomain we want to change
633 * \param base_dir new base directory for the appdomain
634 * \param config_file_name path to the new configuration for the app domain
636 * Used to set the system configuration for an appdomain
638 * Without using this, embedded builds will get 'System.Configuration.ConfigurationErrorsException:
639 * Error Initializing the configuration system. ---> System.ArgumentException:
640 * The 'ExeConfigFilename' argument cannot be null.' for some managed calls.
643 mono_domain_set_config (MonoDomain
*domain
, const char *base_dir
, const char *config_file_name
)
645 HANDLE_FUNCTION_ENTER ();
646 MONO_ENTER_GC_UNSAFE
;
648 mono_domain_set_config_checked (domain
, base_dir
, config_file_name
, error
);
649 mono_error_cleanup (error
);
651 HANDLE_FUNCTION_RETURN ();
655 mono_domain_set_config_checked (MonoDomain
*domain
, const char *base_dir
, const char *config_file_name
, MonoError
*error
)
658 MonoAppDomainSetupHandle setup
= MONO_HANDLE_NEW (MonoAppDomainSetup
, domain
->setup
);
659 MonoStringHandle base_dir_str
= mono_string_new_handle (domain
, base_dir
, error
);
660 goto_if_nok (error
, leave
);
661 MONO_HANDLE_SET (setup
, application_base
, base_dir_str
);
662 MonoStringHandle config_file_name_str
;
663 config_file_name_str
= mono_string_new_handle (domain
, config_file_name
, error
);
664 goto_if_nok (error
, leave
);
665 MONO_HANDLE_SET (setup
, configuration_file
, config_file_name_str
);
667 return is_ok (error
);
670 static MonoAppDomainSetupHandle
671 copy_app_domain_setup (MonoDomain
*domain
, MonoAppDomainSetupHandle setup
, MonoError
*error
)
673 HANDLE_FUNCTION_ENTER ();
674 MonoDomain
*caller_domain
;
675 MonoClass
*ads_class
;
676 MonoAppDomainSetupHandle result
= MONO_HANDLE_NEW (MonoAppDomainSetup
, NULL
);
680 caller_domain
= mono_domain_get ();
681 ads_class
= mono_class_get_appdomain_setup_class ();
683 MonoAppDomainSetupHandle copy
= MONO_HANDLE_CAST (MonoAppDomainSetup
, mono_object_new_handle(domain
, ads_class
, error
));
684 goto_if_nok (error
, leave
);
686 mono_domain_set_internal_with_options (domain
, TRUE
);
688 #define XCOPY_FIELD(type, dst, field, src, error) \
690 TYPED_HANDLE_NAME (type) src_val = MONO_HANDLE_NEW_GET (type, (src), field); \
691 TYPED_HANDLE_NAME (type) copied_val = MONO_HANDLE_CAST (type, mono_marshal_xdomain_copy_value_handle (MONO_HANDLE_CAST (MonoObject, src_val), error)); \
692 goto_if_nok (error, leave); \
693 MONO_HANDLE_SET ((dst),field,copied_val); \
696 #define COPY_VAL(dst,field,type,src) \
698 MONO_HANDLE_SETVAL ((dst), field, type, MONO_HANDLE_GETVAL ((src),field)); \
701 XCOPY_FIELD (MonoString
, copy
, application_base
, setup
, error
);
702 XCOPY_FIELD (MonoString
, copy
, application_name
, setup
, error
);
703 XCOPY_FIELD (MonoString
, copy
, cache_path
, setup
, error
);
704 XCOPY_FIELD (MonoString
, copy
, configuration_file
, setup
, error
);
705 XCOPY_FIELD (MonoString
, copy
, dynamic_base
, setup
, error
);
706 XCOPY_FIELD (MonoString
, copy
, license_file
, setup
, error
);
707 XCOPY_FIELD (MonoString
, copy
, private_bin_path
, setup
, error
);
708 XCOPY_FIELD (MonoString
, copy
, private_bin_path_probe
, setup
, error
);
709 XCOPY_FIELD (MonoString
, copy
, shadow_copy_directories
, setup
, error
);
710 XCOPY_FIELD (MonoString
, copy
, shadow_copy_files
, setup
, error
);
711 COPY_VAL (copy
, publisher_policy
, MonoBoolean
, setup
);
712 COPY_VAL (copy
, path_changed
, MonoBoolean
, setup
);
713 COPY_VAL (copy
, loader_optimization
, int, setup
);
714 COPY_VAL (copy
, disallow_binding_redirects
, MonoBoolean
, setup
);
715 COPY_VAL (copy
, disallow_code_downloads
, MonoBoolean
, setup
);
716 XCOPY_FIELD (MonoArray
, copy
, domain_initializer_args
, setup
, error
);
717 COPY_VAL (copy
, disallow_appbase_probe
, MonoBoolean
, setup
);
718 XCOPY_FIELD (MonoObject
, copy
, application_trust
, setup
, error
);
719 XCOPY_FIELD (MonoArray
, copy
, configuration_bytes
, setup
, error
);
720 XCOPY_FIELD (MonoArray
, copy
, serialized_non_primitives
, setup
, error
);
725 mono_domain_set_internal_with_options (caller_domain
, TRUE
);
727 MONO_HANDLE_ASSIGN (result
, copy
);
729 HANDLE_FUNCTION_RETURN_REF (MonoAppDomainSetup
, result
);
732 static MonoAppDomainHandle
733 mono_domain_create_appdomain_internal (char *friendly_name
, MonoAppDomainSetupHandle setup
, MonoError
*error
)
735 HANDLE_FUNCTION_ENTER ();
736 MonoAppDomainHandle result
= MONO_HANDLE_NEW (MonoAppDomain
, NULL
);
742 adclass
= mono_class_get_appdomain_class ();
744 /* FIXME: pin all those objects */
745 data
= mono_domain_create();
747 MonoAppDomainHandle ad
= MONO_HANDLE_CAST (MonoAppDomain
, mono_object_new_handle (data
, adclass
, error
));
748 goto_if_nok (error
, leave
);
749 MONO_HANDLE_SETVAL (ad
, data
, MonoDomain
*, data
);
750 data
->domain
= MONO_HANDLE_RAW (ad
);
751 data
->friendly_name
= g_strdup (friendly_name
);
753 MONO_PROFILER_RAISE (domain_name
, (data
, data
->friendly_name
));
755 MonoStringHandle app_base
;
756 app_base
= MONO_HANDLE_NEW_GET (MonoString
, setup
, application_base
);
757 if (MONO_HANDLE_IS_NULL (app_base
)) {
758 /* Inherit from the root domain since MS.NET does this */
759 MonoDomain
*root
= mono_get_root_domain ();
760 MonoAppDomainSetupHandle root_setup
= MONO_HANDLE_NEW (MonoAppDomainSetup
, root
->setup
);
761 MonoStringHandle root_app_base
= MONO_HANDLE_NEW_GET (MonoString
, root_setup
, application_base
);
762 if (!MONO_HANDLE_IS_NULL (root_app_base
)) {
763 /* N.B. new string is in the new domain */
764 uint32_t gchandle
= mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject
, root_app_base
), TRUE
);
765 MonoStringHandle s
= mono_string_new_utf16_handle (data
, mono_string_chars_internal (MONO_HANDLE_RAW (root_app_base
)), mono_string_handle_length (root_app_base
), error
);
766 mono_gchandle_free_internal (gchandle
);
767 if (!is_ok (error
)) {
768 g_free (data
->friendly_name
);
771 MONO_HANDLE_SET (setup
, application_base
, s
);
775 mono_context_init_checked (data
, error
);
776 goto_if_nok (error
, leave
);
778 data
->setup
= MONO_HANDLE_RAW (copy_app_domain_setup (data
, setup
, error
));
779 if (!is_ok (error
)) {
780 g_free (data
->friendly_name
);
784 mono_domain_set_options_from_config (data
);
785 add_assemblies_to_domain (data
, mono_defaults
.corlib
->assembly
, NULL
);
787 #ifndef DISABLE_SHADOW_COPY
788 /*FIXME, guard this for when the debugger is not running */
789 char *shadow_location
;
790 shadow_location
= get_shadow_assembly_location_base (data
, error
);
791 if (!is_ok (error
)) {
792 g_free (data
->friendly_name
);
796 g_free (shadow_location
);
799 create_domain_objects (data
);
801 MONO_HANDLE_ASSIGN (result
, ad
);
803 HANDLE_FUNCTION_RETURN_REF (MonoAppDomain
, result
);
807 * mono_domain_has_type_resolve:
808 * \param domain application domain being looked up
810 * \returns TRUE if the \c AppDomain.TypeResolve field has been set.
813 mono_domain_has_type_resolve (MonoDomain
*domain
)
815 // Check whether managed code is running, and if the managed AppDomain object doesn't exist neither does the event handler
819 #ifdef ENABLE_NETCORE
824 MONO_STATIC_POINTER_INIT (MonoClassField
, field
)
826 field
= mono_class_get_field_from_name_full (mono_defaults
.appdomain_class
, "TypeResolve", NULL
);
829 MONO_STATIC_POINTER_INIT_END (MonoClassField
, field
)
831 mono_field_get_value_internal ((MonoObject
*)(domain
->domain
), field
, &o
);
837 * mono_domain_try_type_resolve:
838 * \param domain application domain in which to resolve the type
839 * \param name the name of the type to resolve or NULL.
840 * \param typebuilder A \c System.Reflection.Emit.TypeBuilder, used if name is NULL.
842 * This routine invokes the internal \c System.AppDomain.DoTypeResolve and returns
843 * the assembly that matches name, or ((TypeBuilder)typebuilder).FullName.
845 * \returns A \c MonoReflectionAssembly or NULL if not found
847 MonoReflectionAssembly
*
848 mono_domain_try_type_resolve (MonoDomain
*domain
, char *name
, MonoObject
*typebuilder_raw
)
850 HANDLE_FUNCTION_ENTER ();
853 g_assert (name
|| typebuilder_raw
);
857 MonoReflectionAssemblyHandle ret
= NULL_HANDLE_INIT
;
859 // This will not work correctly on netcore
861 MonoStringHandle name_handle
= mono_string_new_handle (mono_domain_get (), name
, error
);
862 goto_if_nok (error
, exit
);
863 ret
= mono_domain_try_type_resolve_name (domain
, NULL
, name_handle
, error
);
865 #ifndef ENABLE_NETCORE
866 MONO_HANDLE_DCL (MonoObject
, typebuilder
);
867 ret
= mono_domain_try_type_resolve_typebuilder (domain
, MONO_HANDLE_CAST (MonoReflectionTypeBuilder
, typebuilder
), error
);
869 // TODO: make this work on netcore when working on SRE.TypeBuilder
870 g_assert_not_reached ();
875 mono_error_cleanup (error
);
876 HANDLE_FUNCTION_RETURN_OBJ (ret
);
879 #ifdef ENABLE_NETCORE
880 MonoReflectionAssemblyHandle
881 mono_domain_try_type_resolve_name (MonoDomain
*domain
, MonoAssembly
*assembly
, MonoStringHandle name
, MonoError
*error
)
883 MonoObjectHandle ret
;
884 MonoReflectionAssemblyHandle assembly_handle
;
886 HANDLE_FUNCTION_ENTER ();
888 MONO_STATIC_POINTER_INIT (MonoMethod
, method
)
890 MonoClass
*alc_class
= mono_class_get_assembly_load_context_class ();
891 g_assert (alc_class
);
892 method
= mono_class_get_method_from_name_checked (alc_class
, "OnTypeResolve", -1, 0, error
);
894 MONO_STATIC_POINTER_INIT_END (MonoMethod
, method
)
896 goto_if_nok (error
, return_null
);
899 g_assert (MONO_HANDLE_BOOL (name
));
901 if (mono_runtime_get_no_exec ())
905 assembly_handle
= mono_assembly_get_object_handle (domain
, assembly
, error
);
906 goto_if_nok (error
, return_null
);
910 args
[0] = assembly
? MONO_HANDLE_RAW (assembly_handle
) : NULL
;
911 args
[1] = MONO_HANDLE_RAW (name
);
912 ret
= mono_runtime_try_invoke_handle (method
, NULL_HANDLE
, args
, error
);
913 goto_if_nok (error
, return_null
);
920 HANDLE_FUNCTION_RETURN_REF (MonoReflectionAssembly
, MONO_HANDLE_CAST (MonoReflectionAssembly
, ret
));
924 * mono_class_get_appdomain_do_type_resolve_method:
926 * This routine returns System.AppDomain.DoTypeResolve.
929 mono_class_get_appdomain_do_type_resolve_method (MonoError
*error
)
931 MONO_STATIC_POINTER_INIT (MonoMethod
, method
)
933 method
= mono_class_get_method_from_name_checked (mono_class_get_appdomain_class (), "DoTypeResolve", -1, 0, error
);
935 MONO_STATIC_POINTER_INIT_END (MonoMethod
, method
)
938 g_warning ("%s method AppDomain.DoTypeResolve not found. %s\n", __func__
, mono_error_get_message (error
));
944 * mono_class_get_appdomain_do_type_builder_resolve_method:
946 * This routine returns System.AppDomain.DoTypeBuilderResolve.
949 mono_class_get_appdomain_do_type_builder_resolve_method (MonoError
*error
)
951 MONO_STATIC_POINTER_INIT (MonoMethod
, method
)
953 method
= mono_class_get_method_from_name_checked (mono_class_get_appdomain_class (), "DoTypeBuilderResolve", -1, 0, error
);
955 MONO_STATIC_POINTER_INIT_END (MonoMethod
, method
)
958 g_warning ("%s method AppDomain.DoTypeBuilderResolve not found. %s\n", __func__
, mono_error_get_message (error
));
964 * mono_domain_try_type_resolve_name:
965 * \param domain application domain in which to resolve the type
966 * \param name the name of the type to resolve.
968 * This routine invokes the internal \c System.AppDomain.DoTypeResolve and returns
969 * the assembly that matches name.
971 * \returns A \c MonoReflectionAssembly or NULL if not found
973 MonoReflectionAssemblyHandle
974 mono_domain_try_type_resolve_name (MonoDomain
*domain
, MonoAssembly
*assembly
, MonoStringHandle name
, MonoError
*error
)
976 HANDLE_FUNCTION_ENTER ();
978 void *params
[1] = { 0 };
981 g_assert (MONO_HANDLE_BOOL (name
));
987 method
= mono_class_get_appdomain_do_type_resolve_method (error
);
988 goto_if_nok (error
, return_null
);
990 MonoAppDomainHandle appdomain
;
991 appdomain
= MONO_HANDLE_NEW (MonoAppDomain
, domain
->domain
);
993 MonoObjectHandle ret
;
994 params
[0] = MONO_HANDLE_RAW (name
);
995 ret
= mono_runtime_invoke_handle (method
, MONO_HANDLE_CAST (MonoObject
, appdomain
), params
, error
);
996 goto_if_nok (error
, return_null
);
1001 HANDLE_FUNCTION_RETURN_REF (MonoReflectionAssembly
, MONO_HANDLE_CAST (MonoReflectionAssembly
, ret
));
1005 * mono_domain_try_type_resolve_typebuilder:
1006 * \param domain application domain in which to resolve the type
1007 * \param typebuilder A \c System.Reflection.Emit.TypeBuilder; typebuilder.FullName is the name of the type to resolve.
1009 * This routine invokes the internal \c System.AppDomain.DoTypeBuilderResolve and returns
1010 * the assembly that matches typebuilder.FullName.
1012 * \returns A \c MonoReflectionAssembly or NULL_HANDLE if not found
1014 MonoReflectionAssemblyHandle
1015 mono_domain_try_type_resolve_typebuilder (MonoDomain
*domain
, MonoReflectionTypeBuilderHandle typebuilder
, MonoError
*error
)
1017 HANDLE_FUNCTION_ENTER ();
1020 g_assert (MONO_HANDLE_BOOL (typebuilder
));
1025 MonoMethod
* const method
= mono_class_get_appdomain_do_type_builder_resolve_method (error
);
1026 goto_if_nok (error
, return_null
);
1028 MonoAppDomainHandle appdomain
;
1029 appdomain
= MONO_HANDLE_NEW (MonoAppDomain
, domain
->domain
);
1031 args
[0] = MONO_HANDLE_RAW (typebuilder
);
1033 MonoObjectHandle ret
;
1034 ret
= mono_runtime_invoke_handle (method
, MONO_HANDLE_CAST (MonoObject
, appdomain
), args
, error
);
1035 goto_if_nok (error
, return_null
);
1040 HANDLE_FUNCTION_RETURN_REF (MonoReflectionAssembly
, MONO_HANDLE_CAST (MonoReflectionAssembly
, ret
));
1045 * mono_domain_owns_vtable_slot:
1046 * \returns Whether \p vtable_slot is inside a vtable which belongs to \p domain.
1049 mono_domain_owns_vtable_slot (MonoDomain
*domain
, gpointer vtable_slot
)
1053 mono_domain_lock (domain
);
1054 res
= mono_mempool_contains_addr (domain
->mp
, vtable_slot
);
1055 mono_domain_unlock (domain
);
1060 mono_domain_set_fast (MonoDomain
*domain
, gboolean force
)
1062 MONO_REQ_GC_UNSAFE_MODE
;
1063 if (!force
&& domain
->state
== MONO_APPDOMAIN_UNLOADED
)
1066 mono_domain_set_internal_with_options (domain
, TRUE
);
1070 #ifndef ENABLE_NETCORE
1072 ves_icall_System_AppDomain_GetData (MonoAppDomainHandle ad
, MonoStringHandle name
, MonoError
*error
)
1076 if (MONO_HANDLE_IS_NULL (name
)) {
1077 mono_error_set_argument_null (error
, "name", "");
1081 g_assert (!MONO_HANDLE_IS_NULL (ad
));
1082 MonoDomain
*add
= MONO_HANDLE_GETVAL (ad
, data
);
1085 char *str
= mono_string_handle_to_utf8 (name
, error
);
1086 return_val_if_nok (error
, NULL_HANDLE
);
1088 mono_domain_lock (add
);
1090 MonoAppDomainSetupHandle ad_setup
= MONO_HANDLE_NEW (MonoAppDomainSetup
, add
->setup
);
1092 if (!strcmp (str
, "APPBASE"))
1093 o
= MONO_HANDLE_NEW_GET (MonoString
, ad_setup
, application_base
);
1094 else if (!strcmp (str
, "APP_CONFIG_FILE"))
1095 o
= MONO_HANDLE_NEW_GET (MonoString
, ad_setup
, configuration_file
);
1096 else if (!strcmp (str
, "DYNAMIC_BASE"))
1097 o
= MONO_HANDLE_NEW_GET (MonoString
, ad_setup
, dynamic_base
);
1098 else if (!strcmp (str
, "APP_NAME"))
1099 o
= MONO_HANDLE_NEW_GET (MonoString
, ad_setup
, application_name
);
1100 else if (!strcmp (str
, "CACHE_BASE"))
1101 o
= MONO_HANDLE_NEW_GET (MonoString
, ad_setup
, cache_path
);
1102 else if (!strcmp (str
, "PRIVATE_BINPATH"))
1103 o
= MONO_HANDLE_NEW_GET (MonoString
, ad_setup
, private_bin_path
);
1104 else if (!strcmp (str
, "BINPATH_PROBE_ONLY"))
1105 o
= MONO_HANDLE_NEW_GET (MonoString
, ad_setup
, private_bin_path_probe
);
1106 else if (!strcmp (str
, "SHADOW_COPY_DIRS"))
1107 o
= MONO_HANDLE_NEW_GET (MonoString
, ad_setup
, shadow_copy_directories
);
1108 else if (!strcmp (str
, "FORCE_CACHE_INSTALL"))
1109 o
= MONO_HANDLE_NEW_GET (MonoString
, ad_setup
, shadow_copy_files
);
1111 o
= MONO_HANDLE_NEW (MonoString
, (MonoString
*)mono_g_hash_table_lookup (add
->env
, MONO_HANDLE_RAW (name
)));
1113 mono_domain_unlock (add
);
1116 return MONO_HANDLE_CAST (MonoObject
, o
);
1120 ves_icall_System_AppDomain_SetData (MonoAppDomainHandle ad
, MonoStringHandle name
, MonoObjectHandle data
, MonoError
*error
)
1124 if (MONO_HANDLE_IS_NULL (name
)) {
1125 mono_error_set_argument_null (error
, "name", "");
1129 g_assert (!MONO_HANDLE_IS_NULL (ad
));
1130 MonoDomain
*add
= MONO_HANDLE_GETVAL (ad
, data
);
1133 mono_domain_lock (add
);
1135 mono_g_hash_table_insert_internal (add
->env
, MONO_HANDLE_RAW (name
), MONO_HANDLE_RAW (data
));
1137 mono_domain_unlock (add
);
1140 MonoAppDomainSetupHandle
1141 ves_icall_System_AppDomain_getSetup (MonoAppDomainHandle ad
, MonoError
*error
)
1144 g_assert (!MONO_HANDLE_IS_NULL (ad
));
1145 MonoDomain
*domain
= MONO_HANDLE_GETVAL (ad
, data
);
1148 return MONO_HANDLE_NEW (MonoAppDomainSetup
, domain
->setup
);
1152 ves_icall_System_AppDomain_getFriendlyName (MonoAppDomainHandle ad
, MonoError
*error
)
1155 g_assert (!MONO_HANDLE_IS_NULL (ad
));
1156 MonoDomain
*domain
= MONO_HANDLE_GETVAL (ad
, data
);
1159 return mono_string_new_handle (domain
, domain
->friendly_name
, error
);
1163 ves_icall_System_AppDomain_getCurDomain (MonoError
*error
)
1166 MonoDomain
*add
= mono_domain_get ();
1168 return MONO_HANDLE_NEW (MonoAppDomain
, add
->domain
);
1172 ves_icall_System_AppDomain_getRootDomain (MonoError
*error
)
1175 MonoDomain
*root
= mono_get_root_domain ();
1177 return MONO_HANDLE_NEW (MonoAppDomain
, root
->domain
);
1181 ves_icall_System_CLRConfig_CheckThrowUnobservedTaskExceptions (MonoError
*error
)
1183 MonoDomain
*domain
= mono_domain_get ();
1185 return domain
->throw_unobserved_task_exceptions
;
1190 get_attribute_value (const gchar
**attribute_names
,
1191 const gchar
**attribute_values
,
1192 const char *att_name
)
1195 for (n
= 0; attribute_names
[n
] != NULL
; n
++) {
1196 if (strcmp (attribute_names
[n
], att_name
) == 0)
1197 return g_strdup (attribute_values
[n
]);
1203 start_element (GMarkupParseContext
*context
,
1204 const gchar
*element_name
,
1205 const gchar
**attribute_names
,
1206 const gchar
**attribute_values
,
1210 RuntimeConfig
*runtime_config
= (RuntimeConfig
*)user_data
;
1212 if (strcmp (element_name
, "runtime") == 0) {
1213 runtime_config
->runtime_count
++;
1217 if (strcmp (element_name
, "assemblyBinding") == 0) {
1218 runtime_config
->assemblybinding_count
++;
1222 if (runtime_config
->runtime_count
!= 1)
1225 if (strcmp (element_name
, "ThrowUnobservedTaskExceptions") == 0) {
1226 const char *value
= get_attribute_value (attribute_names
, attribute_values
, "enabled");
1228 if (value
&& g_ascii_strcasecmp (value
, "true") == 0)
1229 runtime_config
->domain
->throw_unobserved_task_exceptions
= TRUE
;
1232 if (runtime_config
->assemblybinding_count
!= 1)
1235 if (strcmp (element_name
, "probing") != 0)
1238 g_free (runtime_config
->domain
->private_bin_path
);
1239 runtime_config
->domain
->private_bin_path
= get_attribute_value (attribute_names
, attribute_values
, "privatePath");
1240 if (runtime_config
->domain
->private_bin_path
&& !runtime_config
->domain
->private_bin_path
[0]) {
1241 g_free (runtime_config
->domain
->private_bin_path
);
1242 runtime_config
->domain
->private_bin_path
= NULL
;
1248 end_element (GMarkupParseContext
*context
,
1249 const gchar
*element_name
,
1253 RuntimeConfig
*runtime_config
= (RuntimeConfig
*)user_data
;
1254 if (strcmp (element_name
, "runtime") == 0)
1255 runtime_config
->runtime_count
--;
1256 else if (strcmp (element_name
, "assemblyBinding") == 0)
1257 runtime_config
->assemblybinding_count
--;
1261 parse_error (GMarkupParseContext
*context
, GError
*gerror
, gpointer user_data
)
1263 RuntimeConfig
*state
= (RuntimeConfig
*)user_data
;
1265 const gchar
*filename
;
1267 filename
= state
&& state
->filename
? (gchar
*) state
->filename
: "<unknown>";
1268 msg
= gerror
&& gerror
->message
? gerror
->message
: "";
1269 g_warning ("Error parsing %s: %s", filename
, msg
);
1272 static const GMarkupParser
1282 mono_domain_set_options_from_config (MonoDomain
*domain
)
1285 gchar
*config_file_name
= NULL
, *text
= NULL
, *config_file_path
= NULL
;
1287 GMarkupParseContext
*context
;
1288 RuntimeConfig runtime_config
;
1291 if (!domain
|| !domain
->setup
|| !domain
->setup
->configuration_file
)
1294 config_file_name
= mono_string_to_utf8_checked_internal (domain
->setup
->configuration_file
, error
);
1295 if (!is_ok (error
)) {
1296 mono_error_cleanup (error
);
1300 config_file_path
= mono_portability_find_file (config_file_name
, TRUE
);
1301 if (!config_file_path
)
1302 config_file_path
= config_file_name
;
1304 if (!g_file_get_contents (config_file_path
, &text
, &len
, NULL
))
1307 runtime_config
.runtime_count
= 0;
1308 runtime_config
.assemblybinding_count
= 0;
1309 runtime_config
.domain
= domain
;
1310 runtime_config
.filename
= config_file_path
;
1313 if (len
> 3 && text
[0] == '\xef' && text
[1] == (gchar
) '\xbb' && text
[2] == '\xbf')
1314 offset
= 3; /* Skip UTF-8 BOM */
1316 context
= g_markup_parse_context_new (&mono_parser
, (GMarkupParseFlags
)0, &runtime_config
, NULL
);
1317 if (g_markup_parse_context_parse (context
, text
+ offset
, len
- offset
, NULL
))
1318 g_markup_parse_context_end_parse (context
, NULL
);
1319 g_markup_parse_context_free (context
);
1323 if (config_file_name
!= config_file_path
)
1324 g_free (config_file_name
);
1325 g_free (config_file_path
);
1328 #ifndef ENABLE_NETCORE
1330 ves_icall_System_AppDomain_createDomain (MonoStringHandle friendly_name
, MonoAppDomainSetupHandle setup
, MonoError
*error
)
1333 MonoAppDomainHandle ad
= MONO_HANDLE_NEW (MonoAppDomain
, NULL
);
1335 #ifdef DISABLE_APPDOMAINS
1336 mono_error_set_not_supported (error
, "AppDomain creation is not supported on this runtime.");
1340 fname
= mono_string_handle_to_utf8 (friendly_name
, error
);
1341 return_val_if_nok (error
, ad
);
1342 ad
= mono_domain_create_appdomain_internal (fname
, setup
, error
);
1350 add_assembly_to_array (MonoDomain
*domain
, MonoArrayHandle dest
, int dest_idx
, MonoAssembly
* assm
, MonoError
*error
)
1352 HANDLE_FUNCTION_ENTER ();
1354 MonoReflectionAssemblyHandle assm_obj
= mono_assembly_get_object_handle (domain
, assm
, error
);
1355 goto_if_nok (error
, leave
);
1356 MONO_HANDLE_ARRAY_SETREF (dest
, dest_idx
, assm_obj
);
1358 HANDLE_FUNCTION_RETURN_VAL (is_ok (error
));
1361 static MonoArrayHandle
1362 get_assembly_array_from_domain (MonoDomain
*domain
, MonoBoolean refonly
, MonoError
*error
)
1365 GPtrArray
*assemblies
;
1367 assemblies
= mono_domain_get_assemblies (domain
, refonly
);
1369 MonoArrayHandle res
= mono_array_new_handle (domain
, mono_class_get_assembly_class (), assemblies
->len
, error
);
1370 goto_if_nok (error
, leave
);
1371 for (i
= 0; i
< assemblies
->len
; ++i
) {
1372 if (!add_assembly_to_array (domain
, res
, i
, (MonoAssembly
*)g_ptr_array_index (assemblies
, i
), error
))
1377 g_ptr_array_free (assemblies
, TRUE
);
1381 #ifdef ENABLE_NETCORE
1383 ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalGetLoadedAssemblies (MonoError
*error
)
1385 MonoDomain
*domain
= mono_domain_get ();
1386 return get_assembly_array_from_domain (domain
, FALSE
, error
);
1390 ves_icall_System_AppDomain_GetAssemblies (MonoAppDomainHandle ad
, MonoBoolean refonly
, MonoError
*error
)
1392 MonoDomain
*domain
= MONO_HANDLE_GETVAL (ad
, data
);
1393 return get_assembly_array_from_domain (domain
, refonly
, error
);
1398 mono_try_assembly_resolve (MonoAssemblyLoadContext
*alc
, const char *fname_raw
, MonoAssembly
*requesting
, gboolean refonly
, MonoError
*error
)
1400 HANDLE_FUNCTION_ENTER ();
1402 MonoAssembly
*result
= NULL
;
1403 MonoStringHandle fname
= mono_string_new_handle (mono_alc_domain (alc
), fname_raw
, error
);
1404 goto_if_nok (error
, leave
);
1405 result
= mono_try_assembly_resolve_handle (alc
, fname
, requesting
, refonly
, error
);
1407 HANDLE_FUNCTION_RETURN_VAL (result
);
1411 mono_try_assembly_resolve_handle (MonoAssemblyLoadContext
*alc
, MonoStringHandle fname
, MonoAssembly
*requesting
, gboolean refonly
, MonoError
*error
)
1413 HANDLE_FUNCTION_ENTER ();
1414 MonoAssembly
*ret
= NULL
;
1415 MonoDomain
*domain
= mono_alc_domain (alc
);
1417 if (mono_runtime_get_no_exec ())
1420 #ifndef ENABLE_NETCORE
1422 static MonoMethod
*method
;
1423 MonoBoolean isrefonly
;
1424 gpointer params
[3];
1426 g_assert (domain
!= NULL
&& !MONO_HANDLE_IS_NULL (fname
));
1430 method
= mono_class_get_method_from_name_checked (mono_class_get_appdomain_class (), "DoAssemblyResolve", -1, 0, error
);
1431 g_assert (method
!= NULL
);
1433 isrefonly
= refonly
? 1 : 0;
1434 MonoReflectionAssemblyHandle requesting_handle
;
1436 requesting_handle
= mono_assembly_get_object_handle (domain
, requesting
, error
);
1437 goto_if_nok (error
, leave
);
1439 params
[0] = MONO_HANDLE_RAW (fname
);
1440 params
[1] = requesting
? MONO_HANDLE_RAW (requesting_handle
) : NULL
;
1441 params
[2] = &isrefonly
;
1444 MonoReflectionAssemblyHandle result
;
1445 result
= MONO_HANDLE_CAST (MonoReflectionAssembly
, MONO_HANDLE_NEW (MonoObject
, mono_runtime_try_invoke (method
, domain
->domain
, params
, &exc
, error
)));
1446 if (!is_ok (error
) || exc
!= NULL
) {
1448 mono_error_set_exception_instance (error
, (MonoException
*)exc
);
1451 ret
= !MONO_HANDLE_IS_NULL (result
) ? MONO_HANDLE_GETVAL (result
, assembly
) : NULL
;
1453 if (ret
&& !refonly
&& mono_asmctx_get_kind (&ret
->context
) == MONO_ASMCTX_REFONLY
) {
1454 /* .NET Framework throws System.IO.FileNotFoundException in this case */
1455 mono_error_set_file_not_found (error
, NULL
, "AssemblyResolveEvent handlers cannot return Assemblies loaded for reflection only");
1460 MONO_STATIC_POINTER_INIT (MonoMethod
, method
)
1462 ERROR_DECL (local_error
);
1463 MonoClass
*alc_class
= mono_class_get_assembly_load_context_class ();
1464 g_assert (alc_class
);
1465 method
= mono_class_get_method_from_name_checked (alc_class
, "OnAssemblyResolve", -1, 0, local_error
);
1466 mono_error_assert_ok (local_error
);
1468 MONO_STATIC_POINTER_INIT_END (MonoMethod
, method
)
1472 MonoReflectionAssemblyHandle requesting_handle
;
1474 requesting_handle
= mono_assembly_get_object_handle (domain
, requesting
, error
);
1475 goto_if_nok (error
, leave
);
1478 gpointer params
[2];
1479 params
[0] = requesting
? MONO_HANDLE_RAW (requesting_handle
) : NULL
;
1480 params
[1] = MONO_HANDLE_RAW (fname
);
1481 MonoReflectionAssemblyHandle result
;
1482 result
= MONO_HANDLE_CAST (MonoReflectionAssembly
, mono_runtime_try_invoke_handle (method
, NULL_HANDLE
, params
, error
));
1483 goto_if_nok (error
, leave
);
1485 if (MONO_HANDLE_BOOL (result
))
1486 ret
= MONO_HANDLE_GETVAL (result
, assembly
);
1490 HANDLE_FUNCTION_RETURN_VAL (ret
);
1494 mono_domain_assembly_postload_search (MonoAssemblyLoadContext
*alc
, MonoAssembly
*requesting
,
1495 MonoAssemblyName
*aname
,
1496 gboolean refonly
, gboolean postload
,
1498 MonoError
*error_out
)
1501 MonoAssembly
*assembly
;
1504 aname_str
= mono_stringify_assembly_name (aname
);
1506 /* FIXME: We invoke managed code here, so there is a potential for deadlocks */
1508 assembly
= mono_try_assembly_resolve (alc
, aname_str
, requesting
, refonly
, error
);
1510 mono_error_cleanup (error
);
1516 * LOCKING: assumes assemblies_lock in the domain is already locked.
1519 add_assemblies_to_domain (MonoDomain
*domain
, MonoAssembly
*ass
, GHashTable
*ht
)
1523 gboolean destroy_ht
= FALSE
;
1525 g_assert (ass
!= NULL
);
1527 if (!ass
->aname
.name
)
1531 ht
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
1533 for (tmp
= domain
->domain_assemblies
; tmp
; tmp
= tmp
->next
) {
1534 g_hash_table_insert (ht
, tmp
->data
, tmp
->data
);
1538 /* FIXME: handle lazy loaded assemblies */
1540 if (!g_hash_table_lookup (ht
, ass
)) {
1541 mono_assembly_addref (ass
);
1542 g_hash_table_insert (ht
, ass
, ass
);
1543 domain
->domain_assemblies
= g_slist_append (domain
->domain_assemblies
, ass
);
1544 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_ASSEMBLY
, "Assembly %s[%p] added to domain %s, ref_count=%d", ass
->aname
.name
, ass
, domain
->friendly_name
, ass
->ref_count
);
1547 if (ass
->image
->references
) {
1548 for (i
= 0; i
< ass
->image
->nreferences
; i
++) {
1549 if (ass
->image
->references
[i
] && ass
->image
->references
[i
] != REFERENCE_MISSING
) {
1550 if (!g_hash_table_lookup (ht
, ass
->image
->references
[i
])) {
1551 add_assemblies_to_domain (domain
, ass
->image
->references
[i
], ht
);
1557 g_hash_table_destroy (ht
);
1560 #ifdef ENABLE_NETCORE
1562 add_assembly_to_alc (MonoAssemblyLoadContext
*alc
, MonoAssembly
*ass
)
1567 g_assert (ass
!= NULL
);
1569 if (!ass
->aname
.name
)
1572 mono_alc_assemblies_lock (alc
);
1574 for (tmp
= alc
->loaded_assemblies
; tmp
; tmp
= tmp
->next
) {
1575 if (tmp
->data
== ass
) {
1576 mono_alc_assemblies_unlock (alc
);
1581 mono_assembly_addref (ass
);
1582 // Prepending here will break the test suite with frequent InvalidCastExceptions, so we have to append
1583 alc
->loaded_assemblies
= g_slist_append (alc
->loaded_assemblies
, ass
);
1584 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_ASSEMBLY
, "Assembly %s[%p] added to ALC (%p), ref_count=%d", ass
->aname
.name
, ass
, (gpointer
)alc
, ass
->ref_count
);
1586 if (ass
->image
->references
) {
1587 for (i
= 0; i
< ass
->image
->nreferences
; i
++) {
1588 // TODO: remove all this after we're confident this assert isn't hit
1589 g_assertf (!ass
->image
->references
[i
], "Did not expect reference %d of %s to be resolved", i
, ass
->image
->name
);
1593 mono_alc_assemblies_unlock (alc
);
1598 mono_domain_fire_assembly_load_event (MonoDomain
*domain
, MonoAssembly
*assembly
, MonoError
*error
)
1600 HANDLE_FUNCTION_ENTER ();
1603 g_assert (assembly
);
1605 #ifdef ENABLE_NETCORE
1606 MONO_STATIC_POINTER_INIT (MonoMethod
, method
)
1608 MonoClass
*alc_class
= mono_class_get_assembly_load_context_class ();
1609 g_assert (alc_class
);
1610 method
= mono_class_get_method_from_name_checked (alc_class
, "OnAssemblyLoad", -1, 0, error
);
1612 MONO_STATIC_POINTER_INIT_END (MonoMethod
, method
)
1613 goto_if_nok (error
, exit
);
1615 MonoReflectionAssemblyHandle assembly_handle
= mono_assembly_get_object_handle (domain
, assembly
, error
);
1616 goto_if_nok (error
, exit
);
1619 args
[0] = MONO_HANDLE_RAW (assembly_handle
);
1620 mono_runtime_try_invoke_handle (method
, NULL_HANDLE
, args
, error
);
1622 MonoObjectHandle appdomain
= MONO_HANDLE_NEW (MonoObject
, &domain
->domain
->mbr
.obj
);
1623 MonoClass
*klass
= mono_handle_class (appdomain
);
1625 MONO_STATIC_POINTER_INIT (MonoClassField
, assembly_load_field
)
1627 assembly_load_field
= mono_class_get_field_from_name_full (klass
, "AssemblyLoad", NULL
);
1628 g_assert (assembly_load_field
);
1630 MONO_STATIC_POINTER_INIT_END (MonoClassField
, assembly_load_field
)
1632 if (!MONO_HANDLE_GET_FIELD_BOOL (appdomain
, MonoObject
*, assembly_load_field
))
1633 goto exit
; // No events waiting to be triggered
1635 MonoReflectionAssemblyHandle reflection_assembly
;
1636 reflection_assembly
= mono_assembly_get_object_handle (domain
, assembly
, error
);
1637 goto_if_nok (error
, exit
);
1639 MONO_STATIC_POINTER_INIT (MonoMethod
, assembly_load_method
)
1641 assembly_load_method
= mono_class_get_method_from_name_checked (klass
, "DoAssemblyLoad", -1, 0, error
);
1642 g_assert (assembly_load_method
);
1644 MONO_STATIC_POINTER_INIT_END (MonoMethod
, assembly_load_method
)
1647 params
[0] = MONO_HANDLE_RAW (reflection_assembly
);
1648 mono_runtime_invoke_handle_void (assembly_load_method
, appdomain
, params
, error
);
1652 HANDLE_FUNCTION_RETURN ();
1656 mono_domain_fire_assembly_load (MonoAssemblyLoadContext
*alc
, MonoAssembly
*assembly
, gpointer user_data
, MonoError
*error_out
)
1659 MonoDomain
*domain
= mono_alc_domain (alc
);
1661 g_assert (assembly
);
1664 if (!MONO_BOOL (domain
->domain
))
1665 goto leave
; // This can happen during startup
1667 if (mono_runtime_get_no_exec ())
1670 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_ASSEMBLY
, "Loading assembly %s (%p) into domain %s (%p) and ALC %p", assembly
->aname
.name
, assembly
, domain
->friendly_name
, domain
, alc
);
1672 mono_domain_assemblies_lock (domain
);
1673 add_assemblies_to_domain (domain
, assembly
, NULL
);
1674 mono_domain_assemblies_unlock (domain
);
1675 #ifdef ENABLE_NETCORE
1676 add_assembly_to_alc (alc
, assembly
);
1679 mono_domain_fire_assembly_load_event (domain
, assembly
, error_out
);
1682 mono_error_cleanup (error
);
1686 mono_domain_asmctx_from_path (const char *fname
, MonoAssembly
*requesting_assembly
, gpointer user_data
, MonoAssemblyContextKind
*out_asmctx
)
1688 MonoDomain
*domain
= mono_domain_get ();
1689 char **search_path
= NULL
;
1691 for (search_path
= domain
->search_path
; search_path
&& *search_path
; search_path
++) {
1692 if (mono_path_filename_in_basedir (fname
, *search_path
)) {
1693 *out_asmctx
= MONO_ASMCTX_DEFAULT
;
1701 * LOCKING: Acquires the domain assemblies lock.
1704 set_domain_search_path (MonoDomain
*domain
)
1706 HANDLE_FUNCTION_ENTER ();
1708 MonoAppDomainSetupHandle setup
;
1710 gchar
*search_path
= NULL
;
1712 gchar
**pvt_split
= NULL
;
1713 GError
*gerror
= NULL
;
1714 gint appbaselen
= -1;
1717 * We use the low-level domain assemblies lock, since this is called from
1718 * assembly loads hooks, which means this thread might hold the loader lock.
1720 mono_domain_assemblies_lock (domain
);
1722 if (!MONO_BOOL (domain
->setup
))
1725 setup
= MONO_HANDLE_NEW (MonoAppDomainSetup
, domain
->setup
);
1727 if (domain
->search_path
&& !MONO_HANDLE_GET_BOOL (setup
, path_changed
))
1730 if (!MONO_HANDLE_GET_BOOL (setup
, application_base
))
1731 goto exit
; // Must set application base to get private path working
1733 if (MONO_HANDLE_GET_BOOL (setup
, private_bin_path
)) {
1734 search_path
= mono_string_handle_to_utf8 (MONO_HANDLE_NEW_GET (MonoString
, setup
, private_bin_path
), error
);
1735 if (!is_ok (error
)) { /*FIXME maybe we should bubble up the error.*/
1736 g_warning ("Could not decode AppDomain search path since it contains invalid characters");
1741 if (domain
->private_bin_path
) {
1742 if (search_path
== NULL
)
1743 search_path
= domain
->private_bin_path
;
1745 gchar
*tmp2
= search_path
;
1746 search_path
= g_strjoin (";", search_path
, domain
->private_bin_path
, (const char*)NULL
);
1753 * As per MSDN documentation, AppDomainSetup.PrivateBinPath contains a list of
1754 * directories relative to ApplicationBase separated by semicolons (see
1755 * http://msdn2.microsoft.com/en-us/library/system.appdomainsetup.privatebinpath.aspx)
1756 * The loop below copes with the fact that some Unix applications may use ':' (or
1757 * System.IO.Path.PathSeparator) as the path search separator. We replace it with
1758 * ';' for the subsequent split.
1760 * The issue was reported in bug #81446
1762 #ifndef TARGET_WIN32
1763 g_strdelimit (search_path
, ':', ';');
1765 pvt_split
= g_strsplit (search_path
, ";", 1000);
1766 g_free (search_path
);
1767 for (tmp
= pvt_split
; *tmp
; tmp
++, npaths
++);
1770 g_strfreev (domain
->search_path
);
1771 domain
->search_path
= NULL
;
1773 tmp
= g_new (gchar
*, npaths
+ 1);
1774 tmp
[npaths
] = NULL
;
1776 *tmp
= mono_string_handle_to_utf8 (MONO_HANDLE_NEW_GET (MonoString
, setup
, application_base
), error
);
1777 if (!is_ok (error
)) {
1782 domain
->search_path
= tmp
;
1784 /* FIXME: is this needed? */
1785 if (strncmp (*tmp
, "file://", 7) == 0) {
1791 uri
= g_strdup_printf ("file:///%s", uri
+ 7);
1794 uri
= mono_escape_uri_string (tmpuri
);
1795 *tmp
= g_filename_from_uri (uri
, NULL
, &gerror
);
1801 if (gerror
!= NULL
) {
1802 g_warning ("%s\n", gerror
->message
);
1803 g_error_free (gerror
);
1810 for (gsize i
= 1; pvt_split
&& i
< npaths
; i
++) {
1811 if (g_path_is_absolute (pvt_split
[i
- 1])) {
1812 tmp
[i
] = g_strdup (pvt_split
[i
- 1]);
1814 tmp
[i
] = g_build_filename (tmp
[0], pvt_split
[i
- 1], (const char*)NULL
);
1817 if (strchr (tmp
[i
], '.')) {
1821 reduced
= mono_path_canonicalize (tmp
[i
]);
1822 if (appbaselen
== -1)
1823 appbaselen
= strlen (tmp
[0]);
1825 if (strncmp (tmp
[0], reduced
, appbaselen
)) {
1828 tmp
[i
] = g_strdup ("");
1838 if (MONO_HANDLE_GET_BOOL (setup
, private_bin_path_probe
)) {
1840 tmp
[0] = g_strdup ("");
1843 MONO_HANDLE_SETVAL (setup
, path_changed
, MonoBoolean
, FALSE
);
1845 mono_error_cleanup (error
);
1846 g_strfreev (pvt_split
);
1847 mono_domain_assemblies_unlock (domain
);
1848 HANDLE_FUNCTION_RETURN ();
1851 #ifdef DISABLE_SHADOW_COPY
1853 mono_is_shadow_copy_enabled (MonoDomain
*domain
, const gchar
*dir_name
)
1859 mono_make_shadow_copy (const char *filename
, MonoError
*error
)
1862 return (char *) filename
;
1867 SHADOW_COPY_SIBLING_EXT_APPEND
,
1868 SHADOW_COPY_SIBLING_EXT_REPLACE
,
1869 } ShadowCopySiblingExt
;
1873 make_sibling_path (const gchar
*path
, gint pathlen
, const char *extension
, ShadowCopySiblingExt extopt
)
1875 gchar
*result
= NULL
;
1877 case SHADOW_COPY_SIBLING_EXT_APPEND
: {
1878 result
= g_strconcat (path
, extension
, (const char*)NULL
);
1881 case SHADOW_COPY_SIBLING_EXT_REPLACE
: {
1882 /* expect path to be a .dll or .exe (or some case insensitive variant) */
1883 g_assert (pathlen
>= 4 && path
[pathlen
- 4] == '.');
1884 GString
*s
= g_string_sized_new (pathlen
- 4 + strlen (extension
));
1885 g_string_append_len (s
, path
, pathlen
- 4);
1886 g_string_append (s
, extension
);
1887 result
= g_string_free (s
, FALSE
);
1891 g_assert_not_reached ();
1897 shadow_copy_sibling (const gchar
*src_pristine
, gint srclen
, const char *extension
, ShadowCopySiblingExt extopt
, const gchar
*target_pristine
, gint targetlen
)
1900 gunichar2
*orig
= NULL
;
1901 gunichar2
*dest
= NULL
;
1902 gboolean copy_result
= TRUE
;
1903 gchar
*target
= NULL
;
1905 char *src
= make_sibling_path (src_pristine
, srclen
, extension
, extopt
);
1907 if (IS_PORTABILITY_CASE
) {
1908 file
= mono_portability_find_file (src
, TRUE
);
1911 } else if (!g_file_test (src
, G_FILE_TEST_IS_REGULAR
))
1914 orig
= g_utf8_to_utf16 (src
, strlen (src
), NULL
, NULL
, NULL
);
1916 target
= make_sibling_path (target_pristine
, targetlen
, extension
, extopt
);
1918 dest
= g_utf8_to_utf16 (target
, strlen (target
), NULL
, NULL
, NULL
);
1920 mono_w32file_delete (dest
);
1923 copy_result
= mono_w32file_copy (orig
, dest
, TRUE
, ©_error
);
1925 /* Fix for bug #556884 - make sure the files have the correct mode so that they can be
1926 * overwritten when updated in their original locations. */
1928 copy_result
= mono_w32file_set_attributes (dest
, FILE_ATTRIBUTE_NORMAL
);
1940 get_cstring_hash (const char *str
)
1945 if (!str
|| !str
[0])
1948 gsize
const len
= strlen (str
);
1950 for (gsize i
= 0; i
< len
; i
++) {
1951 h
= (h
<< 5) - h
+ *p
;
1959 * Returned memory is malloc'd. Called must free it
1962 get_shadow_assembly_location_base (MonoDomain
*domain
, MonoError
*error
)
1964 MonoAppDomainSetup
*setup
;
1965 char *cache_path
= NULL
;
1966 char *appname
= NULL
;
1967 char *userdir
= NULL
;
1972 setup
= domain
->setup
;
1973 if (setup
->cache_path
!= NULL
&& setup
->application_name
!= NULL
) {
1974 cache_path
= mono_string_to_utf8_checked_internal (setup
->cache_path
, error
);
1975 return_val_if_nok (error
, NULL
);
1977 #ifndef TARGET_WIN32
1980 for (i
= strlen (cache_path
) - 1; i
>= 0; i
--)
1981 if (cache_path
[i
] == '\\')
1982 cache_path
[i
] = '/';
1986 appname
= mono_string_to_utf8_checked_internal (setup
->application_name
, error
);
1987 if (!is_ok (error
)) {
1988 g_free (cache_path
);
1992 location
= g_build_filename (cache_path
, appname
, "assembly", "shadow", (const char*)NULL
);
1994 userdir
= g_strdup_printf ("%s-mono-cachepath", g_get_user_name ());
1995 location
= g_build_filename (g_get_tmp_dir (), userdir
, "assembly", "shadow", (const char*)NULL
);
1998 g_free (cache_path
);
2004 get_shadow_assembly_location (const char *filename
, MonoError
*error
)
2006 gint32 hash
= 0, hash2
= 0;
2008 char path_hash
[30];
2009 char *bname
= g_path_get_basename (filename
);
2010 char *dirname
= g_path_get_dirname (filename
);
2011 char *location
, *tmploc
;
2012 MonoDomain
*domain
= mono_domain_get ();
2016 hash
= get_cstring_hash (bname
);
2017 hash2
= get_cstring_hash (dirname
);
2018 g_snprintf (name_hash
, sizeof (name_hash
), "%08x", hash
);
2019 g_snprintf (path_hash
, sizeof (path_hash
), "%08x_%08x_%08x", hash
^ hash2
, hash2
, domain
->shadow_serial
);
2020 tmploc
= get_shadow_assembly_location_base (domain
, error
);
2021 if (!is_ok (error
)) {
2027 location
= g_build_filename (tmploc
, name_hash
, path_hash
, bname
, (const char*)NULL
);
2035 private_file_needs_copying (const char *src
, struct stat
*sbuf_src
, char *dest
)
2037 struct stat sbuf_dest
;
2039 gchar
*real_src
= mono_portability_find_file (src
, TRUE
);
2042 stat_src
= (gchar
*)src
;
2044 stat_src
= real_src
;
2046 if (stat (stat_src
, sbuf_src
) == -1) {
2047 time_t tnow
= time (NULL
);
2052 memset (sbuf_src
, 0, sizeof (*sbuf_src
));
2053 sbuf_src
->st_mtime
= tnow
;
2054 sbuf_src
->st_atime
= tnow
;
2061 if (stat (dest
, &sbuf_dest
) == -1)
2064 if (sbuf_src
->st_size
== sbuf_dest
.st_size
&&
2065 sbuf_src
->st_mtime
== sbuf_dest
.st_mtime
)
2072 shadow_copy_create_ini (const char *shadow
, const char *filename
)
2074 gunichar2
*u16_ini
= NULL
;
2075 gboolean result
= FALSE
;
2077 HANDLE handle
= INVALID_HANDLE_VALUE
;
2078 gchar
*full_path
= NULL
;
2080 char *dir_name
= g_path_get_dirname (shadow
);
2081 char *ini_file
= g_build_filename (dir_name
, "__AssemblyInfo__.ini", (const char*)NULL
);
2083 result
= g_file_test (ini_file
, G_FILE_TEST_IS_REGULAR
);
2087 u16_ini
= g_utf8_to_utf16 (ini_file
, strlen (ini_file
), NULL
, NULL
, NULL
);
2091 handle
= mono_w32file_create (u16_ini
, GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, CREATE_NEW
, FileAttributes_Normal
);
2092 if (handle
== INVALID_HANDLE_VALUE
)
2095 full_path
= mono_path_resolve_symlinks (filename
);
2098 result
= mono_w32file_write (handle
, full_path
, strlen (full_path
), &n
, &win32error
);
2100 if (handle
!= INVALID_HANDLE_VALUE
)
2101 mono_w32file_close (handle
);
2109 mono_is_shadow_copy_enabled (MonoDomain
*domain
, const gchar
*dir_name
)
2112 MonoAppDomainSetup
*setup
;
2113 gchar
*all_dirs
= NULL
;
2115 gchar
**directories
= NULL
;
2116 gchar
*shadow_status_string
;
2117 gchar
*base_dir
= NULL
;
2118 gboolean shadow_enabled
;
2119 gboolean found
= FALSE
;
2124 setup
= domain
->setup
;
2125 if (setup
== NULL
|| setup
->shadow_copy_files
== NULL
)
2128 shadow_status_string
= mono_string_to_utf8_checked_internal (setup
->shadow_copy_files
, error
);
2132 shadow_enabled
= !g_ascii_strncasecmp (shadow_status_string
, "true", 4);
2133 g_free (shadow_status_string
);
2135 if (!shadow_enabled
)
2138 found
= (setup
->shadow_copy_directories
== NULL
);
2142 /* Is dir_name a shadow_copy destination already? */
2143 base_dir
= get_shadow_assembly_location_base (domain
, error
);
2147 found
= !!strstr (dir_name
, base_dir
);
2151 all_dirs
= mono_string_to_utf8_checked_internal (setup
->shadow_copy_directories
, error
);
2155 directories
= g_strsplit (all_dirs
, G_SEARCHPATH_SEPARATOR_S
, 1000);
2156 dir_ptr
= directories
;
2157 while (!found
&& *dir_ptr
) {
2158 found
= (**dir_ptr
!= '\0' && !strcmp (*dir_ptr
, dir_name
));
2162 mono_error_cleanup (error
);
2164 g_strfreev (directories
);
2170 This function raises exceptions so it can cause as sorts of nasty stuff if called
2171 while holding a lock.
2172 Returns old file name if shadow copy is disabled, new shadow copy file name if successful
2173 or NULL if source file not found.
2174 FIXME bubble up the error instead of raising it here
2177 mono_make_shadow_copy (const char *filename
, MonoError
*oerror
)
2180 gint filename_len
, shadow_len
;
2181 gunichar2
*orig
, *dest
;
2184 gboolean copy_result
;
2185 struct stat src_sbuf
;
2186 struct utimbuf utbuf
;
2187 char *dir_name
= g_path_get_dirname (filename
);
2188 MonoDomain
*domain
= mono_domain_get ();
2192 #ifndef ENABLE_NETCORE
2193 set_domain_search_path (domain
);
2196 if (!mono_is_shadow_copy_enabled (domain
, dir_name
)) {
2198 return (char *) filename
;
2201 /* Is dir_name a shadow_copy destination already? */
2202 shadow_dir
= get_shadow_assembly_location_base (domain
, error
);
2203 if (!is_ok (error
)) {
2204 mono_error_cleanup (error
);
2206 mono_error_set_execution_engine (oerror
, "Failed to create shadow copy (invalid characters in shadow directory name).");
2210 if (strstr (dir_name
, shadow_dir
)) {
2211 g_free (shadow_dir
);
2213 return (char *) filename
;
2215 g_free (shadow_dir
);
2218 shadow
= get_shadow_assembly_location (filename
, error
);
2219 if (!is_ok (error
)) {
2220 mono_error_cleanup (error
);
2221 mono_error_set_execution_engine (oerror
, "Failed to create shadow copy (invalid characters in file name).");
2225 if (g_ensure_directory_exists (shadow
) == FALSE
) {
2227 mono_error_set_execution_engine (oerror
, "Failed to create shadow copy (ensure directory exists).");
2231 if (!private_file_needs_copying (filename
, &src_sbuf
, shadow
))
2232 return (char*) shadow
;
2234 orig
= g_utf8_to_utf16 (filename
, strlen (filename
), NULL
, NULL
, NULL
);
2235 dest
= g_utf8_to_utf16 (shadow
, strlen (shadow
), NULL
, NULL
, NULL
);
2236 mono_w32file_delete (dest
);
2238 /* Fix for bug #17066 - make sure we can read the file. if not then don't error but rather
2239 * let the assembly fail to load. This ensures you can do Type.GetType("NS.T, NonExistantAssembly)
2240 * and not have it runtime error" */
2241 attrs
= mono_w32file_get_attributes (orig
);
2242 if (attrs
== INVALID_FILE_ATTRIBUTES
) {
2244 return (char *)filename
;
2247 copy_result
= mono_w32file_copy (orig
, dest
, TRUE
, ©_error
);
2249 /* Fix for bug #556884 - make sure the files have the correct mode so that they can be
2250 * overwritten when updated in their original locations. */
2252 copy_result
= mono_w32file_set_attributes (dest
, FILE_ATTRIBUTE_NORMAL
);
2257 if (copy_result
== FALSE
) {
2260 /* Fix for bug #17251 - if file not found try finding assembly by other means (it is not fatal error) */
2261 if (mono_w32error_get_last() == ERROR_FILE_NOT_FOUND
|| mono_w32error_get_last() == ERROR_PATH_NOT_FOUND
)
2262 return NULL
; /* file not found, shadow copy failed */
2264 mono_error_set_execution_engine (oerror
, "Failed to create shadow copy (mono_w32file_copy).");
2268 /* attempt to copy .mdb, .pdb and .config if they exist */
2269 filename_len
= strlen (filename
);
2270 shadow_len
= strlen (shadow
);
2272 copy_result
= shadow_copy_sibling (filename
, filename_len
, ".mdb", SHADOW_COPY_SIBLING_EXT_APPEND
, shadow
, shadow_len
);
2274 copy_result
= shadow_copy_sibling (filename
, filename_len
, ".pdb", SHADOW_COPY_SIBLING_EXT_REPLACE
, shadow
, shadow_len
);
2276 copy_result
= shadow_copy_sibling (filename
, filename_len
, ".config", SHADOW_COPY_SIBLING_EXT_APPEND
, shadow
, shadow_len
);
2280 mono_error_set_execution_engine (oerror
, "Failed to create shadow copy of sibling data (mono_w32file_copy).");
2284 /* Create a .ini file containing the original assembly location */
2285 if (!shadow_copy_create_ini (shadow
, filename
)) {
2287 mono_error_set_execution_engine (oerror
, "Failed to create shadow copy .ini file.");
2291 utbuf
.actime
= src_sbuf
.st_atime
;
2292 utbuf
.modtime
= src_sbuf
.st_mtime
;
2293 utime (shadow
, &utbuf
);
2297 #endif /* DISABLE_SHADOW_COPY */
2300 * mono_domain_from_appdomain:
2303 mono_domain_from_appdomain (MonoAppDomain
*appdomain_raw
)
2305 HANDLE_FUNCTION_ENTER ();
2307 MONO_ENTER_GC_UNSAFE
;
2308 MONO_HANDLE_DCL (MonoAppDomain
, appdomain
);
2309 result
= mono_domain_from_appdomain_handle (appdomain
);
2310 MONO_EXIT_GC_UNSAFE
;
2311 HANDLE_FUNCTION_RETURN_VAL (result
);
2315 mono_domain_from_appdomain_handle (MonoAppDomainHandle appdomain
)
2317 HANDLE_FUNCTION_ENTER ();
2318 MonoDomain
*dom
= NULL
;
2319 if (MONO_HANDLE_IS_NULL (appdomain
))
2322 if (mono_class_is_transparent_proxy (mono_handle_class (appdomain
))) {
2323 MonoTransparentProxyHandle tp
= MONO_HANDLE_CAST (MonoTransparentProxy
, appdomain
);
2324 MonoRealProxyHandle rp
= MONO_HANDLE_NEW_GET (MonoRealProxy
, tp
, rp
);
2326 dom
= mono_domain_get_by_id (MONO_HANDLE_GETVAL (rp
, target_domain_id
));
2328 dom
= MONO_HANDLE_GETVAL (appdomain
, data
);
2331 HANDLE_FUNCTION_RETURN_VAL (dom
);
2336 try_load_from (MonoAssembly
**assembly
,
2337 const gchar
*path1
, const gchar
*path2
,
2338 const gchar
*path3
, const gchar
*path4
,
2339 const MonoAssemblyOpenRequest
*req
)
2342 gboolean found
= FALSE
;
2345 fullpath
= g_build_filename (path1
, path2
, path3
, path4
, (const char*)NULL
);
2347 if (IS_PORTABILITY_SET
) {
2348 gchar
*new_fullpath
= mono_portability_find_file (fullpath
, TRUE
);
2351 fullpath
= new_fullpath
;
2355 found
= g_file_test (fullpath
, G_FILE_TEST_IS_REGULAR
);
2358 *assembly
= mono_assembly_request_open (fullpath
, req
, NULL
);
2362 return (*assembly
!= NULL
);
2365 static MonoAssembly
*
2366 real_load (gchar
**search_path
, const gchar
*culture
, const gchar
*name
, const MonoAssemblyOpenRequest
*req
)
2368 MonoAssembly
*result
= NULL
;
2371 const gchar
*local_culture
;
2374 if (!culture
|| *culture
== '\0') {
2377 local_culture
= culture
;
2380 filename
= g_strconcat (name
, ".dll", (const char*)NULL
);
2381 len
= strlen (filename
);
2383 for (path
= search_path
; *path
; path
++) {
2384 if (**path
== '\0') {
2385 continue; /* Ignore empty ApplicationBase */
2388 /* See test cases in bug #58992 and bug #57710 */
2389 /* 1st try: [culture]/[name].dll (culture may be empty) */
2390 strcpy (filename
+ len
- 4, ".dll");
2391 if (try_load_from (&result
, *path
, local_culture
, "", filename
, req
))
2394 /* 2nd try: [culture]/[name].exe (culture may be empty) */
2395 strcpy (filename
+ len
- 4, ".exe");
2396 if (try_load_from (&result
, *path
, local_culture
, "", filename
, req
))
2399 /* 3rd try: [culture]/[name]/[name].dll (culture may be empty) */
2400 strcpy (filename
+ len
- 4, ".dll");
2401 if (try_load_from (&result
, *path
, local_culture
, name
, filename
, req
))
2404 /* 4th try: [culture]/[name]/[name].exe (culture may be empty) */
2405 strcpy (filename
+ len
- 4, ".exe");
2406 if (try_load_from (&result
, *path
, local_culture
, name
, filename
, req
))
2415 get_app_context_base_directory (MonoError
*error
)
2417 MONO_STATIC_POINTER_INIT (MonoMethod
, get_basedir
)
2419 ERROR_DECL (local_error
);
2420 MonoClass
*app_context
= mono_class_get_app_context_class ();
2421 g_assert (app_context
);
2422 get_basedir
= mono_class_get_method_from_name_checked (app_context
, "get_BaseDirectory", -1, 0, local_error
);
2423 mono_error_assert_ok (local_error
);
2425 MONO_STATIC_POINTER_INIT_END (MonoMethod
, get_basedir
)
2427 HANDLE_FUNCTION_ENTER ();
2429 MonoStringHandle result
= MONO_HANDLE_CAST (MonoString
, mono_runtime_try_invoke_handle (get_basedir
, NULL_HANDLE
, NULL
, error
));
2430 char *base_dir
= mono_string_handle_to_utf8 (result
, error
);
2432 HANDLE_FUNCTION_RETURN_VAL (base_dir
);
2436 * Try loading the assembly from ApplicationBase and PrivateBinPath
2437 * and then from assemblies_path if any.
2438 * LOCKING: This is called from the assembly loading code, which means the caller
2439 * might hold the loader lock. Thus, this function must not acquire the domain lock.
2441 static MonoAssembly
*
2442 mono_domain_assembly_preload (MonoAssemblyLoadContext
*alc
,
2443 MonoAssemblyName
*aname
,
2444 gchar
**assemblies_path
,
2449 MonoDomain
*domain
= mono_alc_domain (alc
);
2450 MonoAssembly
*result
= NULL
;
2451 #ifdef ENABLE_NETCORE
2453 g_assert (domain
== mono_domain_get ());
2456 #ifndef ENABLE_NETCORE
2457 set_domain_search_path (domain
);
2460 MonoAssemblyCandidatePredicate predicate
= NULL
;
2461 void* predicate_ud
= NULL
;
2462 if (mono_loader_get_strict_assembly_name_check ()) {
2463 predicate
= &mono_assembly_candidate_predicate_sn_same_name
;
2464 predicate_ud
= aname
;
2466 MonoAssemblyOpenRequest req
;
2467 mono_assembly_request_prepare_open (&req
, refonly
? MONO_ASMCTX_REFONLY
: MONO_ASMCTX_DEFAULT
, alc
);
2468 req
.request
.predicate
= predicate
;
2469 req
.request
.predicate_ud
= predicate_ud
;
2471 #ifdef ENABLE_NETCORE
2472 if (!mono_runtime_get_no_exec ()) {
2473 char *search_path
[2];
2474 search_path
[1] = NULL
;
2476 char *base_dir
= get_app_context_base_directory (error
);
2477 search_path
[0] = base_dir
;
2478 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_ASSEMBLY
, "Domain %s (%p) ApplicationBase is %s\n", domain
->friendly_name
, domain
, base_dir
);
2480 result
= real_load (search_path
, aname
->culture
, aname
->name
, &req
);
2485 if (domain
->search_path
&& domain
->search_path
[0] != NULL
) {
2486 if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG
, MONO_TRACE_ASSEMBLY
)) {
2487 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_ASSEMBLY
, "Domain %s search path is:", domain
->friendly_name
);
2488 for (int i
= 0; domain
->search_path
[i
]; i
++) {
2489 const char *p
= domain
->search_path
[i
];
2490 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_ASSEMBLY
, "\tpath[%d] = '%s'", i
, p
);
2492 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_ASSEMBLY
, "End of domain %s search path.", domain
->friendly_name
);
2494 result
= real_load (domain
->search_path
, aname
->culture
, aname
->name
, &req
);
2498 if (result
== NULL
&& assemblies_path
&& assemblies_path
[0] != NULL
) {
2499 result
= real_load (assemblies_path
, aname
->culture
, aname
->name
, &req
);
2506 * mono_assembly_load_from_assemblies_path:
2508 * \param assemblies_path directories to search for given assembly name, terminated by NULL
2509 * \param aname assembly name to look for
2510 * \param asmctx assembly load context for this load operation
2512 * Given a NULL-terminated array of paths, look for \c name.ext, \c name, \c
2513 * culture/name.ext, \c culture/name/name.ext where \c ext is \c dll and \c
2514 * exe and try to load it in the given assembly load context.
2516 * \returns A \c MonoAssembly if probing was successful, or NULL otherwise.
2519 mono_assembly_load_from_assemblies_path (gchar
**assemblies_path
, MonoAssemblyName
*aname
, MonoAssemblyContextKind asmctx
)
2521 MonoAssemblyCandidatePredicate predicate
= NULL
;
2522 void* predicate_ud
= NULL
;
2523 if (mono_loader_get_strict_assembly_name_check ()) {
2524 predicate
= &mono_assembly_candidate_predicate_sn_same_name
;
2525 predicate_ud
= aname
;
2527 MonoAssemblyOpenRequest req
;
2528 mono_assembly_request_prepare_open (&req
, asmctx
, mono_domain_default_alc (mono_domain_get ()));
2529 req
.request
.predicate
= predicate
;
2530 req
.request
.predicate_ud
= predicate_ud
;
2531 MonoAssembly
*result
= NULL
;
2532 if (assemblies_path
&& assemblies_path
[0] != NULL
) {
2533 result
= real_load (assemblies_path
, aname
->culture
, aname
->name
, &req
);
2539 * Check whenever a given assembly was already loaded in the current appdomain.
2541 static MonoAssembly
*
2542 mono_domain_assembly_search (MonoAssemblyLoadContext
*alc
, MonoAssembly
*requesting
,
2543 MonoAssemblyName
*aname
,
2549 g_assert (aname
!= NULL
);
2553 #ifdef ENABLE_NETCORE
2554 const MonoAssemblyNameEqFlags eq_flags
= MONO_ANAME_EQ_IGNORE_PUBKEY
| MONO_ANAME_EQ_IGNORE_VERSION
| MONO_ANAME_EQ_IGNORE_CASE
;
2556 mono_alc_assemblies_lock (alc
);
2557 for (tmp
= alc
->loaded_assemblies
; tmp
; tmp
= tmp
->next
) {
2558 ass
= (MonoAssembly
*)tmp
->data
;
2559 g_assert (ass
!= NULL
);
2560 // FIXME: Can dynamic assemblies match here for netcore?
2561 if (assembly_is_dynamic (ass
) || !mono_assembly_names_equal_flags (aname
, &ass
->aname
, eq_flags
))
2564 mono_alc_assemblies_unlock (alc
);
2567 mono_alc_assemblies_unlock (alc
);
2569 MonoDomain
*domain
= mono_alc_domain (alc
);
2571 const gboolean strong_name
= aname
->public_key_token
[0] != 0;
2572 /* If it's not a strong name, any version that has the right simple
2573 * name is good enough to satisfy the request. .NET Framework also
2574 * ignores case differences in this case. */
2575 const MonoAssemblyNameEqFlags eq_flags
= (MonoAssemblyNameEqFlags
)(strong_name
? MONO_ANAME_EQ_IGNORE_CASE
:
2576 (MONO_ANAME_EQ_IGNORE_PUBKEY
| MONO_ANAME_EQ_IGNORE_VERSION
| MONO_ANAME_EQ_IGNORE_CASE
));
2578 mono_domain_assemblies_lock (domain
);
2579 for (tmp
= domain
->domain_assemblies
; tmp
; tmp
= tmp
->next
) {
2580 ass
= (MonoAssembly
*)tmp
->data
;
2581 g_assert (ass
!= NULL
);
2582 /* Dynamic assemblies can't match here in MS.NET */
2583 gboolean ass_ref_only
= mono_asmctx_get_kind (&ass
->context
) == MONO_ASMCTX_REFONLY
;
2584 if (assembly_is_dynamic (ass
) || refonly
!= ass_ref_only
|| !mono_assembly_names_equal_flags (aname
, &ass
->aname
, eq_flags
))
2587 mono_domain_assemblies_unlock (domain
);
2590 mono_domain_assemblies_unlock (domain
);
2597 MonoReflectionAssemblyHandle
2598 ves_icall_System_Reflection_Assembly_InternalLoad (MonoStringHandle name_handle
, MonoStackCrawlMark
*stack_mark
, gpointer load_Context
, MonoError
*error
)
2601 MonoAssembly
*ass
= NULL
;
2602 MonoAssemblyName aname
;
2603 MonoAssemblyByNameRequest req
;
2604 MonoAssemblyContextKind asmctx
;
2605 MonoImageOpenStatus status
= MONO_IMAGE_OK
;
2609 MonoAssembly
*requesting_assembly
= mono_runtime_get_caller_from_stack_mark (stack_mark
);
2610 MonoAssemblyLoadContext
*alc
= (MonoAssemblyLoadContext
*)load_Context
;
2613 alc
= mono_assembly_get_alc (requesting_assembly
);
2615 g_assert_not_reached ();
2617 MonoDomain
*domain
= mono_alc_domain (alc
);
2619 asmctx
= MONO_ASMCTX_DEFAULT
;
2620 mono_assembly_request_prepare_byname (&req
, asmctx
, alc
);
2622 /* Everything currently goes through this function, and the postload hook (aka the AppDomain.AssemblyResolve event)
2623 * is triggered under some scenarios. It's not completely obvious to me in what situations (if any) this should be disabled,
2624 * other than for corlib satellite assemblies (which I've dealt with further down the call stack).
2626 //req.no_postload_search = TRUE;
2627 req
.requesting_assembly
= requesting_assembly
;
2629 name
= mono_string_handle_to_utf8 (name_handle
, error
);
2630 goto_if_nok (error
, fail
);
2631 parsed
= mono_assembly_name_parse (name
, &aname
);
2636 MonoAssemblyCandidatePredicate predicate
= NULL
;
2637 void* predicate_ud
= NULL
;
2638 if (mono_loader_get_strict_assembly_name_check ()) {
2639 predicate
= &mono_assembly_candidate_predicate_sn_same_name
;
2640 predicate_ud
= &aname
;
2642 req
.request
.predicate
= predicate
;
2643 req
.request
.predicate_ud
= predicate_ud
;
2645 ass
= mono_assembly_request_byname (&aname
, &req
, &status
);
2649 MonoReflectionAssemblyHandle refass
;
2650 refass
= mono_assembly_get_object_handle (domain
, ass
, error
);
2651 goto_if_nok (error
, fail
);
2655 return MONO_HANDLE_CAST (MonoReflectionAssembly
, NULL_HANDLE
);
2659 #ifndef ENABLE_NETCORE
2660 MonoReflectionAssemblyHandle
2661 ves_icall_System_Reflection_Assembly_LoadFrom (MonoStringHandle fname
, MonoBoolean refOnly
, MonoStackCrawlMark
*stack_mark
, MonoError
*error
)
2664 MonoDomain
*domain
= mono_domain_get ();
2665 char *name
, *filename
;
2666 MonoImageOpenStatus status
= MONO_IMAGE_OK
;
2667 MonoReflectionAssemblyHandle result
= MONO_HANDLE_CAST (MonoReflectionAssembly
, NULL_HANDLE
);
2671 if (MONO_HANDLE_IS_NULL (fname
)) {
2672 mono_error_set_argument_null (error
, "assemblyFile", "");
2676 name
= filename
= mono_string_handle_to_utf8 (fname
, error
);
2677 goto_if_nok (error
, leave
);
2679 MonoAssembly
*requesting_assembly
;
2680 requesting_assembly
= NULL
;
2682 requesting_assembly
= mono_runtime_get_caller_from_stack_mark (stack_mark
);
2685 MonoAssemblyOpenRequest req
;
2686 mono_assembly_request_prepare_open (&req
, refOnly
? MONO_ASMCTX_REFONLY
: MONO_ASMCTX_LOADFROM
, mono_domain_default_alc (domain
));
2687 req
.requesting_assembly
= requesting_assembly
;
2688 ass
= mono_assembly_request_open (filename
, &req
, &status
);
2691 if (status
== MONO_IMAGE_IMAGE_INVALID
)
2692 mono_error_set_bad_image_by_name (error
, name
, "Invalid Image");
2694 mono_error_set_file_not_found (error
, name
, "Invalid Image");
2698 result
= mono_assembly_get_object_handle (domain
, ass
, error
);
2708 mono_alc_load_file (MonoAssemblyLoadContext
*alc
, MonoStringHandle fname
, MonoAssembly
*executing_assembly
, MonoAssemblyContextKind asmctx
, MonoError
*error
)
2710 MonoAssembly
*ass
= NULL
;
2711 HANDLE_FUNCTION_ENTER ();
2712 char *filename
= NULL
;
2713 if (MONO_HANDLE_IS_NULL (fname
)) {
2714 mono_error_set_argument_null (error
, "assemblyFile", "");
2718 filename
= mono_string_handle_to_utf8 (fname
, error
);
2719 goto_if_nok (error
, leave
);
2721 if (!g_path_is_absolute (filename
)) {
2722 mono_error_set_argument (error
, "assemblyFile", "Absolute path information is required.");
2726 MonoImageOpenStatus status
;
2727 MonoAssemblyOpenRequest req
;
2728 mono_assembly_request_prepare_open (&req
, asmctx
, alc
);
2729 req
.requesting_assembly
= executing_assembly
;
2730 ass
= mono_assembly_request_open (filename
, &req
, &status
);
2732 if (status
== MONO_IMAGE_IMAGE_INVALID
)
2733 mono_error_set_bad_image_by_name (error
, filename
, "Invalid Image");
2735 mono_error_set_file_not_found (error
, filename
, "Invalid Image");
2740 HANDLE_FUNCTION_RETURN_VAL (ass
);
2743 #ifndef ENABLE_NETCORE
2744 MonoReflectionAssemblyHandle
2745 ves_icall_System_Reflection_Assembly_LoadFile_internal (MonoStringHandle fname
, MonoStackCrawlMark
*stack_mark
, MonoError
*error
)
2747 MonoDomain
*domain
= mono_domain_get ();
2748 MonoReflectionAssemblyHandle result
= MONO_HANDLE_CAST (MonoReflectionAssembly
, NULL_HANDLE
);
2749 MonoAssembly
*executing_assembly
;
2750 executing_assembly
= mono_runtime_get_caller_from_stack_mark (stack_mark
);
2751 MonoAssembly
*ass
= mono_alc_load_file (mono_domain_default_alc (domain
), fname
, executing_assembly
, MONO_ASMCTX_INDIVIDUAL
, error
);
2752 goto_if_nok (error
, leave
);
2754 result
= mono_assembly_get_object_handle (domain
, ass
, error
);
2759 MonoReflectionAssemblyHandle
2760 ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalLoadFile (gpointer alc_ptr
, MonoStringHandle fname
, MonoStackCrawlMark
*stack_mark
, MonoError
*error
)
2762 MonoReflectionAssemblyHandle result
= MONO_HANDLE_CAST (MonoReflectionAssembly
, NULL_HANDLE
);
2763 MonoAssemblyLoadContext
*alc
= (MonoAssemblyLoadContext
*)alc_ptr
;
2764 MonoDomain
*domain
= mono_alc_domain (alc
);
2766 MonoAssembly
*executing_assembly
;
2767 executing_assembly
= mono_runtime_get_caller_from_stack_mark (stack_mark
);
2768 MonoAssembly
*ass
= mono_alc_load_file (alc
, fname
, executing_assembly
, mono_alc_is_default (alc
) ? MONO_ASMCTX_LOADFROM
: MONO_ASMCTX_INDIVIDUAL
, error
);
2769 goto_if_nok (error
, leave
);
2771 result
= mono_assembly_get_object_handle (domain
, ass
, error
);
2778 static MonoAssembly
*
2779 mono_alc_load_raw_bytes (MonoAssemblyLoadContext
*alc
, guint8
*raw_assembly
, guint32 raw_assembly_len
, guint8
*raw_symbol_data
, guint32 raw_symbol_len
, gboolean refonly
, MonoError
*error
);
2781 #ifdef ENABLE_NETCORE
2782 MonoReflectionAssemblyHandle
2783 ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalLoadFromStream (gpointer native_alc
, gpointer raw_assembly_ptr
, gint32 raw_assembly_len
, gpointer raw_symbols_ptr
, gint32 raw_symbols_len
, MonoError
*error
)
2785 MonoAssemblyLoadContext
*alc
= (MonoAssemblyLoadContext
*)native_alc
;
2786 MonoDomain
*domain
= mono_alc_domain (alc
);
2787 MonoReflectionAssemblyHandle result
= MONO_HANDLE_CAST (MonoReflectionAssembly
, NULL_HANDLE
);
2788 MonoAssembly
*assm
= NULL
;
2789 assm
= mono_alc_load_raw_bytes (alc
, (guint8
*)raw_assembly_ptr
, raw_assembly_len
, (guint8
*)raw_symbols_ptr
, raw_symbols_len
, FALSE
, error
);
2790 goto_if_nok (error
, leave
);
2792 result
= mono_assembly_get_object_handle (domain
, assm
, error
);
2798 MonoReflectionAssemblyHandle
2799 ves_icall_System_AppDomain_LoadAssemblyRaw (MonoAppDomainHandle ad
,
2800 MonoArrayHandle raw_assembly
,
2801 MonoArrayHandle raw_symbol_store
, MonoObjectHandle evidence
,
2802 MonoBoolean refonly
,
2806 MonoReflectionAssemblyHandle refass
= MONO_HANDLE_CAST (MonoReflectionAssembly
, NULL_HANDLE
);
2807 MonoDomain
*domain
= MONO_HANDLE_GETVAL(ad
, data
);
2808 guint32 raw_assembly_len
= mono_array_handle_length (raw_assembly
);
2810 /* Copy the data ourselves to unpin the raw assembly byte array as soon as possible */
2811 guint8
*assembly_data
= (guint8
*) g_try_malloc (raw_assembly_len
);
2812 if (!assembly_data
) {
2813 mono_error_set_out_of_memory (error
, "Could not allocate %ud bytes to copy raw assembly data", raw_assembly_len
);
2817 mono_byte
*raw_data
= (mono_byte
*) MONO_ARRAY_HANDLE_PIN (raw_assembly
, gchar
, 0, &gchandle
);
2818 memcpy (assembly_data
, raw_data
, raw_assembly_len
);
2819 mono_gchandle_free_internal (gchandle
); /* unpin */
2820 MONO_HANDLE_ASSIGN (raw_assembly
, NULL_HANDLE
); /* don't reference the data anymore */
2822 MonoAssemblyLoadContext
*alc
= mono_domain_default_alc (domain
);
2824 mono_byte
*raw_symbol_data
= NULL
;
2825 guint32 symbol_len
= 0;
2826 uint32_t symbol_gchandle
= 0;
2827 if (!MONO_HANDLE_IS_NULL (raw_symbol_store
)) {
2828 symbol_len
= mono_array_handle_length (raw_symbol_store
);
2829 raw_symbol_data
= (mono_byte
*) MONO_ARRAY_HANDLE_PIN (raw_symbol_store
, mono_byte
, 0, &symbol_gchandle
);
2832 ass
= mono_alc_load_raw_bytes (alc
, assembly_data
, raw_assembly_len
, raw_symbol_data
, symbol_len
, refonly
, error
);
2833 mono_gchandle_free_internal (symbol_gchandle
);
2834 goto_if_nok (error
, leave
);
2836 refass
= mono_assembly_get_object_handle (domain
, ass
, error
);
2837 if (!MONO_HANDLE_IS_NULL (refass
))
2838 MONO_HANDLE_SET (refass
, evidence
, evidence
);
2843 #endif /* ENABLE_NETCORE */
2845 static MonoAssembly
*
2846 mono_alc_load_raw_bytes (MonoAssemblyLoadContext
*alc
, guint8
*assembly_data
, guint32 raw_assembly_len
, guint8
*raw_symbol_data
, guint32 raw_symbol_len
, gboolean refonly
, MonoError
*error
)
2848 MonoAssembly
*ass
= NULL
;
2849 MonoImageOpenStatus status
;
2850 MonoImage
*image
= mono_image_open_from_data_internal (alc
, (char*)assembly_data
, raw_assembly_len
, FALSE
, NULL
, refonly
, FALSE
, NULL
);
2853 mono_error_set_bad_image_by_name (error
, "In memory assembly", "0x%p", assembly_data
);
2857 if (raw_symbol_data
)
2858 mono_debug_open_image_from_memory (image
, raw_symbol_data
, raw_symbol_len
);
2860 MonoAssembly
* redirected_asm
= NULL
;
2861 MonoImageOpenStatus new_status
= MONO_IMAGE_OK
;
2862 // http://blogs.microsoft.co.il/sasha/2010/06/09/assemblyreflectiononlyload-ignores-assembly-binding-redirects/
2863 if (!refonly
&& (redirected_asm
= mono_assembly_binding_applies_to_image (alc
, image
, &new_status
))) {
2864 mono_image_close (image
);
2865 image
= redirected_asm
->image
;
2866 mono_image_addref (image
); /* so that mono_image close, below, has something to do */
2867 } else if (new_status
!= MONO_IMAGE_OK
) {
2868 mono_image_close (image
);
2869 mono_error_set_bad_image_by_name (error
, "In Memory assembly", "0x%p was assembly binding redirected to another assembly that failed to load", assembly_data
);
2873 MonoAssemblyLoadRequest req
;
2874 mono_assembly_request_prepare_load (&req
, refonly
? MONO_ASMCTX_REFONLY
: MONO_ASMCTX_INDIVIDUAL
, alc
);
2875 ass
= mono_assembly_request_load_from (image
, "", &req
, &status
);
2878 mono_image_close (image
);
2879 mono_error_set_bad_image_by_name (error
, "In Memory assembly", "0x%p", assembly_data
);
2883 /* Clear the reference added by mono_image_open_from_data_internal above */
2884 mono_image_close (image
);
2889 #ifndef ENABLE_NETCORE
2890 MonoReflectionAssemblyHandle
2891 ves_icall_System_AppDomain_LoadAssembly (MonoAppDomainHandle ad
, MonoStringHandle assRef
, MonoObjectHandle evidence
, MonoBoolean refOnly
, MonoStackCrawlMark
*stack_mark
, MonoError
*error
)
2893 MonoDomain
*domain
= MONO_HANDLE_GETVAL (ad
, data
);
2894 MonoImageOpenStatus status
= MONO_IMAGE_OK
;
2896 MonoAssemblyName aname
;
2900 g_assert (!MONO_HANDLE_IS_NULL (assRef
));
2902 name
= mono_string_handle_to_utf8 (assRef
, error
);
2903 goto_if_nok (error
, fail
);
2904 parsed
= mono_assembly_name_parse (name
, &aname
);
2908 MonoReflectionAssemblyHandle refass
= MONO_HANDLE_CAST (MonoReflectionAssembly
, NULL_HANDLE
);
2909 /* This is a parse error... */
2911 MonoAssembly
*assm
= mono_try_assembly_resolve_handle (mono_domain_default_alc (domain
), assRef
, NULL
, refOnly
, error
);
2912 goto_if_nok (error
, fail
);
2914 refass
= mono_assembly_get_object_handle (domain
, assm
, error
);
2915 goto_if_nok (error
, fail
);
2921 MonoAssemblyContextKind asmctx
;
2922 asmctx
= refOnly
? MONO_ASMCTX_REFONLY
: MONO_ASMCTX_DEFAULT
;
2923 const char *basedir
;
2926 /* Determine if the current assembly is in LoadFrom context.
2927 * If it is, we must include the executing assembly's basedir
2928 * when probing for the given assembly name, and also load the
2929 * requested assembly in LoadFrom context.
2931 MonoAssembly
*executing_assembly
= mono_runtime_get_caller_from_stack_mark (stack_mark
);
2932 if (executing_assembly
&& mono_asmctx_get_kind (&executing_assembly
->context
) == MONO_ASMCTX_LOADFROM
) {
2933 asmctx
= MONO_ASMCTX_LOADFROM
;
2934 basedir
= executing_assembly
->basedir
;
2939 MonoAssemblyByNameRequest req
;
2940 mono_assembly_request_prepare_byname (&req
, asmctx
, mono_domain_default_alc (domain
));
2941 req
.basedir
= basedir
;
2942 req
.no_postload_search
= TRUE
;
2943 ass
= mono_assembly_request_byname (&aname
, &req
, &status
);
2944 mono_assembly_name_free_internal (&aname
);
2947 /* MS.NET doesn't seem to call the assembly resolve handler for refonly assemblies */
2949 ass
= mono_try_assembly_resolve_handle (mono_domain_default_alc (domain
), assRef
, NULL
, refOnly
, error
);
2950 goto_if_nok (error
, fail
);
2957 MonoReflectionAssemblyHandle refass
;
2958 refass
= mono_assembly_get_object_handle (domain
, ass
, error
);
2959 goto_if_nok (error
, fail
);
2961 MONO_HANDLE_SET (refass
, evidence
, evidence
);
2965 return MONO_HANDLE_CAST (MonoReflectionAssembly
, NULL_HANDLE
);
2969 ves_icall_System_AppDomain_InternalUnload (gint32 domain_id
, MonoError
*error
)
2971 MonoDomain
* domain
= mono_domain_get_by_id (domain_id
);
2973 if (NULL
== domain
) {
2974 mono_error_set_execution_engine (error
, "Failed to unload domain, domain id not found");
2978 if (domain
== mono_get_root_domain ()) {
2979 mono_error_set_generic_error (error
, "System", "CannotUnloadAppDomainException", "The default appdomain can not be unloaded.");
2984 * Unloading seems to cause problems when running NUnit/NAnt, hence
2987 if (g_hasenv ("MONO_NO_UNLOAD"))
2990 MonoException
*exc
= NULL
;
2991 mono_domain_try_unload (domain
, (MonoObject
**)&exc
);
2993 mono_error_set_exception_instance (error
, exc
);
2997 ves_icall_System_AppDomain_InternalIsFinalizingForUnload (gint32 domain_id
, MonoError
*error
)
2999 MonoDomain
*domain
= mono_domain_get_by_id (domain_id
);
3004 return mono_domain_is_unloading (domain
);
3008 ves_icall_System_AppDomain_DoUnhandledException (MonoAppDomainHandle ad
, MonoExceptionHandle exc
, MonoError
*error
)
3010 mono_unhandled_exception_checked (MONO_HANDLE_CAST (MonoObject
, exc
), error
);
3011 mono_error_assert_ok (error
);
3015 ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomainHandle ad
,
3016 MonoReflectionAssemblyHandle refass
, MonoArrayHandle args
,
3022 g_assert (!MONO_HANDLE_IS_NULL (refass
));
3023 MonoAssembly
*assembly
= MONO_HANDLE_GETVAL (refass
, assembly
);
3024 image
= assembly
->image
;
3027 method
= mono_get_method_checked (image
, mono_image_get_entry_point (image
), NULL
, NULL
, error
);
3030 g_error ("No entry point method found in %s due to %s", image
->name
, mono_error_get_message (error
));
3032 if (MONO_HANDLE_IS_NULL (args
)) {
3033 MonoDomain
*domain
= MONO_HANDLE_GETVAL (ad
, data
);
3034 MONO_HANDLE_ASSIGN (args
, mono_array_new_handle (domain
, mono_defaults
.string_class
, 0, error
));
3035 mono_error_assert_ok (error
);
3038 int res
= mono_runtime_exec_main_checked (method
, MONO_HANDLE_RAW (args
), error
);
3043 ves_icall_System_AppDomain_InternalSetDomain (MonoAppDomainHandle ad
, MonoError
* error
)
3046 MonoDomain
*old_domain
= mono_domain_get ();
3048 if (!mono_domain_set_fast (MONO_HANDLE_GETVAL (ad
, data
), FALSE
)) {
3049 mono_error_set_appdomain_unloaded (error
);
3050 return MONO_HANDLE_CAST (MonoAppDomain
, NULL_HANDLE
);
3053 return MONO_HANDLE_NEW (MonoAppDomain
, old_domain
->domain
);
3057 ves_icall_System_AppDomain_InternalSetDomainByID (gint32 domainid
, MonoError
*error
)
3059 MonoDomain
*current_domain
= mono_domain_get ();
3060 MonoDomain
*domain
= mono_domain_get_by_id (domainid
);
3062 if (!domain
|| !mono_domain_set_fast (domain
, FALSE
)) {
3063 mono_error_set_appdomain_unloaded (error
);
3064 return MONO_HANDLE_CAST (MonoAppDomain
, NULL_HANDLE
);
3067 return MONO_HANDLE_NEW (MonoAppDomain
, current_domain
->domain
);
3071 ves_icall_System_AppDomain_InternalPushDomainRef (MonoAppDomainHandle ad
, MonoError
*error
)
3074 mono_thread_push_appdomain_ref (MONO_HANDLE_GETVAL (ad
, data
));
3078 ves_icall_System_AppDomain_InternalPushDomainRefByID (gint32 domain_id
, MonoError
*error
)
3081 MonoDomain
*domain
= mono_domain_get_by_id (domain_id
);
3085 * Raise an exception to prevent the managed code from executing a pop
3088 mono_error_set_appdomain_unloaded (error
);
3092 mono_thread_push_appdomain_ref (domain
);
3096 ves_icall_System_AppDomain_InternalPopDomainRef (MonoError
*error
)
3099 mono_thread_pop_appdomain_ref ();
3102 MonoAppContextHandle
3103 ves_icall_System_AppDomain_InternalGetContext (MonoError
*error
)
3106 return mono_context_get_handle ();
3109 MonoAppContextHandle
3110 ves_icall_System_AppDomain_InternalGetDefaultContext (MonoError
*error
)
3113 return MONO_HANDLE_NEW (MonoAppContext
, mono_domain_get ()->default_context
);
3116 MonoAppContextHandle
3117 ves_icall_System_AppDomain_InternalSetContext (MonoAppContextHandle mc
, MonoError
*error
)
3120 MonoAppContextHandle old_context
= mono_context_get_handle ();
3122 mono_context_set_handle (mc
);
3128 ves_icall_System_AppDomain_InternalGetProcessGuid (MonoStringHandle newguid
, MonoError
*error
)
3131 MonoDomain
* mono_root_domain
= mono_get_root_domain ();
3132 mono_domain_lock (mono_root_domain
);
3133 if (process_guid_set
) {
3134 mono_domain_unlock (mono_root_domain
);
3135 return mono_string_new_utf16_handle (mono_domain_get (), process_guid
, sizeof(process_guid
)/2, error
);
3137 uint32_t gchandle
= mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject
, newguid
), TRUE
);
3138 memcpy (process_guid
, mono_string_chars_internal (MONO_HANDLE_RAW (newguid
)), sizeof(process_guid
));
3139 mono_gchandle_free_internal (gchandle
);
3140 process_guid_set
= TRUE
;
3141 mono_domain_unlock (mono_root_domain
);
3147 * mono_domain_is_unloading:
3150 mono_domain_is_unloading (MonoDomain
*domain
)
3152 if (domain
->state
== MONO_APPDOMAIN_UNLOADING
|| domain
->state
== MONO_APPDOMAIN_UNLOADED
)
3158 #ifndef ENABLE_NETCORE
3161 clear_cached_vtable (MonoVTable
*vtable
)
3163 MonoClass
*klass
= vtable
->klass
;
3164 MonoDomain
*domain
= vtable
->domain
;
3165 MonoClassRuntimeInfo
*runtime_info
;
3168 runtime_info
= m_class_get_runtime_info (klass
);
3169 if (runtime_info
&& runtime_info
->max_domain
>= domain
->domain_id
)
3170 runtime_info
->domain_vtables
[domain
->domain_id
] = NULL
;
3171 if (m_class_has_static_refs (klass
) && (data
= mono_vtable_get_static_field_data (vtable
)))
3172 mono_gc_free_fixed (data
);
3175 static G_GNUC_UNUSED
void
3176 zero_static_data (MonoVTable
*vtable
)
3178 MonoClass
*klass
= vtable
->klass
;
3181 if (m_class_has_static_refs (klass
) && (data
= mono_vtable_get_static_field_data (vtable
)))
3182 mono_gc_bzero_aligned (data
, mono_class_data_size (klass
));
3185 typedef struct unload_data
{
3188 char *failure_reason
;
3193 unload_data_unref (unload_data
*data
)
3199 mono_atomic_load_acquire (count
, gint32
, &data
->refcount
);
3200 g_assert (count
>= 1 && count
<= 2);
3205 } while (mono_atomic_cas_i32 (&data
->refcount
, count
- 1, count
) != count
);
3209 deregister_reflection_info_roots_from_list (MonoImage
*image
)
3211 GSList
*list
= image
->reflection_info_unregister_classes
;
3214 MonoClass
*klass
= (MonoClass
*)list
->data
;
3216 mono_class_free_ref_info (klass
);
3221 image
->reflection_info_unregister_classes
= NULL
;
3225 deregister_reflection_info_roots (MonoDomain
*domain
)
3229 mono_domain_assemblies_lock (domain
);
3230 for (list
= domain
->domain_assemblies
; list
; list
= list
->next
) {
3231 MonoAssembly
*assembly
= (MonoAssembly
*)list
->data
;
3232 MonoImage
*image
= assembly
->image
;
3236 * No need to take the image lock here since dynamic images are appdomain bound and
3237 * at this point the mutator is gone. Taking the image lock here would mean
3238 * promoting it from a simple lock to a complex lock, which we better avoid if
3241 if (image_is_dynamic (image
))
3242 deregister_reflection_info_roots_from_list (image
);
3244 for (i
= 0; i
< image
->module_count
; ++i
) {
3245 MonoImage
*module
= image
->modules
[i
];
3246 if (module
&& image_is_dynamic (module
))
3247 deregister_reflection_info_roots_from_list (module
);
3250 mono_domain_assemblies_unlock (domain
);
3254 unload_thread_main (void *arg
)
3256 unload_data
*data
= (unload_data
*)arg
;
3257 MonoDomain
*domain
= data
->domain
;
3259 gsize result
= 1; // failure
3261 mono_thread_set_name_constant_ignore_error (mono_thread_internal_current (), "Domain unloader", MonoSetThreadNameFlag_Permanent
);
3264 * FIXME: Abort our parent thread last, so we can return a failure
3265 * indication if aborting times out.
3267 if (!mono_threads_abort_appdomain_threads (domain
, -1)) {
3268 data
->failure_reason
= g_strdup_printf ("Aborting of threads in domain %s timed out.", domain
->friendly_name
);
3272 if (!mono_threadpool_remove_domain_jobs (domain
, -1)) {
3273 data
->failure_reason
= g_strdup_printf ("Cleanup of threadpool jobs of domain %s timed out.", domain
->friendly_name
);
3277 /* Finalize all finalizable objects in the doomed appdomain */
3278 if (!mono_domain_finalize (domain
, -1)) {
3279 data
->failure_reason
= g_strdup_printf ("Finalization of domain %s timed out.", domain
->friendly_name
);
3283 /* Clear references to our vtables in class->runtime_info.
3284 * We also hold the loader lock because we're going to change
3285 * class->runtime_info.
3288 mono_loader_lock ();
3289 mono_domain_lock (domain
);
3291 * We need to make sure that we don't have any remsets
3292 * pointing into static data of the to-be-freed domain because
3293 * at the next collections they would be invalid. So what we
3294 * do is we first zero all static data and then do a minor
3295 * collection. Because all references in the static data will
3296 * now be null we won't do any unnecessary copies and after
3297 * the collection there won't be any more remsets.
3299 for (i
= 0; i
< domain
->class_vtable_array
->len
; ++i
)
3300 zero_static_data ((MonoVTable
*)g_ptr_array_index (domain
->class_vtable_array
, i
));
3301 mono_gc_collect (0);
3302 for (i
= 0; i
< domain
->class_vtable_array
->len
; ++i
)
3303 clear_cached_vtable ((MonoVTable
*)g_ptr_array_index (domain
->class_vtable_array
, i
));
3304 deregister_reflection_info_roots (domain
);
3306 mono_assembly_cleanup_domain_bindings (domain
->domain_id
);
3308 mono_domain_unlock (domain
);
3309 mono_loader_unlock ();
3311 domain
->state
= MONO_APPDOMAIN_UNLOADED
;
3313 /* printf ("UNLOADED %s.\n", domain->friendly_name); */
3315 /* remove from the handle table the items related to this domain */
3316 mono_gchandle_free_domain (domain
);
3318 mono_domain_free (domain
, FALSE
);
3320 mono_gc_collect (mono_gc_max_generation ());
3322 result
= 0; // success
3324 mono_atomic_store_release (&data
->done
, TRUE
);
3325 unload_data_unref (data
);
3334 * mono_domain_unload:
3335 * \param domain The domain to unload
3337 * Unloads an appdomain. Follows the process outlined in the comment
3338 * for \c mono_domain_try_unload.
3341 mono_domain_unload (MonoDomain
*domain
)
3343 MONO_ENTER_GC_UNSAFE
;
3344 MonoObject
*exc
= NULL
;
3345 mono_domain_try_unload (domain
, &exc
);
3346 MONO_EXIT_GC_UNSAFE
;
3349 static MonoThreadInfoWaitRet
3350 guarded_wait (MonoThreadHandle
*thread_handle
, guint32 timeout
, gboolean alertable
)
3352 MonoThreadInfoWaitRet result
;
3355 result
= mono_thread_info_wait_one_handle (thread_handle
, timeout
, alertable
);
3362 * mono_domain_unload:
3363 * \param domain The domain to unload
3364 * \param exc Exception information
3366 * Unloads an appdomain. Follows the process outlined in:
3367 * http://blogs.gotdotnet.com/cbrumme
3369 * If doing things the 'right' way is too hard or complex, we do it the
3370 * 'simple' way, which means do everything needed to avoid crashes and
3371 * memory leaks, but not much else.
3373 * It is required to pass a valid reference to the exc argument, upon return
3374 * from this function *exc will be set to the exception thrown, if any.
3376 * If this method is not called from an icall (embedded scenario for instance),
3377 * it must not be called with any managed frames on the stack, since the unload
3378 * process could end up trying to abort the current thread.
3381 mono_domain_try_unload (MonoDomain
*domain
, MonoObject
**exc
)
3383 HANDLE_FUNCTION_ENTER ();
3385 MonoThreadHandle
*thread_handle
= NULL
;
3386 MonoAppDomainState prev_state
;
3388 unload_data
*thread_data
= NULL
;
3389 MonoInternalThreadHandle internal
;
3390 MonoDomain
*caller_domain
= mono_domain_get ();
3392 /* printf ("UNLOAD STARTING FOR %s (%p) IN THREAD 0x%x.\n", domain->friendly_name, domain, mono_native_thread_id_get ()); */
3394 /* Atomically change our state to UNLOADING */
3395 prev_state
= (MonoAppDomainState
)mono_atomic_cas_i32 ((gint32
*)&domain
->state
,
3396 MONO_APPDOMAIN_UNLOADING_START
,
3397 MONO_APPDOMAIN_CREATED
);
3398 if (prev_state
!= MONO_APPDOMAIN_CREATED
) {
3399 switch (prev_state
) {
3400 case MONO_APPDOMAIN_UNLOADING_START
:
3401 case MONO_APPDOMAIN_UNLOADING
:
3402 *exc
= (MonoObject
*) mono_get_exception_cannot_unload_appdomain ("Appdomain is already being unloaded.");
3404 case MONO_APPDOMAIN_UNLOADED
:
3405 *exc
= (MonoObject
*) mono_get_exception_cannot_unload_appdomain ("Appdomain is already unloaded.");
3408 g_warning ("Invalid appdomain state %d", prev_state
);
3409 g_assert_not_reached ();
3413 mono_domain_set_fast (domain
, FALSE
);
3414 /* Notify OnDomainUnload listeners */
3415 method
= mono_class_get_method_from_name_checked (domain
->domain
->mbr
.obj
.vtable
->klass
, "DoDomainUnload", -1, 0, error
);
3418 mono_runtime_try_invoke (method
, domain
->domain
, NULL
, exc
, error
);
3420 if (!is_ok (error
)) {
3422 mono_error_cleanup (error
);
3424 *exc
= (MonoObject
*)mono_error_convert_to_exception (error
);
3428 /* Roll back the state change */
3429 domain
->state
= MONO_APPDOMAIN_CREATED
;
3430 mono_domain_set_fast (caller_domain
, FALSE
);
3433 mono_domain_set_fast (caller_domain
, FALSE
);
3435 thread_data
= g_new0 (unload_data
, 1);
3436 thread_data
->domain
= domain
;
3437 thread_data
->failure_reason
= NULL
;
3438 thread_data
->done
= FALSE
;
3439 thread_data
->refcount
= 2; /*Must be 2: unload thread + initiator */
3441 /*The managed callback finished successfully, now we start tearing down the appdomain*/
3442 domain
->state
= MONO_APPDOMAIN_UNLOADING
;
3444 * First we create a separate thread for unloading, since
3445 * we might have to abort some threads, including the current one.
3447 * Have to attach to the runtime so shutdown can wait for this thread.
3449 * Force it to be attached to avoid racing during shutdown.
3451 internal
= mono_thread_create_internal_handle (mono_get_root_domain (), unload_thread_main
, thread_data
, MONO_THREAD_CREATE_FLAGS_FORCE_CREATE
, error
);
3452 mono_error_assert_ok (error
);
3454 thread_handle
= mono_threads_open_thread_handle (MONO_HANDLE_GETVAL (internal
, handle
));
3456 /* Wait for the thread */
3457 while (!thread_data
->done
&& guarded_wait (thread_handle
, MONO_INFINITE_WAIT
, TRUE
) == MONO_THREAD_INFO_WAIT_RET_ALERTED
) {
3458 if (mono_thread_internal_has_appdomain_ref (mono_thread_internal_current (), domain
) && (mono_thread_interruption_requested ())) {
3459 /* The unload thread tries to abort us */
3460 /* The icall wrapper will execute the abort */
3465 if (thread_data
->failure_reason
) {
3466 /* Roll back the state change */
3467 domain
->state
= MONO_APPDOMAIN_CREATED
;
3469 g_warning ("%s", thread_data
->failure_reason
);
3471 *exc
= (MonoObject
*) mono_get_exception_cannot_unload_appdomain (thread_data
->failure_reason
);
3473 g_free (thread_data
->failure_reason
);
3474 thread_data
->failure_reason
= NULL
;
3478 mono_threads_close_thread_handle (thread_handle
);
3479 unload_data_unref (thread_data
);
3480 HANDLE_FUNCTION_RETURN ();
3483 #endif /* ENABLE_NETCORE */
3485 #ifdef ENABLE_NETCORE
3487 /* Remember properties so they can be be installed in AppContext during runtime init */
3489 mono_runtime_register_appctx_properties (int nprops
, const char **keys
, const char **values
)
3491 n_appctx_props
= nprops
;
3492 appctx_keys
= g_new0 (gunichar2
*, nprops
);
3493 appctx_values
= g_new0 (gunichar2
*, nprops
);
3495 for (int i
= 0; i
< nprops
; ++i
) {
3496 appctx_keys
[i
] = g_utf8_to_utf16 (keys
[i
], strlen (keys
[i
]), NULL
, NULL
, NULL
);
3497 appctx_values
[i
] = g_utf8_to_utf16 (values
[i
], strlen (values
[i
]), NULL
, NULL
, NULL
);
3501 static GENERATE_GET_CLASS_WITH_CACHE (appctx
, "System", "AppContext")
3503 /* Install properties into AppContext */
3505 mono_runtime_install_appctx_properties (void)
3510 MonoMethod
*setup
= mono_class_get_method_from_name_checked (mono_class_get_appctx_class (), "Setup", 3, 0, error
);
3513 // FIXME: TRUSTED_PLATFORM_ASSEMBLIES is very large
3515 /* internal static unsafe void Setup(char** pNames, char** pValues, int count) */
3516 args
[0] = appctx_keys
;
3517 args
[1] = appctx_values
;
3518 args
[2] = &n_appctx_props
;
3520 mono_runtime_invoke_checked (setup
, NULL
, args
, error
);
3521 mono_error_assert_ok (error
);
3523 /* No longer needed */
3524 for (int i
= 0; i
< n_appctx_props
; ++i
) {
3525 g_free (appctx_keys
[i
]);
3526 g_free (appctx_values
[i
]);
3528 g_free (appctx_keys
);
3529 g_free (appctx_values
);
3531 appctx_values
= NULL
;