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