diff options
author | Tom Deseyn <tom.deseyn@gmail.com> | 2019-01-15 21:43:08 +0100 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2019-01-15 12:43:08 -0800 |
commit | 3f0903598d0e269e6aaf8e237b47269abe4ab7e8 (patch) | |
tree | aff29f9a428caf4b1591987dff07fd146d15909b /src/pal/src/exception/signal.cpp | |
parent | 86b4ac59ef9d19e8f635086ea6a20a291c1dd26a (diff) | |
download | coreclr-3f0903598d0e269e6aaf8e237b47269abe4ab7e8.tar.gz coreclr-3f0903598d0e269e6aaf8e237b47269abe4ab7e8.tar.bz2 coreclr-3f0903598d0e269e6aaf8e237b47269abe4ab7e8.zip |
On SIGTERM default to a non-zero exit code (#21300)
* On SIGTERM default to a non-zero exit code
* Fix Windows builds
* Improve SIG_DFL/SIG_IGN handling
* Remove PAL_GetTerminationExitCode
* Use sa_handler/sa_sigaction based on SA_SIGINFO; remove HAVE_SIGINFO_T.
* configure.cmake: remove siginfo_t check
* Move restore_signal_and_resend so OSX can use it; add function documentation
* Fix OSX build: include pal/process.h for gPID
* Check SIG_IGN and SIG_DFL against sa_handler
* Don't use sa_handler when SA_SIGINFO is set
* Fix equality check
* Swap order of checking SA_SIGINFO and SIG_IGN/SIG_DFL
Diffstat (limited to 'src/pal/src/exception/signal.cpp')
-rw-r--r-- | src/pal/src/exception/signal.cpp | 191 |
1 files changed, 107 insertions, 84 deletions
diff --git a/src/pal/src/exception/signal.cpp b/src/pal/src/exception/signal.cpp index fe15a70f83..df5a5f22a4 100644 --- a/src/pal/src/exception/signal.cpp +++ b/src/pal/src/exception/signal.cpp @@ -23,6 +23,7 @@ SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do #include "pal/corunix.hpp" #include "pal/handleapi.hpp" +#include "pal/process.h" #include "pal/thread.hpp" #include "pal/threadinfo.hpp" #include "pal/threadsusp.hpp" @@ -36,7 +37,6 @@ SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do #if !HAVE_MACH_EXCEPTIONS #include "pal/init.h" -#include "pal/process.h" #include "pal/debug.h" #include "pal/virtual.h" #include "pal/utils.h" @@ -62,12 +62,6 @@ using namespace CorUnix; /* local type definitions *****************************************************/ -#if !HAVE_SIGINFO_T -/* This allows us to compile on platforms that don't have siginfo_t. - * Exceptions will work poorly on those platforms. */ -#warning Exceptions will work poorly on this platform -typedef void *siginfo_t; -#endif /* !HAVE_SIGINFO_T */ typedef void (*SIGFUNC)(int, siginfo_t *, void *); /* internal function declarations *********************************************/ @@ -91,6 +85,7 @@ static void inject_activation_handler(int code, siginfo_t *siginfo, void *contex static void handle_signal(int signal_id, SIGFUNC sigfunc, struct sigaction *previousAction, int additionalFlags = 0, bool skipIgnored = false); static void restore_signal(int signal_id, struct sigaction *previousAction); +static void restore_signal_and_resend(int code, struct sigaction* action); /* internal data declarations *********************************************/ @@ -242,6 +237,68 @@ void SEHCleanupSignals() #if !HAVE_MACH_EXCEPTIONS /*++ Function : + invoke_previous_action + + synchronously invokes the previous action or aborts when that is not possible + +Parameters : + action : previous sigaction struct + code : signal code + siginfo : signal siginfo + context : signal context + signalRestarts: BOOL state : TRUE if the process will be signalled again + + (no return value) +--*/ +static void invoke_previous_action(struct sigaction* action, int code, siginfo_t *siginfo, void *context, bool signalRestarts = true) +{ + _ASSERTE(action != NULL); + + if (action->sa_flags & SA_SIGINFO) + { + // Directly call the previous handler. + _ASSERTE(action->sa_sigaction != NULL); + action->sa_sigaction(code, siginfo, context); + } + else + { + if (action->sa_handler == SIG_IGN) + { + if (signalRestarts) + { + // This signal mustn't be ignored because it will be restarted. + PROCAbort(); + } + return; + } + else if (action->sa_handler == SIG_DFL) + { + if (signalRestarts) + { + // Restore the original and restart h/w exception. + restore_signal(code, action); + } + else + { + // We can't invoke the original handler because returning from the + // handler doesn't restart the exception. + PROCAbort(); + } + } + else + { + // Directly call the previous handler. + _ASSERTE(action->sa_handler != NULL); + action->sa_handler(code); + } + } + + PROCNotifyProcessShutdown(); + PROCCreateCrashDumpIfEnabled(); +} + +/*++ +Function : sigill_handler handle SIGILL signal (EXCEPTION_ILLEGAL_INSTRUCTION, others?) @@ -261,18 +318,7 @@ static void sigill_handler(int code, siginfo_t *siginfo, void *context) } } - if (g_previous_sigill.sa_sigaction != NULL) - { - g_previous_sigill.sa_sigaction(code, siginfo, context); - } - else - { - // Restore the original or default handler and restart h/w exception - restore_signal(code, &g_previous_sigill); - } - - PROCNotifyProcessShutdown(); - PROCCreateCrashDumpIfEnabled(); + invoke_previous_action(&g_previous_sigill, code, siginfo, context); } /*++ @@ -296,18 +342,7 @@ static void sigfpe_handler(int code, siginfo_t *siginfo, void *context) } } - if (g_previous_sigfpe.sa_sigaction != NULL) - { - g_previous_sigfpe.sa_sigaction(code, siginfo, context); - } - else - { - // Restore the original or default handler and restart h/w exception - restore_signal(code, &g_previous_sigfpe); - } - - PROCNotifyProcessShutdown(); - PROCCreateCrashDumpIfEnabled(); + invoke_previous_action(&g_previous_sigfpe, code, siginfo, context); } /*++ @@ -418,18 +453,7 @@ static void sigsegv_handler(int code, siginfo_t *siginfo, void *context) } } - if (g_previous_sigsegv.sa_sigaction != NULL) - { - g_previous_sigsegv.sa_sigaction(code, siginfo, context); - } - else - { - // Restore the original or default handler and restart h/w exception - restore_signal(code, &g_previous_sigsegv); - } - - PROCNotifyProcessShutdown(); - PROCCreateCrashDumpIfEnabled(); + invoke_previous_action(&g_previous_sigsegv, code, siginfo, context); } /*++ @@ -453,19 +477,8 @@ static void sigtrap_handler(int code, siginfo_t *siginfo, void *context) } } - if (g_previous_sigtrap.sa_sigaction != NULL) - { - g_previous_sigtrap.sa_sigaction(code, siginfo, context); - } - else - { - // We abort instead of restore the original or default handler and returning - // because returning from a SIGTRAP handler continues execution past the trap. - PROCAbort(); - } - - PROCNotifyProcessShutdown(); - PROCCreateCrashDumpIfEnabled(); + // The signal doesn't restart, returning from a SIGTRAP handler continues execution past the trap. + invoke_previous_action(&g_previous_sigtrap, code, siginfo, context, /* signalRestarts */ false); } /*++ @@ -492,18 +505,7 @@ static void sigbus_handler(int code, siginfo_t *siginfo, void *context) } } - if (g_previous_sigbus.sa_sigaction != NULL) - { - g_previous_sigbus.sa_sigaction(code, siginfo, context); - } - else - { - // Restore the original or default handler and restart h/w exception - restore_signal(code, &g_previous_sigbus); - } - - PROCNotifyProcessShutdown(); - PROCCreateCrashDumpIfEnabled(); + invoke_previous_action(&g_previous_sigbus, code, siginfo, context); } /*++ @@ -521,9 +523,7 @@ static void sigint_handler(int code, siginfo_t *siginfo, void *context) { PROCNotifyProcessShutdown(); - // Restore the original or default handler and resend signal - restore_signal(code, &g_previous_sigint); - kill(gPID, code); + restore_signal_and_resend(code, &g_previous_sigint); } /*++ @@ -541,9 +541,7 @@ static void sigquit_handler(int code, siginfo_t *siginfo, void *context) { PROCNotifyProcessShutdown(); - // Restore the original or default handler and resend signal - restore_signal(code, &g_previous_sigquit); - kill(gPID, code); + restore_signal_and_resend(code, &g_previous_sigquit); } #endif // !HAVE_MACH_EXCEPTIONS @@ -569,10 +567,7 @@ static void sigterm_handler(int code, siginfo_t *siginfo, void *context) } else { - if (g_previous_sigterm.sa_sigaction != NULL) - { - g_previous_sigterm.sa_sigaction(code, siginfo, context); - } + restore_signal_and_resend(SIGTERM, &g_previous_sigterm); } } @@ -612,9 +607,23 @@ static void inject_activation_handler(int code, siginfo_t *siginfo, void *contex CONTEXTToNativeContext(&winContext, ucontext); } } - else if (g_previous_activation.sa_sigaction != NULL) + else { - g_previous_activation.sa_sigaction(code, siginfo, context); + // Call the original handler when it is not ignored or default (terminate). + if (g_previous_activation.sa_flags & SA_SIGINFO) + { + _ASSERTE(g_previous_activation.sa_sigaction != NULL); + g_previous_activation.sa_sigaction(code, siginfo, context); + } + else + { + if (g_previous_activation.sa_handler != SIG_IGN && + g_previous_activation.sa_handler != SIG_DFL) + { + _ASSERTE(g_previous_activation.sa_handler != NULL); + g_previous_activation.sa_handler(code); + } + } } } #endif @@ -832,13 +841,9 @@ void handle_signal(int signal_id, SIGFUNC sigfunc, struct sigaction *previousAct struct sigaction newAction; newAction.sa_flags = SA_RESTART | additionalFlags; -#if HAVE_SIGINFO_T newAction.sa_handler = NULL; newAction.sa_sigaction = sigfunc; newAction.sa_flags |= SA_SIGINFO; -#else /* HAVE_SIGINFO_T */ - newAction.sa_handler = SIG_DFL; -#endif /* HAVE_SIGINFO_T */ sigemptyset(&newAction.sa_mask); #ifdef INJECT_ACTIVATION_SIGNAL @@ -891,3 +896,21 @@ void restore_signal(int signal_id, struct sigaction *previousAction) errno, strerror(errno)); } } + +/*++ +Function : + restore_signal_and_resend + + restore handler for specified signal and signal the process + +Parameters : + int signal_id : signal to handle + previousAction : previous sigaction struct to restore + + (no return value) +--*/ +void restore_signal_and_resend(int signal_id, struct sigaction* previousAction) +{ + restore_signal(signal_id, previousAction); + kill(gPID, signal_id); +}
\ No newline at end of file |