Skip to content

Commit

Permalink
[mono] More domain cleanups (#50479)
Browse files Browse the repository at this point in the history
* [mono] More domain cleanups.

* [mono] Move the storage of the loaded assemblies list to assembly-load-context.c.

Add a mono_alc_get_all_loaded_assemblies () helper function to return a
array of all the loaded assemblies. Use this instead of accessing
domain->loaded_assemblies directly.

* [mono] Move externally called domain related API functions to external-only.c.

* [mono] Simplify the domain creation code since there is only one domain.

* Remove domain argument from mono_domain_assembly_open_internal ().

* [mono] Make mono_domain_foreach () external only.

* Fix the build.

* [mono] Remove more unused 'domain' arguments.

Move functions from appdomain.c to more assembly-load-context.c/
extern-only.c.
  • Loading branch information
vargaz committed Apr 6, 2021
1 parent 856c879 commit 12edbc0
Show file tree
Hide file tree
Showing 20 changed files with 637 additions and 878 deletions.
351 changes: 4 additions & 347 deletions src/mono/mono/metadata/appdomain.c

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions src/mono/mono/metadata/appdomain.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,13 @@ mono_domain_set_config (MonoDomain *domain, const char *base_dir, const char *co
MONO_API MonoDomain *
mono_domain_get (void);

MONO_API MonoDomain *
MONO_API MONO_RT_EXTERNAL_ONLY MonoDomain *
mono_domain_get_by_id (int32_t domainid);

MONO_API int32_t
MONO_API MONO_RT_EXTERNAL_ONLY int32_t
mono_domain_get_id (MonoDomain *domain);

MONO_API const char *
MONO_API MONO_RT_EXTERNAL_ONLY const char *
mono_domain_get_friendly_name (MonoDomain *domain);

MONO_API MONO_RT_EXTERNAL_ONLY mono_bool
Expand All @@ -91,16 +91,16 @@ mono_domain_set_internal (MonoDomain *domain);
MONO_API MONO_RT_EXTERNAL_ONLY void
mono_domain_unload (MonoDomain *domain);

MONO_API void
MONO_API MONO_RT_EXTERNAL_ONLY void
mono_domain_try_unload (MonoDomain *domain, MonoObject **exc);

MONO_API mono_bool
MONO_API MONO_RT_EXTERNAL_ONLY mono_bool
mono_domain_is_unloading (MonoDomain *domain);

MONO_API MONO_RT_EXTERNAL_ONLY MonoDomain *
mono_domain_from_appdomain (MonoAppDomain *appdomain);

MONO_API void
MONO_API MONO_RT_EXTERNAL_ONLY void
mono_domain_foreach (MonoDomainFunc func, void* user_data);

MONO_API MONO_RT_EXTERNAL_ONLY MonoAssembly *
Expand All @@ -112,7 +112,7 @@ mono_domain_ensure_entry_assembly (MonoDomain *domain, MonoAssembly *assembly);
MONO_API MONO_RT_EXTERNAL_ONLY mono_bool
mono_domain_finalize (MonoDomain *domain, uint32_t timeout);

MONO_API void
MONO_API MONO_RT_EXTERNAL_ONLY void
mono_domain_free (MonoDomain *domain, mono_bool force);

MONO_API mono_bool
Expand All @@ -130,13 +130,13 @@ mono_context_init (MonoDomain *domain);
MONO_API MONO_RT_EXTERNAL_ONLY void
mono_context_set (MonoAppContext *new_context);

MONO_API MonoAppContext *
MONO_API MONO_RT_EXTERNAL_ONLY MonoAppContext *
mono_context_get (void);

MONO_API int32_t
MONO_API MONO_RT_EXTERNAL_ONLY int32_t
mono_context_get_id (MonoAppContext *context);

MONO_API int32_t
MONO_API MONO_RT_EXTERNAL_ONLY int32_t
mono_context_get_domain_id (MonoAppContext *context);

MONO_API MonoJitInfo *
Expand Down
221 changes: 215 additions & 6 deletions src/mono/mono/metadata/assembly-load-context.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,25 @@
#include "mono/utils/mono-compiler.h"

#include "mono/metadata/assembly.h"
#include "mono/metadata/assembly-internals.h"
#include "mono/metadata/domain-internals.h"
#include "mono/metadata/exception-internals.h"
#include "mono/metadata/icall-decl.h"
#include "mono/metadata/loader-internals.h"
#include "mono/metadata/loaded-images-internals.h"
#include "mono/metadata/mono-private-unstable.h"
#include "mono/metadata/mono-debug.h"
#include "mono/utils/mono-error-internals.h"
#include "mono/utils/mono-logger-internals.h"

GENERATE_GET_CLASS_WITH_CACHE (assembly_load_context, "System.Runtime.Loader", "AssemblyLoadContext");
static GENERATE_GET_CLASS_WITH_CACHE (assembly, "System.Reflection", "Assembly");

static GSList *alcs;
static MonoAssemblyLoadContext *default_alc;
static MonoCoopMutex alc_list_lock; /* Used when accessing 'alcs' */
/* Protected by alc_list_lock */
static GSList *loaded_assemblies;

static inline void
alcs_lock (void)
Expand Down Expand Up @@ -92,17 +97,18 @@ mono_alc_cleanup_assemblies (MonoAssemblyLoadContext *alc)
// The minimum refcount on assemblies is 2: one for the domain and one for the ALC.
// The domain refcount might be less than optimal on netcore, but its removal is too likely to cause issues for now.
GSList *tmp;
MonoDomain *domain = mono_get_root_domain ();

// Remove the assemblies from domain_assemblies
mono_domain_assemblies_lock (domain);
// Remove the assemblies from loaded_assemblies
for (tmp = alc->loaded_assemblies; tmp; tmp = tmp->next) {
MonoAssembly *assembly = (MonoAssembly *)tmp->data;
domain->domain_assemblies = g_slist_remove (domain->domain_assemblies, assembly);

alcs_lock ();
loaded_assemblies = g_slist_remove (loaded_assemblies, assembly);
alcs_unlock ();

mono_assembly_decref (assembly);
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Unloading ALC [%p], removing assembly %s[%p] from domain_assemblies, ref_count=%d\n", alc, assembly->aname.name, assembly, assembly->ref_count);
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Unloading ALC [%p], removing assembly %s[%p] from loaded_assemblies, ref_count=%d\n", alc, assembly->aname.name, assembly, assembly->ref_count);
}
mono_domain_assemblies_unlock (domain);

// Release the GC roots
for (tmp = alc->loaded_assemblies; tmp; tmp = tmp->next) {
Expand Down Expand Up @@ -262,6 +268,135 @@ ves_icall_System_Runtime_Loader_AssemblyLoadContext_GetLoadContextForAssembly (M
return (gpointer)alc->gchandle;
}

static gboolean
add_assembly_to_array (MonoArrayHandle dest, int dest_idx, MonoAssembly* assm, MonoError *error)
{
HANDLE_FUNCTION_ENTER ();
error_init (error);
MonoReflectionAssemblyHandle assm_obj = mono_assembly_get_object_handle (assm, error);
goto_if_nok (error, leave);
MONO_HANDLE_ARRAY_SETREF (dest, dest_idx, assm_obj);
leave:
HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
}

MonoArrayHandle
ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalGetLoadedAssemblies (MonoError *error)
{
GPtrArray *assemblies = mono_alc_get_all_loaded_assemblies ();

MonoArrayHandle res = mono_array_new_handle (mono_class_get_assembly_class (), assemblies->len, error);
goto_if_nok (error, leave);
for (int i = 0; i < assemblies->len; ++i) {
if (!add_assembly_to_array (res, i, (MonoAssembly *)g_ptr_array_index (assemblies, i), error))
goto leave;
}

leave:
g_ptr_array_free (assemblies, TRUE);
return res;
}

static
MonoAssembly *
mono_alc_load_file (MonoAssemblyLoadContext *alc, MonoStringHandle fname, MonoAssembly *executing_assembly, MonoAssemblyContextKind asmctx, MonoError *error)
{
MonoAssembly *ass = NULL;
HANDLE_FUNCTION_ENTER ();
char *filename = NULL;
if (MONO_HANDLE_IS_NULL (fname)) {
mono_error_set_argument_null (error, "assemblyFile", "");
goto leave;
}

filename = mono_string_handle_to_utf8 (fname, error);
goto_if_nok (error, leave);

if (!g_path_is_absolute (filename)) {
mono_error_set_argument (error, "assemblyFile", "Absolute path information is required.");
goto leave;
}

MonoImageOpenStatus status;
MonoAssemblyOpenRequest req;
mono_assembly_request_prepare_open (&req, asmctx, alc);
req.requesting_assembly = executing_assembly;
ass = mono_assembly_request_open (filename, &req, &status);
if (!ass) {
if (status == MONO_IMAGE_IMAGE_INVALID)
mono_error_set_bad_image_by_name (error, filename, "Invalid Image: %s", filename);
else
mono_error_set_simple_file_not_found (error, filename);
}

leave:
g_free (filename);
HANDLE_FUNCTION_RETURN_VAL (ass);
}

MonoReflectionAssemblyHandle
ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalLoadFile (gpointer alc_ptr, MonoStringHandle fname, MonoStackCrawlMark *stack_mark, MonoError *error)
{
MonoReflectionAssemblyHandle result = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
MonoAssemblyLoadContext *alc = (MonoAssemblyLoadContext *)alc_ptr;

MonoAssembly *executing_assembly;
executing_assembly = mono_runtime_get_caller_from_stack_mark (stack_mark);
MonoAssembly *ass = mono_alc_load_file (alc, fname, executing_assembly, mono_alc_is_default (alc) ? MONO_ASMCTX_LOADFROM : MONO_ASMCTX_INDIVIDUAL, error);
goto_if_nok (error, leave);

result = mono_assembly_get_object_handle (ass, error);

leave:
return result;
}

static MonoAssembly*
mono_alc_load_raw_bytes (MonoAssemblyLoadContext *alc, guint8 *assembly_data, guint32 raw_assembly_len, guint8 *raw_symbol_data, guint32 raw_symbol_len, MonoError *error)
{
MonoAssembly *ass = NULL;
MonoImageOpenStatus status;
MonoImage *image = mono_image_open_from_data_internal (alc, (char*)assembly_data, raw_assembly_len, TRUE, NULL, FALSE, NULL, NULL);

if (!image) {
mono_error_set_bad_image_by_name (error, "In memory assembly", "0x%p", assembly_data);
return ass;
}

if (raw_symbol_data)
mono_debug_open_image_from_memory (image, raw_symbol_data, raw_symbol_len);

MonoAssemblyLoadRequest req;
mono_assembly_request_prepare_load (&req, MONO_ASMCTX_INDIVIDUAL, alc);
ass = mono_assembly_request_load_from (image, "", &req, &status);

if (!ass) {
mono_image_close (image);
mono_error_set_bad_image_by_name (error, "In Memory assembly", "0x%p", assembly_data);
return ass;
}

/* Clear the reference added by mono_image_open_from_data_internal above */
mono_image_close (image);

return ass;
}

MonoReflectionAssemblyHandle
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)
{
MonoAssemblyLoadContext *alc = (MonoAssemblyLoadContext *)native_alc;
MonoReflectionAssemblyHandle result = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
MonoAssembly *assm = NULL;
assm = mono_alc_load_raw_bytes (alc, (guint8 *)raw_assembly_ptr, raw_assembly_len, (guint8 *)raw_symbols_ptr, raw_symbols_len, error);
goto_if_nok (error, leave);

result = mono_assembly_get_object_handle (assm, error);

leave:
return result;
}

gboolean
mono_alc_is_default (MonoAssemblyLoadContext *alc)
{
Expand Down Expand Up @@ -420,3 +555,77 @@ mono_alc_invoke_resolve_using_resolve_satellite_nofail (MonoAssemblyLoadContext

return result;
}

void
mono_alc_add_assembly (MonoAssemblyLoadContext *alc, MonoAssembly *ass)
{
GSList *tmp;

g_assert (ass);

if (!ass->aname.name)
return;

mono_alc_assemblies_lock (alc);
for (tmp = alc->loaded_assemblies; tmp; tmp = tmp->next) {
if (tmp->data == ass) {
mono_alc_assemblies_unlock (alc);
return;
}
}

mono_assembly_addref (ass);
// Prepending here will break the test suite with frequent InvalidCastExceptions, so we have to append
alc->loaded_assemblies = g_slist_append (alc->loaded_assemblies, ass);
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly %s[%p] added to ALC (%p), ref_count=%d", ass->aname.name, ass, (gpointer)alc, ass->ref_count);
mono_alc_assemblies_unlock (alc);

alcs_lock ();
loaded_assemblies = g_slist_append (loaded_assemblies, ass);
alcs_unlock ();
}

MonoAssembly*
mono_alc_find_assembly (MonoAssemblyLoadContext *alc, MonoAssemblyName *aname)
{
GSList *tmp;
MonoAssembly *ass;

const MonoAssemblyNameEqFlags eq_flags = MONO_ANAME_EQ_IGNORE_PUBKEY | MONO_ANAME_EQ_IGNORE_VERSION | MONO_ANAME_EQ_IGNORE_CASE;

mono_alc_assemblies_lock (alc);
for (tmp = alc->loaded_assemblies; tmp; tmp = tmp->next) {
ass = (MonoAssembly *)tmp->data;
g_assert (ass != NULL);
// FIXME: Can dynamic assemblies match here for netcore?
if (assembly_is_dynamic (ass) || !mono_assembly_names_equal_flags (aname, &ass->aname, eq_flags))
continue;

mono_alc_assemblies_unlock (alc);
return ass;
}
mono_alc_assemblies_unlock (alc);
return NULL;
}

/*
* mono_alc_get_all_loaded_assemblies:
*
* Return a list of loaded assemblies in all appdomains.
*/
GPtrArray*
mono_alc_get_all_loaded_assemblies (void)
{
GSList *tmp;
GPtrArray *assemblies;
MonoAssembly *ass;

assemblies = g_ptr_array_new ();
alcs_lock ();
for (tmp = loaded_assemblies; tmp; tmp = tmp->next) {
ass = (MonoAssembly *)tmp->data;
g_ptr_array_add (assemblies, ass);
}
alcs_unlock ();
return assemblies;
}
9 changes: 8 additions & 1 deletion src/mono/mono/metadata/class-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -1536,6 +1536,13 @@ m_field_get_offset (MonoClassField *field)
* the lifetime of the image/class/method.
*/

static inline MonoMemoryManager*
mono_mem_manager_get_ambient (void)
{
// FIXME: All callers should get a MemoryManager from their callers or context
return (MonoMemoryManager *)mono_alc_get_default ()->memory_manager;
}

static inline MonoMemoryManager*
m_image_get_mem_manager (MonoImage *image)
{
Expand Down Expand Up @@ -1582,7 +1589,7 @@ static inline MonoMemoryManager*
m_method_get_mem_manager (MonoMethod *method)
{
// FIXME:
return mono_domain_memory_manager (mono_get_root_domain ());
return (MonoMemoryManager *)mono_alc_get_default ()->memory_manager;
}

static inline void *
Expand Down
Loading

0 comments on commit 12edbc0

Please sign in to comment.