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