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