Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mono] fix two call get_default_jit_mm make hotreload work in non default alc #84247

Merged
merged 19 commits into from
Apr 23, 2023

Conversation

srxqds
Copy link
Contributor

@srxqds srxqds commented Apr 3, 2023

hi, we found if the code is not in default alc, it's not invalidate_transformed when metadata update

clear two places // FIXME: Enumerate all memory managers

@vargaz @lambdageek @lateralusX can you take time to reivew it?

the interp_jit_info_foreach will be called by ep-rt-mono.c

@ghost ghost added the community-contribution Indicates that the PR has been added by a community member label Apr 3, 2023
@srxqds srxqds changed the title [mono] fix two call get_default_jit_mm [mono] fix two call get_default_jit_mm make hotreload work in non default alc Apr 3, 2023
Copy link
Member

@lambdageek lambdageek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! This is definitly something we need to address, otherwise hot reload has no effect on methods in non-default ALCs.

The current PR introduces a lock order dependency between two low-level locks that I think will be fragile. It would be better if we could iterate over a copy of the ALCs list, while also having some way to prevent the individual ALCs from being collected until the iteration is done.

InterpJitInfoFuncUserData func_data;
func_data.func = func;
func_data.user_data = user_data;
mono_alc_foreach (interp_invalidate_transformed_func, &func_data);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo? should be interp_jit_info_foreach_func

jit_mm_lock (jit_mm);
mono_internal_hash_table_apply (&jit_mm->interp_code_hash, invalidate_transform, NULL);
jit_mm_unlock (jit_mm);
mono_alc_foreach (interp_invalidate_transformed_func, NULL);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will call interp_invalidate_transformed_func while holding the alc_list_lock

MonoAssemblyLoadContext* alc = (MonoAssemblyLoadContext*)data;
MonoJitMemoryManager *jit_mm = (MonoJitMemoryManager*)(alc->memory_manager->runtime_info);

jit_mm_lock (jit_mm);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When interp_invalidate_transformed_func is called, it will take the jit memory manager lock.

So we're implicitly introducing a lock order: alcs_list_lock > MonoMemoryManager:lock

Comment on lines 90 to 92
alcs_lock ();
g_slist_foreach (alcs, func, user_data);
alcs_unlock ();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like that this creates a lock ordering dependency between the jit memory manager locks and the alcs lock. It's not particularly obvious that those locks are related, so if another piece of code takes locks in a different order, we could get a classic deadlock.

What if mono_alc_foreach made a copy of the alcs list while holding the lock, and then called g_slist_foreach on the copy?

(And also we would need to protect each ALC, if it is collectible, from being collected while we're iterating)

@srxqds
Copy link
Contributor Author

srxqds commented Apr 3, 2023

@lambdageek hi, I have adjusted according to your comments, the only thing not did

while also having some way to prevent the individual ALCs from being collected until the iteration is done.

I found the alc is not cleanup now and other function like mono_alc_get_all_loaded_assemblies also not did this point.
I leave FIXME in mono_alc_get_all () function.

@srxqds
Copy link
Contributor Author

srxqds commented Apr 6, 2023

hi, can you review it again? @lambdageek

@srxqds
Copy link
Contributor Author

srxqds commented Apr 10, 2023

comment so you don't forget

@srxqds
Copy link
Contributor Author

srxqds commented Apr 21, 2023

hi, can this got merged or anything to adjust?

for (guint i = 0; i < alcs->len; ++i) {
alc = (MonoAssemblyLoadContext*)g_ptr_array_index (alcs, i);
MonoJitMemoryManager *jit_mm = (MonoJitMemoryManager*)(alc->memory_manager->runtime_info);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be:

MonoJitMemoryManager *jit_mm = jit_mm_for_mm (alc->memory_manager);

@vargaz
Copy link
Contributor

vargaz commented Apr 22, 2023

Why do we need to iterate over all ALCs ?

@srxqds
Copy link
Contributor Author

srxqds commented Apr 22, 2023

Why do we need to iterate over all ALCs ?

because the invalidate_transformed method should process all ALCs to make hotreload on non default ALC

@vargaz vargaz merged commit 0693424 into dotnet:main Apr 23, 2023
@ghost ghost locked as resolved and limited conversation to collaborators May 24, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-EnC-mono Hot Reload for WebAssembly, iOS/Android, etc community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants