summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--error.c4
-rw-r--r--signal.c32
-rw-r--r--vm_core.h2
3 files changed, 25 insertions, 13 deletions
diff --git a/error.c b/error.c
index 56ea9ae084..f8d2545fa6 100644
--- a/error.c
+++ b/error.c
@@ -599,7 +599,7 @@ rb_bug(const char *fmt, ...)
}
void
-rb_bug_for_fatal_signal(const void *ctx, const char *fmt, ...)
+rb_bug_for_fatal_signal(RETSIGTYPE (*default_sighandler)(int), int sig, const void *ctx, const char *fmt, ...)
{
const char *file = NULL;
int line = 0;
@@ -610,6 +610,8 @@ rb_bug_for_fatal_signal(const void *ctx, const char *fmt, ...)
report_bug(file, line, fmt, ctx);
+ if (default_sighandler) default_sighandler(sig);
+
die();
}
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
diff --git a/vm_core.h b/vm_core.h
index 052b1b5c0d..30559b0255 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -1624,7 +1624,7 @@ extern void rb_vmdebug_debug_print_post(const rb_execution_context_t *ec, const
#define SDR() rb_vmdebug_stack_dump_raw(GET_EC(), GET_EC()->cfp)
#define SDR2(cfp) rb_vmdebug_stack_dump_raw(GET_EC(), (cfp))
void rb_vm_bugreport(const void *);
-NORETURN(void rb_bug_for_fatal_signal(const void *, const char *fmt, ...));
+NORETURN(void rb_bug_for_fatal_signal(RETSIGTYPE (*default_sighandler)(int), int sig, const void *, const char *fmt, ...));
/* functions about thread/vm execution */
RUBY_SYMBOL_EXPORT_BEGIN