diff --git a/src/coreclr/debug/ee/controller.cpp b/src/coreclr/debug/ee/controller.cpp index 47b6e0b5a8134..544bc824aa0e0 100644 --- a/src/coreclr/debug/ee/controller.cpp +++ b/src/coreclr/debug/ee/controller.cpp @@ -7585,7 +7585,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 6bc046e2b40bd..505ceb174684f 100644 --- a/src/coreclr/vm/threadsuspend.cpp +++ b/src/coreclr/vm/threadsuspend.cpp @@ -5732,8 +5732,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); @@ -5918,7 +5919,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());