1 /*
2 * Copyright (c) 2004, Bull S.A.. All rights reserved.
3 * Created by: Sebastien Decugis
4
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
17 * This stress test aims to test the following assertions:
18 * -> pthread_kill() does not make the system unstable
19 * -> no signal get lost when they are not already pending.
20
21 * The steps are:
22 * -> create 2 threads which send signals heavily to a 3rd thread.
23 * -> Create another thread which sends a signal synchronously to another one.
24
25 * The test fails if a signal is lost. The other assertion is tested implicitely
26
27 */
28
29 /********************************************************************************************/
30 /****************************** standard includes *****************************************/
31 /********************************************************************************************/
32 #include <pthread.h>
33 #include <stdarg.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <unistd.h>
38
39 #include <semaphore.h>
40 #include <errno.h>
41 #include <signal.h>
42
43 /********************************************************************************************/
44 /****************************** Test framework *****************************************/
45 /********************************************************************************************/
46 #include "testfrmw.h"
47 #include "testfrmw.c"
48 /* This header is responsible for defining the following macros:
49 * UNRESOLVED(ret, descr);
50 * where descr is a description of the error and ret is an int (error code for example)
51 * FAILED(descr);
52 * where descr is a short text saying why the test has failed.
53 * PASSED();
54 * No parameter.
55 *
56 * Both three macros shall terminate the calling process.
57 * The testcase shall not terminate in any other maneer.
58 *
59 * The other file defines the functions
60 * void output_init()
61 * void output(char * string, ...)
62 *
63 * Those may be used to output information.
64 */
65
66 /********************************************************************************************/
67 /********************************** Configuration ******************************************/
68 /********************************************************************************************/
69 #ifndef VERBOSE
70 #define VERBOSE 1
71 #endif
72
73 /********************************************************************************************/
74 /*********************************** Test cases *****************************************/
75 /********************************************************************************************/
76
77 static char do_it = 1;
78 static long long iterations = 0;
79
80 /* Handler for user request to terminate */
sighdl(int sig)81 static void sighdl(int sig)
82 {
83 /* do_it = 0 */
84
85 do {
86 do_it = 0;
87 }
88 while (do_it);
89 }
90
floodsighdl(int sig)91 static void floodsighdl(int sig)
92 {
93 /* Nothing to do */
94 return;
95 }
96
97 /* Signals flood receiver thread */
flood_receiver(void * arg)98 static void *flood_receiver(void *arg)
99 {
100 int ret = 0;
101 /* register the signal handler for this one thread */
102
103 struct sigaction sa;
104 sigemptyset(&sa.sa_mask);
105 sa.sa_flags = 0;
106 sa.sa_handler = floodsighdl;
107
108 if ((ret = sigaction(SIGABRT, &sa, NULL))) {
109 UNRESOLVED(ret, "Unable to register signal handler");
110 }
111
112 if ((ret = sigaction(SIGBUS, &sa, NULL))) {
113 UNRESOLVED(ret, "Unable to register signal handler");
114 }
115
116 /* Wait for the other threads to terminate */
117
118 do {
119 sched_yield();
120 } while (*(int *)arg);
121
122 return NULL;
123 }
124
125 /* Signal flood threads */
flooder_1(void * arg)126 static void *flooder_1(void *arg)
127 {
128 int ret = 0;
129
130 while (do_it) {
131 iterations++;
132 ret = pthread_kill(*(pthread_t *) arg, SIGABRT);
133
134 if (ret != 0) {
135 UNRESOLVED(ret, "Flooder 1 thread got an error");
136 }
137 }
138
139 return NULL;
140 }
141
flooder_2(void * arg)142 static void *flooder_2(void *arg)
143 {
144 int ret = 0;
145
146 while (do_it) {
147 iterations++;
148 ret = pthread_kill(*(pthread_t *) arg, SIGBUS);
149
150 if (ret != 0) {
151 UNRESOLVED(ret, "Flooder 1 thread got an error");
152 }
153 }
154
155 return NULL;
156 }
157
158 /* Synchronized threads */
159 static int sync;
syncsighdl(int sig)160 static void syncsighdl(int sig)
161 {
162 /* signal we have been called */
163 sync = 1;
164 return;
165 }
166
sync_rec(void * arg)167 static void *sync_rec(void *arg)
168 {
169 int ret = 0;
170
171 struct sigaction sa;
172 sigemptyset(&sa.sa_mask);
173 sa.sa_flags = 0;
174 sa.sa_handler = syncsighdl;
175
176 if ((ret = sigaction(SIGILL, &sa, NULL))) {
177 UNRESOLVED(ret, "Unable to register signal handler");
178 }
179
180 /* wait until termination */
181 do {
182 sched_yield();
183 } while (*(int *)arg);
184
185 return NULL;
186 }
187
sync_send(void * arg)188 static void *sync_send(void *arg)
189 {
190 int ret = 0;
191
192 while (do_it) {
193 /* Disarm the flag */
194 sync = 0;
195 /* Send the signal */
196 ret = pthread_kill(*(pthread_t *) arg, SIGILL);
197
198 if (ret != 0) {
199 UNRESOLVED(ret, "Failed to send signal");
200 }
201
202 /* Sleep up to 5 sec */
203 for (ret = 0; (ret < 5) && (sync == 0); ret++)
204 sleep(1);
205
206 /* Test if signal was received */
207 if (sync == 0) {
208 FAILED
209 ("Signal SIGILL was not delivered within 5 second -- lost?");
210 }
211 }
212
213 return NULL;
214
215 }
216
217 /* Main function */
main(int argc,char * argv[])218 int main(int argc, char *argv[])
219 {
220 int ret = 0;
221
222 int flooding = 1;
223 pthread_t fl_rec;
224 pthread_t fl_snd1, fl_snd2;
225
226 int synchro = 1;
227 pthread_t sy_rec;
228 pthread_t sy_snd;
229
230 struct sigaction sa;
231
232 /* Initialize output routine */
233 output_init();
234
235 /* Register the signal handler for SIGUSR1 */
236 sigemptyset(&sa.sa_mask);
237
238 sa.sa_flags = 0;
239
240 sa.sa_handler = sighdl;
241
242 if ((ret = sigaction(SIGUSR1, &sa, NULL))) {
243 UNRESOLVED(ret, "Unable to register signal handler");
244 }
245
246 if ((ret = sigaction(SIGALRM, &sa, NULL))) {
247 UNRESOLVED(ret, "Unable to register signal handler");
248 }
249 #if VERBOSE > 1
250 output("[parent] Signal handler registered\n");
251
252 #endif
253
254 ret = pthread_create(&fl_rec, NULL, flood_receiver, &flooding);
255
256 if (ret != 0) {
257 UNRESOLVED(ret, "Unable to create a thread");
258 }
259
260 ret = pthread_create(&fl_snd1, NULL, flooder_1, &fl_rec);
261
262 if (ret != 0) {
263 UNRESOLVED(ret, "Unable to create a thread");
264 }
265
266 ret = pthread_create(&fl_snd2, NULL, flooder_2, &fl_rec);
267
268 if (ret != 0) {
269 UNRESOLVED(ret, "Unable to create a thread");
270 }
271
272 ret = pthread_create(&sy_rec, NULL, sync_rec, &synchro);
273
274 if (ret != 0) {
275 UNRESOLVED(ret, "Unable to create a thread");
276 }
277
278 ret = pthread_create(&sy_snd, NULL, sync_send, &sy_rec);
279
280 if (ret != 0) {
281 UNRESOLVED(ret, "Unable to create a thread");
282 }
283
284 /* Wait the user stops the test */
285 ret = pthread_join(fl_snd1, NULL);
286
287 if (ret != 0) {
288 UNRESOLVED(ret, "Failed to join a thread");
289 }
290
291 ret = pthread_join(fl_snd2, NULL);
292
293 if (ret != 0) {
294 UNRESOLVED(ret, "Failed to join a thread");
295 }
296
297 flooding = 0;
298 ret = pthread_join(fl_rec, NULL);
299
300 if (ret != 0) {
301 UNRESOLVED(ret, "Failed to join a thread");
302 }
303
304 ret = pthread_join(sy_snd, NULL);
305
306 if (ret != 0) {
307 UNRESOLVED(ret, "Failed to join a thread");
308 }
309
310 synchro = 0;
311
312 ret = pthread_join(sy_rec, NULL);
313
314 if (ret != 0) {
315 UNRESOLVED(ret, "Failed to join a thread");
316 }
317
318 /* We've been asked to stop */
319 output("pthread_kill stress test PASSED -- %llu iterations\n",
320 iterations);
321
322 PASSED;
323 }
324