Clarify license of the *.m4 files.
[libsigsegv.git] / m4 / sigaltstack-siglongjmp.m4
blob0d2d4bcbc064798c7505235fd47588b7f5bc56e2
1 # sigaltstack-siglongjmp.m4
2 # serial 8 (libsigsegv-2.15)
3 dnl Copyright (C) 2002-2024 Bruno Haible <bruno@clisp.org>
4 dnl This file is free software, distributed under the terms of the GNU
5 dnl General Public License as published by the Free Software Foundation;
6 dnl either version 2 of the License, or (at your option) any later version.
7 dnl As a special exception to the GNU General Public License, this file
8 dnl may be distributed as part of a program that contains a configuration
9 dnl script generated by Autoconf, under the same distribution terms as
10 dnl the rest of that program.
12 dnl How to siglongjmp out of a signal handler, in such a way that the
13 dnl alternate signal stack remains functional.
14 dnl SV_TRY_LEAVE_HANDLER_SIGLONGJMP(KIND, CACHESYMBOL, KNOWN-SYSTEMS,
15 dnl                                 INCLUDES, RESETCODE)
16 AC_DEFUN([SV_TRY_LEAVE_HANDLER_SIGLONGJMP],
18   AC_REQUIRE([AC_PROG_CC])
19   AC_REQUIRE([AC_CANONICAL_HOST])
21   AC_CACHE_CHECK([whether a signal handler can be left through siglongjmp$1], [$2], [
22     AC_RUN_IFELSE([
23       AC_LANG_SOURCE([[
24 #include <stdlib.h>
25 #include <signal.h>
26 #include <setjmp.h>
28 #if HAVE_SETRLIMIT
29 # include <sys/types.h>
30 # include <sys/time.h>
31 # include <sys/resource.h>
32 #endif
33 /* In glibc >= 2.34, when _GNU_SOURCE is defined, SIGSTKSZ is no longer a
34    compile-time constant.  But we need a simple constant here.  */
35 #if __GLIBC__ >= 2
36 # undef SIGSTKSZ
37 # if defined __ia64__
38 #  define SIGSTKSZ 262144
39 # else
40 #  define SIGSTKSZ 16384
41 # endif
42 #endif
43 #ifndef SIGSTKSZ
44 # define SIGSTKSZ 16384
45 #endif
46 sigjmp_buf mainloop;
47 int pass = 0;
48 void stackoverflow_handler (int sig)
50   pass++;
51   { $5 }
52   siglongjmp (mainloop, pass);
54 volatile int * recurse_1 (volatile int n, volatile int *p)
56   if (n >= 0)
57     *recurse_1 (n + 1, p) += n;
58   return p;
60 int recurse (volatile int n)
62   int sum = 0;
63   return *recurse_1 (n, &sum);
65 char mystack[2 * SIGSTKSZ];
66 int main ()
68   stack_t altstack;
69   struct sigaction action;
70 #ifdef __BEOS__
71   /* On BeOS, this would hang, burning CPU time.  Better fail than hang.  */
72   exit (1);
73 #endif
74 #if defined HAVE_SETRLIMIT && defined RLIMIT_STACK
75   /* Before starting the endless recursion, try to be friendly to the user's
76      machine.  On some Linux 2.2.x systems, there is no stack limit for user
77      processes at all.  We don't want to kill such systems.  */
78   struct rlimit rl;
79   rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
80   setrlimit (RLIMIT_STACK, &rl);
81 #endif
82   /* Install the alternate stack.  Use the midpoint of mystack, to guard
83      against a buggy interpretation of ss_sp on IRIX.  */
84   altstack.ss_sp = mystack + SIGSTKSZ;
85   altstack.ss_size = SIGSTKSZ;
86   altstack.ss_flags = 0; /* no SS_DISABLE */
87   if (sigaltstack (&altstack, NULL) < 0)
88     exit (1);
89   /* Install the SIGSEGV handler.  */
90   sigemptyset (&action.sa_mask);
91   action.sa_handler = &stackoverflow_handler;
92   action.sa_flags = SA_ONSTACK;
93   sigaction (SIGSEGV, &action, (struct sigaction *) NULL);
94   sigaction (SIGBUS, &action, (struct sigaction *) NULL);
95   /* Provoke two stack overflows in a row.  */
96   if (sigsetjmp (mainloop, 1) < 2)
97     {
98       recurse (0);
99       exit (2);
100     }
101   exit (0);
102 }]])],
103       [$2=yes],
104       [$2=no],
105       [case "$host" in
106          m4_if([$3], [], [], [[$3]) $2=yes ;;])
107          *) $2="guessing no" ;;
108        esac
109       ])
110   ])