Skip to content

Commit

Permalink
Fix the race condition issue of aot_module loading (#104918)
Browse files Browse the repository at this point in the history
  • Loading branch information
fanyang-mono authored Jul 23, 2024
1 parent 096dafb commit 9b9f7ed
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 22 deletions.
6 changes: 3 additions & 3 deletions src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,7 @@ get_module_event_data (
module_data->module_flags = MODULE_FLAGS_MANIFEST_MODULE;
if (image && image->dynamic)
module_data->module_flags |= MODULE_FLAGS_DYNAMIC_MODULE;
if (image && image->aot_module)
if (image && image->aot_module && (image->aot_module != AOT_MODULE_NOT_FOUND))
module_data->module_flags |= MODULE_FLAGS_NATIVE_MODULE;

module_data->module_il_path = NULL;
Expand Down Expand Up @@ -905,7 +905,7 @@ fire_assembly_events (
if (assembly->dynamic)
assembly_flags |= ASSEMBLY_FLAGS_DYNAMIC_ASSEMBLY;

if (assembly->image && assembly->image->aot_module) {
if (assembly->image && assembly->image->aot_module && (assembly->image->aot_module != AOT_MODULE_NOT_FOUND)) {
assembly_flags |= ASSEMBLY_FLAGS_NATIVE_ASSEMBLY;
}

Expand Down Expand Up @@ -2154,7 +2154,7 @@ get_assembly_event_data (
if (assembly->dynamic)
assembly_data->assembly_flags |= ASSEMBLY_FLAGS_DYNAMIC_ASSEMBLY;

if (assembly->image && assembly->image->aot_module)
if (assembly->image && assembly->image->aot_module && (assembly->image->aot_module != AOT_MODULE_NOT_FOUND))
assembly_data->assembly_flags |= ASSEMBLY_FLAGS_NATIVE_ASSEMBLY;

assembly_data->assembly_name = mono_stringify_assembly_name (&assembly->aname);
Expand Down
58 changes: 41 additions & 17 deletions src/mono/mono/mini/aot-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -1795,7 +1795,7 @@ init_amodule_got (MonoAotModule *amodule, gboolean preinit)
if (mono_defaults.corlib) {
MonoAotModule *mscorlib_amodule = mono_defaults.corlib->aot_module;

if (mscorlib_amodule)
if (mscorlib_amodule && (mscorlib_amodule != AOT_MODULE_NOT_FOUND))
amodule->shared_got [i] = mscorlib_amodule->got;
} else {
amodule->shared_got [i] = amodule->got;
Expand Down Expand Up @@ -2053,6 +2053,7 @@ load_aot_module (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, gpointer
g_free (aot_name);
}
#endif
assembly->image->aot_module = AOT_MODULE_NOT_FOUND;
return;
}
}
Expand Down Expand Up @@ -2104,7 +2105,7 @@ load_aot_module (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, gpointer
mono_dl_close (sofile, close_error);
mono_error_cleanup (close_error);
}
assembly->image->aot_module = NULL;
assembly->image->aot_module = AOT_MODULE_NOT_FOUND;
return;
}

Expand Down Expand Up @@ -2487,7 +2488,7 @@ load_container_amodule (MonoAssemblyLoadContext *alc)

load_aot_module(alc, assm, NULL, error);
mono_memory_barrier ();
g_assert (assm->image->aot_module);
g_assert (assm->image->aot_module && (assm->image->aot_module != AOT_MODULE_NOT_FOUND));
container_amodule = assm->image->aot_module;
}

Expand Down Expand Up @@ -2561,7 +2562,7 @@ mono_aot_get_method_from_vt_slot (MonoVTable *vtable, int slot, MonoError *error

error_init (error);

if (MONO_CLASS_IS_INTERFACE_INTERNAL (klass) || m_class_get_rank (klass) || !amodule)
if (MONO_CLASS_IS_INTERFACE_INTERNAL (klass) || m_class_get_rank (klass) || !amodule || (amodule == AOT_MODULE_NOT_FOUND))
return NULL;

info = &amodule->blob [mono_aot_get_offset (amodule->class_info_offsets, mono_metadata_token_index (m_class_get_type_token (klass)) - 1)];
Expand Down Expand Up @@ -2597,7 +2598,7 @@ mono_aot_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
guint8 *p;
gboolean err;

if (m_class_get_rank (klass) || !m_class_get_type_token (klass) || !amodule)
if (m_class_get_rank (klass) || !m_class_get_type_token (klass) || !amodule || (amodule == AOT_MODULE_NOT_FOUND))
return FALSE;

p = (guint8*)&amodule->blob [mono_aot_get_offset (amodule->class_info_offsets, mono_metadata_token_index (m_class_get_type_token (klass)) - 1)];
Expand Down Expand Up @@ -2637,7 +2638,7 @@ mono_aot_get_class_from_name (MonoImage *image, const char *name_space, const ch
uint32_t debug_hash;
#endif

if (!amodule || !amodule->class_name_table)
if (!amodule || (amodule == AOT_MODULE_NOT_FOUND) || !amodule->class_name_table)
return FALSE;

amodule_lock (amodule);
Expand Down Expand Up @@ -2746,7 +2747,7 @@ mono_aot_get_weak_field_indexes (MonoImage *image)
{
MonoAotModule *amodule = image->aot_module;

if (!amodule)
if (!amodule || (amodule == AOT_MODULE_NOT_FOUND))
return NULL;

#if ENABLE_WEAK_ATTR
Expand Down Expand Up @@ -3437,7 +3438,7 @@ mono_aot_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len)
amodule = ji->d.aot_info;
else
amodule = m_class_get_image (jinfo_get_method (ji)->klass)->aot_module;
g_assert (amodule);
g_assert (amodule && (amodule != AOT_MODULE_NOT_FOUND));
g_assert (ji->from_aot);

if (!amodule_contains_code_addr (amodule, code)) {
Expand Down Expand Up @@ -3574,7 +3575,7 @@ mono_aot_find_jit_info (MonoImage *image, gpointer addr)
int methods_len;
gboolean async;

if (!amodule)
if (!amodule || (amodule == AOT_MODULE_NOT_FOUND))
return NULL;

addr = MINI_FTNPTR_TO_ADDR (addr);
Expand Down Expand Up @@ -4468,7 +4469,7 @@ find_aot_method_in_amodule (MonoAotModule *code_amodule, MonoMethod *method, gui
// the caching breaking. The solution seems to be to cache using the "metadata" amodule.
MonoAotModule *metadata_amodule = m_class_get_image (method->klass)->aot_module;

if (!metadata_amodule || metadata_amodule->out_of_date || !code_amodule || code_amodule->out_of_date)
if (!metadata_amodule || (metadata_amodule == AOT_MODULE_NOT_FOUND) || metadata_amodule->out_of_date || !code_amodule || code_amodule->out_of_date)
return 0xffffff;

table = code_amodule->extra_method_table;
Expand Down Expand Up @@ -4638,7 +4639,7 @@ find_aot_method (MonoMethod *method, MonoAotModule **out_amodule)

/* Try the method's module first */
*out_amodule = m_class_get_image (method->klass)->aot_module;
index = find_aot_method_in_amodule (m_class_get_image (method->klass)->aot_module, method, hash);
index = find_aot_method_in_amodule (*out_amodule, method, hash);
if (index != 0xffffff)
return index;

Expand Down Expand Up @@ -4873,14 +4874,37 @@ mono_aot_get_method (MonoMethod *method, MonoError *error)
MonoClass *klass = method->klass;
MonoMethod *orig_method = method;
guint32 method_index;
MonoAotModule *amodule = m_class_get_image (klass)->aot_module;
MonoImage *image = m_class_get_image (klass);

guint8 *code;
gboolean cache_result = FALSE;
ERROR_DECL (inner_error);

error_init (error);

if (!amodule)
if (!(image->aot_module)) {
// aot_module was uninitialized
MonoMethodHeader *header = mono_method_get_header_checked (method, inner_error);
mono_error_cleanup (inner_error);
if (!header) {
return NULL;
} else if (header->code_size != 0) {
return NULL;
} else {
// IL code for the method body doesn't exist. Try waiting for aot_module to be loaded probably by another thread
int count = 0;
while (!(image->aot_module) && (count < 10)) { // The threshold of count should never be removed to prevent deadlock.
g_usleep (100);
count++;
}
if (!(image->aot_module))
return NULL;
}
}

MonoAotModule *amodule = image->aot_module;

if (amodule == AOT_MODULE_NOT_FOUND)
return NULL;

if (amodule->out_of_date)
Expand Down Expand Up @@ -5094,7 +5118,7 @@ mono_aot_get_method_from_token (MonoImage *image, guint32 token, MonoError *erro

error_init (error);

if (!aot_module)
if (!aot_module || aot_module == AOT_MODULE_NOT_FOUND)
return NULL;

method_index = mono_metadata_token_index (token) - 1;
Expand Down Expand Up @@ -5596,7 +5620,7 @@ get_mscorlib_aot_module (void)
MonoAotModule *amodule;

image = mono_defaults.corlib;
if (image && image->aot_module)
if (image && image->aot_module && (image->aot_module != AOT_MODULE_NOT_FOUND))
amodule = image->aot_module;
else
amodule = mscorlib_aot_module;
Expand Down Expand Up @@ -6048,7 +6072,7 @@ ui16_idx_comparer (const void *key, const void *member)
static gboolean
aot_is_slim_amodule (MonoAotModule *amodule)
{
if (!amodule)
if (!amodule || amodule == AOT_MODULE_NOT_FOUND)
return FALSE;

/* "slim" only applies to mscorlib.dll */
Expand Down Expand Up @@ -6086,7 +6110,7 @@ mono_aot_get_unbox_trampoline (MonoMethod *method, gpointer addr)
} else
amodule = m_class_get_image (method->klass)->aot_module;

if (amodule == NULL || method_index == 0xffffff || aot_is_slim_amodule (amodule)) {
if (!amodule || amodule == AOT_MODULE_NOT_FOUND || method_index == 0xffffff || aot_is_slim_amodule (amodule)) {
/* couldn't find unbox trampoline specifically generated for that
* method. this should only happen when an unbox trampoline is needed
* for `fullAOT code -> native-to-interp -> interp` transition if
Expand Down
3 changes: 2 additions & 1 deletion src/mono/mono/mini/interp/transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -1231,7 +1231,8 @@ mono_interp_jit_call_supported (MonoMethod *method, MonoMethodSignature *sig)
if (!interp_jit_call_can_be_supported (method, sig, mono_llvm_only))
return FALSE;

if (mono_aot_only && m_class_get_image (method->klass)->aot_module && !(method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)) {
MonoAotModule *amodule = m_class_get_image (method->klass)->aot_module;
if (mono_aot_only && amodule && (amodule != AOT_MODULE_NOT_FOUND) && !(method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)) {
ERROR_DECL (error);
mono_class_init_internal (method->klass);
gpointer addr = mono_aot_get_method (method, error);
Expand Down
3 changes: 2 additions & 1 deletion src/mono/mono/mini/mini-amd64.c
Original file line number Diff line number Diff line change
Expand Up @@ -3034,7 +3034,8 @@ emit_call (MonoCompile *cfg, MonoCallInst *call, guint8 *code, MonoJitICallId ji

MonoMethod* const method = call->method;

if (m_class_get_image (method->klass)->aot_module)
MonoAotModule *amodule = m_class_get_image (method->klass)->aot_module;
if (amodule && (amodule != AOT_MODULE_NOT_FOUND))
/* The callee might be an AOT method */
near_call = FALSE;
if (method->dynamic)
Expand Down
2 changes: 2 additions & 0 deletions src/mono/mono/mini/mini.h
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,8 @@ struct MonoSpillInfo {
int offset;
};

#define AOT_MODULE_NOT_FOUND GINT_TO_POINTER (-1)

/*
* Information about a call site for the GC map creation code
*/
Expand Down

0 comments on commit 9b9f7ed

Please sign in to comment.