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