• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_01                             |
21 | ==================================================================== |
22 |                                                                      |
23 | Description:  Simplistic test to verify the signal system function   |
24 |               calls:                                                 |
25 |                                                                      |
26 | Algorithm:    o  Setup a signal-catching function for every possible |
27 |                  signal                                              |
28 |               o  Send signals to the process and verify that they    |
29 |                  were received by the signal-catching function       |
30 |               o  Block a few signals by changing the process signal  |
31 |                  mask.  Send signals to the process and verify that  |
32 |                  they indeed were blocked                            |
33 |               o  Add additional signals to the process signal mask.  |
34 |                  Verify that they were blocked too                   |
35 |               o  Change the process signal mask to unblock one       |
36 |                  signal and suspend execution of the process until   |
37 |                  the signal is received.  Verify that the unblocked  |
38 |                  signal is received                                  |
39 |                                                                      |
40 | System calls: The following system calls are tested:                 |
41 |                                                                      |
42 |               sigstack () - Sets signal stack context                |
43 |               sigsetmask () - Sets the current signal mask           |
44 |               sigblock () - Sets the current signal mask             |
45 |               sigpause () - Automically changes the set of blocked   |
46 |                             signals and waits for a signal           |
47 |               sigvec () - Specify the action to take upon delivery   |
48 |                           of a signal.                               |
49 |               kill () - Sends a signal to a process                  |
50 |                                                                      |
51 | Usage:        signal_test_01                                         |
52 |                                                                      |
53 | To compile:   cc -o signal_test_01 signal_test_01.c                  |
54 |                                                                      |
55 | Last update:   Ver. 1.3, 4 June 2001                                 |
56 |                                                                      |
57 | Change Activity                                                      |
58 |                                                                      |
59 |   Version  Date    Name  Reason                                      |
60 |    0.1     050689  CTU   Initial version                             |
61 |    0.2     112293  DJK   Rewrite for AIX version 4.1                 |
62 |    1.2     020794  DJK   Move to "prod" directory                    |
63 |    1.3     060401  VHM   Port to work in linux                       |
64 |                                                                      |
65 +---------------------------------------------------------------------*/
66 
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include <string.h>
70 #include <errno.h>
71 #ifdef _LINUX_
72 #define __USE_XOPEN
73 #endif
74 #include <signal.h>
75 #include <unistd.h>
76 
77 /* Macro for specifying signal masks */
78 #define STACKSIZE SIGSTKSZ
79 
80 /* Define an alternative stack for processing signals */
81 char stackarray[STACKSIZE];
82 
83 #include "signals.h"
84 
85 #ifdef _LINUX_
86 stack_t stack = {
87 ss_sp:	stackarray + STACKSIZE,	// stack pointer
88 ss_flags:0,			//SS_ONSTACK,      // flags
89 ss_size:STACKSIZE		// size
90 };
91 
92 stack_t *oldstack;
93 
94 // SIGMAX is defined in the AIX headers to be 63 - 64 seems to work in linux??
95 // however, signals 32, 33, and 34 are not valid
96 #define SIGMAX 64
97 
98 #else // ! _LINUX_
99 
100 struct sigstack stack = {
101 	stackarray + STACKSIZE,	/* signal stack pointer */
102 	(_ONSTACK & ~_OLDSTYLE)	/* current status */
103 };
104 #endif
105 
106 /* Function prototypes */
107 void handler(int);		/* signal catching function */
108 void init_sig_vec();		/* setup signal handler for signals */
109 void reset_valid_sig();		/* reset valid_sig array */
110 void sys_error(const char *, int);	/* system error message function */
111 void error(const char *, int);	/* error message function */
112 
113 /* Define an array for verifying received signals */
114 int valid_sig[SIGMAX + 1];
115 
116 /*---------------------------------------------------------------------+
117 |                               main ()                                |
118 | ==================================================================== |
119 |                                                                      |
120 | Function:  Main program  (see prolog for more details)               |
121 |                                                                      |
122 +---------------------------------------------------------------------*/
main(int argc,char ** argv)123 int main(int argc, char **argv)
124 {
125 	sigset_t mask,		/* Initial process signal mask */
126 	 newmask,		/* Second process signal mask */
127 	 oldmask;		/* Signal mask returned by sigblock */
128 	pid_t pid = getpid();	/* Process ID (of this process) */
129 
130 	/* Print out program header */
131 	printf("%s: IPC Signals TestSuite program\n\n", *argv);
132 
133 	/*
134 	 * Establish signal handler for each signal & reset "valid signals"
135 	 * array, and setup alternative stack for processing signals
136 	 */
137 	init_sig_vec();
138 	reset_valid_sig();
139 #ifdef _LINUX_
140 	// sigstack function is obsolete, use sigaltstack instead
141 	if (sigaltstack(&stack, NULL) < 0)
142 		sys_error("sigaltstack failed", __LINE__);
143 #else
144 	if (sigstack(&stack, NULL) < 0)
145 		sys_error("sigstack failed", __LINE__);
146 #endif
147 	/*
148 	 * Send SIGILL, SIGALRM & SIGIOT signals to this process:
149 	 *
150 	 * First indicate which signals the signal handler should expect
151 	 * by setting the corresponding valid_sig[] array fields.
152 	 *
153 	 * Then send the signals to this process.
154 	 *
155 	 * And finally verify that the signals were caught by the signal
156 	 * handler by checking to see if the corresponding valid_sig[] array
157 	 * fields were reset.
158 	 */
159 	printf("\tSend SIGILL, SIGALRM, SIGIOT signals to process\n");
160 	valid_sig[SIGILL] = 1;
161 	valid_sig[SIGALRM] = 1;
162 	valid_sig[SIGIOT] = 1;
163 
164 	kill(pid, SIGILL);
165 	kill(pid, SIGALRM);
166 	kill(pid, SIGIOT);
167 
168 	if (valid_sig[SIGILL])
169 		error("failed to receive SIGILL signal!", __LINE__);
170 	if (valid_sig[SIGALRM])
171 		error("failed to receive SIGALRM signal!", __LINE__);
172 	if (valid_sig[SIGIOT])
173 		error("failed to receive SIGIOT signal!", __LINE__);
174 
175 	/*
176 	 * Block SIGILL, SIGALRM & SIGIOT signals:
177 	 *
178 	 * First create the process signal mask by ORing together the
179 	 * signal values.
180 	 *
181 	 * Then change the process signal mask with sigsetmask ().
182 	 *
183 	 * Verify that the desired signals are blocked from interrupting the
184 	 * process, by sending both blocked and unblocked signals to the
185 	 * process. Only the unblocked signals should interrupt the process.
186 	 */
187 	printf("\n\tBlock SIGILL, SIGALRM, SIGIOT signals, "
188 	       "and resend signals + others\n");
189 	sigemptyset(&mask);
190 	sigaddset(&mask, SIGILL);
191 	sigaddset(&mask, SIGALRM);
192 	sigaddset(&mask, SIGIOT);
193 #ifdef _LINUX_
194 	sigprocmask(SIG_SETMASK, &mask, NULL);
195 #else
196 	if (sigsetmask(mask) < 0)
197 		sys_error("setsigmask failed", __LINE__);
198 #endif
199 	valid_sig[SIGFPE] = 1;
200 	valid_sig[SIGTERM] = 1;
201 	valid_sig[SIGINT] = 1;
202 
203 	kill(pid, SIGILL);
204 	kill(pid, SIGALRM);
205 	kill(pid, SIGIOT);
206 	kill(pid, SIGFPE);
207 	kill(pid, SIGTERM);
208 	kill(pid, SIGINT);
209 
210 	if (valid_sig[SIGFPE])
211 		error("failed to receive SIGFPE signal!", __LINE__);
212 	if (valid_sig[SIGTERM])
213 		error("failed to receive SIGTERM signal!", __LINE__);
214 	if (valid_sig[SIGINT])
215 		error("failed to receive SIGINT signal!", __LINE__);
216 
217 	/*
218 	 * Block additional SIGFPE, SIGTERM & SIGINT signals:
219 	 *
220 	 * Create a signal mask containing the additional signals to block.
221 	 *
222 	 * Change the process signal mask to block the additional signals
223 	 * with the sigprocmask () function.
224 	 *
225 	 * Verify that all of the desired signals are now blocked from
226 	 * interrupting the process.  None of the specified signals should
227 	 * interrupt the process until the process signal mask is changed.
228 	 */
229 	printf("\n\tBlock rest of signals\n");
230 	sigemptyset(&newmask);
231 	sigaddset(&newmask, SIGFPE);
232 	sigaddset(&newmask, SIGTERM);
233 	sigaddset(&newmask, SIGINT);
234 	sigemptyset(&oldmask);
235 	if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {
236 		perror("sigprocmask failed");
237 		exit(-1);
238 	}
239 	if (memcmp(&mask, &oldmask, sizeof(mask)) != 0)
240 		error("value returned by sigblock () does not match the "
241 		      "old signal mask", __LINE__);
242 
243 	kill(pid, SIGILL);
244 	kill(pid, SIGALRM);
245 	kill(pid, SIGIOT);
246 	kill(pid, SIGFPE);
247 	kill(pid, SIGTERM);
248 	kill(pid, SIGINT);
249 
250 	/* Wait two seconds just to make sure that none of the specified
251 	 * signals interrupt the process (They should all be blocked).
252 	 */
253 	sleep(2);
254 
255 	/* Change the process signal mask:
256 	 *
257 	 * Now allow the SIGINT signal to interrupt the process.
258 	 * Thus by using sigpause (), force the process to suspend
259 	 * execution until delivery of an unblocked signal (here SIGINT).
260 	 *
261 	 * Additionally, verify that the SIGINT signal was received.
262 	 */
263 	valid_sig[SIGINT] = 1;
264 
265 	printf
266 	    ("\n\tChange signal mask & wait until signal interrupts process\n");
267 	if (sigpause(SIGINT) != -1 || errno != 4)
268 		sys_error("sigpause failed", __LINE__);
269 
270 	if (valid_sig[SIGINT])
271 		error("failed to receive SIGINT signal!", __LINE__);
272 
273 	/* Program completed successfully -- exit */
274 	printf("\nsuccessful!\n");
275 
276 	return (0);
277 }
278 
279 /*---------------------------------------------------------------------+
280 |                           init_sig_vec ()                            |
281 | ==================================================================== |
282 |                                                                      |
283 | Function:  Initialize the signal vector for ALL possible signals     |
284 |            (as defined in /usr/include/sys/signal.h) except for      |
285 |            the following signals which cannot be caught or ignored:  |
286 |                                                                      |
287 |              o  SIGKILL (9)                                          |
288 |              o  SIGSTOP (17)                                         |
289 |              o  SIGCONT (19)                                         |
290 |                                                                      |
291 | Returns:   Nothing                                                   |
292 |                                                                      |
293 +---------------------------------------------------------------------*/
init_sig_vec()294 void init_sig_vec()
295 {
296 	char errmsg[256];
297 	int i;
298 
299 #ifdef _LINUX_
300 	static struct sigaction invec;
301 
302 	for (i = 1; i <= SIGMAX; i++) {
303 		if ((i == SIGKILL) || (i == SIGSTOP)
304 		    || ((i >= 32) && (i <= 34)))
305 			continue;
306 		invec.sa_handler = handler;
307 		//sigaction.sa_mask = 0;
308 		invec.sa_flags = 0;
309 
310 		if (sigaction(i, &invec, NULL)) {
311 			sprintf(errmsg,
312 				"init_sig_vec: sigaction failed on signal (%d)",
313 				i);
314 			perror(errmsg);
315 			sys_error(errmsg, __LINE__);
316 		}
317 	}
318 #else
319 	static struct sigvec invec;
320 
321 	for (i = 1; i <= SIGMAX; i++) {
322 
323 		/* Cannot catch or ignore the following signals */
324 #ifdef _IA64			/* SIGWAITING NOT supported, RESERVED */
325 		if ((i == SIGKILL) || (i == SIGSTOP) ||
326 		    (i == SIGCONT) || (i == SIGWAITING))
327 			continue;
328 #else
329 		if ((i == SIGKILL) || (i == SIGSTOP) || (i == SIGCONT))
330 			continue;
331 #endif
332 
333 		invec.sv_handler = handler;
334 		//invec.sv_mask = SA_NOMASK;
335 #if defined  _IA64
336 		invec.sv_flags = 1;
337 #else
338 		invec.sv_onstack = 1;
339 #endif
340 		if (sigvec(i, &invec, NULL)) {
341 			sprintf(errmsg,
342 				"init_sig_vec: sigvec failed on signal (%d)",
343 				i);
344 			perror(errmsg);
345 			sys_error(errmsg, __LINE__);
346 		}
347 	}
348 #endif //ifdef _LINUX_
349 }
350 
351 /*---------------------------------------------------------------------+
352 |                             handler ()                               |
353 | ==================================================================== |
354 |                                                                      |
355 | Function:  Signal catching function.  As specified in init_sig_vec() |
356 |            this function is automatically called each time a signal  |
357 |            is received by the process.                               |
358 |                                                                      |
359 |            Once receiving the signal, verify that the corresponding  |
360 |            signal was expected.                                      |
361 |                                                                      |
362 | Returns:   Aborts program if an unexpected signal was received.      |
363 |                                                                      |
364 +---------------------------------------------------------------------*/
handler(int sig)365 void handler(int sig)
366 {
367 	char errmsg[256];
368 
369 	/* Check to insure that expected signal was received */
370 	if (valid_sig[sig]) {
371 		valid_sig[sig] = 0;
372 		printf("\treceived signal: (%s)\n", signames[sig]);
373 	} else {
374 		sprintf(errmsg, "unexpected signal (%d,%s)", sig,
375 			(sig < 32) ? signames[sig] : "unknown signal");
376 		error(errmsg, __LINE__);
377 	}
378 }
379 
380 /*---------------------------------------------------------------------+
381 |                         reset_valid_sig ()                           |
382 | ==================================================================== |
383 |                                                                      |
384 | Function:  Reset the valid "signal" array                            |
385 |                                                                      |
386 | Returns:   Nothing                                                   |
387 |                                                                      |
388 +---------------------------------------------------------------------*/
reset_valid_sig()389 void reset_valid_sig()
390 {
391 	int i;
392 
393 	for (i = 0; i < (SIGMAX + 1); i++)
394 		valid_sig[i] = 0;
395 }
396 
397 /*---------------------------------------------------------------------+
398 |                             sys_error ()                             |
399 | ==================================================================== |
400 |                                                                      |
401 | Function:  Creates system error message and calls error ()           |
402 |                                                                      |
403 +---------------------------------------------------------------------*/
sys_error(const char * msg,int line)404 void sys_error(const char *msg, int line)
405 {
406 	char syserr_msg[256];
407 
408 	sprintf(syserr_msg, "%s: %s\n", msg, strerror(errno));
409 	error(syserr_msg, line);
410 }
411 
412 /*---------------------------------------------------------------------+
413 |                               error ()                               |
414 | ==================================================================== |
415 |                                                                      |
416 | Function:  Prints out message and exits...                           |
417 |                                                                      |
418 +---------------------------------------------------------------------*/
error(const char * msg,int line)419 void error(const char *msg, int line)
420 {
421 	char derr[256];
422 	sprintf(derr, "ERROR [line: %d] %s\n", line, msg);
423 	perror(derr);
424 	exit(-1);
425 }
426