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 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_kill() 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 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 */ 227int 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