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_once
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_equal() and checks that EINTR is never returned. */
181void * test( void * arg )
182{
183	int ret = 0;
184
185	/* We don't block the signals SIGUSR1 and SIGUSR2 for this THREAD */
186	ret = pthread_sigmask( SIG_UNBLOCK, &usersigs, NULL );
187
188	if ( ret != 0 )
189	{
190		UNRESOLVED( ret, "Unable to unblock SIGUSR1 and SIGUSR2 in worker thread" );
191	}
192
193
194	while ( do_it )
195	{
196		pthread_once_t once_ctl = PTHREAD_ONCE_INIT;
197
198		count_ope++;
199
200		init_ctl = 0;
201
202		ret = pthread_once( &once_ctl, initializer );
203
204		if ( ret == EINTR )
205		{
206			FAILED( "pthread_once returned EINTR" );
207		}
208
209		if ( ret != 0 )
210		{
211			UNRESOLVED( ret, "pthread_once failed" );
212		}
213
214		ret = pthread_once( &once_ctl, initializer );
215
216		if ( ret == EINTR )
217		{
218			FAILED( "pthread_once returned EINTR" );
219		}
220
221		if ( ret != 0 )
222		{
223			UNRESOLVED( ret, "pthread_once failed" );
224		}
225
226		if ( init_ctl != 1 )
227		{
228			output( "init_ctl:%d\n", init_ctl );
229			FAILED( "The initializer did not execute as expected" );
230		}
231
232	}
233
234	return NULL;
235}
236
237/* Main function */
238int main ( int argc, char * argv[] )
239{
240	int ret;
241	pthread_t th_work, th_sig1, th_sig2;
242	thestruct arg1, arg2;
243
244	struct sigaction sa;
245
246	/* Initialize output routine */
247	output_init();
248
249	/* We need to register the signal handlers for the PROCESS */
250	sigemptyset ( &sa.sa_mask );
251	sa.sa_flags = 0;
252	sa.sa_handler = sighdl1;
253
254	if ( ( ret = sigaction ( SIGUSR1, &sa, NULL ) ) )
255	{
256		UNRESOLVED( ret, "Unable to register signal handler1" );
257	}
258
259	sa.sa_handler = sighdl2;
260
261	if ( ( ret = sigaction ( SIGUSR2, &sa, NULL ) ) )
262	{
263		UNRESOLVED( ret, "Unable to register signal handler2" );
264	}
265
266	/* We prepare a signal set which includes SIGUSR1 and SIGUSR2 */
267	sigemptyset( &usersigs );
268
269	ret = sigaddset( &usersigs, SIGUSR1 );
270
271	ret |= sigaddset( &usersigs, SIGUSR2 );
272
273	if ( ret != 0 )
274	{
275		UNRESOLVED( ret, "Unable to add SIGUSR1 or 2 to a signal set" );
276	}
277
278	/* We now block the signals SIGUSR1 and SIGUSR2 for this THREAD */
279	ret = pthread_sigmask( SIG_BLOCK, &usersigs, NULL );
280
281	if ( ret != 0 )
282	{
283		UNRESOLVED( ret, "Unable to block SIGUSR1 and SIGUSR2 in main thread" );
284	}
285
286#ifdef WITH_SYNCHRO
287	if ( sem_init( &semsig1, 0, 1 ) )
288	{
289		UNRESOLVED( errno, "Semsig1  init" );
290	}
291
292	if ( sem_init( &semsig2, 0, 1 ) )
293	{
294		UNRESOLVED( errno, "Semsig2  init" );
295	}
296
297#endif
298
299	if ( ( ret = pthread_create( &th_work, NULL, test, NULL ) ) )
300	{
301		UNRESOLVED( ret, "Worker thread creation failed" );
302	}
303
304	arg1.sig = SIGUSR1;
305	arg2.sig = SIGUSR2;
306#ifdef WITH_SYNCHRO
307	arg1.sem = &semsig1;
308	arg2.sem = &semsig2;
309#endif
310
311
312
313	if ( ( ret = pthread_create( &th_sig1, NULL, sendsig, ( void * ) & arg1 ) ) )
314	{
315		UNRESOLVED( ret, "Signal 1 sender thread creation failed" );
316	}
317
318	if ( ( ret = pthread_create( &th_sig2, NULL, sendsig, ( void * ) & arg2 ) ) )
319	{
320		UNRESOLVED( ret, "Signal 2 sender thread creation failed" );
321	}
322
323
324
325	/* Let's wait for a while now */
326	sleep( 1 );
327
328
329	/* Now stop the threads and join them */
330	do
331	{
332		do_it = 0;
333	}
334	while ( do_it );
335
336
337	if ( ( ret = pthread_join( th_sig1, NULL ) ) )
338	{
339		UNRESOLVED( ret, "Signal 1 sender thread join failed" );
340	}
341
342	if ( ( ret = pthread_join( th_sig2, NULL ) ) )
343	{
344		UNRESOLVED( ret, "Signal 2 sender thread join failed" );
345	}
346
347
348	if ( ( ret = pthread_join( th_work, NULL ) ) )
349	{
350		UNRESOLVED( ret, "Worker thread join failed" );
351	}
352
353
354#if VERBOSE > 0
355	output( "Test executed successfully.\n" );
356
357	output( "  %d initializations.\n", count_ope );
358
359#ifdef WITH_SYNCHRO
360	output( "  %d signals were sent meanwhile.\n", count_sig );
361
362#endif
363 #endif
364	PASSED;
365}
366