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