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