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 * No atexit() registered routine shall be called because of pthread_exit(). 20 21 * The steps are: 22 * 23 * -> Create threads with different attributes (but all must be joinable) 24 * -> inside the thread, 25 * -> register a function with atexit() 26 * -> call pthread_exit. 27 * -> In the main thread, we join the thread and check the function did not execute. 28 29 */ 30 31 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ 32#define _POSIX_C_SOURCE 200112L 33 34 /* Some routines are part of the XSI Extensions */ 35#ifndef WITHOUT_XOPEN 36#define _XOPEN_SOURCE 600 37#endif 38 39/********************************************************************************************/ 40/****************************** standard includes *****************************************/ 41/********************************************************************************************/ 42#include <pthread.h> 43#include <stdarg.h> 44#include <stdio.h> 45#include <stdlib.h> 46#include <string.h> 47#include <unistd.h> 48 49#include <sched.h> 50#include <semaphore.h> 51#include <errno.h> 52#include <assert.h> 53/********************************************************************************************/ 54/****************************** Test framework *****************************************/ 55/********************************************************************************************/ 56#include "../testfrmw/testfrmw.h" 57#include "../testfrmw/testfrmw.c" 58 /* This header is responsible for defining the following macros: 59 * UNRESOLVED(ret, descr); 60 * where descr is a description of the error and ret is an int (error code for example) 61 * FAILED(descr); 62 * where descr is a short text saying why the test has failed. 63 * PASSED(); 64 * No parameter. 65 * 66 * Both three macros shall terminate the calling process. 67 * The testcase shall not terminate in any other maneer. 68 * 69 * The other file defines the functions 70 * void output_init() 71 * void output(char * string, ...) 72 * 73 * Those may be used to output information. 74 */ 75 76/********************************************************************************************/ 77/********************************** Configuration ******************************************/ 78/********************************************************************************************/ 79#ifndef VERBOSE 80#define VERBOSE 1 81#endif 82 83/********************************************************************************************/ 84/*********************************** Test cases *****************************************/ 85/********************************************************************************************/ 86 87#include "../testfrmw/threads_scenarii.c" 88 89/* This file will define the following objects: 90 * scenarii: array of struct __scenario type. 91 * NSCENAR : macro giving the total # of scenarii 92 * scenar_init(): function to call before use the scenarii array. 93 * scenar_fini(): function to call after end of use of the scenarii array. 94 */ 95 96/********************************************************************************************/ 97/*********************************** Real Test *****************************************/ 98/********************************************************************************************/ 99 100int global = 0; 101 102/* atexit() routines */ 103void at1(void) 104{ 105 global +=1; 106} 107 108void at2(void) 109{ 110 global +=2; 111} 112 113/* Thread routine */ 114void *threaded(void *arg) 115{ 116 int ret = 0; 117 118 /* Note that this funtion will be registered once again for each scenario. 119 POSIX requires the ability to register at least 32 functions so it should 120 not be an issue in our case, as long as we don't get more than 32 scenarii 121 (with joinable threads) */ 122 ret = atexit(at2); 123 if (ret != 0) { 124 UNRESOLVED(ret, "Failed to register an atexit() routine"); 125 } 126 127 pthread_exit(NULL + 1); 128 129 FAILED("pthread_exit() did not terminate the thread"); 130 return NULL; 131} 132 133int main(void) 134{ 135 int ret = 0; 136 void *rval; 137 pthread_t child; 138 int i; 139 140 output_init(); 141 142 scenar_init(); 143 144 for (i = 0; i < NSCENAR; i++) { 145 if (scenarii[i].detached == 0) { 146#if VERBOSE > 0 147 output("-----\n"); 148 output("Starting test with scenario (%i): %s\n", i, 149 scenarii[i].descr); 150#endif 151 152 ret = 153 pthread_create(&child, &scenarii[i].ta, threaded, 154 NULL); 155 switch (scenarii[i].result) { 156 case 0: /* Operation was expected to succeed */ 157 if (ret != 0) { 158 UNRESOLVED(ret, 159 "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 break; 169 170 case 2: /* We did not know the expected result */ 171 default: 172#if VERBOSE > 0 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 ret = pthread_join(child, &rval); 185 if (ret != 0) { 186 UNRESOLVED(ret, 187 "Unable to join a thread"); 188 } 189 190 if (rval != (NULL + 1)) { 191 FAILED 192 ("pthread_join() did not retrieve the pthread_exit() param"); 193 } 194 195 if (global !=0) { 196 FAILED 197 ("The function registered with atexit() executed"); 198 } 199 200 } 201 } 202 } 203 204 scenar_fini(); 205#if VERBOSE > 0 206 output("-----\n"); 207 output("All test data destroyed\n"); 208 output("Test PASSED\n"); 209#endif 210 211 PASSED; 212} 213