* signal.c (register_sigaltstack): use alternative stack for

SIGSEGV to avoid uncaught stack overflow. based on a patch from
  Hiro Yoshioka <hyoshiok at miraclelinux.com> in [ruby-dev:37134].
  [ruby-dev:36993]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20293 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2008-11-21 18:27:33 +00:00
parent a48f1bfb81
commit 68a75f19e9
3 changed files with 43 additions and 2 deletions

View File

@ -1,3 +1,10 @@
Fri Nov 21 21:50:54 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
* signal.c (register_sigaltstack): use alternative stack for
SIGSEGV to avoid uncaught stack overflow. based on a patch from
Hiro Yoshioka <hyoshiok at miraclelinux.com> in [ruby-dev:37134].
[ruby-dev:36993]
Fri Nov 21 16:06:54 2008 Yukihiro Matsumoto <matz@ruby-lang.org> Fri Nov 21 16:06:54 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
* vm.c (thread_free): th->vm may be NULL when pthread_create * vm.c (thread_free): th->vm may be NULL when pthread_create

View File

@ -786,7 +786,7 @@ AC_CHECK_FUNCS(fmod killpg wait4 waitpid fork spawnv syscall chroot fsync getcwd
setsid telldir seekdir fchmod cosh sinh tanh log2 round signbit\ setsid telldir seekdir fchmod cosh sinh tanh log2 round signbit\
setuid setgid daemon select_large_fdset setenv unsetenv\ setuid setgid daemon select_large_fdset setenv unsetenv\
mktime timegm gmtime_r clock_gettime gettimeofday\ mktime timegm gmtime_r clock_gettime gettimeofday\
pread sendfile shutdown) pread sendfile shutdown sigaltstack)
AC_CACHE_CHECK(for __builtin_setjmp, ac_cv_func___builtin_setjmp, AC_CACHE_CHECK(for __builtin_setjmp, ac_cv_func___builtin_setjmp,
[AC_TRY_LINK([@%:@include <setjmp.h> [AC_TRY_LINK([@%:@include <setjmp.h>

View File

@ -47,6 +47,11 @@ typedef int rb_atomic_t;
# define NSIG (_SIGMAX + 1) /* For QNX */ # define NSIG (_SIGMAX + 1) /* For QNX */
#endif #endif
#if defined(SIGSEGV) && defined(HAVE_SIGALTSTACK)
#define USE_SIGALTSTACK
int is_altstack_defined = 0;
#endif
static const struct signals { static const struct signals {
const char *signm; const char *signm;
int signo; int signo;
@ -410,6 +415,28 @@ static struct {
typedef RETSIGTYPE (*sighandler_t)(int); typedef RETSIGTYPE (*sighandler_t)(int);
#ifdef POSIX_SIGNAL #ifdef POSIX_SIGNAL
#ifdef USE_SIGALTSTACK
#define ALT_STACK_SIZE (4*1024)
/* alternate stack for SIGSEGV */
static void register_sigaltstack() {
stack_t newSS, oldSS;
if(is_altstack_defined)
return;
newSS.ss_sp = malloc(ALT_STACK_SIZE);
if(newSS.ss_sp == NULL)
/* should handle error */
rb_bug("register_sigaltstack. malloc error\n");
newSS.ss_size = ALT_STACK_SIZE;
newSS.ss_flags = 0;
if (sigaltstack(&newSS, &oldSS) < 0)
rb_bug("register_sigaltstack. error\n");
is_altstack_defined = 1;
}
#endif
static sighandler_t static sighandler_t
ruby_signal(int signum, sighandler_t handler) ruby_signal(int signum, sighandler_t handler)
{ {
@ -432,7 +459,12 @@ ruby_signal(int signum, sighandler_t handler)
if (signum == SIGCHLD && handler == SIG_IGN) if (signum == SIGCHLD && handler == SIG_IGN)
sigact.sa_flags |= SA_NOCLDWAIT; sigact.sa_flags |= SA_NOCLDWAIT;
#endif #endif
sigaction(signum, &sigact, &old); #if defined(SA_ONSTACK) && defined(USE_SIGALTSTACK)
if (signum == SIGSEGV)
sigact.sa_flags |= SA_ONSTACK;
#endif
if (sigaction(signum, &sigact, &old) < 0)
rb_bug("sigaction error.\n");
return old.sa_handler; return old.sa_handler;
} }
@ -663,6 +695,7 @@ default_handler(int sig)
#ifdef SIGSEGV #ifdef SIGSEGV
case SIGSEGV: case SIGSEGV:
func = sigsegv; func = sigsegv;
register_sigaltstack();
break; break;
#endif #endif
#ifdef SIGPIPE #ifdef SIGPIPE
@ -1070,6 +1103,7 @@ Init_signal(void)
install_sighandler(SIGBUS, sigbus); install_sighandler(SIGBUS, sigbus);
#endif #endif
#ifdef SIGSEGV #ifdef SIGSEGV
register_sigaltstack();
install_sighandler(SIGSEGV, sigsegv); install_sighandler(SIGSEGV, sigsegv);
#endif #endif
} }