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