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 * pthread_detach() will indicate that the thread resources 20 * can be reclaimed as soon as the thread terminates. 21 * This means that pthread_join() will fail on such a thread. 22 23 * The steps are: 24 * 25 * -> create a thread with a joinable state 26 * -> detach the thread, either from inside the thread or from outside 27 * -> try and join the thread, and check an error is returned. 28 29 * The test fails if pthread_join succeeds. 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 <errno.h> 53 #include <assert.h> 54 /********************************************************************************************/ 55 /****************************** Test framework *****************************************/ 56 /********************************************************************************************/ 57 #include "../testfrmw/testfrmw.h" 58 #include "../testfrmw/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 /********************************************************************************************/ 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 void *threaded(void *arg) 102 { 103 int ret = 0; 104 105 if (arg != NULL) { 106 ret = pthread_detach(pthread_self()); 107 if (ret != 0) { 108 UNRESOLVED(ret, "Failed to detach the thread"); 109 } 110 } 111 112 /* Post the semaphore to unlock the main thread in case of a detached thread */ 113 do { 114 ret = sem_post(&(scenarii[sc].sem)); 115 } 116 while ((ret == -1) && (errno == EINTR)); 117 if (ret == -1) { 118 UNRESOLVED(errno, "Failed to post the semaphore"); 119 } 120 121 return arg; 122 } 123 124 int main(void) 125 { 126 int ret = 0; 127 pthread_t child; 128 129 output_init(); 130 131 scenar_init(); 132 133 for (sc = 0; sc < NSCENAR; sc++) { 134 #if VERBOSE > 0 135 output("-----\n"); 136 output("Starting test with scenario (%i): %s\n", sc, 137 scenarii[sc].descr); 138 #endif 139 140 if (scenarii[sc].detached != 0) { /* only joinable threads can be detached */ 141 ret = 142 pthread_attr_setdetachstate(&scenarii[sc].ta, 143 PTHREAD_CREATE_JOINABLE); 144 if (ret != 0) { 145 UNRESOLVED(ret, 146 "Unable to set detachstate back to joinable"); 147 } 148 } 149 150 /* for detached scenarii, we will call pthread_detach from inside the thread. 151 for joinable scenarii, we'll call pthread_detach from this thread. */ 152 153 ret = 154 pthread_create(&child, &scenarii[sc].ta, threaded, 155 (scenarii[sc].detached != 0) ? &ret : NULL); 156 switch (scenarii[sc].result) { 157 case 0: /* Operation was expected to succeed */ 158 if (ret != 0) { 159 UNRESOLVED(ret, "Failed to create this thread"); 160 } 161 break; 162 163 case 1: /* Operation was expected to fail */ 164 if (ret == 0) { 165 UNRESOLVED(-1, 166 "An error was expected but the thread creation succeeded"); 167 } 168 #if VERBOSE > 0 169 break; 170 171 case 2: /* We did not know the expected result */ 172 default: 173 if (ret == 0) { 174 output 175 ("Thread has been created successfully for this scenario\n"); 176 } else { 177 output 178 ("Thread creation failed with the error: %s\n", 179 strerror(ret)); 180 } 181 #endif 182 } 183 if (ret == 0) { /* The new thread is running */ 184 /* Just wait for the thread to terminate */ 185 do { 186 ret = sem_wait(&(scenarii[sc].sem)); 187 } 188 while ((ret == -1) && (errno == EINTR)); 189 if (ret == -1) { 190 UNRESOLVED(errno, 191 "Failed to post the semaphore"); 192 } 193 194 /* If we must detach from here, we do it now. */ 195 if (scenarii[sc].detached == 0) { 196 ret = pthread_detach(child); 197 if (ret != 0) { 198 UNRESOLVED(ret, 199 "Failed to detach the child thread."); 200 } 201 } 202 203 /* now check that the thread resources are freed. */ 204 ret = pthread_join(child, NULL); 205 if (ret == 0) { 206 FAILED 207 ("We were able to join a detached thread."); 208 } 209 210 /* Let the thread an additionnal row to cleanup */ 211 sched_yield(); 212 } 213 } 214 215 scenar_fini(); 216 #if VERBOSE > 0 217 output("-----\n"); 218 output("All test data destroyed\n"); 219 output("Test PASSED\n"); 220 #endif 221 222 PASSED; 223 } 224