diff options
Diffstat (limited to 'src/pal/src/exception/signal.cpp')
-rw-r--r-- | src/pal/src/exception/signal.cpp | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/src/pal/src/exception/signal.cpp b/src/pal/src/exception/signal.cpp index 57ae62ea21..10eecf7b02 100644 --- a/src/pal/src/exception/signal.cpp +++ b/src/pal/src/exception/signal.cpp @@ -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); } @@ -761,12 +781,13 @@ __attribute__((noinline)) static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext, int numParams, ...) { sigset_t signal_set; + CONTEXT signalContextRecord; CONTEXT *contextRecord; EXCEPTION_RECORD *exceptionRecord; native_context_t *ucontext; ucontext = (native_context_t *)sigcontext; - g_common_signal_handler_context_locvar_offset = (int)((char*)&ucontext - (char*)__builtin_frame_address(0)); + g_common_signal_handler_context_locvar_offset = (int)((char*)&signalContextRecord - (char*)__builtin_frame_address(0)); AllocateExceptionRecords(&exceptionRecord, &contextRecord); @@ -809,6 +830,9 @@ static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext } contextRecord->ContextFlags |= CONTEXT_EXCEPTION_ACTIVE; + + memcpy_s(&signalContextRecord, sizeof(CONTEXT), contextRecord, sizeof(CONTEXT)); + // The exception object takes ownership of the exceptionRecord and contextRecord PAL_SEHException exception(exceptionRecord, contextRecord); @@ -852,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", |