• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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