From ab6e8f65d4ff52f95485f9849fc8aec582ea1802 Mon Sep 17 00:00:00 2001 From: Konstantin Baladurin Date: Tue, 13 Feb 2018 15:56:58 +0300 Subject: [PATCH 1/3] CatchHardwareExceptionHolder: use GetCurrentPalThread instead of InternalGetCurrentThread in IsEnabled method. InternalGetCurrentThread tries to create pal thread if it doesn't exist for the current thread. It's unnecessary because in this case there are no hardware exception handlers for such thread. Also CatchHardwareExceptionHolder::IsEnable is called from signal handlers and during pal thread creation non-async-signal-safe function are called. --- src/pal/src/exception/seh.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pal/src/exception/seh.cpp b/src/pal/src/exception/seh.cpp index 9f5f074f1820..73d8ce505b13 100644 --- a/src/pal/src/exception/seh.cpp +++ b/src/pal/src/exception/seh.cpp @@ -344,8 +344,8 @@ CatchHardwareExceptionHolder::~CatchHardwareExceptionHolder() bool CatchHardwareExceptionHolder::IsEnabled() { - CPalThread *pThread = InternalGetCurrentThread(); - return pThread->IsHardwareExceptionsEnabled(); + CPalThread *pThread = GetCurrentPalThread(); + return pThread ? pThread->IsHardwareExceptionsEnabled() : false; } /*++ From fee4ab12ab62e7189390b0c56f8ae3b4e79dd6f4 Mon Sep 17 00:00:00 2001 From: Konstantin Baladurin Date: Tue, 13 Feb 2018 16:14:37 +0300 Subject: [PATCH 2/3] vm/threads: change tls model for gCurrentThreadInfo variable We should use initial-exec tls model to avoid memory allocations during first access to this variable because it may ocuur in signal handlers. --- src/vm/threads.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/threads.inl b/src/vm/threads.inl index f5a439c350b1..0a72d832926c 100644 --- a/src/vm/threads.inl +++ b/src/vm/threads.inl @@ -26,7 +26,7 @@ #ifndef __llvm__ EXTERN_C __declspec(thread) ThreadLocalInfo gCurrentThreadInfo; #else // !__llvm__ -EXTERN_C __thread ThreadLocalInfo gCurrentThreadInfo; +EXTERN_C __thread ThreadLocalInfo gCurrentThreadInfo __attribute__ ((tls_model("initial-exec"))); #endif // !__llvm__ EXTERN_C inline Thread* STDCALL GetThread() From 29ff424273e1c3989ded1545eb002d5acbce41ac Mon Sep 17 00:00:00 2001 From: Konstantin Baladurin Date: Tue, 13 Feb 2018 16:27:01 +0300 Subject: [PATCH 3/3] sigsegv_handler: handle case when it is called on original stack If sigsegv_handler is called on original stack (for example, if segmentation fault occurs in native application's thread that hasn't alternate signal stack) we should call common_signal_handler directly othersize sigsegv_handler's stackframe will be corrupted. --- src/pal/src/exception/signal.cpp | 38 ++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/pal/src/exception/signal.cpp b/src/pal/src/exception/signal.cpp index a27382315cd4..96dca507063f 100644 --- a/src/pal/src/exception/signal.cpp +++ b/src/pal/src/exception/signal.cpp @@ -477,23 +477,37 @@ static void sigsegv_handler(int code, siginfo_t *siginfo, void *context) // Establish a return point in case the common_signal_handler returns - volatile bool contextInitialization = true; + if (GetCurrentPalThread()) + { + volatile bool contextInitialization = true; - SignalHandlerWorkerReturnPoint returnPoint; - RtlCaptureContext(&returnPoint.context); + void *ptr = alloca(sizeof(SignalHandlerWorkerReturnPoint) + alignof(SignalHandlerWorkerReturnPoint) - 1); + SignalHandlerWorkerReturnPoint *pReturnPoint = (SignalHandlerWorkerReturnPoint *)ALIGN_UP(ptr, alignof(SignalHandlerWorkerReturnPoint)); + RtlCaptureContext(&pReturnPoint->context); - // When the signal handler worker completes, it uses setcontext to return to this point + // When the signal handler worker completes, it uses setcontext to return to this point - if (contextInitialization) - { - contextInitialization = false; - ExecuteHandlerOnOriginalStack(code, siginfo, context, &returnPoint); - _ASSERTE(FALSE); // The ExecuteHandlerOnOriginalStack should never return + if (contextInitialization) + { + contextInitialization = false; + ExecuteHandlerOnOriginalStack(code, siginfo, context, pReturnPoint); + _ASSERTE(FALSE); // The ExecuteHandlerOnOriginalStack should never return + } + + if (pReturnPoint->returnFromHandler) + { + return; + } } - - if (returnPoint.returnFromHandler) + else { - return; + // If thread isn't created by coreclr and has alternate signal stack GetCurrentPalThread() will return NULL too. + // But since in this case we don't handle hardware exceptions (IsSafeToHandleHardwareException returns false) + // we can call common_signal_handler on the alternate stack. + if (common_signal_handler(code, siginfo, context, 2, (size_t)0, (size_t)siginfo->si_addr)) + { + return; + } } }