diff --git a/src/coreclr/debug/ee/controller.cpp b/src/coreclr/debug/ee/controller.cpp index fd26e7fe3135dd..4e1736c96583ad 100644 --- a/src/coreclr/debug/ee/controller.cpp +++ b/src/coreclr/debug/ee/controller.cpp @@ -7410,7 +7410,15 @@ bool DebuggerStepper::TriggerSingleStep(Thread *thread, const BYTE *ip) if (!g_pEEInterface->IsManagedNativeCode(ip)) { LOG((LF_CORDB,LL_INFO10000, "DS::TSS: not in managed code, Returning false (case 0)!\n")); - DisableSingleStep(); + // Sometimes we can get here with a callstack that is coming from an APC + // this will disable the single stepping and incorrectly resume an app that the user + // is stepping through. +#ifdef FEATURE_THREAD_ACTIVATION + if ((thread->m_State & Thread::TS_DebugWillSync) == 0) +#endif + { + DisableSingleStep(); + } return false; } diff --git a/src/coreclr/vm/threadsuspend.cpp b/src/coreclr/vm/threadsuspend.cpp index 71f59672eba1c7..2ddc2c3b120c99 100644 --- a/src/coreclr/vm/threadsuspend.cpp +++ b/src/coreclr/vm/threadsuspend.cpp @@ -5746,8 +5746,9 @@ BOOL CheckActivationSafePoint(SIZE_T ip) Thread *pThread = GetThreadNULLOk(); // The criteria for safe activation is to be running managed code. - // Also we are not interested in handling interruption if we are already in preemptive mode. - BOOL isActivationSafePoint = pThread != NULL && + // Also we are not interested in handling interruption if we are already in preemptive mode nor if we are single stepping + BOOL isActivationSafePoint = pThread != NULL && + (pThread->m_StateNC & Thread::TSNC_DebuggerIsStepping) == 0 && pThread->PreemptiveGCDisabled() && ExecutionManager::IsManagedCode(ip); @@ -5932,7 +5933,12 @@ bool Thread::InjectActivation(ActivationReason reason) { return true; } - + // Avoid APC calls when the thread is in single step state to avoid any + // wrong resume because it's running a native code. + if ((m_StateNC & Thread::TSNC_DebuggerIsStepping) != 0) + { + return false; + } #ifdef FEATURE_SPECIAL_USER_MODE_APC _ASSERTE(UseSpecialUserModeApc());