summaryrefslogtreecommitdiff
path: root/signal.c
diff options
context:
space:
mode:
authorYusuke Endoh <mame@ruby-lang.org>2019-10-09 23:13:59 +0900
committerYusuke Endoh <mame@ruby-lang.org>2019-10-09 23:22:15 +0900
commit891cbd66a411725d7300a28b1a95619c2902f0eb (patch)
tree58d4c2749523b7c1bc083d8686e6ce5cc02e5355 /signal.c
parentdd477df411691803fc5a83c7daa64faac112a0e4 (diff)
signal.c: save the original sighandlers for fatal signals
On Android, a signal handler that is not SIG_DFL is set by default for SIGSEGV. Ruby's install_sighandler inserts Ruby's handler only when the signal has no handler, so it does not insert Ruby's SEGV report handler, which caused some test failures. This changeset forces to install Ruby's handler for some fatal signals (sigbus, sigsegv, and sigill). They keep the original handlers, and call them when the interpreter receives the signals.
Diffstat (limited to 'signal.c')
-rw-r--r--signal.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/signal.c b/signal.c
index 638a0d1483..2876e8706e 100644
--- a/signal.c
+++ b/signal.c
@@ -918,6 +918,7 @@ NOINLINE(static void check_reserved_signal_(const char *name, size_t name_len));
#ifdef SIGBUS
+static sighandler_t default_sigbus_handler;
NORETURN(static ruby_sigaction_t sigbus);
static RETSIGTYPE
@@ -933,12 +934,13 @@ sigbus(int sig SIGINFO_ARG)
#if defined __APPLE__ || defined __linux__
CHECK_STACK_OVERFLOW();
#endif
- rb_bug_for_fatal_signal(SIGINFO_CTX, "Bus Error" MESSAGE_FAULT_ADDRESS);
+ rb_bug_for_fatal_signal(default_sigbus_handler, sig, SIGINFO_CTX, "Bus Error" MESSAGE_FAULT_ADDRESS);
}
#endif
#ifdef SIGSEGV
+static sighandler_t default_sigsegv_handler;
NORETURN(static ruby_sigaction_t sigsegv);
static RETSIGTYPE
@@ -946,12 +948,13 @@ sigsegv(int sig SIGINFO_ARG)
{
check_reserved_signal("SEGV");
CHECK_STACK_OVERFLOW();
- rb_bug_for_fatal_signal(SIGINFO_CTX, "Segmentation fault" MESSAGE_FAULT_ADDRESS);
+ rb_bug_for_fatal_signal(default_sigsegv_handler, sig, SIGINFO_CTX, "Segmentation fault" MESSAGE_FAULT_ADDRESS);
}
#endif
#ifdef SIGILL
+static sighandler_t default_sigill_handler;
NORETURN(static ruby_sigaction_t sigill);
static RETSIGTYPE
@@ -961,7 +964,7 @@ sigill(int sig SIGINFO_ARG)
#if defined __APPLE__
CHECK_STACK_OVERFLOW();
#endif
- rb_bug_for_fatal_signal(SIGINFO_CTX, "Illegal instruction" MESSAGE_FAULT_ADDRESS);
+ rb_bug_for_fatal_signal(default_sigill_handler, sig, SIGINFO_CTX, "Illegal instruction" MESSAGE_FAULT_ADDRESS);
}
#endif
@@ -1432,21 +1435,28 @@ sig_list(VALUE _)
perror(failed); \
} while (0)
static int
-install_sighandler(int signum, sighandler_t handler)
+install_sighandler_core(int signum, sighandler_t handler, sighandler_t *old_handler)
{
sighandler_t old;
old = ruby_signal(signum, handler);
if (old == SIG_ERR) return -1;
- /* signal handler should be inherited during exec. */
- if (old != SIG_DFL) {
- ruby_signal(signum, old);
+ if (old_handler) {
+ *old_handler = (old == SIG_DFL || old == SIG_IGN) ? 0 : old;
+ }
+ else {
+ /* signal handler should be inherited during exec. */
+ if (old != SIG_DFL) {
+ ruby_signal(signum, old);
+ }
}
return 0;
}
# define install_sighandler(signum, handler) \
- INSTALL_SIGHANDLER(install_sighandler(signum, handler), #signum, signum)
+ INSTALL_SIGHANDLER(install_sighandler_core(signum, handler, NULL), #signum, signum)
+# define force_install_sighandler(signum, handler, old_handler) \
+ INSTALL_SIGHANDLER(install_sighandler_core(signum, handler, old_handler), #signum, signum)
#if RUBY_SIGCHLD
static int
@@ -1558,14 +1568,14 @@ Init_signal(void)
if (!ruby_enable_coredump) {
#ifdef SIGBUS
- install_sighandler(SIGBUS, (sighandler_t)sigbus);
+ force_install_sighandler(SIGBUS, (sighandler_t)sigbus, &default_sigbus_handler);
#endif
#ifdef SIGILL
- install_sighandler(SIGILL, (sighandler_t)sigill);
+ force_install_sighandler(SIGILL, (sighandler_t)sigill, &default_sigill_handler);
#endif
#ifdef SIGSEGV
RB_ALTSTACK_INIT(GET_VM()->main_altstack);
- install_sighandler(SIGSEGV, (sighandler_t)sigsegv);
+ force_install_sighandler(SIGSEGV, (sighandler_t)sigsegv, &default_sigsegv_handler);
#endif
}
#ifdef SIGPIPE