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 * pthread_detach() does not force a thread to terminate. 21 22 * The steps are: 23 * 24 * -> Create a thread 25 * -> detach the thread 26 * -> wait for the thread to post a semaphore. 27 28 * The test fails if the semaphore is not posted within a certain duration. 29 30 */ 31 32 33 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ 34 #define _POSIX_C_SOURCE 200112L 35 36 /* Some routines are part of the XSI Extensions */ 37#ifndef WITHOUT_XOPEN 38 #define _XOPEN_SOURCE 600 39#endif 40/********************************************************************************************/ 41/****************************** standard includes *****************************************/ 42/********************************************************************************************/ 43 #include <pthread.h> 44 #include <stdarg.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <unistd.h> 49 50 #include <sched.h> 51 #include <semaphore.h> 52 #include <time.h> 53 #include <errno.h> 54 #include <assert.h> 55/********************************************************************************************/ 56/****************************** Test framework *****************************************/ 57/********************************************************************************************/ 58 #include "testfrmw.h" 59 #include "testfrmw.c" 60 /* This header is responsible for defining the following macros: 61 * UNRESOLVED(ret, descr); 62 * where descr is a description of the error and ret is an int (error code for example) 63 * FAILED(descr); 64 * where descr is a short text saying why the test has failed. 65 * PASSED(); 66 * No parameter. 67 * 68 * Both three macros shall terminate the calling process. 69 * The testcase shall not terminate in any other maneer. 70 * 71 * The other file defines the functions 72 * void output_init() 73 * void output(char * string, ...) 74 * 75 * Those may be used to output information. 76 */ 77 78/********************************************************************************************/ 79/********************************** Configuration ******************************************/ 80/********************************************************************************************/ 81#ifndef VERBOSE 82#define VERBOSE 1 83#endif 84 85#define TIMEOUT 5 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/*********************************** Real Test *****************************************/ 102/********************************************************************************************/ 103 104sem_t sem_sync; 105 106void * threaded (void * arg) 107{ 108 int ret=0; 109 110 if (arg != NULL) 111 { 112 ret = pthread_detach(pthread_self()); 113 if (ret != 0) { UNRESOLVED(ret, "Failed to detach the thread"); } 114 } 115 /* Wait for this semaphore which indicates that pthread_detach has been called */ 116 do { ret = sem_wait(&sem_sync); } 117 while ((ret == -1) && (errno == EINTR)); 118 if (ret == -1) { UNRESOLVED(errno, "Failed to wait for the semaphore"); } 119 120 /* Post the semaphore to indicate the main thread we're alive */ 121 do { ret = sem_post(&(scenarii[sc].sem)); } 122 while ((ret == -1) && (errno == EINTR)); 123 if (ret == -1) { UNRESOLVED(errno, "Failed to post the semaphore"); } 124 125 return arg; 126} 127 128int main (int argc, char *argv[]) 129{ 130 int ret=0; 131 pthread_t child; 132 struct timespec ts; 133 134 output_init(); 135 136 scenar_init(); 137 138 ret = sem_init(&sem_sync, 0, 0); 139 if (ret != 0) { UNRESOLVED(ret, "Failed to initialize a semaphore"); } 140 141 for (sc=0; sc < NSCENAR; sc++) 142 { 143 #if VERBOSE > 0 144 output("-----\n"); 145 output("Starting test with scenario (%i): %s\n", sc, scenarii[sc].descr); 146 #endif 147 148 if (scenarii[sc].detached != 0) /* only joinable threads can be detached */ 149 { 150 ret = pthread_attr_setdetachstate(&scenarii[sc].ta, PTHREAD_CREATE_JOINABLE); 151 if (ret != 0) { UNRESOLVED(ret, "Unable to set detachstate back to joinable"); } 152 } 153 154 /* for detached scenarii, we will call pthread_detach from inside the thread. 155 for joinable scenarii, we'll call pthread_detach from this thread. */ 156 157 ret = pthread_create(&child, &scenarii[sc].ta, threaded, (scenarii[sc].detached != 0)?&ret:NULL); 158 switch (scenarii[sc].result) 159 { 160 case 0: /* Operation was expected to succeed */ 161 if (ret != 0) { UNRESOLVED(ret, "Failed to create this thread"); } 162 break; 163 164 case 1: /* Operation was expected to fail */ 165 if (ret == 0) { UNRESOLVED(-1, "An error was expected but the thread creation succeeded"); } 166 #if VERBOSE > 0 167 break; 168 169 case 2: /* We did not know the expected result */ 170 default: 171 if (ret == 0) 172 { output("Thread has been created successfully for this scenario\n"); } 173 else 174 { output("Thread creation failed with the error: %s\n", strerror(ret)); } 175 #endif 176 } 177 if (ret == 0) /* The new thread is running */ 178 { 179 /* If we must detach from here, we do it now. */ 180 if (scenarii[sc].detached == 0) 181 { 182 ret = pthread_detach(child); 183 if (ret != 0) { UNRESOLVED(ret, "Failed to detach the child thread."); } 184 } 185 186 /* Now, allow the thread to terminate */ 187 do { ret = sem_post(&sem_sync); } 188 while ((ret == -1) && (errno == EINTR)); 189 if (ret == -1) { UNRESOLVED(errno, "Failed to post the semaphore"); } 190 191 /* Just wait for the thread to terminate */ 192 ret = clock_gettime(CLOCK_REALTIME, &ts); 193 if (ret != 0) { UNRESOLVED(ret, "Failed to get time"); } 194 195 ts.tv_sec += TIMEOUT; 196 197 do { ret = sem_timedwait(&(scenarii[sc].sem), &ts); } 198 while ((ret == -1) && (errno == EINTR)); 199 if (ret == -1) 200 { 201 if (errno == ETIMEDOUT) { FAILED("pthread_detach made the thread terminate"); } 202 /* else */ 203 UNRESOLVED(errno, "Failed to wait for the semaphore"); 204 } 205 206 /* Let the thread an additionnal row to cleanup */ 207 sched_yield(); 208 } 209 } 210 211 ret = sem_destroy(&sem_sync); 212 if (ret != 0) { UNRESOLVED(ret, "Failed to destroy the semaphore"); } 213 214 scenar_fini(); 215 #if VERBOSE > 0 216 output("-----\n"); 217 output("All test data destroyed\n"); 218 output("Test PASSED\n"); 219 #endif 220 221 PASSED; 222} 223 224