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_join 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/*********************************** Helper *****************************************/ 81/********************************************************************************************/ 82#include "threads_scenarii.c" 83/* this file defines: 84* scenarii: array of struct __scenario type. 85* NSCENAR : macro giving the total # of scenarii 86* scenar_init(): function to call before use the scenarii array. 87* scenar_fini(): function to call after end of use of the scenarii array. 88*/ 89 90/********************************************************************************************/ 91/*********************************** Test cases *****************************************/ 92/********************************************************************************************/ 93 94char do_it = 1; 95unsigned long count_ope = 0; 96#ifdef WITH_SYNCHRO 97sem_t semsig1; 98sem_t semsig2; 99unsigned long count_sig = 0; 100#endif 101 102sigset_t usersigs; 103 104typedef struct 105{ 106 int sig; 107#ifdef WITH_SYNCHRO 108 sem_t *sem; 109#endif 110} 111 112thestruct; 113 114/* the following function keeps on sending the signal to the process */ 115void * sendsig ( void * arg ) 116{ 117 thestruct * thearg = ( thestruct * ) arg; 118 int ret; 119 pid_t process; 120 121 process = getpid(); 122 123 /* We block the signals SIGUSR1 and SIGUSR2 for this THREAD */ 124 ret = pthread_sigmask( SIG_BLOCK, &usersigs, NULL ); 125 126 if ( ret != 0 ) 127 { 128 UNRESOLVED( ret, "Unable to block SIGUSR1 and SIGUSR2 in signal thread" ); 129 } 130 131 while ( do_it ) 132 { 133#ifdef WITH_SYNCHRO 134 135 if ( ( ret = sem_wait( thearg->sem ) ) ) 136 { 137 UNRESOLVED( errno, "Sem_wait in sendsig" ); 138 } 139 140 count_sig++; 141#endif 142 143 ret = kill( process, thearg->sig ); 144 145 if ( ret != 0 ) 146 { 147 UNRESOLVED( errno, "Kill in sendsig" ); 148 } 149 150 } 151 152 return NULL; 153} 154 155/* Next are the signal handlers. */ 156/* This one is registered for signal SIGUSR1 */ 157void sighdl1( int sig ) 158{ 159#ifdef WITH_SYNCHRO 160 161 if ( sem_post( &semsig1 ) ) 162 { 163 UNRESOLVED( errno, "Sem_post in signal handler 1" ); 164 } 165 166#endif 167} 168 169/* This one is registered for signal SIGUSR2 */ 170void sighdl2( int sig ) 171{ 172#ifdef WITH_SYNCHRO 173 174 if ( sem_post( &semsig2 ) ) 175 { 176 UNRESOLVED( errno, "Sem_post in signal handler 2" ); 177 } 178 179#endif 180} 181 182/* thread function */ 183void *threaded( void* arg ) 184{ 185 /* do nothing */ 186 sched_yield(); 187 188 return NULL; 189} 190 191 192/* Test function -- calls pthread_join() and checks that EINTR is never returned. */ 193void * test( void * arg ) 194{ 195 int ret = 0; 196 pthread_t child; 197 198 /* We don't block the signals SIGUSR1 and SIGUSR2 for this THREAD */ 199 ret = pthread_sigmask( SIG_UNBLOCK, &usersigs, NULL ); 200 201 if ( ret != 0 ) 202 { 203 UNRESOLVED( ret, "Unable to unblock SIGUSR1 and SIGUSR2 in worker thread" ); 204 } 205 206 207 while ( do_it ) 208 { 209 for ( sc = 0; sc < NSCENAR; sc++ ) 210 { 211 ret = pthread_create( &child, &scenarii[ sc ].ta, threaded, NULL ); 212 213 if ( ( scenarii[ sc ].result == 0 ) && ( ret != 0 ) ) 214 { 215 UNRESOLVED( ret, "Failed to create this thread" ); 216 } 217 218 if ( ( scenarii[ sc ].result == 1 ) && ( ret == 0 ) ) 219 { 220 221 UNRESOLVED( -1, "An error was expected but the thread creation succeeded" ); 222 } 223 224 225 if ( ret == 0 ) /* The new thread is running */ 226 { 227 count_ope++; 228 229 ret = pthread_join( child, NULL ); 230 231 if ( ret == EINTR ) 232 { 233 FAILED( "pthread_join returned EINTR" ); 234 } 235 236 if ( ret != 0 ) 237 { 238 UNRESOLVED( ret, "Unable to join a thread" ); 239 } 240 241 } 242 } 243 } 244 245 return NULL; 246} 247 248/* Main function */ 249int main ( int argc, char * argv[] ) 250{ 251 int ret; 252 pthread_t th_work, th_sig1, th_sig2; 253 thestruct arg1, arg2; 254 255 struct sigaction sa; 256 257 /* Initialize output routine */ 258 output_init(); 259 260 /* We need to register the signal handlers for the PROCESS */ 261 sigemptyset ( &sa.sa_mask ); 262 sa.sa_flags = 0; 263 sa.sa_handler = sighdl1; 264 265 if ( ( ret = sigaction ( SIGUSR1, &sa, NULL ) ) ) 266 { 267 UNRESOLVED( ret, "Unable to register signal handler1" ); 268 } 269 270 sa.sa_handler = sighdl2; 271 272 if ( ( ret = sigaction ( SIGUSR2, &sa, NULL ) ) ) 273 { 274 UNRESOLVED( ret, "Unable to register signal handler2" ); 275 } 276 277 /* We prepare a signal set which includes SIGUSR1 and SIGUSR2 */ 278 sigemptyset( &usersigs ); 279 280 ret = sigaddset( &usersigs, SIGUSR1 ); 281 282 ret |= sigaddset( &usersigs, SIGUSR2 ); 283 284 if ( ret != 0 ) 285 { 286 UNRESOLVED( ret, "Unable to add SIGUSR1 or 2 to a signal set" ); 287 } 288 289 /* We now block the signals SIGUSR1 and SIGUSR2 for this THREAD */ 290 ret = pthread_sigmask( SIG_BLOCK, &usersigs, NULL ); 291 292 if ( ret != 0 ) 293 { 294 UNRESOLVED( ret, "Unable to block SIGUSR1 and SIGUSR2 in main thread" ); 295 } 296 297#ifdef WITH_SYNCHRO 298 if ( sem_init( &semsig1, 0, 1 ) ) 299 { 300 UNRESOLVED( errno, "Semsig1 init" ); 301 } 302 303 if ( sem_init( &semsig2, 0, 1 ) ) 304 { 305 UNRESOLVED( errno, "Semsig2 init" ); 306 } 307 308#endif 309 310 /* Initialize thread attribute objects */ 311 scenar_init(); 312 313 314 if ( ( ret = pthread_create( &th_work, NULL, test, NULL ) ) ) 315 { 316 UNRESOLVED( ret, "Worker thread creation failed" ); 317 } 318 319 arg1.sig = SIGUSR1; 320 arg2.sig = SIGUSR2; 321#ifdef WITH_SYNCHRO 322 arg1.sem = &semsig1; 323 arg2.sem = &semsig2; 324#endif 325 326 327 328 if ( ( ret = pthread_create( &th_sig1, NULL, sendsig, ( void * ) & arg1 ) ) ) 329 { 330 UNRESOLVED( ret, "Signal 1 sender thread creation failed" ); 331 } 332 333 if ( ( ret = pthread_create( &th_sig2, NULL, sendsig, ( void * ) & arg2 ) ) ) 334 { 335 UNRESOLVED( ret, "Signal 2 sender thread creation failed" ); 336 } 337 338 339 340 /* Let's wait for a while now */ 341 sleep( 10 ); 342 343 344 /* Now stop the threads and join them */ 345 do 346 { 347 do_it = 0; 348 } 349 while ( do_it ); 350 351 352 if ( ( ret = pthread_join( th_sig1, NULL ) ) ) 353 { 354 UNRESOLVED( ret, "Signal 1 sender thread join failed" ); 355 } 356 357 if ( ( ret = pthread_join( th_sig2, NULL ) ) ) 358 { 359 UNRESOLVED( ret, "Signal 2 sender thread join failed" ); 360 } 361 362 363 if ( ( ret = pthread_join( th_work, NULL ) ) ) 364 { 365 UNRESOLVED( ret, "Worker thread join failed" ); 366 } 367 368 scenar_fini(); 369 370#if VERBOSE > 0 371 output( "Test executed successfully.\n" ); 372 373 output( " %d pthread_join calls.\n", count_ope ); 374 375#ifdef WITH_SYNCHRO 376 output( " %d signals were sent meanwhile.\n", count_sig ); 377 378#endif 379 #endif 380 PASSED; 381} 382