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 * -> pthread_kill a thread which creates threads 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 /* Some routines are part of the XSI Extensions */ 33#ifndef WITHOUT_XOPEN 34 #define _XOPEN_SOURCE 600 35#endif 36/********************************************************************************************/ 37/****************************** standard includes *****************************************/ 38/********************************************************************************************/ 39 #include <pthread.h> 40 #include <stdarg.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <unistd.h> 45 46 #include <sched.h> 47 #include <semaphore.h> 48 #include <errno.h> 49 #include <assert.h> 50 #include <sys/wait.h> 51 #include <time.h> 52 #include <signal.h> 53 54/********************************************************************************************/ 55/****************************** Test framework *****************************************/ 56/********************************************************************************************/ 57 #include "testfrmw.h" 58 #include "testfrmw.c" 59 /* This header is responsible for defining the following macros: 60 * UNRESOLVED(ret, descr); 61 * where descr is a description of the error and ret is an int (error code for example) 62 * FAILED(descr); 63 * where descr is a short text saying why the test has failed. 64 * PASSED(); 65 * No parameter. 66 * 67 * Both three macros shall terminate the calling process. 68 * The testcase shall not terminate in any other maneer. 69 * 70 * The other file defines the functions 71 * void output_init() 72 * void output(char * string, ...) 73 * 74 * Those may be used to output information. 75 */ 76 77/********************************************************************************************/ 78/********************************** Configuration ******************************************/ 79/********************************************************************************************/ 80#ifndef VERBOSE 81#define VERBOSE 1 82#endif 83 84#define WITH_SYNCHRO 85 86 87/********************************************************************************************/ 88/*********************************** Test cases *****************************************/ 89/********************************************************************************************/ 90 91#include "threads_scenarii.c" 92 93/* This file will define the following objects: 94 * scenarii: array of struct __scenario type. 95 * NSCENAR : macro giving the total # of scenarii 96 * scenar_init(): function to call before use the scenarii array. 97 * scenar_fini(): function to call after end of use of the scenarii array. 98 */ 99 100 101/********************************************************************************************/ 102/*********************************** Real Test *****************************************/ 103/********************************************************************************************/ 104 105char do_it=1; 106char woken=0; 107unsigned long count_ope=0; 108#ifdef WITH_SYNCHRO 109sem_t semsig1; 110sem_t semsig2; 111unsigned long count_sig=0; 112#endif 113 114sigset_t usersigs; 115 116typedef struct 117{ 118 int sig; 119#ifdef WITH_SYNCHRO 120 sem_t *sem; 121#endif 122} thestruct; 123 124/* the following function keeps on sending the signal to the process */ 125void * sendsig (void * arg) 126{ 127 thestruct *thearg = (thestruct *) arg; 128 int ret; 129 pid_t process; 130 131 process=getpid(); 132 133 /* We block the signals SIGUSR1 and SIGUSR2 for this THREAD */ 134 ret = pthread_sigmask(SIG_BLOCK, &usersigs, NULL); 135 if (ret != 0) { UNRESOLVED(ret, "Unable to block SIGUSR1 and SIGUSR2 in signal thread"); } 136 137 while (do_it) 138 { 139 #ifdef WITH_SYNCHRO 140 if ((ret = sem_wait(thearg->sem))) 141 { UNRESOLVED(errno, "Sem_wait in sendsig"); } 142 count_sig++; 143 #endif 144 145 ret = kill(process, thearg->sig); 146 if (ret != 0) { UNRESOLVED(errno, "Kill in sendsig"); } 147 148 } 149 150 return NULL; 151} 152 153/* Next are the signal handlers. */ 154/* This one is registered for signal SIGUSR1 */ 155void sighdl1(int sig) 156{ 157#ifdef WITH_SYNCHRO 158 if (sem_post(&semsig1)) 159 { UNRESOLVED(errno, "Sem_post in signal handler 1"); } 160#endif 161} 162/* This one is registered for signal SIGUSR2 */ 163void sighdl2(int sig) 164{ 165#ifdef WITH_SYNCHRO 166 if (sem_post(&semsig2)) 167 { UNRESOLVED(errno, "Sem_post in signal handler 2"); } 168#endif 169} 170 171/* Thread function -- almost does nothing */ 172void * threaded(void * arg) 173{ 174 int ret; 175 176 /* Signal we're done (especially in case of a detached thread) */ 177 do { ret = sem_post(&scenarii[sc].sem); } 178 while ((ret == -1) && (errno == EINTR)); 179 if (ret == -1) { UNRESOLVED(errno, "Failed to wait for the semaphore"); } 180 181 /* return */ 182 return arg; 183} 184 185/* Test function -- creates the threads and check that EINTR is never returned. */ 186void * test(void * arg) 187{ 188 int ret=0; 189 pthread_t child; 190 191 /* We don't block the signals SIGUSR1 and SIGUSR2 for this THREAD */ 192 ret = pthread_sigmask(SIG_UNBLOCK, &usersigs, NULL); 193 if (ret != 0) { UNRESOLVED(ret, "Unable to unblock SIGUSR1 and SIGUSR2 in worker thread"); } 194 195 sc = 0; 196 197 while (do_it) 198 { 199 #if VERBOSE > 5 200 output("-----\n"); 201 output("Starting test with scenario (%i): %s\n", sc, scenarii[sc].descr); 202 #endif 203 204 count_ope++; 205 206 ret = pthread_create(&child, &scenarii[sc].ta, threaded, NULL); 207 if (ret == EINTR) { FAILED("pthread_create returned EINTR"); } 208 switch (scenarii[sc].result) 209 { 210 case 0: /* Operation was expected to succeed */ 211 if (ret != 0) { UNRESOLVED(ret, "Failed to create this thread"); } 212 break; 213 214 case 1: /* Operation was expected to fail */ 215 if (ret == 0) { UNRESOLVED(-1, "An error was expected but the thread creation succeeded"); } 216 break; 217 218 case 2: /* We did not know the expected result */ 219 default: 220 #if VERBOSE > 5 221 if (ret == 0) 222 { output("Thread has been created successfully for this scenario\n"); } 223 else 224 { output("Thread creation failed with the error: %s\n", strerror(ret)); } 225 #endif 226 ; 227 } 228 if (ret == 0) /* The new thread is running */ 229 { 230 if (scenarii[sc].detached == 0) 231 { 232 ret = pthread_join(child, NULL); 233 if (ret != 0) { UNRESOLVED(ret, "Unable to join a thread"); } 234 } 235 else 236 { 237 /* Just wait for the thread to terminate */ 238 do { ret = sem_wait(&scenarii[sc].sem); } 239 while ((ret == -1) && (errno == EINTR)); 240 if (ret == -1) { UNRESOLVED(errno, "Failed to wait for the semaphore"); } 241 } 242 } 243 244 /* Change thread attribute for the next loop */ 245 sc++; 246 sc %= NSCENAR; 247 } 248 return NULL; 249} 250 251/* Main function */ 252int main (int argc, char * argv[]) 253{ 254 int ret; 255 pthread_t th_work, th_sig1, th_sig2; 256 thestruct arg1, arg2; 257 struct sigaction sa; 258 259 /* Initialize output routine */ 260 output_init(); 261 262 /* Initialize thread attribute objects */ 263 scenar_init(); 264 265 /* We need to register the signal handlers for the PROCESS */ 266 sigemptyset (&sa.sa_mask); 267 sa.sa_flags = 0; 268 sa.sa_handler = sighdl1; 269 if ((ret = sigaction (SIGUSR1, &sa, NULL))) 270 { UNRESOLVED(ret, "Unable to register signal handler1"); } 271 sa.sa_handler = sighdl2; 272 if ((ret = sigaction (SIGUSR2, &sa, NULL))) 273 { UNRESOLVED(ret, "Unable to register signal handler2"); } 274 275 /* We prepare a signal set which includes SIGUSR1 and SIGUSR2 */ 276 sigemptyset(&usersigs); 277 ret = sigaddset(&usersigs, SIGUSR1); 278 ret |= sigaddset(&usersigs, SIGUSR2); 279 if (ret != 0) { UNRESOLVED(ret, "Unable to add SIGUSR1 or 2 to a signal set"); } 280 281 /* We now block the signals SIGUSR1 and SIGUSR2 for this THREAD */ 282 ret = pthread_sigmask(SIG_BLOCK, &usersigs, NULL); 283 if (ret != 0) { UNRESOLVED(ret, "Unable to block SIGUSR1 and SIGUSR2 in main thread"); } 284 285 #ifdef WITH_SYNCHRO 286 if (sem_init(&semsig1, 0, 1)) 287 { UNRESOLVED(errno, "Semsig1 init"); } 288 if (sem_init(&semsig2, 0, 1)) 289 { UNRESOLVED(errno, "Semsig2 init"); } 290 #endif 291 292 if ((ret = pthread_create(&th_work, NULL, test, NULL))) 293 { UNRESOLVED(ret, "Worker thread creation failed"); } 294 295 arg1.sig = SIGUSR1; 296 arg2.sig = SIGUSR2; 297#ifdef WITH_SYNCHRO 298 arg1.sem = &semsig1; 299 arg2.sem = &semsig2; 300#endif 301 302 if ((ret = pthread_create(&th_sig1, NULL, sendsig, (void *)&arg1))) 303 { UNRESOLVED(ret, "Signal 1 sender thread creation failed"); } 304 if ((ret = pthread_create(&th_sig2, NULL, sendsig, (void *)&arg2))) 305 { UNRESOLVED(ret, "Signal 2 sender thread creation failed"); } 306 307 /* Let's wait for a while now */ 308 sleep(1); 309 310 /* Now stop the threads and join them */ 311 do { do_it=0; } 312 while (do_it); 313 314 if ((ret = pthread_join(th_sig1, NULL))) 315 { UNRESOLVED(ret, "Signal 1 sender thread join failed"); } 316 if ((ret = pthread_join(th_sig2, NULL))) 317 { UNRESOLVED(ret, "Signal 2 sender thread join failed"); } 318 319 if ((ret = pthread_join(th_work, NULL))) 320 { UNRESOLVED(ret, "Worker thread join failed"); } 321 322 scenar_fini(); 323 324 #if VERBOSE > 0 325 output("Test executed successfully.\n"); 326 output(" %d thread creations.\n", count_ope); 327 #ifdef WITH_SYNCHRO 328 output(" %d signals were sent meanwhile.\n", count_sig); 329 #endif 330 #endif 331 PASSED; 332} 333 334