diff options
author | Andrew Cagney <cagney@redhat.com> | 2004-04-05 21:00:21 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 2004-04-05 21:00:21 +0000 |
commit | c5530df284953865b79931e0f9738ccfdb39c93c (patch) | |
tree | fb485e77875cc851e26adad591068a157e376a15 /gdb/testsuite/gdb.base/sigaltstack.c | |
parent | 7fa8936029f4f27a703ae96a994b7c88e14656b4 (diff) | |
download | gdb-c5530df284953865b79931e0f9738ccfdb39c93c.tar.gz |
2004-04-05 Andrew Cagney <cagney@redhat.com>
* gdb.base/sigaltstack.c: New file.
* gdb.base/sigaltstack.exp: New file.
Diffstat (limited to 'gdb/testsuite/gdb.base/sigaltstack.c')
-rw-r--r-- | gdb/testsuite/gdb.base/sigaltstack.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.base/sigaltstack.c b/gdb/testsuite/gdb.base/sigaltstack.c new file mode 100644 index 00000000000..afcc8fbcb38 --- /dev/null +++ b/gdb/testsuite/gdb.base/sigaltstack.c @@ -0,0 +1,95 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 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 of the License, 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. + + Please email any bugs, comments, and/or additions to this file to: + bug-gdb@prep.ai.mit.edu */ + +#include <signal.h> +#include <stdio.h> +#include <sys/time.h> + +enum level { MAIN, OUTER, INNER, LEAF, NR_LEVELS }; + +/* Levels completed flag. */ +volatile enum level level = NR_LEVELS; + +void catcher (int signal); + +void +thrower (enum level next_level, int sig, int itimer, int on_stack) +{ + level = next_level; + /* Set up the signal handler. */ + { + struct sigaction act; + memset (&act, 0, sizeof (act)); + act.sa_handler = catcher; + act.sa_flags |= on_stack; + sigaction (sig, &act, NULL); + } + /* Set up a one-off timer. A timer, rather than SIGSEGV, is used as + after a timer handler finishes the interrupted code can safely + resume. */ + { + struct itimerval itime; + memset (&itime, 0, sizeof (itime)); + itime.it_value.tv_usec = 250 * 1000; + setitimer (itimer, &itime, NULL); + } + /* Wait. */ + while (level != LEAF); +} + +void +catcher (int signal) +{ + /* Find the next level. */ + switch (level) + { + case MAIN: + thrower (OUTER, SIGALRM, ITIMER_REAL, SA_ONSTACK); + break; + case OUTER: + thrower (INNER, SIGVTALRM, ITIMER_VIRTUAL, SA_ONSTACK); + break; + case INNER: + level = LEAF; + return; + } +} + + +main () +{ + /* Set up the altstack. */ + { + static char stack[SIGSTKSZ * NR_LEVELS]; + struct sigaltstack alt; + memset (&alt, 0, sizeof (alt)); + alt.ss_sp = stack; + alt.ss_size = SIGSTKSZ; + alt.ss_flags = 0; + if (sigaltstack (&alt, NULL) < 0) + { + perror ("sigaltstack"); + exit (0); + } + } + level = MAIN; + catcher (0); +} |