Home | History | Annotate | Download | only in pthread_detach
      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