When embedders call mono_runtime_quit or mono_jit_cleanup, we need to do unbalanced transitions to GC Unsafe, because after mini_cleanup runs we don't have GC thread states anymore and MONO_EXIT_GC_UNSAFE will assert.
* [runtime] Do an unbalanced GC Unsafe transition in mono_jit_cleanup
After mini_cleanup, we don't have GC thread states anymore because all that
stuff was cleaned up, so MONO_EXIT_GC_UNSAFE would assert
* [runtime] Mark mono_runtime_quit external only.
Runtime should use mono_runtime_quit_internal.
After we call the quit_function (aka mini_cleanup) we don't have any GC thread
states anymore because all that stuff got cleaned up. So MONO_EXIT_GC_UNSAFE
can't work.
Commit migrated from https://github.com/mono/mono/commit/
0e3caf00df54199be88cfcb53ed847226defebb4
* mono_runtime_quit:
*/
void
-mono_runtime_quit ()
+mono_runtime_quit (void)
{
+ MONO_STACKDATA (dummy);
+ (void) mono_threads_enter_gc_unsafe_region_unbalanced_internal (&dummy);
+ // after quit_function (in particular, mini_cleanup) everything is
+ // cleaned up so MONO_EXIT_GC_UNSAFE can't work and doesn't make sense.
+
+ mono_runtime_quit_internal ();
+}
+
+/**
+ * mono_runtime_quit_internal:
+ */
+void
+mono_runtime_quit_internal (void)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+ // but note that when we return, we're not in GC Unsafe mode anymore.
+ // After clean up threads don't _have_ a thread state anymore.
+
if (quit_function != NULL)
quit_function (mono_get_root_domain (), NULL);
}
MONO_API void
mono_install_runtime_cleanup (MonoDomainFunc func);
-MONO_API void
+MONO_API MONO_RT_EXTERNAL_ONLY void
mono_runtime_quit (void);
MONO_API void
if (error) {
g_free (error);
g_free (file_name);
- mono_runtime_quit ();
+ mono_runtime_quit_internal ();
return FALSE;
}
g_free (corlib_version_error);
g_free (file_name);
MessageBox (NULL, L"Corlib not in sync with this runtime.", NULL, MB_ICONERROR);
- mono_runtime_quit ();
+ mono_runtime_quit_internal ();
ExitProcess (1);
}
if (!assembly) {
g_free (file_name);
MessageBox (NULL, L"Cannot open assembly.", NULL, MB_ICONERROR);
- mono_runtime_quit ();
+ mono_runtime_quit_internal ();
ExitProcess (1);
}
if (!entry) {
g_free (file_name);
MessageBox (NULL, L"Assembly doesn't have an entry point.", NULL, MB_ICONERROR);
- mono_runtime_quit ();
+ mono_runtime_quit_internal ();
ExitProcess (1);
}
g_free (file_name);
mono_error_cleanup (error); /* FIXME don't swallow the error */
MessageBox (NULL, L"The entry point method could not be loaded.", NULL, MB_ICONERROR);
- mono_runtime_quit ();
+ mono_runtime_quit_internal ();
ExitProcess (1);
}
mono_error_raise_exception_deprecated (error); /* OK, triggers unhandled exn handler */
mono_thread_manage_internal ();
- mono_runtime_quit ();
+ mono_runtime_quit_internal ();
/* return does not terminate the process. */
ExitProcess (mono_environment_exitcode_get ());
if (mono_get_root_domain () && !mono_runtime_is_shutting_down ()) {
mono_runtime_set_shutting_down ();
mono_thread_suspend_all_other_threads ();
- mono_runtime_quit ();
+ mono_runtime_quit_internal ();
}
#endif
ExitProcess (exitCode);
void
mono_install_free_domain_hook (MonoFreeDomainFunc func);
+void
+mono_runtime_quit_internal (void);
+
void
mono_cleanup (void);
mono_thread_suspend_all_other_threads ();
#endif
- mono_runtime_quit ();
+ mono_runtime_quit_internal ();
/* we may need to do some cleanup here... */
exit (result);
/*TODO move the follow to here:
mono_thread_suspend_all_other_threads (); OR mono_thread_wait_all_other_threads
- mono_runtime_quit ();
+ mono_runtime_quit_internal ();
*/
return TRUE;
mono_thread_suspend_all_other_threads ();
#endif
DEBUG_PRINTF (1, "Shutting down the runtime...\n");
- mono_runtime_quit ();
+ mono_runtime_quit_internal ();
transport_close2 ();
DEBUG_PRINTF (1, "Exiting...\n");
void
mono_jit_cleanup (MonoDomain *domain)
{
- MONO_ENTER_GC_UNSAFE;
+ MONO_STACKDATA (dummy);
+ (void) mono_threads_enter_gc_unsafe_region_unbalanced_internal (&dummy);
+
+ // after mini_cleanup everything is cleaned up so MONO_EXIT_GC_UNSAFE
+ // can't work and doesn't make sense.
+
mono_thread_manage_internal ();
mini_cleanup (domain);
- MONO_EXIT_GC_UNSAFE;
+
}
void