summaryrefslogtreecommitdiff
path: root/signal.c
diff options
context:
space:
mode:
authorMichael Leibowitz <michael.leibowitz@intel.com>2013-08-15 15:02:54 -0700
committerMichael Leibowitz <michael.leibowitz@intel.com>2013-08-15 15:02:54 -0700
commit6b0e2a11aeccf2ebc707c22548a0c15c8c2bae06 (patch)
treed9d59f4b502927634d32832e963db76629ff5a2e /signal.c
parent3b35de2a90e26b99e2a6d4f61dc56d6ce7ded748 (diff)
downloadruby-upstream.tar.gz
ruby-upstream.tar.bz2
ruby-upstream.zip
Imported Upstream version 1.9.3.p448upstream/1.9.3.p448upstream
Diffstat (limited to 'signal.c')
-rw-r--r--signal.c73
1 files changed, 48 insertions, 25 deletions
diff --git a/signal.c b/signal.c
index d4e56dc..bd17874 100644
--- a/signal.c
+++ b/signal.c
@@ -2,7 +2,7 @@
signal.c -
- $Author: kosaki $
+ $Author: usa $
created at: Tue Dec 20 10:13:44 JST 1994
Copyright (C) 1993-2007 Yukihiro Matsumoto
@@ -16,7 +16,10 @@
#include <signal.h>
#include <stdio.h>
#include <errno.h>
-#include "atomic.h"
+#include "ruby_atomic.h"
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
#if !defined(_WIN32) && !defined(HAVE_GCC_ATOMIC_BUILTINS)
rb_atomic_t
@@ -564,6 +567,23 @@ rb_get_next_signal(void)
return sig;
}
+
+#ifdef USE_SIGALTSTACK
+static void
+check_stack_overflow(const void *addr)
+{
+ int ruby_stack_overflowed_p(const rb_thread_t *, const void *);
+ NORETURN(void ruby_thread_stack_overflow(rb_thread_t *th));
+ rb_thread_t *th = GET_THREAD();
+ if (ruby_stack_overflowed_p(th, addr)) {
+ ruby_thread_stack_overflow(th);
+ }
+}
+#define CHECK_STACK_OVERFLOW() check_stack_overflow(info->si_addr)
+#else
+#define CHECK_STACK_OVERFLOW() (void)0
+#endif
+
#ifdef SIGBUS
static RETSIGTYPE
sigbus(int sig SIGINFO_ARG)
@@ -573,41 +593,44 @@ sigbus(int sig SIGINFO_ARG)
* and it's delivered as SIGBUS instaed of SIGSEGV to userland. It's crazy
* wrong IMHO. but anyway we have to care it. Sigh.
*/
-#if defined __MACH__ && defined __APPLE__ && defined USE_SIGALTSTACK
- int ruby_stack_overflowed_p(const rb_thread_t *, const void *);
- NORETURN(void ruby_thread_stack_overflow(rb_thread_t *th));
- rb_thread_t *th = GET_THREAD();
- if (ruby_stack_overflowed_p(th, info->si_addr)) {
- ruby_thread_stack_overflow(th);
- }
+#if defined __APPLE__
+ CHECK_STACK_OVERFLOW();
#endif
rb_bug("Bus Error");
}
#endif
#ifdef SIGSEGV
+static void ruby_abort(void)
+{
+#ifdef __sun
+ /* Solaris's abort() is async signal unsafe. Of course, it is not
+ * POSIX compliant.
+ */
+ raise(SIGABRT);
+#else
+ abort();
+#endif
+
+}
+
static int segv_received = 0;
+extern int ruby_disable_gc_stress;
+
static RETSIGTYPE
sigsegv(int sig SIGINFO_ARG)
{
-#ifdef USE_SIGALTSTACK
- int ruby_stack_overflowed_p(const rb_thread_t *, const void *);
- NORETURN(void ruby_thread_stack_overflow(rb_thread_t *th));
- rb_thread_t *th = GET_THREAD();
- if (ruby_stack_overflowed_p(th, info->si_addr)) {
- ruby_thread_stack_overflow(th);
- }
-#endif
if (segv_received) {
- fprintf(stderr, "SEGV received in SEGV handler\n");
- abort();
- }
- else {
- extern int ruby_disable_gc_stress;
- segv_received = 1;
- ruby_disable_gc_stress = 1;
- rb_bug("Segmentation fault");
+ char msg[] = "SEGV received in SEGV handler\n";
+ write(2, msg, sizeof(msg));
+ ruby_abort();
}
+
+ CHECK_STACK_OVERFLOW();
+
+ segv_received = 1;
+ ruby_disable_gc_stress = 1;
+ rb_bug("Segmentation fault");
}
#endif