Bump to m4 1.4.19
[platform/upstream/m4.git] / m4 / sigaltstack.m4
1 # sigaltstack.m4 serial 14
2 dnl Copyright (C) 2002-2021 Bruno Haible <bruno@clisp.org>
3 dnl Copyright (C) 2008 Eric Blake <ebb9@byu.net>
4 dnl This file is free software, distributed under the terms of the GNU
5 dnl General Public License.  As a special exception to the GNU General
6 dnl Public License, this file may be distributed as part of a program
7 dnl that contains a configuration script generated by Autoconf, under
8 dnl the same distribution terms as the rest of that program.
9
10 AC_DEFUN([SV_SIGALTSTACK],
11 [
12   AC_REQUIRE([AC_PROG_CC])
13   AC_REQUIRE([AC_CANONICAL_HOST])
14
15   AC_CHECK_FUNCS_ONCE([sigaltstack setrlimit])
16
17   if test "$ac_cv_func_sigaltstack" = yes; then
18     AC_CHECK_TYPE([stack_t], ,
19       [AC_DEFINE(stack_t, [struct sigaltstack],
20          [Define to 'struct sigaltstack' if that's the type of the argument to sigaltstack])
21       ],
22       [
23 #include <signal.h>
24 #if HAVE_SYS_SIGNAL_H
25 # include <sys/signal.h>
26 #endif
27       ])
28   fi
29
30   AC_CACHE_CHECK([for working sigaltstack], [sv_cv_sigaltstack], [
31     if test "$ac_cv_func_sigaltstack" = yes; then
32       case "$host_os" in
33         macos* | darwin[[6-9]]* | darwin[[1-9]][[0-9]]*)
34           # On MacOS X 10.2 or newer, just assume that if it compiles, it will
35           # work. If we were to perform the real test, 1 Crash Report dialog
36           # window would pop up.
37           AC_LINK_IFELSE([
38             AC_LANG_PROGRAM([[#include <signal.h>]],
39               [[int x = SA_ONSTACK; stack_t ss; sigaltstack ((stack_t*)0, &ss);]])],
40             [sv_cv_sigaltstack="guessing yes"],
41             [sv_cv_sigaltstack=no])
42           ;;
43         *)
44           AC_RUN_IFELSE([
45             AC_LANG_SOURCE([[
46 #include <stdlib.h>
47 #include <signal.h>
48 #if HAVE_SYS_SIGNAL_H
49 # include <sys/signal.h>
50 #endif
51 #if HAVE_SETRLIMIT
52 # include <sys/types.h>
53 # include <sys/time.h>
54 # include <sys/resource.h>
55 #endif
56 void stackoverflow_handler (int sig)
57 {
58   /* If we get here, the stack overflow was caught.  */
59   exit (0);
60 }
61 volatile int * recurse_1 (volatile int n, volatile int *p)
62 {
63   if (n >= 0)
64     *recurse_1 (n + 1, p) += n;
65   return p;
66 }
67 int recurse (volatile int n)
68 {
69   int sum = 0;
70   return *recurse_1 (n, &sum);
71 }
72 char mystack[2 * (1 << 24)];
73 int main ()
74 {
75   stack_t altstack;
76   struct sigaction action;
77 #if defined HAVE_SETRLIMIT && defined RLIMIT_STACK
78   /* Before starting the endless recursion, try to be friendly to the user's
79      machine.  On some Linux 2.2.x systems, there is no stack limit for user
80      processes at all.  We don't want to kill such systems.  */
81   struct rlimit rl;
82   rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
83   setrlimit (RLIMIT_STACK, &rl);
84 #endif
85   /* Install the alternate stack.  Use the midpoint of mystack, to guard
86      against a buggy interpretation of ss_sp on IRIX.  */
87 #ifdef SIGSTKSZ
88   if (sizeof mystack / 2 < SIGSTKSZ)
89     exit (3);
90 #endif
91   altstack.ss_sp = mystack + sizeof mystack / 2;
92   altstack.ss_size = sizeof mystack / 2;
93   altstack.ss_flags = 0; /* no SS_DISABLE */
94   if (sigaltstack (&altstack, NULL) < 0)
95     exit (1);
96   /* Install the SIGSEGV handler.  */
97   sigemptyset (&action.sa_mask);
98   action.sa_handler = &stackoverflow_handler;
99   action.sa_flags = SA_ONSTACK;
100   sigaction (SIGSEGV, &action, (struct sigaction *) NULL);
101   sigaction (SIGBUS, &action, (struct sigaction *) NULL);
102   /* Provoke a stack overflow.  */
103   recurse (0);
104   exit (2);
105 }]])],
106             [sv_cv_sigaltstack=yes],
107             [sv_cv_sigaltstack=no],
108             [
109               dnl FIXME: Put in some more known values here.
110               case "$host_os" in
111                 *)
112                   AC_LINK_IFELSE([
113                     AC_LANG_PROGRAM([[#include <signal.h>]],
114                       [[int x = SA_ONSTACK; stack_t ss; sigaltstack ((stack_t*)0, &ss);]])],
115                     [sv_cv_sigaltstack="guessing yes"],
116                     [sv_cv_sigaltstack=no])
117                   ;;
118               esac
119             ])
120           ;;
121       esac
122     else
123       sv_cv_sigaltstack=no
124     fi
125   ])
126   if test "$sv_cv_sigaltstack" != no; then
127     AC_DEFINE([HAVE_WORKING_SIGALTSTACK], [1],
128       [Define if you have the sigaltstack() function and it works.])
129
130     dnl The ss_sp field of a stack_t is, according to POSIX, the lowest address
131     dnl of the memory block designated as an alternate stack. But IRIX 5.3
132     dnl interprets it as the highest address!
133     AC_CACHE_CHECK([for correct stack_t interpretation],
134       [sv_cv_sigaltstack_low_base], [
135       AC_RUN_IFELSE([
136         AC_LANG_SOURCE([[
137 #include <stdlib.h>
138 #include <signal.h>
139 #if HAVE_SYS_SIGNAL_H
140 # include <sys/signal.h>
141 #endif
142 volatile char *stack_lower_bound;
143 volatile char *stack_upper_bound;
144 static void check_stack_location (volatile char *addr)
145 {
146   if (addr >= stack_lower_bound && addr <= stack_upper_bound)
147     exit (0);
148   else
149     exit (1);
150 }
151 static void stackoverflow_handler (int sig)
152 {
153   char dummy;
154   check_stack_location (&dummy);
155 }
156 char mystack[2 * (1 << 24)];
157 int main ()
158 {
159   stack_t altstack;
160   struct sigaction action;
161   /* Install the alternate stack.  */
162   altstack.ss_sp = mystack + sizeof mystack / 2;
163   altstack.ss_size = sizeof mystack / 2;
164   stack_lower_bound = (char *) altstack.ss_sp;
165   stack_upper_bound = (char *) altstack.ss_sp + altstack.ss_size - 1;
166   altstack.ss_flags = 0; /* no SS_DISABLE */
167   if (sigaltstack (&altstack, NULL) < 0)
168     exit (2);
169   /* Install the SIGSEGV handler.  */
170   sigemptyset (&action.sa_mask);
171   action.sa_handler = &stackoverflow_handler;
172   action.sa_flags = SA_ONSTACK;
173   if (sigaction (SIGSEGV, &action, (struct sigaction *) NULL) < 0)
174     exit(3);
175   /* Provoke a SIGSEGV.  */
176   raise (SIGSEGV);
177   exit (3);
178 }]])],
179       [sv_cv_sigaltstack_low_base=yes],
180       [sv_cv_sigaltstack_low_base=no],
181       [
182         dnl FIXME: Put in some more known values here.
183         case "$host_os" in
184           irix5*) sv_cv_sigaltstack_low_base="no" ;;
185           *)      sv_cv_sigaltstack_low_base="guessing yes" ;;
186         esac
187       ])
188     ])
189     if test "$sv_cv_sigaltstack_low_base" = no; then
190       AC_DEFINE([SIGALTSTACK_SS_REVERSED], [1],
191         [Define if sigaltstack() interprets the stack_t.ss_sp field incorrectly,
192          as the highest address of the alternate stack range rather than as the
193          lowest address.])
194     fi
195   fi
196 ])