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 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 171/* Init function */ 172void * 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. */ 183void * 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 */ 234int 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