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 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
30 #define _POSIX_C_SOURCE 200112L
31
32 /********************************************************************************************/
33 /****************************** standard includes *****************************************/
34 /********************************************************************************************/
35 #include <pthread.h>
36 #include <stdarg.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41
42 #include <semaphore.h>
43 #include <errno.h>
44 #include <signal.h>
45
46 /********************************************************************************************/
47 /****************************** Test framework *****************************************/
48 /********************************************************************************************/
49 #include "testfrmw.h"
50 #include "testfrmw.c"
51 /* This header is responsible for defining the following macros:
52 * UNRESOLVED(ret, descr);
53 * where descr is a description of the error and ret is an int (error code for example)
54 * FAILED(descr);
55 * where descr is a short text saying why the test has failed.
56 * PASSED();
57 * No parameter.
58 *
59 * Both three macros shall terminate the calling process.
60 * The testcase shall not terminate in any other maneer.
61 *
62 * The other file defines the functions
63 * void output_init()
64 * void output(char * string, ...)
65 *
66 * Those may be used to output information.
67 */
68
69 /********************************************************************************************/
70 /********************************** Configuration ******************************************/
71 /********************************************************************************************/
72 #ifndef VERBOSE
73 #define VERBOSE 1
74 #endif
75
76 /********************************************************************************************/
77 /*********************************** Test cases *****************************************/
78 /********************************************************************************************/
79
80 char do_it = 1;
81 long long iterations = 0;
82
83 /* Handler for user request to terminate */
sighdl(int sig)84 void sighdl(int sig)
85 {
86 /* do_it = 0 */
87
88 do {
89 do_it = 0;
90 }
91 while (do_it);
92 }
93
floodsighdl(int sig)94 void floodsighdl(int sig)
95 {
96 /* Nothing to do */
97 return;
98 }
99
100 /* Signals flood receiver thread */
flood_receiver(void * arg)101 void *flood_receiver(void *arg)
102 {
103 int ret = 0;
104 /* register the signal handler for this one thread */
105
106 struct sigaction sa;
107 sigemptyset(&sa.sa_mask);
108 sa.sa_flags = 0;
109 sa.sa_handler = floodsighdl;
110
111 if ((ret = sigaction(SIGABRT, &sa, NULL))) {
112 UNRESOLVED(ret, "Unable to register signal handler");
113 }
114
115 if ((ret = sigaction(SIGBUS, &sa, NULL))) {
116 UNRESOLVED(ret, "Unable to register signal handler");
117 }
118
119 /* Wait for the other threads to terminate */
120
121 do {
122 sched_yield();
123 } while (*(int *)arg);
124
125 return NULL;
126 }
127
128 /* Signal flood threads */
flooder_1(void * arg)129 void *flooder_1(void *arg)
130 {
131 int ret = 0;
132
133 while (do_it) {
134 iterations++;
135 ret = pthread_kill(*(pthread_t *) arg, SIGABRT);
136
137 if (ret != 0) {
138 UNRESOLVED(ret, "Flooder 1 thread got an error");
139 }
140 }
141
142 return NULL;
143 }
144
flooder_2(void * arg)145 void *flooder_2(void *arg)
146 {
147 int ret = 0;
148
149 while (do_it) {
150 iterations++;
151 ret = pthread_kill(*(pthread_t *) arg, SIGBUS);
152
153 if (ret != 0) {
154 UNRESOLVED(ret, "Flooder 1 thread got an error");
155 }
156 }
157
158 return NULL;
159 }
160
161 /* Synchronized threads */
162 int sync;
syncsighdl(int sig)163 void syncsighdl(int sig)
164 {
165 /* signal we have been called */
166 sync = 1;
167 return;
168 }
169
sync_rec(void * arg)170 void *sync_rec(void *arg)
171 {
172 int ret = 0;
173
174 struct sigaction sa;
175 sigemptyset(&sa.sa_mask);
176 sa.sa_flags = 0;
177 sa.sa_handler = syncsighdl;
178
179 if ((ret = sigaction(SIGILL, &sa, NULL))) {
180 UNRESOLVED(ret, "Unable to register signal handler");
181 }
182
183 /* wait until termination */
184 do {
185 sched_yield();
186 } while (*(int *)arg);
187
188 return NULL;
189 }
190
sync_send(void * arg)191 void *sync_send(void *arg)
192 {
193 int ret = 0;
194
195 while (do_it) {
196 /* Disarm the flag */
197 sync = 0;
198 /* Send the signal */
199 ret = pthread_kill(*(pthread_t *) arg, SIGILL);
200
201 if (ret != 0) {
202 UNRESOLVED(ret, "Failed to send signal");
203 }
204
205 /* Sleep up to 5 sec */
206 for (ret = 0; (ret < 5) && (sync == 0); ret++)
207 sleep(1);
208
209 /* Test if signal was received */
210 if (sync == 0) {
211 FAILED
212 ("Signal SIGILL was not delivered within 5 second -- lost?");
213 }
214 }
215
216 return NULL;
217
218 }
219
220 /* Main function */
main(int argc,char * argv[])221 int main(int argc, char *argv[])
222 {
223 int ret = 0;
224
225 int flooding = 1;
226 pthread_t fl_rec;
227 pthread_t fl_snd1, fl_snd2;
228
229 int synchro = 1;
230 pthread_t sy_rec;
231 pthread_t sy_snd;
232
233 struct sigaction sa;
234
235 /* Initialize output routine */
236 output_init();
237
238 /* Register the signal handler for SIGUSR1 */
239 sigemptyset(&sa.sa_mask);
240
241 sa.sa_flags = 0;
242
243 sa.sa_handler = sighdl;
244
245 if ((ret = sigaction(SIGUSR1, &sa, NULL))) {
246 UNRESOLVED(ret, "Unable to register signal handler");
247 }
248
249 if ((ret = sigaction(SIGALRM, &sa, NULL))) {
250 UNRESOLVED(ret, "Unable to register signal handler");
251 }
252 #if VERBOSE > 1
253 output("[parent] Signal handler registered\n");
254
255 #endif
256
257 ret = pthread_create(&fl_rec, NULL, flood_receiver, &flooding);
258
259 if (ret != 0) {
260 UNRESOLVED(ret, "Unable to create a thread");
261 }
262
263 ret = pthread_create(&fl_snd1, NULL, flooder_1, &fl_rec);
264
265 if (ret != 0) {
266 UNRESOLVED(ret, "Unable to create a thread");
267 }
268
269 ret = pthread_create(&fl_snd2, NULL, flooder_2, &fl_rec);
270
271 if (ret != 0) {
272 UNRESOLVED(ret, "Unable to create a thread");
273 }
274
275 ret = pthread_create(&sy_rec, NULL, sync_rec, &synchro);
276
277 if (ret != 0) {
278 UNRESOLVED(ret, "Unable to create a thread");
279 }
280
281 ret = pthread_create(&sy_snd, NULL, sync_send, &sy_rec);
282
283 if (ret != 0) {
284 UNRESOLVED(ret, "Unable to create a thread");
285 }
286
287 /* Wait the user stops the test */
288 ret = pthread_join(fl_snd1, NULL);
289
290 if (ret != 0) {
291 UNRESOLVED(ret, "Failed to join a thread");
292 }
293
294 ret = pthread_join(fl_snd2, NULL);
295
296 if (ret != 0) {
297 UNRESOLVED(ret, "Failed to join a thread");
298 }
299
300 flooding = 0;
301 ret = pthread_join(fl_rec, NULL);
302
303 if (ret != 0) {
304 UNRESOLVED(ret, "Failed to join a thread");
305 }
306
307 ret = pthread_join(sy_snd, NULL);
308
309 if (ret != 0) {
310 UNRESOLVED(ret, "Failed to join a thread");
311 }
312
313 synchro = 0;
314
315 ret = pthread_join(sy_rec, NULL);
316
317 if (ret != 0) {
318 UNRESOLVED(ret, "Failed to join a thread");
319 }
320
321 /* We've been asked to stop */
322 output("pthread_kill stress test PASSED -- %llu iterations\n",
323 iterations);
324
325 PASSED;
326 }
327