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 
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 int init_ctl;
172 /* Init function */
initializer(void)173 void initializer( void )
174 {
175 	init_ctl++;
176 	return ;
177 }
178 
179 
180 /* Test function -- calls pthread_kill() and checks that EINTR is never returned. */
test(void * arg)181 void * 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 */
main(int argc,char * argv[])227 int 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