1/* This testcase is part of GDB, the GNU debugger. 2 3 Copyright 2004, 2005, 2007 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 26static volatile int done[2]; 27static volatile int repeats[2]; 28static int itimer[2] = { ITIMER_REAL, ITIMER_VIRTUAL }; 29static int alarm[2] = { SIGALRM, SIGVTALRM }; 30 31static void 32handler (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 76int 77main () 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