summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Vorlicek <janvorli@microsoft.com>2015-09-08 14:50:24 +0200
committerJan Vorlicek <janvorli@microsoft.com>2015-09-08 14:50:24 +0200
commit508454cc76e1bd35c07521ebfc73617c00c5bcb3 (patch)
tree5244f456977e118ad3e0d8ab6bfd1e48fa67dd41
parentf7552e5a5076b63d88886f9d4ec5c781508e307e (diff)
parent88cf961965911b21f26699ac35ad5223e6f4496a (diff)
downloadcoreclr-508454cc76e1bd35c07521ebfc73617c00c5bcb3.tar.gz
coreclr-508454cc76e1bd35c07521ebfc73617c00c5bcb3.tar.bz2
coreclr-508454cc76e1bd35c07521ebfc73617c00c5bcb3.zip
Merge pull request #1496 from janvorli/fix-exception-memleak
Fix memory leak from managed exceptions
-rw-r--r--src/pal/inc/pal.h19
-rw-r--r--src/pal/src/thread/thread.cpp6
-rw-r--r--src/vm/amd64/unixasmhelpers.S6
-rw-r--r--src/vm/exceptionhandling.cpp50
-rw-r--r--src/vm/exceptmacros.h11
5 files changed, 68 insertions, 24 deletions
diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h
index 5d8e56e0ef..43fc0694f5 100644
--- a/src/pal/inc/pal.h
+++ b/src/pal/inc/pal.h
@@ -6364,6 +6364,25 @@ public:
ExceptionRecord = *pExceptionRecord;
ContextRecord = *pContextRecord;
}
+
+ PAL_SEHException()
+ {
+ }
+
+ PAL_SEHException(const PAL_SEHException& ex)
+ {
+ *this = ex;
+ }
+
+ PAL_SEHException& operator=(const PAL_SEHException& ex)
+ {
+ ExceptionPointers.ExceptionRecord = &ExceptionRecord;
+ ExceptionPointers.ContextRecord = &ContextRecord;
+ ExceptionRecord = ex.ExceptionRecord;
+ ContextRecord = ex.ContextRecord;
+
+ return *this;
+ }
};
typedef VOID (PALAPI *PHARDWARE_EXCEPTION_HANDLER)(PAL_SEHException* ex);
diff --git a/src/pal/src/thread/thread.cpp b/src/pal/src/thread/thread.cpp
index 2c7b2388a8..33dbfbc914 100644
--- a/src/pal/src/thread/thread.cpp
+++ b/src/pal/src/thread/thread.cpp
@@ -2446,6 +2446,9 @@ PAL_GetStackBase()
status = pthread_attr_getstack(&attr, &stackAddr, &stackSize);
_ASSERT_MSG(status == 0, "pthread_attr_getstack call failed");
+ status = pthread_attr_destroy(&attr);
+ _ASSERT_MSG(status == 0, "pthread_attr_destroy call failed");
+
return (void*)((size_t)stackAddr + stackSize);
#endif
}
@@ -2480,6 +2483,9 @@ PAL_GetStackLimit()
status = pthread_attr_getstack(&attr, &stackAddr, &stackSize);
_ASSERT_MSG(status == 0, "pthread_attr_getstack call failed");
+
+ status = pthread_attr_destroy(&attr);
+ _ASSERT_MSG(status == 0, "pthread_attr_destroy call failed");
return stackAddr;
#endif
diff --git a/src/vm/amd64/unixasmhelpers.S b/src/vm/amd64/unixasmhelpers.S
index e3f4adc259..ccf552367c 100644
--- a/src/vm/amd64/unixasmhelpers.S
+++ b/src/vm/amd64/unixasmhelpers.S
@@ -291,7 +291,7 @@ LEAF_END SinglecastDelegateInvokeStub, _TEXT
// from the passed in context and finally sets the RSP to that frame and sets the return
// address to the target frame's RIP.
//
-// EXTERN_C void StartUnwindingNativeFrames(CONTEXT* context);
+// EXTERN_C void StartUnwindingNativeFrames(CONTEXT* context, PAL_SEHException* ex);
LEAF_ENTRY StartUnwindingNativeFrames, _TEXT
// Save the RBP to the stack so that the unwind can work at the instruction after
// loading the RBP from the context, but before loading the RSP from the context.
@@ -316,6 +316,8 @@ LEAF_ENTRY StartUnwindingNativeFrames, _TEXT
// Store return address to the stack
push_register rax
push_nonvol_reg rbp
- call EXTERNAL_C_FUNC(__cxa_rethrow)
+ // The PAL_SEHException pointer
+ mov rdi, rsi
+ call EXTERNAL_C_FUNC(ThrowExceptionHelper)
LEAF_END StartUnwindingNativeFrames, _TEXT
diff --git a/src/vm/exceptionhandling.cpp b/src/vm/exceptionhandling.cpp
index 5d5f3e61c0..982c3e06d5 100644
--- a/src/vm/exceptionhandling.cpp
+++ b/src/vm/exceptionhandling.cpp
@@ -3631,7 +3631,7 @@ ExceptionTracker* ExceptionTracker::GetOrCreateTracker(
fIsRethrow = true;
}
else
- if (pTracker->m_ptrs.ExceptionRecord != pExceptionRecord)
+ if ((pTracker->m_ptrs.ExceptionRecord != pExceptionRecord) && !fIsInterleavedHandling)
{
EH_LOG((LL_INFO100, ">>NEW exception (exception records do not match)\n"));
fCreateNewTracker = true;
@@ -4396,7 +4396,8 @@ bool IsSpInStackLimits(ULONG64 sp, ULONG64 stackLowAddress, ULONG64 stackHighAdd
//
// Arguments:
// context - context at which to start the native unwinding
-extern "C" void StartUnwindingNativeFrames(CONTEXT* context);
+// ex - pointer to the exception to use to unwind the native frames
+extern "C" void StartUnwindingNativeFrames(CONTEXT* context, PAL_SEHException* ex);
//---------------------------------------------------------------------------------------
//
@@ -4678,7 +4679,7 @@ VOID DECLSPEC_NORETURN UnwindManagedExceptionPass1(PAL_SEHException& ex)
// Now we need to unwind the native frames until we reach managed frames again or the exception is
// handled in the native code.
- StartUnwindingNativeFrames(&frameContext);
+ StartUnwindingNativeFrames(&frameContext, &ex);
UNREACHABLE();
}
@@ -4688,16 +4689,35 @@ VOID DECLSPEC_NORETURN UnwindManagedExceptionPass1(PAL_SEHException& ex)
EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
}
+//---------------------------------------------------------------------------------------
+//
+// Helper function to throw the passed in exception.
+// It is called from the assembler function StartUnwindingNativeFrames
+// Arguments:
+//
+// ex - the exception to throw.
+//
+extern "C"
+void ThrowExceptionHelper(PAL_SEHException* ex)
+{
+ throw *ex;
+}
+
VOID DECLSPEC_NORETURN DispatchManagedException(PAL_SEHException& ex)
{
- try
- {
- UnwindManagedExceptionPass1(ex);
- }
- catch (PAL_SEHException& ex)
+ do
{
- DispatchManagedException(ex);
+ try
+ {
+ UnwindManagedExceptionPass1(ex);
+ UNREACHABLE();
+ }
+ catch (PAL_SEHException& ex2)
+ {
+ ex = ex2;
+ }
}
+ while (true);
}
#ifdef _AMD64_
@@ -5064,17 +5084,7 @@ VOID PALAPI HandleHardwareException(PAL_SEHException* ex)
}
#endif //_AMD64_
- // We throw the exception and catch it right away so that in case the DispatchManagedException
- // needs to cross managed to native stack frames boundary, there is an exception that can
- // be rethrow in the StartUnwindingNativeFrames.
- try
- {
- throw *ex;
- }
- catch (PAL_SEHException& ex2)
- {
- DispatchManagedException(ex2);
- }
+ DispatchManagedException(*ex);
UNREACHABLE();
}
}
diff --git a/src/vm/exceptmacros.h b/src/vm/exceptmacros.h
index e712f217e7..3c426fd3bd 100644
--- a/src/vm/exceptmacros.h
+++ b/src/vm/exceptmacros.h
@@ -323,14 +323,21 @@ VOID DECLSPEC_NORETURN UnwindAndContinueRethrowHelperAfterCatch(Frame* pEntryFra
VOID DECLSPEC_NORETURN DispatchManagedException(PAL_SEHException& ex);
#define INSTALL_MANAGED_EXCEPTION_DISPATCHER \
- try { \
+ PAL_SEHException exCopy; \
+ bool hasCaughtException = false; \
+ try {
#define UNINSTALL_MANAGED_EXCEPTION_DISPATCHER \
} \
catch (PAL_SEHException& ex) \
{ \
- DispatchManagedException(ex); \
+ exCopy = ex; \
+ hasCaughtException = true; \
} \
+ if (hasCaughtException) \
+ { \
+ DispatchManagedException(exCopy); \
+ }
#else