summaryrefslogtreecommitdiff
path: root/src/vm/stackwalk.cpp
diff options
context:
space:
mode:
authorJan Vorlicek <janvorli@microsoft.com>2016-03-07 23:17:10 +0100
committerJan Vorlicek <janvorli@microsoft.com>2016-03-08 22:02:08 +0100
commit76c2dfc6321bff28c90ac48b0f2ca5abb02abe72 (patch)
tree44661f96cd37868935b28216d60f5624f6f96091 /src/vm/stackwalk.cpp
parentdc64c3254c7c60d8b7965defa97db61f5fddfe87 (diff)
downloadcoreclr-76c2dfc6321bff28c90ac48b0f2ca5abb02abe72.tar.gz
coreclr-76c2dfc6321bff28c90ac48b0f2ca5abb02abe72.tar.bz2
coreclr-76c2dfc6321bff28c90ac48b0f2ca5abb02abe72.zip
Fix stack walking on Unix in case of finally
The issue is that the code in the StackFrameIterator::Filter that handles cases when a funclet frame that was already removed from the stack due to native frames unwinding works for catch funclets only and not for finally ones. The ExceptionTracker::GetCallerOfActualHandlingFrame is set for catch funclets only. To make it work for the finally funclets as well, we need to use information from the ExceptionTracker::m_EnclosingClauseInfoForGCReporting instead. There was also another problem in the Filter method that caused the function to spin in an infinite loop when a parent of a funclet was also a funclet. In such case, the code in the method rechecks the current frame but the special functionality to check the exception trackers data needs to be skipped for the recheck. And finally, when we find that the current frame was a parent of an unwound funclet from the evidence in the exception trackers, we also need to set the fSkippingFunclet.
Diffstat (limited to 'src/vm/stackwalk.cpp')
-rw-r--r--src/vm/stackwalk.cpp13
1 files changed, 8 insertions, 5 deletions
diff --git a/src/vm/stackwalk.cpp b/src/vm/stackwalk.cpp
index ec9acfbac2..a2eb2895b0 100644
--- a/src/vm/stackwalk.cpp
+++ b/src/vm/stackwalk.cpp
@@ -1689,8 +1689,6 @@ StackWalkAction StackFrameIterator::Filter(void)
ProcessFuncletsForGCReporting:
do
{
- fRecheckCurrentFrame = false;
-
// When enumerating GC references for "liveness" reporting, depending upon the architecture,
// the responsibility of who reports what varies:
//
@@ -1751,7 +1749,7 @@ ProcessFuncletsForGCReporting:
// only source of evidence about it.
// This is different from Windows where the full stack is preserved until an exception is fully handled
// and so we can detect it just from walking the stack.
- if (!fSkippingFunclet && (pTracker != NULL))
+ if (!fRecheckCurrentFrame && !fSkippingFunclet && (pTracker != NULL))
{
// The stack walker is not skipping frames now, which means it didn't find a funclet frame that
// would require skipping the current frame. If we find a tracker with caller of actual handling
@@ -1764,14 +1762,14 @@ ProcessFuncletsForGCReporting:
{
if (hasFuncletStarted)
{
- sfFuncletParent = pCurrTracker->GetCallerOfActualHandlingFrame();
+ sfFuncletParent = pCurrTracker->GetCallerOfEnclosingClause();
if (!sfFuncletParent.IsNull() && ExceptionTracker::IsUnwoundToTargetParentFrame(&m_crawl, sfFuncletParent))
{
break;
}
}
- sfFuncletParent = pCurrTracker->GetCallerOfCollapsedActualHandlingFrame();
+ sfFuncletParent = pCurrTracker->GetCallerOfCollapsedEnclosingClause();
if (!sfFuncletParent.IsNull() && ExceptionTracker::IsUnwoundToTargetParentFrame(&m_crawl, sfFuncletParent))
{
break;
@@ -1793,9 +1791,12 @@ ProcessFuncletsForGCReporting:
m_sfFuncletParent = sfFuncletParent;
m_fProcessNonFilterFunclet = true;
m_fDidFuncletReportGCReferences = false;
+ fSkippingFunclet = true;
}
}
#endif // FEATURE_PAL
+
+ fRecheckCurrentFrame = false;
// Do we already have a reference to a funclet parent?
if (!m_sfFuncletParent.IsNull())
{
@@ -2000,6 +2001,7 @@ ProcessFuncletsForGCReporting:
// Since we are in GC reference reporting mode,
// then avoid code duplication and go to
// funclet processing.
+ fRecheckCurrentFrame = true;
goto ProcessFuncletsForGCReporting;
}
}
@@ -2105,6 +2107,7 @@ ProcessFuncletsForGCReporting:
// If we are in GC reference reporting mode,
// then avoid code duplication and go to
// funclet processing.
+ fRecheckCurrentFrame = true;
goto ProcessFuncletsForGCReporting;
}
else