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 sample test aims to check the following assertion:
19*
20* The function does not return EINTR
21
22* The steps are:
23* -> kill a thread which calls pthread_sigmask
24* -> check that EINTR is never returned
25
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#define WITH_SYNCHRO
77
78
79/********************************************************************************************/
80/***********************************    Test cases  *****************************************/
81/********************************************************************************************/
82
83char do_it = 1;
84unsigned long count_ope = 0;
85#ifdef WITH_SYNCHRO
86sem_t semsig1;
87sem_t semsig2;
88unsigned long count_sig = 0;
89#endif
90
91sigset_t usersigs;
92
93typedef struct
94{
95	int sig;
96#ifdef WITH_SYNCHRO
97	sem_t *sem;
98#endif
99}
100
101thestruct;
102
103/* the following function keeps on sending the signal to the process */
104void * sendsig ( void * arg )
105{
106	thestruct * thearg = ( thestruct * ) arg;
107	int ret;
108	pid_t process;
109
110	process = getpid();
111
112	/* We block the signals SIGUSR1 and SIGUSR2 for this THREAD */
113	ret = pthread_sigmask( SIG_BLOCK, &usersigs, NULL );
114
115	if ( ret != 0 )
116	{
117		UNRESOLVED( ret, "Unable to block SIGUSR1 and SIGUSR2 in signal thread" );
118	}
119
120	while ( do_it )
121	{
122#ifdef WITH_SYNCHRO
123
124		if ( ( ret = sem_wait( thearg->sem ) ) )
125		{
126			UNRESOLVED( errno, "Sem_wait in sendsig" );
127		}
128
129		count_sig++;
130#endif
131
132		ret = kill( process, thearg->sig );
133
134		if ( ret != 0 )
135		{
136			UNRESOLVED( errno, "Kill in sendsig" );
137		}
138
139	}
140
141	return NULL;
142}
143
144/* Next are the signal handlers. */
145/* This one is registered for signal SIGUSR1 */
146void sighdl1( int sig )
147{
148#ifdef WITH_SYNCHRO
149
150	if ( sem_post( &semsig1 ) )
151	{
152		UNRESOLVED( errno, "Sem_post in signal handler 1" );
153	}
154
155#endif
156}
157
158/* This one is registered for signal SIGUSR2 */
159void sighdl2( int sig )
160{
161#ifdef WITH_SYNCHRO
162
163	if ( sem_post( &semsig2 ) )
164	{
165		UNRESOLVED( errno, "Sem_post in signal handler 2" );
166	}
167
168#endif
169}
170
171int init_ctl;
172/* Init function */
173void initializer( void )
174{
175	init_ctl++;
176	return ;
177}
178
179
180/* Test function -- calls pthread_sigmask() and checks that EINTR is never returned. */
181void * test( void * arg )
182{
183	int ret = 0;
184	sigset_t set;
185	int i, j=0;
186	int signals[] = { SIGBUS, SIGKILL, SIGABRT, SIGCHLD, SIGHUP };
187#define NUM_SIGNALS (sizeof(signals)/sizeof(int))
188	int operation[] = {SIG_SETMASK, SIG_BLOCK, SIG_UNBLOCK};
189
190	ret = sigemptyset( &set );
191
192	if ( ret != 0 )
193	{
194		UNRESOLVED( ret, "Failed to initialize signal set" );
195	}
196
197	/* We don't block the signals SIGUSR1 and SIGUSR2 for this THREAD */
198	ret = pthread_sigmask( SIG_UNBLOCK, &usersigs, NULL );
199
200	if ( ret != 0 )
201	{
202		UNRESOLVED( ret, "Unable to unblock SIGUSR1 and SIGUSR2 in worker thread" );
203	}
204
205
206	while ( do_it )
207	{
208		count_ope++;
209
210		for ( i = 0; i < 3; i++ )
211		{
212			j++;
213			j %= 2 * NUM_SIGNALS;
214
215			if ( j >= NUM_SIGNALS )
216				ret = sigdelset( &set, signals[ j - NUM_SIGNALS ] );
217			else
218				ret = sigaddset( &set, signals[ j ] );
219
220			if ( ret != 0 )
221			{
222				UNRESOLVED( errno, "Failed to initialize signal set" );
223			}
224
225			ret = pthread_sigmask( operation[ i ], &set, NULL );
226
227			if ( ret == EINTR )
228			{
229				FAILED( "pthread_sigmask returned EINTR" );
230			}
231
232			if ( ret != 0 )
233			{
234				UNRESOLVED( ret, "Failed to initialize signal set" );
235			}
236		}
237	}
238
239	return NULL;
240}
241
242/* Main function */
243int main ( int argc, char * argv[] )
244{
245	int ret;
246	pthread_t th_work, th_sig1, th_sig2;
247	thestruct arg1, arg2;
248
249	struct sigaction sa;
250
251	/* Initialize output routine */
252	output_init();
253
254	/* We need to register the signal handlers for the PROCESS */
255	sigemptyset ( &sa.sa_mask );
256	sa.sa_flags = 0;
257	sa.sa_handler = sighdl1;
258
259	if ( ( ret = sigaction ( SIGUSR1, &sa, NULL ) ) )
260	{
261		UNRESOLVED( ret, "Unable to register signal handler1" );
262	}
263
264	sa.sa_handler = sighdl2;
265
266	if ( ( ret = sigaction ( SIGUSR2, &sa, NULL ) ) )
267	{
268		UNRESOLVED( ret, "Unable to register signal handler2" );
269	}
270
271	/* We prepare a signal set which includes SIGUSR1 and SIGUSR2 */
272	sigemptyset( &usersigs );
273
274	ret = sigaddset( &usersigs, SIGUSR1 );
275
276	ret |= sigaddset( &usersigs, SIGUSR2 );
277
278	if ( ret != 0 )
279	{
280		UNRESOLVED( ret, "Unable to add SIGUSR1 or 2 to a signal set" );
281	}
282
283	/* We now block the signals SIGUSR1 and SIGUSR2 for this THREAD */
284	ret = pthread_sigmask( SIG_BLOCK, &usersigs, NULL );
285
286	if ( ret != 0 )
287	{
288		UNRESOLVED( ret, "Unable to block SIGUSR1 and SIGUSR2 in main thread" );
289	}
290
291#ifdef WITH_SYNCHRO
292	if ( sem_init( &semsig1, 0, 1 ) )
293	{
294		UNRESOLVED( errno, "Semsig1  init" );
295	}
296
297	if ( sem_init( &semsig2, 0, 1 ) )
298	{
299		UNRESOLVED( errno, "Semsig2  init" );
300	}
301
302#endif
303
304	if ( ( ret = pthread_create( &th_work, NULL, test, NULL ) ) )
305	{
306		UNRESOLVED( ret, "Worker thread creation failed" );
307	}
308
309	arg1.sig = SIGUSR1;
310	arg2.sig = SIGUSR2;
311#ifdef WITH_SYNCHRO
312	arg1.sem = &semsig1;
313	arg2.sem = &semsig2;
314#endif
315
316
317
318	if ( ( ret = pthread_create( &th_sig1, NULL, sendsig, ( void * ) & arg1 ) ) )
319	{
320		UNRESOLVED( ret, "Signal 1 sender thread creation failed" );
321	}
322
323	if ( ( ret = pthread_create( &th_sig2, NULL, sendsig, ( void * ) & arg2 ) ) )
324	{
325		UNRESOLVED( ret, "Signal 2 sender thread creation failed" );
326	}
327
328
329
330	/* Let's wait for a while now */
331	sleep( 1 );
332
333
334	/* Now stop the threads and join them */
335	do
336	{
337		do_it = 0;
338	}
339	while ( do_it );
340
341
342	if ( ( ret = pthread_join( th_sig1, NULL ) ) )
343	{
344		UNRESOLVED( ret, "Signal 1 sender thread join failed" );
345	}
346
347	if ( ( ret = pthread_join( th_sig2, NULL ) ) )
348	{
349		UNRESOLVED( ret, "Signal 2 sender thread join failed" );
350	}
351
352
353	if ( ( ret = pthread_join( th_work, NULL ) ) )
354	{
355		UNRESOLVED( ret, "Worker thread join failed" );
356	}
357
358
359#if VERBOSE > 0
360	output( "Test executed successfully.\n" );
361
362	output( "  %d operations.\n", count_ope );
363
364#ifdef WITH_SYNCHRO
365	output( "  %d signals were sent meanwhile.\n", count_sig );
366
367#endif
368#endif
369	PASSED;
370}
371
372