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 
83 char do_it = 1;
84 unsigned long count_ope = 0;
85 #ifdef WITH_SYNCHRO
86 sem_t semsig1;
87 sem_t semsig2;
88 unsigned long count_sig = 0;
89 #endif
90 
91 sigset_t usersigs;
92 
93 typedef struct
94 {
95 	int sig;
96 #ifdef WITH_SYNCHRO
97 	sem_t *sem;
98 #endif
99 }
100 
101 thestruct;
102 
103 /* the following function keeps on sending the signal to the process */
sendsig(void * arg)104 void * 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 */
sighdl1(int sig)146 void 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 */
sighdl2(int sig)159 void 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 */
testth(void * arg)172 void * 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. */
test(void * arg)183 void * 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 */
main(int argc,char * argv[])234 int 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