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_detach() 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; 106unsigned long count_ope=0; 107#ifdef WITH_SYNCHRO 108sem_t semsig1; 109sem_t semsig2; 110unsigned long count_sig=0; 111#endif 112 113sigset_t usersigs; 114 115typedef struct 116{ 117 int sig; 118#ifdef WITH_SYNCHRO 119 sem_t *sem; 120#endif 121} thestruct; 122 123/* the following function keeps on sending the signal to the process */ 124void * sendsig (void * arg) 125{ 126 thestruct *thearg = (thestruct *) arg; 127 int ret; 128 pid_t process; 129 130 process=getpid(); 131 132 /* We block the signals SIGUSR1 and SIGUSR2 for this THREAD */ 133 ret = pthread_sigmask(SIG_BLOCK, &usersigs, NULL); 134 if (ret != 0) { UNRESOLVED(ret, "Unable to block SIGUSR1 and SIGUSR2 in signal thread"); } 135 136 while (do_it) 137 { 138 #ifdef WITH_SYNCHRO 139 if ((ret = sem_wait(thearg->sem))) 140 { UNRESOLVED(errno, "Sem_wait in sendsig"); } 141 count_sig++; 142 #endif 143 144 ret = kill(process, thearg->sig); 145 if (ret != 0) { UNRESOLVED(errno, "Kill in sendsig"); } 146 147 } 148 return NULL; 149} 150 151/* Next are the signal handlers. */ 152/* This one is registered for signal SIGUSR1 */ 153void sighdl1(int sig) 154{ 155#ifdef WITH_SYNCHRO 156 if (sem_post(&semsig1)) 157 { UNRESOLVED(errno, "Sem_post in signal handler 1"); } 158#endif 159} 160/* This one is registered for signal SIGUSR2 */ 161void sighdl2(int sig) 162{ 163#ifdef WITH_SYNCHRO 164 if (sem_post(&semsig2)) 165 { UNRESOLVED(errno, "Sem_post in signal handler 2"); } 166#endif 167} 168 169/* Thread function -- almost does nothing */ 170void * threaded(void * arg) 171{ 172 int ret; 173 174 /* We don't block the signals SIGUSR1 and SIGUSR2 for this THREAD */ 175 ret = pthread_sigmask(SIG_UNBLOCK, &usersigs, NULL); 176 if (ret != 0) { UNRESOLVED(ret, "Unable to unblock SIGUSR1 and SIGUSR2 in worker thread"); } 177 178 ret = pthread_detach(pthread_self()); 179 if (ret == EINTR) { FAILED("pthread_detach() returned EINTR"); } 180 181 /* Signal we're done */ 182 do { ret = sem_post(&scenarii[sc].sem); } 183 while ((ret == -1) && (errno == EINTR)); 184 if (ret == -1) { UNRESOLVED(errno, "Failed to wait for the semaphore"); } 185 186 /* return */ 187 return arg; 188} 189 190/* Test function -- creates the thread. */ 191void * test(void * arg) 192{ 193 int ret=0; 194 pthread_t child; 195 196 /* We block the signals SIGUSR1 and SIGUSR2 for this THREAD */ 197 ret = pthread_sigmask(SIG_BLOCK, &usersigs, NULL); 198 if (ret != 0) { UNRESOLVED(ret, "Unable to block SIGUSR1 and SIGUSR2 in signal thread"); } 199 200 sc = 0; 201 202 while (do_it) 203 { 204 #if VERBOSE > 5 205 output("-----\n"); 206 output("Starting test with scenario (%i): %s\n", sc, scenarii[sc].descr); 207 #endif 208 209 count_ope++; 210 211 ret = pthread_create(&child, &scenarii[sc].ta, threaded, NULL); 212 switch (scenarii[sc].result) 213 { 214 case 0: /* Operation was expected to succeed */ 215 if (ret != 0) { UNRESOLVED(ret, "Failed to create this thread"); } 216 break; 217 218 case 1: /* Operation was expected to fail */ 219 if (ret == 0) { UNRESOLVED(-1, "An error was expected but the thread creation succeeded"); } 220 break; 221 222 case 2: /* We did not know the expected result */ 223 default: 224 #if VERBOSE > 5 225 if (ret == 0) 226 { output("Thread has been created successfully for this scenario\n"); } 227 else 228 { output("Thread creation failed with the error: %s\n", strerror(ret)); } 229 #endif 230 ; 231 } 232 if (ret == 0) /* The new thread is running */ 233 { 234 /* Just wait for the thread to terminate */ 235 do { ret = sem_wait(&scenarii[sc].sem); } 236 while ((ret == -1) && (errno == EINTR)); 237 if (ret == -1) { UNRESOLVED(errno, "Failed to wait for the semaphore"); } 238 } 239 240 /* Change thread attribute for the next loop */ 241 sc++; 242 sc %= NSCENAR; 243 } 244 return NULL; 245} 246 247/* Main function */ 248int main (int argc, char * argv[]) 249{ 250 int ret; 251 pthread_t th_work, th_sig1, th_sig2; 252 thestruct arg1, arg2; 253 struct sigaction sa; 254 255 /* Initialize output routine */ 256 output_init(); 257 258 /* Initialize thread attribute objects */ 259 scenar_init(); 260 261 /* We need to register the signal handlers for the PROCESS */ 262 sigemptyset (&sa.sa_mask); 263 sa.sa_flags = 0; 264 sa.sa_handler = sighdl1; 265 if ((ret = sigaction (SIGUSR1, &sa, NULL))) 266 { UNRESOLVED(ret, "Unable to register signal handler1"); } 267 sa.sa_handler = sighdl2; 268 if ((ret = sigaction (SIGUSR2, &sa, NULL))) 269 { UNRESOLVED(ret, "Unable to register signal handler2"); } 270 271 /* We prepare a signal set which includes SIGUSR1 and SIGUSR2 */ 272 sigemptyset(&usersigs); 273 ret = sigaddset(&usersigs, SIGUSR1); 274 ret |= sigaddset(&usersigs, SIGUSR2); 275 if (ret != 0) { UNRESOLVED(ret, "Unable to add SIGUSR1 or 2 to a signal set"); } 276 277 /* We now block the signals SIGUSR1 and SIGUSR2 for this THREAD */ 278 ret = pthread_sigmask(SIG_BLOCK, &usersigs, NULL); 279 if (ret != 0) { UNRESOLVED(ret, "Unable to block SIGUSR1 and SIGUSR2 in main thread"); } 280 281 #ifdef WITH_SYNCHRO 282 if (sem_init(&semsig1, 0, 1)) 283 { UNRESOLVED(errno, "Semsig1 init"); } 284 if (sem_init(&semsig2, 0, 1)) 285 { UNRESOLVED(errno, "Semsig2 init"); } 286 #endif 287 288 if ((ret = pthread_create(&th_work, NULL, test, NULL))) 289 { UNRESOLVED(ret, "Worker thread creation failed"); } 290 291 arg1.sig = SIGUSR1; 292 arg2.sig = SIGUSR2; 293#ifdef WITH_SYNCHRO 294 arg1.sem = &semsig1; 295 arg2.sem = &semsig2; 296#endif 297 298 299 300 if ((ret = pthread_create(&th_sig1, NULL, sendsig, (void *)&arg1))) 301 { UNRESOLVED(ret, "Signal 1 sender thread creation failed"); } 302 if ((ret = pthread_create(&th_sig2, NULL, sendsig, (void *)&arg2))) 303 { UNRESOLVED(ret, "Signal 2 sender thread creation failed"); } 304 305 306 307 /* Let's wait for a while now */ 308 sleep(1); 309 310 311 /* Now stop the threads and join them */ 312 do { do_it=0; } 313 while (do_it); 314 315 316 if ((ret = pthread_join(th_sig1, NULL))) 317 { UNRESOLVED(ret, "Signal 1 sender thread join failed"); } 318 319 if ((ret = pthread_join(th_sig2, NULL))) 320 { UNRESOLVED(ret, "Signal 2 sender thread join failed"); } 321 322 323 if ((ret = pthread_join(th_work, NULL))) 324 { UNRESOLVED(ret, "Worker thread join failed"); } 325 326 327 scenar_fini(); 328 329 #if VERBOSE > 0 330 output("Test executed successfully.\n"); 331 output(" %d thread detached.\n", count_ope); 332 #ifdef WITH_SYNCHRO 333 output(" %d signals were sent meanwhile.\n", count_sig); 334 #endif 335 #endif 336 PASSED; 337} 338 339