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