summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--signal.c21
-rw-r--r--thread_pthread.c16
3 files changed, 36 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index 5444f123ea..959504c4f4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Sun Jul 3 04:50:08 2011 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
+
+ * thread_pthread.c (get_stack): add to a care of gurad page on Mac
+ OS X. [Bug #1813] [ruby-core:24540]
+ * signal.c (ruby_signal): SIGBUS use alternative stack too.
+ * signal.c (sigbus): On Mac, thread stack overflow makes SIGBUS
+ instead of SIGSEGV. thus, added stackoverflow check.
+ * signal.c (default_handler): get rid of compilation warning.
+ * signal.c (Init_signal): ditto.
+
Sat Jul 02 08:59:20 2011 Martin Bosslet <Martin.Bosslet@googlemail.com>
* test/openssl/test_ocsp.rb
diff --git a/signal.c b/signal.c
index f02e3db15c..14b7d67344 100644
--- a/signal.c
+++ b/signal.c
@@ -470,7 +470,7 @@ ruby_signal(int signum, sighandler_t handler)
sigact.sa_flags |= SA_NOCLDWAIT;
#endif
#if defined(SA_ONSTACK) && defined(USE_SIGALTSTACK)
- if (signum == SIGSEGV)
+ if (signum == SIGSEGV || signum == SIGBUS)
sigact.sa_flags |= SA_ONSTACK;
#endif
if (sigaction(signum, &sigact, &old) < 0) {
@@ -573,8 +573,21 @@ rb_get_next_signal(void)
#ifdef SIGBUS
static RETSIGTYPE
-sigbus(int sig)
+sigbus(int sig SIGINFO_ARG)
{
+/*
+ * Mac OS X makes KERN_PROTECTION_FAILURE when thread touch guard page.
+ * 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);
+ }
+#endif
rb_bug("Bus Error");
}
#endif
@@ -703,7 +716,7 @@ default_handler(int sig)
break;
#ifdef SIGBUS
case SIGBUS:
- func = sigbus;
+ func = (sighandler_t)sigbus;
break;
#endif
#ifdef SIGSEGV
@@ -1092,7 +1105,7 @@ Init_signal(void)
if (!ruby_enable_coredump) {
#ifdef SIGBUS
- install_sighandler(SIGBUS, sigbus);
+ install_sighandler(SIGBUS, (sighandler_t)sigbus);
#endif
#ifdef SIGSEGV
# ifdef USE_SIGALTSTACK
diff --git a/thread_pthread.c b/thread_pthread.c
index bd481ddc70..06e2b1d237 100644
--- a/thread_pthread.c
+++ b/thread_pthread.c
@@ -458,13 +458,14 @@ get_stack(void **addr, size_t *size)
{
#define CHECK_ERR(expr) \
{int err = (expr); if (err) return err;}
-#if defined HAVE_PTHREAD_GETATTR_NP || defined HAVE_PTHREAD_ATTR_GET_NP
+#if defined HAVE_PTHREAD_GETATTR_NP || defined HAVE_PTHREAD_ATTR_GET_NP || \
+ (defined HAVE_PTHREAD_GET_STACKADDR_NP && defined HAVE_PTHREAD_GET_STACKSIZE_NP)
pthread_attr_t attr;
size_t guard = 0;
# ifdef HAVE_PTHREAD_GETATTR_NP
CHECK_ERR(pthread_getattr_np(pthread_self(), &attr));
-# ifdef HAVE_PTHREAD_ATTR_GETSTACK
+# ifdef HAVE_PTHREAD_ATTR_GETSTACK /* Linux */
CHECK_ERR(pthread_attr_getstack(&attr, addr, size));
# else
CHECK_ERR(pthread_attr_getstackaddr(&attr, addr));
@@ -475,19 +476,20 @@ get_stack(void **addr, size_t *size)
STACK_DIR_UPPER((void)0, (void)(*addr = (char *)*addr + guard));
*size -= guard;
}
-# else
+# elif defined HAVE_PTHREAD_ATTR_GET_NP /* FreeBSD, DragonFly BSD, NetBSD */
CHECK_ERR(pthread_attr_init(&attr));
CHECK_ERR(pthread_attr_get_np(pthread_self(), &attr));
CHECK_ERR(pthread_attr_getstackaddr(&attr, addr));
CHECK_ERR(pthread_attr_getstacksize(&attr, size));
+# else /* MacOS X */
+ pthread_t th = pthread_self();
+ *addr = pthread_get_stackaddr_np(th);
+ *size = pthread_get_stacksize_np(th);
+ CHECK_ERR(pthread_attr_init(&attr));
# endif
CHECK_ERR(pthread_attr_getguardsize(&attr, &guard));
*size -= guard;
pthread_attr_destroy(&attr);
-#elif defined HAVE_PTHREAD_GET_STACKADDR_NP && defined HAVE_PTHREAD_GET_STACKSIZE_NP
- pthread_t th = pthread_self();
- *addr = pthread_get_stackaddr_np(th);
- *size = pthread_get_stacksize_np(th);
#elif defined HAVE_THR_STKSEGMENT || defined HAVE_PTHREAD_STACKSEG_NP
stack_t stk;
# if defined HAVE_THR_STKSEGMENT