/* internal data declarations *********************************************/
+static bool ensure_alt_signal_stack = false;
static bool registered_sigterm_handler = false;
+#if !HAVE_MACH_EXCEPTIONS
+static bool registered_signal_handlers = false;
+#endif // !HAVE_MACH_EXCEPTIONS
struct sigaction g_previous_sigterm;
#if !HAVE_MACH_EXCEPTIONS
--*/
BOOL EnsureSignalAlternateStack()
{
- stack_t oss;
-
- // Query the current alternate signal stack
- int st = sigaltstack(NULL, &oss);
+ int st = 0;
- if ((st == 0) && (oss.ss_flags == SS_DISABLE))
+ if (ensure_alt_signal_stack)
{
- // There is no alternate stack for SIGSEGV handling installed yet so allocate one
+ stack_t oss;
- // We include the size of the SignalHandlerWorkerReturnPoint in the alternate stack size since the
- // context contained in it is large and the SIGSTKSZ was not sufficient on ARM64 during testing.
- int altStackSize = SIGSTKSZ + ALIGN_UP(sizeof(SignalHandlerWorkerReturnPoint), 16) + GetVirtualPageSize();
-#ifdef HAS_ASAN
- // Asan also uses alternate stack so we increase its size on the SIGSTKSZ * 4 that enough for asan
- // (see kAltStackSize in compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc)
- altStackSize += SIGSTKSZ * 4;
-#endif
- altStackSize = ALIGN_UP(altStackSize, GetVirtualPageSize());
- void* altStack = mmap(NULL, altStackSize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_STACK | MAP_PRIVATE, -1, 0);
- if (altStack != MAP_FAILED)
+ // Query the current alternate signal stack
+ st = sigaltstack(NULL, &oss);
+
+ if ((st == 0) && (oss.ss_flags == SS_DISABLE))
{
- // create a guard page for the alternate stack
- st = mprotect(altStack, GetVirtualPageSize(), PROT_NONE);
- if (st == 0)
- {
- stack_t ss;
- ss.ss_sp = (char*)altStack;
- ss.ss_size = altStackSize;
- ss.ss_flags = 0;
- st = sigaltstack(&ss, NULL);
- }
+ // There is no alternate stack for SIGSEGV handling installed yet so allocate one
- if (st != 0)
+ // We include the size of the SignalHandlerWorkerReturnPoint in the alternate stack size since the
+ // context contained in it is large and the SIGSTKSZ was not sufficient on ARM64 during testing.
+ int altStackSize = SIGSTKSZ + ALIGN_UP(sizeof(SignalHandlerWorkerReturnPoint), 16) + GetVirtualPageSize();
+#ifdef HAS_ASAN
+ // Asan also uses alternate stack so we increase its size on the SIGSTKSZ * 4 that enough for asan
+ // (see kAltStackSize in compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc)
+ altStackSize += SIGSTKSZ * 4;
+#endif
+ altStackSize = ALIGN_UP(altStackSize, GetVirtualPageSize());
+ void* altStack = mmap(NULL, altStackSize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_STACK | MAP_PRIVATE, -1, 0);
+ if (altStack != MAP_FAILED)
{
- int st2 = munmap(altStack, altStackSize);
- _ASSERTE(st2 == 0);
+ // create a guard page for the alternate stack
+ st = mprotect(altStack, GetVirtualPageSize(), PROT_NONE);
+ if (st == 0)
+ {
+ stack_t ss;
+ ss.ss_sp = (char*)altStack;
+ ss.ss_size = altStackSize;
+ ss.ss_flags = 0;
+ st = sigaltstack(&ss, NULL);
+ }
+
+ if (st != 0)
+ {
+ int st2 = munmap(altStack, altStackSize);
+ _ASSERTE(st2 == 0);
+ }
}
}
}
--*/
void FreeSignalAlternateStack()
{
- stack_t ss, oss;
- // The man page for sigaltstack says that when the ss.ss_flags is set to SS_DISABLE,
- // all other ss fields are ignored. However, MUSL implementation checks that the
- // ss_size is >= MINSIGSTKSZ even in this case.
- ss.ss_size = MINSIGSTKSZ;
- ss.ss_flags = SS_DISABLE;
- int st = sigaltstack(&ss, &oss);
- if ((st == 0) && (oss.ss_flags != SS_DISABLE))
- {
- int st = munmap(oss.ss_sp, oss.ss_size);
- _ASSERTE(st == 0);
+ if (ensure_alt_signal_stack)
+ {
+ stack_t ss, oss;
+ // The man page for sigaltstack says that when the ss.ss_flags is set to SS_DISABLE,
+ // all other ss fields are ignored. However, MUSL implementation checks that the
+ // ss_size is >= MINSIGSTKSZ even in this case.
+ ss.ss_size = MINSIGSTKSZ;
+ ss.ss_flags = SS_DISABLE;
+ int st = sigaltstack(&ss, &oss);
+ if ((st == 0) && (oss.ss_flags != SS_DISABLE))
+ {
+ int st = munmap(oss.ss_sp, oss.ss_size);
+ _ASSERTE(st == 0);
+ }
}
}
#endif // !HAVE_MACH_EXCEPTIONS
TRACE("Initializing signal handlers\n");
#if !HAVE_MACH_EXCEPTIONS
- /* we call handle_signal for every possible signal, even
- if we don't provide a signal handler.
-
- handle_signal will set SA_RESTART flag for specified signal.
- Therefore, all signals will have SA_RESTART flag set, preventing
- slow Unix system calls from being interrupted. On systems without
- siginfo_t, SIGKILL and SIGSTOP can't be restarted, so we don't
- handle those signals. Both the Darwin and FreeBSD man pages say
- that SIGKILL and SIGSTOP can't be handled, but FreeBSD allows us
- to register a handler for them anyway. We don't do that.
-
- see sigaction man page for more details
- */
- handle_signal(SIGILL, sigill_handler, &g_previous_sigill);
- handle_signal(SIGTRAP, sigtrap_handler, &g_previous_sigtrap);
- handle_signal(SIGFPE, sigfpe_handler, &g_previous_sigfpe);
- handle_signal(SIGBUS, sigbus_handler, &g_previous_sigbus);
- // SIGSEGV handler runs on a separate stack so that we can handle stack overflow
- handle_signal(SIGSEGV, sigsegv_handler, &g_previous_sigsegv, SA_ONSTACK);
- // We don't setup a handler for SIGINT/SIGQUIT when those signals are ignored.
- // Otherwise our child processes would reset to the default on exec causing them
- // to terminate on these signals.
- handle_signal(SIGINT, sigint_handler, &g_previous_sigint , 0 /* additionalFlags */, true /* skipIgnored */);
- handle_signal(SIGQUIT, sigquit_handler, &g_previous_sigquit, 0 /* additionalFlags */, true /* skipIgnored */);
-
- if (!EnsureSignalAlternateStack())
- {
- return FALSE;
+ if (flags & PAL_INITIALIZE_REGISTER_SIGNALS)
+ {
+ registered_signal_handlers = true;
+ /* we call handle_signal for every possible signal, even
+ if we don't provide a signal handler.
+
+ handle_signal will set SA_RESTART flag for specified signal.
+ Therefore, all signals will have SA_RESTART flag set, preventing
+ slow Unix system calls from being interrupted. On systems without
+ siginfo_t, SIGKILL and SIGSTOP can't be restarted, so we don't
+ handle those signals. Both the Darwin and FreeBSD man pages say
+ that SIGKILL and SIGSTOP can't be handled, but FreeBSD allows us
+ to register a handler for them anyway. We don't do that.
+
+ see sigaction man page for more details
+ */
+ handle_signal(SIGILL, sigill_handler, &g_previous_sigill);
+ handle_signal(SIGTRAP, sigtrap_handler, &g_previous_sigtrap);
+ handle_signal(SIGFPE, sigfpe_handler, &g_previous_sigfpe);
+ handle_signal(SIGBUS, sigbus_handler, &g_previous_sigbus);
+ // SIGSEGV handler runs on a separate stack so that we can handle stack overflow
+ handle_signal(SIGSEGV, sigsegv_handler, &g_previous_sigsegv, SA_ONSTACK);
+ // We don't setup a handler for SIGINT/SIGQUIT when those signals are ignored.
+ // Otherwise our child processes would reset to the default on exec causing them
+ // to terminate on these signals.
+ handle_signal(SIGINT, sigint_handler, &g_previous_sigint, 0 /* additionalFlags */, true /* skipIgnored */);
+ handle_signal(SIGQUIT, sigquit_handler, &g_previous_sigquit, 0 /* additionalFlags */, true /* skipIgnored */);
+
+#ifdef INJECT_ACTIVATION_SIGNAL
+ handle_signal(INJECT_ACTIVATION_SIGNAL, inject_activation_handler, &g_previous_activation);
+#endif
}
-#endif // !HAVE_MACH_EXCEPTIONS
- if (flags & PAL_INITIALIZE_REGISTER_SIGTERM_HANDLER)
+ if (flags & PAL_INITIALIZE_ENSURE_ALT_SIGNAL_STACK)
{
- handle_signal(SIGTERM, sigterm_handler, &g_previous_sigterm);
- registered_sigterm_handler = true;
+ ensure_alt_signal_stack = true;
+ if (!EnsureSignalAlternateStack())
+ {
+ return FALSE;
+ }
}
-#if !HAVE_MACH_EXCEPTIONS
-#ifdef INJECT_ACTIVATION_SIGNAL
- handle_signal(INJECT_ACTIVATION_SIGNAL, inject_activation_handler, &g_previous_activation);
-#endif
-
/* The default action for SIGPIPE is process termination.
Since SIGPIPE can be signaled when trying to write on a socket for which
the connection has been dropped, we need to tell the system we want
signal(SIGPIPE, SIG_IGN);
#endif // !HAVE_MACH_EXCEPTIONS
+ if (flags & PAL_INITIALIZE_REGISTER_SIGTERM_HANDLER)
+ {
+ registered_sigterm_handler = true;
+ handle_signal(SIGTERM, sigterm_handler, &g_previous_sigterm);
+ }
+
return TRUE;
}
TRACE("Restoring default signal handlers\n");
#if !HAVE_MACH_EXCEPTIONS
- restore_signal(SIGILL, &g_previous_sigill);
- restore_signal(SIGTRAP, &g_previous_sigtrap);
- restore_signal(SIGFPE, &g_previous_sigfpe);
- restore_signal(SIGBUS, &g_previous_sigbus);
- restore_signal(SIGSEGV, &g_previous_sigsegv);
- restore_signal(SIGINT, &g_previous_sigint);
- restore_signal(SIGQUIT, &g_previous_sigquit);
+ if (registered_signal_handlers)
+ {
+ restore_signal(SIGILL, &g_previous_sigill);
+ restore_signal(SIGTRAP, &g_previous_sigtrap);
+ restore_signal(SIGFPE, &g_previous_sigfpe);
+ restore_signal(SIGBUS, &g_previous_sigbus);
+ restore_signal(SIGSEGV, &g_previous_sigsegv);
+ restore_signal(SIGINT, &g_previous_sigint);
+ restore_signal(SIGQUIT, &g_previous_sigquit);
+#ifdef INJECT_ACTIVATION_SIGNAL
+ restore_signal(INJECT_ACTIVATION_SIGNAL, &g_previous_activation);
+#endif
+ }
#endif // !HAVE_MACH_EXCEPTIONS
if (registered_sigterm_handler)
{
restore_signal(SIGTERM, &g_previous_sigterm);
}
-
-#if !HAVE_MACH_EXCEPTIONS
-#ifdef INJECT_ACTIVATION_SIGNAL
- restore_signal(INJECT_ACTIVATION_SIGNAL, &g_previous_activation);
-#endif
-#endif // !HAVE_MACH_EXCEPTIONS
}
/* internal function definitions **********************************************/