1 /*
2  *   Copyright (C) Bull S.A. 1996
3  *   Copyright (c) International Business Machines  Corp., 2001
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 2 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
13  *   the 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, write to the Free Software
17  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 /*---------------------------------------------------------------------+
20 |                            signal_test_07                            |
21 | ==================================================================== |
22 |                                                                      |
23 | Description:  Signal stress - send many signals to the process and   |
24 |               verify that it receives every one                      |
25 |                                                                      |
26 | Algorithm:    o  Block all signals from interrupting the process     |
27 |               o  Send MAX signals to the current process             |
28 |               o  Sleep for a short time                              |
29 |               o  Verify that signals are pending                     |
30 |               o  Change the signal mask and suspend execution until  |
31 |                  a signal interrupts the process                     |
32 |               o  Verify that at least one signal was received        |
33 |                                                                      |
34 |                                                                      |
35 | System calls: The following system calls are tested:                 |
36 |                                                                      |
37 |               sigaction () - Specify the action to take upon         |
38 |                              delivery of a signal                    |
39 |               wait () - Waits for a child process to stop or         |
40 |                         terminate                                    |
41 |               kill () - Sends a signal to a process                  |
42 |                                                                      |
43 | Usage:        signal_test_07                                         |
44 |                                                                      |
45 | To compile:   cc -o signal_test_07 signal_test_07                    |
46 |                                                                      |
47 | Last update:   Ver. 1.3, 7/7/94 16:18:19                           |
48 |                                                                      |
49 | Change Activity                                                      |
50 |                                                                      |
51 |   Version  Date    Name  Reason                                      |
52 |    0.1     050689  CTU   Initial version                             |
53 |    0.2     112993  DJK   Rewrite for AIX version 4.1                 |
54 |    1.2     020794  DJK   Move to "prod" directory                    |
55 |                                                                      |
56 +---------------------------------------------------------------------*/
57 
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #include <unistd.h>
62 #include <sys/signal.h>
63 #include <sys/wait.h>
64 #include <errno.h>
65 
66 #ifdef _LINUX_
67 // bits/signum.h defines _NSIG as 64
68 #define SIGMAX 64
69 #endif
70 
71 /* Function prototypes */
72 void handler(int, int, struct sigcontext *);
73 void init_sig();
74 void sys_error(const char *, int);
75 void error(const char *, int);
76 
77 int signals_received = 0;
78 
79 #define MAXSIG 	1024*1024	/* Max interrupts */
80 #define MAXTIME	2		/* Time out (minutes) */
81 
82 /*---------------------------------------------------------------------+
83 |                               main ()                                |
84 | ==================================================================== |
85 |                                                                      |
86 | Function:  Main program  (see prolog for more details)               |
87 |                                                                      |
88 +---------------------------------------------------------------------*/
main(int argc,char ** argv)89 int main(int argc, char **argv)
90 {
91 	int timeout = MAXTIME * 60;	/* Timeout value */
92 	int i;			/* Loop index */
93 	char msg[256];		/* Buffer for error message */
94 
95 	/* Print out program header */
96 	printf("%s: IPC TestSuite program\n\n", *argv);
97 	fflush(stdout);
98 
99 	/* Set up our signal handler */
100 	init_sig();
101 
102 	/*
103 	 * Send MAXSIG signals to the process
104 	 *
105 	 * Using raise, send MAX signals to the process.  Then loop until
106 	 * every signal is caught by the signal handler (or the timer expires).
107 	 */
108 	printf("\tSend MAX (%d) signals to the process...\n", MAXSIG);
109 	fflush(stdout);
110 	for (i = 0; i < MAXSIG; i++)
111 		raise(SIGUSR1);
112 
113 	while (signals_received < MAXSIG && --timeout)
114 		sleep(1);
115 
116 	if (timeout == 0) {
117 		sprintf(msg, "failed to received %d signals in %d minutes\n",
118 			MAXSIG, MAXTIME);
119 		error(msg, __LINE__);
120 	}
121 
122 	/*
123 	 * Received ALL of the sent signals!  Exit with success
124 	 */
125 	printf("\n\tReceived EVERY signal!\n");
126 
127 	printf("\nsuccessful!\n");
128 	return (0);
129 }
130 
131 /*---------------------------------------------------------------------+
132 |                               handler ()                             |
133 | ==================================================================== |
134 |                                                                      |
135 | Function:  Signal handler                                            |
136 |                                                                      |
137 | Parms:     signal - signal number caught                             |
138 |                                                                      |
139 | Returns:   Aborts if an unexpected signal is caught                  |
140 |                                                                      |
141 +---------------------------------------------------------------------*/
handler(int signal,int code,struct sigcontext * scp)142 void handler(int signal, int code, struct sigcontext *scp)
143 {
144 	char msg[256];		/* Buffer for error message */
145 
146 	if (signal == SIGUSR1) {
147 		signals_received++;
148 	} else if (signal == SIGUSR2) {
149 		printf("\tcaught signal (%d)\n", signal);
150 	} else {
151 		sprintf(msg, "caught an unexpected signal (%d)", signal);
152 		error(msg, __LINE__);
153 	}
154 }
155 
156 /*---------------------------------------------------------------------+
157 |                             init_sig ()                              |
158 | ==================================================================== |
159 |                                                                      |
160 | Function:  Initialize the signal vector for ALL possible signals     |
161 |            (as defined in /usr/include/sys/signal.h) except for      |
162 |            the following signals which cannot be caught or ignored:  |
163 |                                                                      |
164 |              o  SIGKILL (9)                                          |
165 |              o  SIGSTOP (17)                                         |
166 |              o  SIGCONT (19)                                         |
167 |                                                                      |
168 | Returns:   n/a                                                       |
169 |                                                                      |
170 +---------------------------------------------------------------------*/
init_sig()171 void init_sig()
172 {
173 	struct sigaction invec;
174 	char msg[256];		/* Buffer for error message */
175 	int i;
176 
177 	for (i = 1; i <= SIGMAX; i++) {
178 
179 		/* Cannot catch or ignore the following signals */
180 #ifdef _IA64			/* SIGWAITING not supported, RESERVED */
181 		if ((i == SIGKILL) || (i == SIGSTOP) ||
182 		    (i == SIGCONT) || (i == SIGWAITING))
183 			continue;
184 #else
185 #ifdef _LINUX_
186 		if ((i == SIGKILL) || (i == SIGSTOP)
187 		    || ((i >= 32) && (i <= 34)))
188 			continue;
189 #else
190 		if (i == SIGKILL || i == SIGSTOP || i == SIGCONT)
191 			continue;
192 #endif
193 #endif
194 
195 		invec.sa_handler = (void (*)(int))handler;
196 		sigemptyset(&invec.sa_mask);
197 		invec.sa_flags = 0;
198 
199 		if (sigaction(i, &invec, NULL) < 0) {
200 			sprintf(msg, "sigaction failed on signal %d", i);
201 			error(msg, __LINE__);
202 		}
203 	}
204 }
205 
206 /*---------------------------------------------------------------------+
207 |                             sys_error ()                             |
208 | ==================================================================== |
209 |                                                                      |
210 | Function:  Creates system error message and calls error ()           |
211 |                                                                      |
212 +---------------------------------------------------------------------*/
sys_error(const char * msg,int line)213 void sys_error(const char *msg, int line)
214 {
215 	char syserr_msg[256];
216 
217 	sprintf(syserr_msg, "%s: %s\n", msg, strerror(errno));
218 	error(syserr_msg, line);
219 }
220 
221 /*---------------------------------------------------------------------+
222 |                               error ()                               |
223 | ==================================================================== |
224 |                                                                      |
225 | Function:  Prints out message and exits...                           |
226 |                                                                      |
227 +---------------------------------------------------------------------*/
error(const char * msg,int line)228 void error(const char *msg, int line)
229 {
230 	fprintf(stderr, "ERROR [line: %d] %s\n", line, msg);
231 	exit(-1);
232 }
233