summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--signal.c35
2 files changed, 31 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 69534f618a..5741667979 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Thu Feb 21 14:14:13 2013 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
+
+ * signal.c (sigsegv): avoid to use async signal unsafe functions
+ when nested sigsegv is happen.
+ [Bug #5014] [ruby-dev:44082]
+
Thu Feb 21 13:47:59 2013 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
* file.c (rb_group_member): added an error check. SUS says,
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