sigsegv_handler: handle case when it is called on original stack (dotnet/coreclr...
authorKonstantin Baladurin <k.baladurin@partner.samsung.com>
Thu, 15 Feb 2018 01:25:32 +0000 (04:25 +0300)
committerJan Vorlicek <janvorli@microsoft.com>
Thu, 15 Feb 2018 01:25:32 +0000 (02:25 +0100)
* 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.

* 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.

* 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.

Commit migrated from https://github.com/dotnet/coreclr/commit/24b4aff35c51938f01fcb740777af510f50074d0

src/coreclr/src/pal/src/exception/seh.cpp
src/coreclr/src/pal/src/exception/signal.cpp
src/coreclr/src/vm/threads.inl

index 9f5f074..73d8ce5 100644 (file)
@@ -344,8 +344,8 @@ CatchHardwareExceptionHolder::~CatchHardwareExceptionHolder()
 
 bool CatchHardwareExceptionHolder::IsEnabled()
 {
-    CPalThread *pThread = InternalGetCurrentThread();
-    return pThread->IsHardwareExceptionsEnabled();
+    CPalThread *pThread = GetCurrentPalThread();
+    return pThread ? pThread->IsHardwareExceptionsEnabled() : false;
 }
 
 /*++
index a273823..96dca50 100644 (file)
@@ -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;
+            }
         }
     }
 
index f5a439c..0a72d83 100644 (file)
@@ -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()