[前][次][番号順一覧][スレッド一覧]

ruby-changes:58176

From: Yusuke <ko1@a...>
Date: Wed, 9 Oct 2019 23:23:02 +0900 (JST)
Subject: [ruby-changes:58176] 891cbd66a4 (master): signal.c: save the original sighandlers for fatal signals

https://git.ruby-lang.org/ruby.git/commit/?id=891cbd66a4

From 891cbd66a411725d7300a28b1a95619c2902f0eb Mon Sep 17 00:00:00 2001
From: Yusuke Endoh <mame@r...>
Date: Wed, 9 Oct 2019 23:13:59 +0900
Subject: 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.

diff --git a/error.c b/error.c
index 56ea9ae..f8d2545 100644
--- a/error.c
+++ b/error.c
@@ -599,7 +599,7 @@ rb_bug(const char *fmt, ...) https://github.com/ruby/ruby/blob/trunk/error.c#L599
 }
 
 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, ...) https://github.com/ruby/ruby/blob/trunk/error.c#L610
 
     report_bug(file, line, fmt, ctx);
 
+    if (default_sighandler) default_sighandler(sig);
+
     die();
 }
 
diff --git a/signal.c b/signal.c
index 638a0d1..2876e87 100644
--- a/signal.c
+++ b/signal.c
@@ -918,6 +918,7 @@ NOINLINE(static void check_reserved_signal_(const char *name, size_t name_len)); https://github.com/ruby/ruby/blob/trunk/signal.c#L918
 
 #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) https://github.com/ruby/ruby/blob/trunk/signal.c#L934
 #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) https://github.com/ruby/ruby/blob/trunk/signal.c#L948
 {
     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) https://github.com/ruby/ruby/blob/trunk/signal.c#L964
 #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 _) https://github.com/ruby/ruby/blob/trunk/signal.c#L1435
 	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) https://github.com/ruby/ruby/blob/trunk/signal.c#L1568
 
     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 052b1b5..30559b0 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 https://github.com/ruby/ruby/blob/trunk/vm_core.h#L1624
 #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
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]