Home | History | Annotate | Line # | Download | only in gdb.base
sigaltstack.c revision 1.1.1.4
      1      1.1  christos /* This testcase is part of GDB, the GNU debugger.
      2      1.1  christos 
      3  1.1.1.4  christos    Copyright 2004-2017 Free Software Foundation, Inc.
      4      1.1  christos 
      5      1.1  christos    This program is free software; you can redistribute it and/or modify
      6      1.1  christos    it under the terms of the GNU General Public License as published by
      7      1.1  christos    the Free Software Foundation; either version 3 of the License, or
      8      1.1  christos    (at your option) any later version.
      9      1.1  christos 
     10      1.1  christos    This program is distributed in the hope that it will be useful,
     11      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     12      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13      1.1  christos    GNU General Public License for more details.
     14      1.1  christos 
     15      1.1  christos    You should have received a copy of the GNU General Public License
     16      1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     17      1.1  christos 
     18      1.1  christos #include <signal.h>
     19      1.1  christos #include <stdio.h>
     20      1.1  christos #include <stdlib.h>
     21      1.1  christos #include <string.h>
     22      1.1  christos #include <sys/time.h>
     23      1.1  christos 
     24      1.1  christos enum level { MAIN, OUTER, INNER, LEAF, NR_LEVELS };
     25      1.1  christos 
     26      1.1  christos /* Levels completed flag.  */
     27      1.1  christos volatile enum level level = NR_LEVELS;
     28      1.1  christos 
     29      1.1  christos void catcher (int signal);
     30      1.1  christos 
     31      1.1  christos void
     32      1.1  christos thrower (enum level next_level, int sig, int itimer, int on_stack)
     33      1.1  christos {
     34      1.1  christos   level = next_level;
     35      1.1  christos   /* Set up the signal handler.  */
     36      1.1  christos   {
     37      1.1  christos     struct sigaction act;
     38      1.1  christos     memset (&act, 0, sizeof (act));
     39      1.1  christos     act.sa_handler = catcher;
     40      1.1  christos     act.sa_flags |= on_stack;
     41      1.1  christos     sigaction (sig, &act, NULL);
     42      1.1  christos   }
     43      1.1  christos   /* Set up a one-off timer.  A timer, rather than SIGSEGV, is used as
     44      1.1  christos      after a timer handler finishes the interrupted code can safely
     45      1.1  christos      resume.  */
     46      1.1  christos   {
     47      1.1  christos     struct itimerval itime;
     48      1.1  christos     memset (&itime, 0, sizeof (itime));
     49      1.1  christos     itime.it_value.tv_usec = 250 * 1000;
     50      1.1  christos     setitimer (itimer, &itime, NULL);
     51      1.1  christos   }
     52      1.1  christos   /* Wait.  */
     53      1.1  christos   while (level != LEAF);
     54      1.1  christos }
     55      1.1  christos 
     56      1.1  christos void
     57      1.1  christos catcher (int signal)
     58      1.1  christos {
     59      1.1  christos   /* Find the next level.  */
     60      1.1  christos   switch (level)
     61      1.1  christos     {
     62      1.1  christos     case MAIN:
     63      1.1  christos       thrower (OUTER, SIGALRM, ITIMER_REAL, SA_ONSTACK);
     64      1.1  christos       break;
     65      1.1  christos     case OUTER:
     66      1.1  christos       thrower (INNER, SIGVTALRM, ITIMER_VIRTUAL, SA_ONSTACK);
     67      1.1  christos       break;
     68      1.1  christos     case INNER:
     69      1.1  christos       level = LEAF;
     70      1.1  christos       return;
     71      1.1  christos     }
     72      1.1  christos }
     73      1.1  christos 
     74      1.1  christos 
     75  1.1.1.2  christos int
     76      1.1  christos main ()
     77      1.1  christos {
     78      1.1  christos   /* Set up the altstack.  */
     79      1.1  christos   {
     80      1.1  christos     static char stack[SIGSTKSZ * NR_LEVELS];
     81      1.1  christos     stack_t alt;
     82      1.1  christos     memset (&alt, 0, sizeof (alt));
     83      1.1  christos     alt.ss_sp = stack;
     84      1.1  christos     alt.ss_size = SIGSTKSZ;
     85      1.1  christos     alt.ss_flags = 0;
     86      1.1  christos     if (sigaltstack (&alt, NULL) < 0)
     87      1.1  christos       {
     88      1.1  christos 	perror ("sigaltstack");
     89      1.1  christos 	exit (0);
     90      1.1  christos       }
     91      1.1  christos   }
     92      1.1  christos   level = MAIN;
     93      1.1  christos   catcher (0);
     94  1.1.1.2  christos   return 0;
     95      1.1  christos }
     96