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_06 |
21 | ==================================================================== |
22 | |
23 | Description: Verifies that when multiple identical signals are sent |
24 | to a process, at least one is queued. |
25 | |
26 | Algorithm: o Block all signals from interrupting the process |
27 | o Send MAXSIG 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 | System calls: The following system calls are tested: |
35 | |
36 | sigprocmask () - Sets the current signal mask |
37 | sigismember () - Creates and manipulates signal masks |
38 | sigfillset () - Creates and manipulates signal masks |
39 | sigpending () - Returns a set of signals that are |
40 | blocked from delivery |
41 | sigsuspend () - Automatically changes the set of |
42 | blocked signals and waits for a signal |
43 | raise () - Sends a signal to the executing program |
44 | |
45 | Usage: signal_test_06 |
46 | |
47 | To compile: cc -o signal_test_06 signal_test_06 |
48 | |
49 | Last update: Ver. 1.2, 2/7/94 23:24:14 |
50 | |
51 | Change Activity |
52 | |
53 | Version Date Name Reason |
54 | 0.1 122193 DJK Wrote initial test for AIX version 4.1 |
55 | 1.2 020794 DJK Move to "prod" directory |
56 | |
57 +---------------------------------------------------------------------*/
58
59 #define MAXSIG 1024*1024 /* Number of signals sent to process */
60
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #include <unistd.h>
65 #include <sys/signal.h>
66 #include <errno.h>
67
68 #ifdef _LINUX_
69 // bits/signum.h defines _NSIG as 64
70 #define SIGMAX 64
71 #endif
72
73 /* Function prototypes */
74 void handler(int, int, struct sigcontext *);
75 void init_sig();
76 void sys_error(const char *, int);
77 void error(const char *, int);
78
79 /* Global variables */
80 int signals_received = 0;
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 sigset_t newmask, /* New signal mask */
92 oldmask, /* Initial signal mask */
93 pendmask; /* Pending signal mask */
94 int i; /* Loop index */
95
96 /* Print out program header */
97 printf("%s: IPC TestSuite program\n\n", *argv);
98
99 /* Set up our signal handler */
100 init_sig();
101
102 /*
103 * Block ALL signals from interrupting the process
104 */
105 printf("\tBlock all signals from interrupting the process\n");
106 if (sigfillset(&newmask) < 0)
107 error("sigfillset failed", __LINE__);
108 if (sigprocmask(SIG_SETMASK, &newmask, &oldmask) < 0)
109 error("sigprocmask failed", __LINE__);
110
111 /*
112 * Send MAXSIG signals to the current process -- since ALL of the
113 * signals are blocked, none of the signals should interrupt the
114 * process
115 */
116 printf("\n\tSend MAX (%d) SIGUSR1 signals to the process...\n", MAXSIG);
117 for (i = 0; i < MAXSIG; i++)
118 raise(SIGUSR1);
119
120 /*
121 * Sleep for a short time and the check to ensure that a SIGUSR1
122 * signal is pending
123 */
124 sleep(2);
125
126 printf("\n\tEnsure at least one SIGUSR1 signal is pending\n");
127 if (sigpending(&pendmask) < 0)
128 error("sigpending failed", __LINE__);
129
130 if (sigismember(&pendmask, SIGUSR1) == 0)
131 error("sent multiple SIGUSR1 signals to process, "
132 "yet none are pending!", __LINE__);
133
134 /*
135 * Change the signal mask to allow signals to interrupt the process
136 * and then suspend execution until a signal reaches the process
137 *
138 * Then verify that at least one signal was received
139 */
140 printf("\n\tChange signal mask & wait for SIGUSR1 signal\n");
141 if (sigsuspend(&oldmask) != -1 || errno != 4)
142 error("sigsuspend failed", __LINE__);
143
144 if (signals_received != 1) {
145 printf("Signals are queued! Sent %d signals, "
146 "while %d were queued\n", MAXSIG, signals_received);
147 }
148
149 /* Program completed successfully -- exit */
150 printf("\nsuccessful!\n");
151 return (0);
152 }
153
154 /*---------------------------------------------------------------------+
155 | handler () |
156 | ==================================================================== |
157 | |
158 | Function: Catches signals and aborts the program if a signal other |
159 | than SIGUSR1 was received |
160 | |
161 | Updates: signals_received - global variable indicating the number |
162 | of SIGUSR1 signals received |
163 | |
164 | Returns: Aborts if an unexpected signal is caught |
165 | |
166 +---------------------------------------------------------------------*/
handler(int signal,int code,struct sigcontext * scp)167 void handler(int signal, int code, struct sigcontext *scp)
168 {
169 char msg[256]; /* Buffer for error message */
170
171 if (signal != SIGUSR1) {
172 sprintf(msg, "unexpected signal (%d)", signal);
173 error(msg, __LINE__);
174 }
175
176 printf("\tcaught SIGUSR1 (%d) signal\n", signal);
177 signals_received++;
178 }
179
180 /*---------------------------------------------------------------------+
181 | init_sig () |
182 | ==================================================================== |
183 | |
184 | Function: Initialize the signal vector for ALL possible signals |
185 | (as defined in /usr/include/sys/signal.h) except for |
186 | the following signals which cannot be caught or ignored: |
187 | |
188 | o SIGKILL (9) |
189 | o SIGSTOP (17) |
190 | o SIGCONT (19) |
191 | |
192 | Returns: n/a |
193 | |
194 +---------------------------------------------------------------------*/
init_sig()195 void init_sig()
196 {
197 struct sigaction invec;
198 char msg[256]; /* Buffer for error message */
199 int i;
200
201 for (i = 1; i <= SIGMAX; i++) {
202
203 /* Cannot catch or ignore the following signals */
204 #ifdef _IA64 /* SIGWAITING not supported, RESERVED */
205 if ((i == SIGKILL) || (i == SIGSTOP) ||
206 (i == SIGCONT) || (i == SIGWAITING))
207 continue;
208 #else
209 #ifdef _LINUX_
210 if ((i == SIGKILL) || (i == SIGSTOP)
211 || ((i >= 32) && (i <= 34)))
212 continue;
213 #else
214 if (i == SIGKILL || i == SIGSTOP || i == SIGCONT)
215 continue;
216 #endif
217 #endif
218
219 invec.sa_handler = (void (*)(int))handler;
220 sigemptyset(&invec.sa_mask);
221 invec.sa_flags = 0;
222
223 if (sigaction(i, &invec, NULL) < 0) {
224 sprintf(msg, "sigaction failed on signal %d", i);
225 error(msg, __LINE__);
226 }
227 }
228 }
229
230 /*---------------------------------------------------------------------+
231 | sys_error () |
232 | ==================================================================== |
233 | |
234 | Function: Creates system error message and calls error () |
235 | |
236 +---------------------------------------------------------------------*/
sys_error(const char * msg,int line)237 void sys_error(const char *msg, int line)
238 {
239 char syserr_msg[256];
240
241 sprintf(syserr_msg, "%s: %s\n", msg, strerror(errno));
242 error(syserr_msg, line);
243 }
244
245 /*---------------------------------------------------------------------+
246 | error () |
247 | ==================================================================== |
248 | |
249 | Function: Prints out message and exits... |
250 | |
251 +---------------------------------------------------------------------*/
error(const char * msg,int line)252 void error(const char *msg, int line)
253 {
254 fprintf(stderr, "ERROR [line: %d] %s\n", line, msg);
255 exit(-1);
256 }
257