diff --git a/mono/utils/mono-threads-coop.c b/mono/utils/mono-threads-coop.c index 7f2748536830..ed6b1807a3a2 100644 --- a/mono/utils/mono-threads-coop.c +++ b/mono/utils/mono-threads-coop.c @@ -288,6 +288,12 @@ mono_threads_exit_gc_safe_region_unbalanced (gpointer cookie, gpointer *stackdat default: g_error ("Unknown thread state"); } + + if (info->async_target) { + info->async_target (info->user_data); + info->async_target = NULL; + info->user_data = NULL; + } } void @@ -355,6 +361,12 @@ mono_threads_enter_gc_unsafe_region_unbalanced_with_info (MonoThreadInfo *info, g_error ("Unknown thread state"); } + if (info->async_target) { + info->async_target (info->user_data); + info->async_target = NULL; + info->user_data = NULL; + } + return info; } diff --git a/mono/utils/mono-threads.c b/mono/utils/mono-threads.c index b0e98d43f287..76821d0d3599 100644 --- a/mono/utils/mono-threads.c +++ b/mono/utils/mono-threads.c @@ -1005,8 +1005,12 @@ currently used only to deliver exceptions. void mono_thread_info_setup_async_call (MonoThreadInfo *info, void (*target_func)(void*), void *user_data) { - /* An async call can only be setup on an async suspended thread */ - g_assert (mono_thread_info_run_state (info) == STATE_ASYNC_SUSPENDED); + if (!mono_threads_is_coop_enabled ()) { + /* In non-coop mode, an async call can only be setup on an async suspended thread, but in coop mode, a thread + * may be in blocking state, and will execute the async call when leaving the safepoint, leaving a gc safe + * region or entering a gc unsafe region */ + g_assert (mono_thread_info_run_state (info) == STATE_ASYNC_SUSPENDED); + } /*FIXME this is a bad assert, we probably should do proper locking and fail if one is already set*/ g_assert (!info->async_target); info->async_target = target_func;