Home | History | Annotate | Line # | Download | only in gdb.base
sigrepeat.c revision 1.10
      1 /* This testcase is part of GDB, the GNU debugger.
      2 
      3    Copyright 2004-2023 Free Software Foundation, Inc.
      4 
      5    This program is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU General Public License as published by
      7    the Free Software Foundation; either version 3 of the License, or
      8    (at your option) any later version.
      9 
     10    This program is distributed in the hope that it will be useful,
     11    but WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13    GNU General Public License for more details.
     14 
     15    You should have received a copy of the GNU General Public License
     16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18 */
     19 
     20 #include <stdio.h>
     21 #include <stdlib.h>
     22 #include <string.h>
     23 #include <signal.h>
     24 #include <sys/time.h>
     25 
     26 static volatile int done[2];
     27 static volatile int repeats[2];
     28 static int itimer[2] = { ITIMER_REAL, ITIMER_VIRTUAL };
     29 static int alarm[2] = { SIGALRM, SIGVTALRM };
     30 
     31 static void
     32 handler (int sig)
     33 {
     34   int sigi;
     35   switch (sig)
     36     {
     37     case SIGALRM: sigi = 0; break;
     38     case SIGVTALRM: sigi = 1; break;
     39     default: abort ();
     40     }
     41   if (repeats[sigi]++ > 3)
     42     {
     43       /* Hit with enough signals, cancel everything and get out.  */
     44       {
     45 	struct itimerval itime;
     46 	memset (&itime, 0, sizeof (itime));
     47 	setitimer (itimer[sigi], &itime, NULL);
     48       }
     49       {
     50 	struct sigaction action;
     51 	memset (&action, 0, sizeof (action));
     52 	action.sa_handler = SIG_IGN;
     53 	sigaction (sig, &action, NULL);
     54       }
     55       done[sigi] = 1;
     56       return;
     57     }
     58   /* Set up a nested virtual timer.  */
     59   while (1)
     60     {
     61       /* Wait until a signal has become pending, that way when this
     62 	 handler returns it will be immediatly delivered leading to
     63 	 back-to-back signals.  */
     64       sigset_t set;
     65       sigemptyset (&set);
     66       if (sigpending (&set) < 0)
     67 	{
     68 	  perror ("sigrepeat");
     69 	  abort ();
     70 	}
     71       if (sigismember (&set, sig))
     72 	break;
     73     }
     74 } /* handler */
     75 
     76 int
     77 main ()
     78 {
     79   int i;
     80   /* Set up the signal handler.  */
     81   for (i = 0; i < 2; i++)
     82     {
     83       struct sigaction action;
     84       memset (&action, 0, sizeof (action));
     85       action.sa_handler = handler;
     86       sigaction (alarm[i], &action, NULL);
     87     }
     88 
     89   /* Set up a rapidly repeating timers.  A timer, rather than SIGSEGV,
     90      is used as after a timer handler returns the interrupted code can
     91      safely resume.  The intent is for the program to swamp GDB with a
     92      backlog of pending signals.  */
     93   for (i = 0; i < 2; i++)
     94     {
     95       struct itimerval itime;
     96       memset (&itime, 0, sizeof (itime));
     97       itime.it_interval.tv_usec = 1;
     98       itime.it_value.tv_usec = 250 * 1000;
     99       setitimer (itimer[i], &itime, NULL);
    100     }
    101 
    102   /* Wait.  */
    103   while (!done[0] && !done[1]); /* infinite loop */
    104   return 0;
    105 }
    106