[Loader] Change mono_trace level from info to debug (#19110)
[mono-project.git] / mono / metadata / assembly-load-context.c
blobdf7fe4fbd01ae9da9afc51a365da896faa84f9d7
1 #include "config.h"
2 #include "mono/utils/mono-compiler.h"
4 #ifdef ENABLE_NETCORE // MonoAssemblyLoadContext support only in netcore Mono
6 #include "mono/metadata/assembly.h"
7 #include "mono/metadata/domain-internals.h"
8 #include "mono/metadata/exception-internals.h"
9 #include "mono/metadata/icall-decl.h"
10 #include "mono/metadata/loader-internals.h"
11 #include "mono/metadata/loaded-images-internals.h"
12 #include "mono/utils/mono-error-internals.h"
13 #include "mono/utils/mono-logger-internals.h"
15 GENERATE_GET_CLASS_WITH_CACHE (assembly_load_context, "System.Runtime.Loader", "AssemblyLoadContext");
17 void
18 mono_alc_init (MonoAssemblyLoadContext *alc, MonoDomain *domain)
20 MonoLoadedImages *li = g_new0 (MonoLoadedImages, 1);
21 mono_loaded_images_init (li, alc);
22 alc->domain = domain;
23 alc->loaded_images = li;
24 alc->loaded_assemblies = NULL;
25 alc->pinvoke_scopes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
26 mono_coop_mutex_init (&alc->assemblies_lock);
27 mono_coop_mutex_init (&alc->pinvoke_lock);
30 void
31 mono_alc_cleanup (MonoAssemblyLoadContext *alc)
34 * As it stands, ALC and domain cleanup is probably broken on netcore. Without ALC collectability, this should not
35 * be hit. I've documented roughly the things that still need to be accomplish, but the implementation is TODO and
36 * the ideal order and locking unclear.
38 * For now, this makes two important assumptions:
39 * 1. The minimum refcount on assemblies is 2: one for the domain and one for the ALC. The domain refcount might
40 * be less than optimal on netcore, but its removal is too likely to cause issues for now.
41 * 2. An ALC will have been removed from the domain before cleanup.
43 //GSList *tmp;
44 //MonoDomain *domain = alc->domain;
47 * Missing steps:
49 * + Release GC roots for all assemblies in the ALC
50 * + Iterate over the domain_assemblies and remove ones that belong to the ALC, which will probably require
51 * converting domain_assemblies to a doubly-linked list, ideally GQueue
52 * + Close dynamic and then remaining assemblies, potentially nulling the data field depending on refcount
53 * + Second pass to call mono_assembly_close_finish on remaining assemblies
54 * + Free the loaded_assemblies list itself
57 alc->loaded_assemblies = NULL;
58 g_hash_table_destroy (alc->pinvoke_scopes);
59 mono_coop_mutex_destroy (&alc->assemblies_lock);
60 mono_coop_mutex_destroy (&alc->pinvoke_lock);
62 mono_loaded_images_free (alc->loaded_images);
64 g_assert_not_reached ();
67 void
68 mono_alc_assemblies_lock (MonoAssemblyLoadContext *alc)
70 mono_coop_mutex_lock (&alc->assemblies_lock);
73 void
74 mono_alc_assemblies_unlock (MonoAssemblyLoadContext *alc)
76 mono_coop_mutex_unlock (&alc->assemblies_lock);
79 gpointer
80 ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalInitializeNativeALC (gpointer this_gchandle_ptr, MonoBoolean is_default_alc, MonoBoolean collectible, MonoError *error)
82 /* If the ALC is collectible, this_gchandle is weak, otherwise it's strong. */
83 uint32_t this_gchandle = (uint32_t)GPOINTER_TO_UINT (this_gchandle_ptr);
84 if (collectible) {
85 mono_error_set_execution_engine (error, "Collectible AssemblyLoadContexts are not yet supported by MonoVM");
86 return NULL;
89 MonoDomain *domain = mono_domain_get ();
90 MonoAssemblyLoadContext *alc = NULL;
92 if (is_default_alc) {
93 alc = mono_domain_default_alc (domain);
94 g_assert (alc);
95 if (!alc->gchandle)
96 alc->gchandle = this_gchandle;
97 } else {
98 /* create it */
99 alc = mono_domain_create_individual_alc (domain, this_gchandle, collectible, error);
101 return alc;
104 gpointer
105 ves_icall_System_Runtime_Loader_AssemblyLoadContext_GetLoadContextForAssembly (MonoReflectionAssemblyHandle assm_obj, MonoError *error)
107 MonoAssembly *assm = MONO_HANDLE_GETVAL (assm_obj, assembly);
108 MonoAssemblyLoadContext *alc = mono_assembly_get_alc (assm);
110 return GUINT_TO_POINTER (alc->gchandle);
113 gboolean
114 mono_alc_is_default (MonoAssemblyLoadContext *alc)
116 return alc == mono_alc_domain (alc)->default_alc;
119 static MonoAssembly*
120 invoke_resolve_method (MonoMethod *resolve_method, MonoAssemblyLoadContext *alc, MonoAssemblyName *aname, MonoError *error)
122 MonoAssembly *result = NULL;
123 char* aname_str = NULL;
125 if (mono_runtime_get_no_exec ())
126 return NULL;
128 HANDLE_FUNCTION_ENTER ();
130 aname_str = mono_stringify_assembly_name (aname);
132 MonoStringHandle aname_obj = mono_string_new_handle (mono_alc_domain (alc), aname_str, error);
133 goto_if_nok (error, leave);
135 MonoReflectionAssemblyHandle assm;
136 gpointer gchandle;
137 gchandle = GUINT_TO_POINTER (alc->gchandle);
138 gpointer args [2];
139 args [0] = &gchandle;
140 args [1] = MONO_HANDLE_RAW (aname_obj);
141 assm = MONO_HANDLE_CAST (MonoReflectionAssembly, mono_runtime_try_invoke_handle (resolve_method, NULL_HANDLE, args, error));
142 goto_if_nok (error, leave);
144 if (MONO_HANDLE_BOOL (assm))
145 result = MONO_HANDLE_GETVAL (assm, assembly);
147 leave:
148 g_free (aname_str);
149 HANDLE_FUNCTION_RETURN_VAL (result);
152 static MonoAssembly*
153 mono_alc_invoke_resolve_using_load (MonoAssemblyLoadContext *alc, MonoAssemblyName *aname, MonoError *error)
155 MONO_STATIC_POINTER_INIT (MonoMethod, resolve)
157 ERROR_DECL (local_error);
158 MonoClass *alc_class = mono_class_get_assembly_load_context_class ();
159 g_assert (alc_class);
160 resolve = mono_class_get_method_from_name_checked (alc_class, "MonoResolveUsingLoad", -1, 0, local_error);
161 mono_error_assert_ok (local_error);
163 MONO_STATIC_POINTER_INIT_END (MonoMethod, resolve)
165 g_assert (resolve);
167 return invoke_resolve_method (resolve, alc, aname, error);
170 MonoAssembly*
171 mono_alc_invoke_resolve_using_load_nofail (MonoAssemblyLoadContext *alc, MonoAssemblyName *aname)
173 MonoAssembly *result = NULL;
174 ERROR_DECL (error);
176 result = mono_alc_invoke_resolve_using_load (alc, aname, error);
177 if (!is_ok (error))
178 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Error while invoking ALC Load(\"%s\") method: '%s'", aname->name, mono_error_get_message (error));
180 mono_error_cleanup (error);
182 return result;
185 static MonoAssembly*
186 mono_alc_invoke_resolve_using_resolving_event (MonoAssemblyLoadContext *alc, MonoAssemblyName *aname, MonoError *error)
188 MONO_STATIC_POINTER_INIT (MonoMethod, resolve)
190 ERROR_DECL (local_error);
191 MonoClass *alc_class = mono_class_get_assembly_load_context_class ();
192 g_assert (alc_class);
193 resolve = mono_class_get_method_from_name_checked (alc_class, "MonoResolveUsingResolvingEvent", -1, 0, local_error);
194 mono_error_assert_ok (local_error);
196 MONO_STATIC_POINTER_INIT_END (MonoMethod, resolve)
198 g_assert (resolve);
200 return invoke_resolve_method (resolve, alc, aname, error);
203 MonoAssembly*
204 mono_alc_invoke_resolve_using_resolving_event_nofail (MonoAssemblyLoadContext *alc, MonoAssemblyName *aname)
206 MonoAssembly *result = NULL;
207 ERROR_DECL (error);
209 result = mono_alc_invoke_resolve_using_resolving_event (alc, aname, error);
210 if (!is_ok (error))
211 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Error while invoking ALC Resolving(\"%s\") event: '%s'", aname->name, mono_error_get_message (error));
213 mono_error_cleanup (error);
215 return result;
218 static MonoAssembly*
219 mono_alc_invoke_resolve_using_resolve_satellite (MonoAssemblyLoadContext *alc, MonoAssemblyName *aname, MonoError *error)
221 MONO_STATIC_POINTER_INIT (MonoMethod, resolve)
223 ERROR_DECL (local_error);
224 MonoClass *alc_class = mono_class_get_assembly_load_context_class ();
225 g_assert (alc_class);
226 resolve = mono_class_get_method_from_name_checked (alc_class, "MonoResolveUsingResolveSatelliteAssembly", -1, 0, local_error);
227 mono_error_assert_ok (local_error);
229 MONO_STATIC_POINTER_INIT_END (MonoMethod, resolve)
231 g_assert (resolve);
233 return invoke_resolve_method (resolve, alc, aname, error);
236 MonoAssembly*
237 mono_alc_invoke_resolve_using_resolve_satellite_nofail (MonoAssemblyLoadContext *alc, MonoAssemblyName *aname)
239 MonoAssembly *result = NULL;
240 ERROR_DECL (error);
242 result = mono_alc_invoke_resolve_using_resolve_satellite (alc, aname, error);
243 if (!is_ok (error))
244 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Error while invoking ALC ResolveSatelliteAssembly(\"%s\") method: '%s'", aname->name, mono_error_get_message (error));
246 mono_error_cleanup (error);
248 return result;
251 #endif /* ENABLE_NETCORE */
253 MONO_EMPTY_SOURCE_FILE (assembly_load_context)