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