summaryrefslogtreecommitdiff
path: root/signal.c
diff options
context:
space:
mode:
authorkosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-02-21 05:18:38 +0000
committerkosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-02-21 05:18:38 +0000
commit7355c6d9c99d7636c9acbd262149f72d1f900d9f (patch)
tree4532789c68a73f9130f7f0cbd404a0273a5bbfce /signal.c
parent8a9dc061f5737543eaca17ceafa6ebe4886cb26e (diff)
* signal.c (sigsegv): avoid to use async signal unsafe functions
when nested sigsegv is happen. [Bug #5014] [ruby-dev:44082] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@39354 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'signal.c')
-rw-r--r--signal.c35
1 files changed, 25 insertions, 10 deletions
diff --git a/signal.c b/signal.c
index c823347899..4bcb79e389 100644
--- a/signal.c
+++ b/signal.c
@@ -626,10 +626,31 @@ sigbus(int sig SIGINFO_ARG)
#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)
{
+ if (segv_received) {
+ char msg[] = "SEGV received in SEGV handler\n";
+ write(2, msg, sizeof(msg));
+ ruby_abort();
+ }
+
#ifdef USE_SIGALTSTACK
int ruby_stack_overflowed_p(const rb_thread_t *, const void *);
NORETURN(void ruby_thread_stack_overflow(rb_thread_t *th));
@@ -638,16 +659,10 @@ sigsegv(int sig SIGINFO_ARG)
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");
- }
+
+ segv_received = 1;
+ ruby_disable_gc_stress = 1;
+ rb_bug("Segmentation fault");
}
#endif