- 
                Notifications
    You must be signed in to change notification settings 
- Fork 5.2k
Fix handling exceptions from native code when interpreted #121212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Fix handling exceptions from native code when interpreted #121212
Conversation
There were two issues. One is that the SfiNextWorker was incorrectly advancing the stack frame iterator in case the interpreter was called from CallDescrWorker in some cases. The second was that the call to MethodDesc::GetMethodDescOfVirtualizedCode that is made by the InterpExecMethod can end up running managed code and throw managed exception. So it needs to have PAL_TRY/PAL_EXCEPT around the invocation, since the main loop of the interpreter can only catch and process C++ exceptions.
| Tagging subscribers to this area: @BrzVlad, @janvorli, @kg | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR improves exception handling in the CoreCLR interpreter by:
- Wrapping calls to GetMethodDescOfVirtualizedCodein a new helper function that properly handles both C++ and managed exceptions
- Refining the stack frame iteration logic to correctly distinguish between managed and native callers during exception unwinding
Key changes:
- Introduces CallGetMethodDescOfVirtualizedCodewrapper function for proper exception handling
- Updates virtual call and delegate invocation sites to use the new wrapper
- Improves exception handling logic to check if return addresses point to managed code before advancing the stack frame iterator
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description | 
|---|---|
| src/coreclr/vm/interpexec.cpp | Adds CallGetMethodDescOfVirtualizedCodewrapper function and updates two call sites to use it for proper exception handling | 
| src/coreclr/vm/exceptionhandling.cpp | Refines stack frame unwinding logic to properly distinguish managed from native callers using ExecutionManager::IsManagedCode | 
| // The caller is a managed code, so we can update the regdisplay to point to it. | ||
| pInterpreterFrame->UpdateRegDisplay(pThis->m_crawl.GetRegisterSet(), /* updateFloats */ true); | ||
| } | ||
| // The caller of the interpreted code is a managed code | 
    
      
    
      Copilot
AI
    
    
    
      Oct 30, 2025 
    
  
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment should say 'is managed code' rather than 'is a managed code' for consistency with line 3985.
| // The caller of the interpreted code is a managed code | |
| // The caller of the interpreted code is managed code | 
| if (ExecutionManager::IsManagedCode(returnAddress)) | ||
| { | ||
| // The caller is a managed code, so we can update the regdisplay to point to it. | ||
| pInterpreterFrame->UpdateRegDisplay(pThis->m_crawl.GetRegisterSet(), /* updateFloats */ true); | ||
| } | ||
| // The caller of the interpreted code is a managed code | ||
| retVal = pThis->Next(); | ||
| _ASSERTE(retVal != SWA_FAILED); | ||
| _ASSERTE(pThis->GetFrameState() == StackFrameIterator::SFITER_FRAMELESS_METHOD); | ||
| isNativeTransition = false; | 
    
      
    
      Copilot
AI
    
    
    
      Oct 30, 2025 
    
  
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment at line 3977 should explain why we call Next() when the caller is managed code, to clarify that we're advancing to the managed caller frame. Consider expanding: 'The caller of the interpreted code is managed code, so advance to that frame.'
There were two issues. One is that the
SfiNextWorkerwas incorrectly advancing the stack frame iterator in case the interpreter was called fromCallDescrWorkerInternalin some cases.The second was that the call to
MethodDesc::GetMethodDescOfVirtualizedCodethat is made by theInterpExecMethodcan end up running managed code and throw managed exception. So it needs to have PAL_TRY/PAL_EXCEPT around the invocation, since the main loop of the interpreter can only catch and process C++ exceptions.This fixes the
Loader\classloader\regressions\vsw529206\vsw529206ModuleCctortest.