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 | 44f4de1ac3147b7e968eef5d859de4d1a3f82ac0 (patch) | |
tree | 54c270e4358ea9ecb2ad4a6e18efe079dc39aa14 /gdb/testsuite/gdb.base/sigaltstack.c | |
parent | 24d18d3088761bd75b7b2aec6d2861e7cd85a2dc (diff) | |
download | gdb-44f4de1ac3147b7e968eef5d859de4d1a3f82ac0.zip gdb-44f4de1ac3147b7e968eef5d859de4d1a3f82ac0.tar.gz gdb-44f4de1ac3147b7e968eef5d859de4d1a3f82ac0.tar.bz2 |
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 0000000..afcc8fb --- /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); +} |