Imported Upstream version 7.9
[platform/upstream/gdb.git] / gdb / testsuite / gdb.base / sigrepeat.c
1 /* This testcase is part of GDB, the GNU debugger.
2
3    Copyright 2004-2015 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 }