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