Mask INJECT_ACTIVATION_SIGNAL while on alternate signal stack.
authorAditya Mandaleeka <adityam@microsoft.com>
Mon, 3 Jul 2017 17:41:02 +0000 (10:41 -0700)
committerAditya Mandaleeka <adityam@microsoft.com>
Thu, 6 Jul 2017 00:00:49 +0000 (17:00 -0700)
Commit migrated from https://github.com/dotnet/coreclr/commit/94f2d05cd8e2f0d0be0e264b808dccb58b5d8f33

src/coreclr/src/pal/src/exception/signal.cpp

index b580ba4..3e28115 100644 (file)
@@ -411,7 +411,27 @@ extern "C" void signal_handler_worker(int code, siginfo_t *siginfo, void *contex
     // TODO: First variable parameter says whether a read (0) or write (non-0) caused the
     // fault. We must disassemble the instruction at record.ExceptionAddress
     // to correctly fill in this value.
+
+    // Unmask the activation signal now that we are running on the original stack of the thread
+    sigset_t signal_set;
+    sigemptyset(&signal_set);
+    sigaddset(&signal_set, INJECT_ACTIVATION_SIGNAL);
+
+    int sigmaskRet = pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL);
+    if (sigmaskRet != 0)
+    {
+        ASSERT("pthread_sigmask failed; error number is %d\n", sigmaskRet);
+    }
+
     returnPoint->returnFromHandler = common_signal_handler(code, siginfo, context, 2, (size_t)0, (size_t)siginfo->si_addr);
+
+    // We are going to return to the alternate stack, so block the activation signal again
+    sigmaskRet = pthread_sigmask(SIG_BLOCK, &signal_set, NULL);
+    if (sigmaskRet != 0)
+    {
+        ASSERT("pthread_sigmask failed; error number is %d\n", sigmaskRet);
+    }
+
     RtlRestoreContext(&returnPoint->context, NULL);
 }
 
@@ -856,6 +876,16 @@ void handle_signal(int signal_id, SIGFUNC sigfunc, struct sigaction *previousAct
 #endif  /* HAVE_SIGINFO_T */
     sigemptyset(&newAction.sa_mask);
 
+#ifdef INJECT_ACTIVATION_SIGNAL
+    if ((additionalFlags & SA_ONSTACK) != 0)
+    {
+        // A handler that runs on a separate stack should not be interrupted by the activation signal
+        // until it switches back to the regular stack, since that signal's handler would run on the
+        // limited separate stack and likely run into a stack overflow.
+        sigaddset(&newAction.sa_mask, INJECT_ACTIVATION_SIGNAL);
+    }
+#endif
+
     if (-1 == sigaction(signal_id, &newAction, previousAction))
     {
         ASSERT("handle_signal: sigaction() call failed with error code %d (%s)\n",