• 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 /* 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