aboutsummaryrefslogtreecommitdiffstats
path: root/libsigsegv/m4/sigaltstack-longjmp.m4
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2010-07-16 14:52:31 +0300
committerArnold D. Robbins <arnold@skeeve.com>2010-07-16 14:52:31 +0300
commit3ba50a15ebd976f7a88393e2e45dc14b6478b9a9 (patch)
tree6a6bbe6bed1141051fefe94b2d39eacd4854235a /libsigsegv/m4/sigaltstack-longjmp.m4
parent6a2caf2157d87b4b582b2494bdd7d6a688dd0b1f (diff)
downloadegawk-3ba50a15ebd976f7a88393e2e45dc14b6478b9a9.tar.gz
egawk-3ba50a15ebd976f7a88393e2e45dc14b6478b9a9.tar.bz2
egawk-3ba50a15ebd976f7a88393e2e45dc14b6478b9a9.zip
Move to gawk-3.1.7.
Diffstat (limited to 'libsigsegv/m4/sigaltstack-longjmp.m4')
-rw-r--r--libsigsegv/m4/sigaltstack-longjmp.m4100
1 files changed, 100 insertions, 0 deletions
diff --git a/libsigsegv/m4/sigaltstack-longjmp.m4 b/libsigsegv/m4/sigaltstack-longjmp.m4
new file mode 100644
index 00000000..1f72a19e
--- /dev/null
+++ b/libsigsegv/m4/sigaltstack-longjmp.m4
@@ -0,0 +1,100 @@
+# sigaltstack-longjmp.m4 serial 6 (libsigsegv-2.7)
+dnl Copyright (C) 2002-2003, 2006, 2008 Bruno Haible <bruno@clisp.org>
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl How to longjmp out of a signal handler, in such a way that the
+dnl alternate signal stack remains functional.
+dnl SV_TRY_LEAVE_HANDLER_LONGJMP(KIND, CACHESYMBOL, KNOWN-SYSTEMS,
+dnl INCLUDES, RESETCODE)
+AC_DEFUN([SV_TRY_LEAVE_HANDLER_LONGJMP],
+[
+ AC_REQUIRE([AC_PROG_CC])
+ AC_REQUIRE([AC_CANONICAL_HOST])
+
+ AC_CACHE_CHECK([whether a signal handler can be left through longjmp$1], [$2], [
+ AC_RUN_IFELSE([
+ AC_LANG_SOURCE([[
+#include <stdlib.h>
+#include <signal.h>
+#include <setjmp.h>
+$4
+#if HAVE_SETRLIMIT
+# include <sys/types.h>
+# include <sys/time.h>
+# include <sys/resource.h>
+#endif
+#ifndef SIGSTKSZ
+# define SIGSTKSZ 16384
+#endif
+jmp_buf mainloop;
+sigset_t mainsigset;
+int pass = 0;
+void stackoverflow_handler (int sig)
+{
+ pass++;
+ sigprocmask (SIG_SETMASK, &mainsigset, NULL);
+ { $5 }
+ longjmp (mainloop, pass);
+}
+volatile int * recurse_1 (volatile int n, volatile int *p)
+{
+ if (n >= 0)
+ *recurse_1 (n + 1, p) += n;
+ return p;
+}
+int recurse (volatile int n)
+{
+ int sum = 0;
+ return *recurse_1 (n, &sum);
+}
+int main ()
+{
+ char mystack[2 * SIGSTKSZ];
+ stack_t altstack;
+ struct sigaction action;
+ sigset_t emptyset;
+#if defined 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
+ /* Install the alternate stack. Use the midpoint of mystack, to guard
+ against a buggy interpretation of ss_sp on IRIX. */
+ altstack.ss_sp = mystack + SIGSTKSZ;
+ altstack.ss_size = SIGSTKSZ;
+ altstack.ss_flags = 0; /* no SS_DISABLE */
+ if (sigaltstack (&altstack, NULL) < 0)
+ exit (1);
+ /* Install the SIGSEGV handler. */
+ sigemptyset (&action.sa_mask);
+ action.sa_handler = &stackoverflow_handler;
+ action.sa_flags = SA_ONSTACK;
+ sigaction (SIGSEGV, &action, (struct sigaction *) NULL);
+ sigaction (SIGBUS, &action, (struct sigaction *) NULL);
+ /* Save the current signal mask. */
+ sigemptyset (&emptyset);
+ sigprocmask (SIG_BLOCK, &emptyset, &mainsigset);
+ /* Provoke two stack overflows in a row. */
+ if (setjmp (mainloop) < 2)
+ {
+ recurse (0);
+ exit (2);
+ }
+ exit (0);
+}]])],
+ [$2=yes],
+ [$2=no],
+ [case "$host" in
+ m4_if([$3], [], [], [[$3]) $2=yes ;;])
+ *) $2="guessing no" ;;
+ esac
+ ])
+ ])
+])