1 /* 2 * Copyright (c) 2005, 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 * If there is not enough memory to store handler adresses, 20 * the function returns ENOMEM. 21 22 * The steps are: 23 * -> Register up to 10000 handlers. 24 * -> In case of failure, check the error code is ENOMEM. 25 * -> Otherwise, check the handlers are all executed.. 26 27 */ 28 29 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ 30 #define _POSIX_C_SOURCE 200112L 31 32 /******************************************************************************/ 33 /*************************** standard includes ********************************/ 34 /******************************************************************************/ 35 #include <pthread.h> 36 #include <stdarg.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <unistd.h> 41 42 #include <sys/wait.h> 43 #include <errno.h> 44 45 /******************************************************************************/ 46 /*************************** Test framework *******************************/ 47 /******************************************************************************/ 48 #include "../testfrmw/testfrmw.h" 49 #include "../testfrmw/testfrmw.c" 50 /* This header is responsible for defining the following macros: 51 * UNRESOLVED(ret, descr); 52 * where descr is a description of the error and ret is an int 53 * (error code for example) 54 * FAILED(descr); 55 * where descr is a short text saying why the test has failed. 56 * PASSED(); 57 * No parameter. 58 * 59 * Both three macros shall terminate the calling process. 60 * The testcase shall not terminate in any other maneer. 61 * 62 * The other file defines the functions 63 * void output_init() 64 * void output(char * string, ...) 65 * 66 * Those may be used to output information. 67 */ 68 69 /******************************************************************************/ 70 /**************************** Configuration ***********************************/ 71 /******************************************************************************/ 72 #ifndef VERBOSE 73 #define VERBOSE 1 74 #endif 75 76 /******************************************************************************/ 77 /*************************** Test case ***********************************/ 78 /******************************************************************************/ 79 80 pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; 81 82 int controls[3] = { 0, 0, 0 }; 83 84 /* pthread_atfork handlers */ 85 void prepare(void) 86 { 87 controls[0]++; 88 } 89 90 void parent(void) 91 { 92 controls[1]++; 93 } 94 95 void child(void) 96 { 97 controls[2]++; 98 } 99 100 /* Thread function */ 101 void *threaded(void *arg) 102 { 103 int ret, status; 104 pid_t child, ctl; 105 106 /* Wait main thread has registered the handler */ 107 ret = pthread_mutex_lock(&mtx); 108 109 if (ret != 0) { 110 UNRESOLVED(ret, "Failed to lock mutex"); 111 } 112 113 ret = pthread_mutex_unlock(&mtx); 114 115 if (ret != 0) { 116 UNRESOLVED(ret, "Failed to unlock mutex"); 117 } 118 119 /* fork */ 120 child = fork(); 121 122 if (child == -1) { 123 UNRESOLVED(errno, "Failed to fork"); 124 } 125 126 /* child */ 127 if (child == 0) { 128 if (controls[0] != 10000) { 129 FAILED("prepare handler skipped some rounds"); 130 } 131 132 if (controls[2] != 10000) { 133 FAILED("child handler skipped some rounds"); 134 } 135 136 /* We're done */ 137 exit(PTS_PASS); 138 } 139 140 if (controls[0] != 10000) { 141 FAILED("prepare handler skipped some rounds"); 142 } 143 144 if (controls[1] != 10000) { 145 FAILED("parent handler skipped some rounds"); 146 } 147 148 /* Parent joins the child */ 149 ctl = waitpid(child, &status, 0); 150 151 if (ctl != child) { 152 UNRESOLVED(errno, "Waitpid returned the wrong PID"); 153 } 154 155 if (!WIFEXITED(status) || (WEXITSTATUS(status) != PTS_PASS)) { 156 FAILED("Child exited abnormally"); 157 } 158 159 /* quit */ 160 return NULL; 161 } 162 163 /* The main test function. */ 164 int main(void) 165 { 166 int ret, i; 167 pthread_t ch; 168 169 /* Initialize output */ 170 output_init(); 171 172 ret = pthread_mutex_lock(&mtx); 173 174 if (ret != 0) { 175 UNRESOLVED(ret, "Failed to lock mutex"); 176 } 177 178 ret = pthread_create(&ch, NULL, threaded, NULL); 179 180 if (ret != 0) { 181 UNRESOLVED(ret, "Failed to create a thread"); 182 } 183 184 /* Register the handlers */ 185 for (i = 0; i < 10000; i++) { 186 ret = pthread_atfork(prepare, parent, child); 187 188 if (ret == ENOMEM) { 189 output("ENOMEM returned after %i iterations\n", i); 190 break; 191 } 192 193 if (ret != 0) { 194 UNRESOLVED(ret, 195 "Failed to register the atfork handlers"); 196 } 197 } 198 199 if (ret == 0) { 200 201 /* Let the child go on */ 202 ret = pthread_mutex_unlock(&mtx); 203 204 if (ret != 0) { 205 UNRESOLVED(ret, "Failed to unlock mutex"); 206 } 207 208 ret = pthread_join(ch, NULL); 209 210 if (ret != 0) { 211 UNRESOLVED(ret, "Failed to join the thread"); 212 } 213 } 214 215 /* Test passed */ 216 #if VERBOSE > 0 217 218 output("Test passed\n"); 219 220 #endif 221 222 PASSED; 223 } 224