From b003a22b90f34c7a64d57063a6ac9f41f633c95f Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Tue, 7 Jul 2026 23:39:21 +0200 Subject: [PATCH] Fix exception native to managed transition frame I've recently added an explicit frame to ProcessCLRException on Windows to properly handle case when exception transitions from native to managed code. However, the ResumableFrame I've used wasn't a good choice. This frame kind is meant for contexts where the execution can resume and more importantly, the context needs to be the context of the active method. This causes issues in some GC stress tests when a call return value is a managed reference reported to GC. This change replaces that frame by SoftwareException frame initialized from the context that OS passes to the ProcessCLRException. That fixes the problem, as such frame is no longer considered to reference the active managed frame. --- src/coreclr/vm/excep.cpp | 14 ++++++++++++++ src/coreclr/vm/exceptionhandling.cpp | 5 +++-- src/coreclr/vm/frames.h | 1 + 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index 46741b04604d01..1758528113b164 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -10330,6 +10330,20 @@ void SoftwareExceptionFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool u } #ifndef DACCESS_COMPILE + +void SoftwareExceptionFrame::SetContext(T_CONTEXT *pContext) +{ + LIMITED_METHOD_CONTRACT; + + m_Context = *pContext; + +#define CALLEE_SAVED_REGISTER(regname) m_ContextPointers.regname = &m_Context.regname; + ENUM_CALLEE_SAVED_REGISTERS(); +#undef CALLEE_SAVED_REGISTER + + m_ReturnAddress = ::GetIP(&m_Context); +} + #ifdef TARGET_X86 void SoftwareExceptionFrame::UpdateContextFromTransitionBlock(TransitionBlock *pTransitionBlock) diff --git a/src/coreclr/vm/exceptionhandling.cpp b/src/coreclr/vm/exceptionhandling.cpp index cacb59ebe46d5b..dd6cfe57b315a1 100644 --- a/src/coreclr/vm/exceptionhandling.cpp +++ b/src/coreclr/vm/exceptionhandling.cpp @@ -663,8 +663,9 @@ ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord, TADDR ssp = 0; #endif - ResumableFrame resFrame(pContextRecord); - resFrame.Push(pThread); + SoftwareExceptionFrame exceptionFrame; + exceptionFrame.SetContext(pContextRecord); + exceptionFrame.InitAndLink(pThread); OBJECTREF oref = ExInfo::CreateThrowable(pExceptionRecord, FALSE); INSTALL_RESUME_AFTER_CATCH_HANDLER_WITH_CONTEXT(pContextRecord, ssp); diff --git a/src/coreclr/vm/frames.h b/src/coreclr/vm/frames.h index b25ea276fb629d..dc1a954604369f 100644 --- a/src/coreclr/vm/frames.h +++ b/src/coreclr/vm/frames.h @@ -1061,6 +1061,7 @@ class SoftwareExceptionFrame : public Frame } void UpdateContextFromTransitionBlock(TransitionBlock *pTransitionBlock); + void SetContext(T_CONTEXT *pContext); #endif TADDR GetReturnAddressPtr_Impl()