Skip to content

Commit

Permalink
[coop] Check async suspend status in ReqSuspendInitSuspendBlocking case
Browse files Browse the repository at this point in the history
So the issue is that calling begin_suspend_for_blocking_thread under hybrid
suspend will perform a preemptive suspension of the victim thread.

The preemptive suspend doesn't always succeed.
In particular, thread_state_init_from_sigctx or thread_state_init_from_handle
could return FALSE and into->suspend_can_continue will be set to FALSE.
When the thread_state_init_* functions return FALSE, they also set the
MonoThreadUnwindState:valid to FALSE.

So it is important to check the value of MonoThreadInfo:suspend_can_continue
before proceeding with a suspension.

As a result in suspend_sync in the ReqSuspendInitSuspendRunning case we call
check_async_suspend which checks (for preemptively suspended threads) whethere
suspend_can_continue is true.  If it isn't, we resume the victim thread and
loop once more in suspend_sync_nolock and try again.

We didn't have a check_async_suspend call in the ReqSuspendInitSuspendBlocking
case, so a thread could be considered suspended even if we couldn't capture a
valid MonoThreadUnwindState for it.

That breaks the assertion the call to mono_thread_info_get_last_managed in
async_suspend_critical which needs a valid MonoThreadUnwindState.

Fixes mono#10031
  • Loading branch information
lambdageek authored and monojenkins committed Aug 16, 2018
1 parent d0e57fb commit 7e36adc
Showing 1 changed file with 7 additions and 0 deletions.
7 changes: 7 additions & 0 deletions mono/utils/mono-threads.c
Expand Up @@ -1140,6 +1140,13 @@ suspend_sync (MonoNativeThreadId tid, gboolean interrupt_kernel)
if (suspend_result != BeginSuspendOkNoWait)
mono_threads_wait_pending_operations ();

if (!check_async_suspend (info, suspend_result)) {
mono_thread_info_core_resume (info);
mono_threads_wait_pending_operations ();
mono_hazard_pointer_clear (hp, 1);
return NULL;
}

// if we tried to preempt the thread already, do nothing.
// otherwise (if it's running in blocking mode) try to abort the syscall.
if (interrupt_kernel && !did_interrupt)
Expand Down

0 comments on commit 7e36adc

Please sign in to comment.