# Check prerequisites for compiling lib/c-stack.c.
-# Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-# 02111-1307, USA.
+# Copyright (C) 2002, 2003, 2004, 2008 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
# Written by Paul Eggert.
+# serial 6
+
AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC],
[# for STACK_DIRECTION
AC_REQUIRE([AC_FUNC_ALLOCA])
- AC_CHECK_FUNCS(setrlimit)
+ AC_CHECK_FUNCS_ONCE([setrlimit])
+ AC_CHECK_HEADERS_ONCE([ucontext.h])
AC_CACHE_CHECK([for working C stack overflow detection],
+ [ac_cv_sys_stack_overflow_works],
+ [AC_TRY_RUN(
+ [
+ #include <unistd.h>
+ #include <signal.h>
+ #if HAVE_SETRLIMIT
+ # include <sys/types.h>
+ # include <sys/time.h>
+ # include <sys/resource.h>
+ #endif
+ #ifndef SIGSTKSZ
+ # define SIGSTKSZ 16384
+ #endif
+
+ static union
+ {
+ char buffer[SIGSTKSZ];
+ long double ld;
+ long u;
+ void *p;
+ } alternate_signal_stack;
+
+ static void
+ segv_handler (int signo)
+ {
+ _exit (0);
+ }
+
+ static int
+ c_stack_action ()
+ {
+ stack_t st;
+ struct sigaction act;
+ int r;
+
+ st.ss_flags = 0;
+ st.ss_sp = alternate_signal_stack.buffer;
+ st.ss_size = sizeof alternate_signal_stack.buffer;
+ r = sigaltstack (&st, 0);
+ if (r != 0)
+ return r;
+
+ sigemptyset (&act.sa_mask);
+ act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND;
+ act.sa_handler = segv_handler;
+ return sigaction (SIGSEGV, &act, 0);
+ }
+
+ static int
+ recurse (char *p)
+ {
+ char array[500];
+ array[0] = 1;
+ return *p + recurse (array);
+ }
+
+ int
+ main ()
+ {
+ #if HAVE_SETRLIMIT && defined RLIMIT_STACK
+ /* Before starting the endless recursion, try to be friendly
+ to the user's machine. On some Linux 2.2.x systems, there
+ is no stack limit for user processes at all. We don't want
+ to kill such systems. */
+ struct rlimit rl;
+ rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
+ setrlimit (RLIMIT_STACK, &rl);
+ #endif
+
+ return c_stack_action () || recurse ("\1");
+ }
+ ],
+ [ac_cv_sys_stack_overflow_works=yes],
+ [ac_cv_sys_stack_overflow_works=no],
+ [ac_cv_sys_stack_overflow_works=cross-compiling])])
+
+ if test $ac_cv_sys_stack_overflow_works = yes; then
+ AC_DEFINE([HAVE_STACK_OVERFLOW_HANDLING], [1],
+ [Define to 1 if extending the stack slightly past the limit causes
+ a SIGSEGV which can be handled on an alternate stack established
+ with sigaltstack.])
+
+ AC_CACHE_CHECK([for precise C stack overflow detection],
ac_cv_sys_xsi_stack_overflow_heuristic,
[AC_TRY_RUN(
[
#include <unistd.h>
#include <signal.h>
- #include <ucontext.h>
+ #if HAVE_UCONTEXT_H
+ # include <ucontext.h>
+ #endif
#if HAVE_SETRLIMIT
# include <sys/types.h>
# include <sys/time.h>
# include <sys/resource.h>
#endif
+ #ifndef SIGSTKSZ
+ # define SIGSTKSZ 16384
+ #endif
static union
{
{
if (0 < info->si_code)
{
+ /* For XSI heuristics to work, we need uc_stack to describe
+ the interrupted stack (as on Solaris), and not the
+ currently executing stack (as on Linux). */
ucontext_t const *user_context = context;
char const *stack_min = user_context->uc_stack.ss_sp;
size_t stack_size = user_context->uc_stack.ss_size;
}
static int
- c_stack_action (void)
+ c_stack_action ()
{
stack_t st;
struct sigaction act;
}
int
- main (void)
+ main ()
{
#if HAVE_SETRLIMIT && defined RLIMIT_STACK
/* Before starting the endless recursion, try to be friendly
setrlimit (RLIMIT_STACK, &rl);
#endif
- c_stack_action ();
- return recurse ("\1");
+ return c_stack_action () || recurse ("\1");
}
],
[ac_cv_sys_xsi_stack_overflow_heuristic=yes],
a SIGSEGV, and an alternate stack can be established with sigaltstack,
and the signal handler is passed a context that specifies the
run time stack. This behavior is defined by POSIX 1003.1-2001
- with the X/Open System Interface (XSI) option
+ with the X/Open System Interface (XSI) option
and is a standardized way to implement a SEGV-based stack
- overflow detection heuristic.])
- fi])
+ overflow detection heuristic.])
+ fi
+ fi])
AC_DEFUN([gl_PREREQ_C_STACK],
[AC_REQUIRE([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC])
+ AC_REQUIRE([gl_LIBSIGSEGV])
# for STACK_DIRECTION
AC_REQUIRE([AC_FUNC_ALLOCA])
- AC_CHECK_FUNCS(getcontext sigaltstack)
- AC_CHECK_DECLS([getcontext], , , [#include <ucontext.h>])
+ AC_CHECK_FUNCS_ONCE([sigaltstack])
AC_CHECK_DECLS([sigaltstack], , , [#include <signal.h>])
- AC_CHECK_HEADERS_ONCE(sys/time.h unistd.h)
- AC_CHECK_HEADERS(sys/resource.h ucontext.h)
+ AC_CHECK_HEADERS_ONCE([unistd.h ucontext.h])
- AC_CHECK_MEMBERS([struct sigaction.sa_sigaction], , , [#include <signal.h>])
+ AC_CHECK_TYPES([stack_t], , , [#include <signal.h>])
- AC_CHECK_TYPES([stack_t], , , [#include <signal.h>])])
+ dnl c-stack does not need -lsigsegv if the system has XSI heuristics.
+ if test "$gl_cv_lib_sigsegv" = yes \
+ && test $"ac_cv_sys_xsi_stack_overflow_heuristic" != yes ; then
+ AC_SUBST([LIBCSTACK], [$LIBSIGSEGV])
+ AC_SUBST([LTLIBCSTACK], [$LTLIBSIGSEGV])
+ fi
+])
AC_DEFUN([gl_C_STACK],
[