Skip to content

Commit b833f6f

Browse files
committed
Fix reverse pinvoke with domain unloading (case 1304163)
Problem: Unattached thread makes reverse pinvoke call into managed code in non-root domain. When domain is unloaded, if the thread has not exited then the thread remains 'attached' and unloading hangs. Solution: This is similar to what we do in mono_unity_thread_fast_attach and mono_unity_thread_fast_detach. Always attach threads initially to the root domain. Then set current thread domain to requested domain and push a reference (mono_thread_push_appdomain_ref). When exiting the reverese pinvoke, set the domain back to previous domain (root) and pop the reference for that thread to the appdomain. This allows native threads to outlive domains they ran code in.
1 parent 741c859 commit b833f6f

File tree

1 file changed

+7
-3
lines changed

1 file changed

+7
-3
lines changed

mono/mini/mini-runtime.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -849,15 +849,17 @@ mono_jit_thread_attach (MonoDomain *domain)
849849
attached = mono_tls_get_jit_tls () != NULL;
850850

851851
if (!attached) {
852-
mono_thread_attach (domain);
852+
mono_thread_attach (mono_get_root_domain ());
853853

854854
// #678164
855855
mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
856856
}
857857

858858
orig = mono_domain_get ();
859-
if (orig != domain)
859+
if (orig != domain) {
860+
mono_thread_push_appdomain_ref (domain);
860861
mono_domain_set (domain, TRUE);
862+
}
861863

862864
return orig != domain ? orig : NULL;
863865
}
@@ -872,8 +874,10 @@ mono_jit_set_domain (MonoDomain *domain)
872874
{
873875
g_assert (!mono_threads_is_blocking_transition_enabled ());
874876

875-
if (domain)
877+
if (domain) {
876878
mono_domain_set (domain, TRUE);
879+
mono_thread_pop_appdomain_ref ();
880+
}
877881
}
878882

879883
/**

0 commit comments

Comments
 (0)