diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-10-16 08:15:46 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-10-16 08:15:46 +0000 |
commit | 0d88cd9394ecbcef0c733f7973504d6ff49db228 (patch) | |
tree | 50414072536eccf84282baded5fb47b622934d27 | |
parent | 5c3c2ddda2f410a25985f0e0fe7092d8c21a3657 (diff) |
signal.c: abort if nesting reserved signal
* signal.c (check_reserved_signal): abort if reserved signal
received in reserved signal handlers.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47977 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | signal.c | 48 |
1 files changed, 39 insertions, 9 deletions
@@ -799,10 +799,14 @@ check_stack_overflow(const void *addr) #define MESSAGE_FAULT_ADDRESS #endif +#if defined SIGSEGV || defined SIGBUS || defined SIGILL || defined SIGFPE +static void check_reserved_signal(const char *name); + #ifdef SIGBUS static RETSIGTYPE sigbus(int sig SIGINFO_ARG) { + check_reserved_signal("BUS"); /* * Mac OS X makes KERN_PROTECTION_FAILURE when thread touch guard page. * and it's delivered as SIGBUS instead of SIGSEGV to userland. It's crazy @@ -815,7 +819,6 @@ sigbus(int sig SIGINFO_ARG) } #endif -#ifdef SIGSEGV static void ruby_abort(void) { @@ -830,25 +833,49 @@ ruby_abort(void) } -static int segv_received = 0; extern int ruby_disable_gc; +#ifdef SIGSEGV static RETSIGTYPE sigsegv(int sig SIGINFO_ARG) { - if (segv_received) { + check_reserved_signal("SEGV"); + CHECK_STACK_OVERFLOW(); + rb_bug_context(SIGINFO_CTX, "Segmentation fault" MESSAGE_FAULT_ADDRESS); +} +#endif + +#ifdef SIGILL +static RETSIGTYPE +sigill(int sig SIGINFO_ARG) +{ + check_reserved_signal("ILL"); +#if defined __APPLE__ + CHECK_STACK_OVERFLOW(); +#endif + rb_bug_context(SIGINFO_CTX, "Illegal instruction" MESSAGE_FAULT_ADDRESS); +} +#endif + +static void +check_reserved_signal(const char *name) +{ + static const char *received; + const char *prev = ATOMIC_PTR_EXCHANGE(received, name); + + if (prev) { ssize_t RB_UNUSED_VAR(err); - static const char msg[] = "SEGV received in SEGV handler\n"; + static const char msg1[] = " received in "; + static const char msg2[] = " handler\n"; - err = write(2, msg, sizeof(msg)); + err = write(2, name, strlen(name)); + err = write(2, msg1, sizeof(msg1)); + err = write(2, prev, strlen(prev)); + err = write(2, msg2, sizeof(msg2)); ruby_abort(); } - CHECK_STACK_OVERFLOW(); - - segv_received = 1; ruby_disable_gc = 1; - rb_bug_context(SIGINFO_CTX, "Segmentation fault" MESSAGE_FAULT_ADDRESS); } #endif @@ -1381,6 +1408,9 @@ Init_signal(void) #ifdef SIGBUS install_sighandler(SIGBUS, (sighandler_t)sigbus); #endif +#ifdef SIGILL + install_sighandler(SIGILL, (sighandler_t)sigill); +#endif #ifdef SIGSEGV # ifdef USE_SIGALTSTACK rb_register_sigaltstack(GET_THREAD()); |