• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 * When pthread_atfork is called several times, the prepare handlers are executed
20 * in reversed order as they were registered, and child and parent handlers are
21 * executed in the same order as they were registered.
22 
23 * The steps are:
24 * -> Register some handlers for which call order is traceable.
25 
26 * The test fails if the registered handlers are not executed as expected.
27 
28 */
29 
30 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
31 #define _POSIX_C_SOURCE 200112L
32 
33 /******************************************************************************/
34 /*************************** standard includes ********************************/
35 /******************************************************************************/
36 #include <pthread.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42 
43 #include <sys/wait.h>
44 #include <errno.h>
45 
46 /******************************************************************************/
47 /***************************   Test framework   *******************************/
48 /******************************************************************************/
49 #include "../testfrmw/testfrmw.h"
50 #include "../testfrmw/testfrmw.c"
51 /* This header is responsible for defining the following macros:
52  * UNRESOLVED(ret, descr);
53  *    where descr is a description of the error and ret is an int
54  *   (error code for example)
55  * FAILED(descr);
56  *    where descr is a short text saying why the test has failed.
57  * PASSED();
58  *    No parameter.
59  *
60  * Both three macros shall terminate the calling process.
61  * The testcase shall not terminate in any other maneer.
62  *
63  * The other file defines the functions
64  * void output_init()
65  * void output(char * string, ...)
66  *
67  * Those may be used to output information.
68  */
69 
70 /******************************************************************************/
71 /**************************** Configuration ***********************************/
72 /******************************************************************************/
73 #ifndef VERBOSE
74 #define VERBOSE 1
75 #endif
76 
77 /******************************************************************************/
78 /***************************    Test case   ***********************************/
79 /******************************************************************************/
80 
81 pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
82 
83 int control = 0;
84 int nerrors = 0;
85 
86 /* pthread_atfork handlers */
pre3(void)87 void pre3(void)
88 {
89 	control++;
90 
91 	if (control != 1)
92 		nerrors++;
93 }
94 
pre2(void)95 void pre2(void)
96 {
97 	control++;
98 
99 	if (control != 2)
100 		nerrors++;
101 }
102 
pre1(void)103 void pre1(void)
104 {
105 	control++;
106 
107 	if (control != 3)
108 		nerrors++;
109 }
110 
par1(void)111 void par1(void)
112 {
113 	control++;
114 
115 	if (control != 4)
116 		nerrors++;
117 }
118 
par2(void)119 void par2(void)
120 {
121 	control++;
122 
123 	if (control != 5)
124 		nerrors++;
125 }
126 
par3(void)127 void par3(void)
128 {
129 	control++;
130 
131 	if (control != 6)
132 		nerrors++;
133 }
134 
chi1(void)135 void chi1(void)
136 {
137 	control += 2;
138 
139 	if (control != 5)
140 		nerrors++;
141 }
142 
chi2(void)143 void chi2(void)
144 {
145 	control += 2;
146 
147 	if (control != 7)
148 		nerrors++;
149 }
150 
chi3(void)151 void chi3(void)
152 {
153 	control += 2;
154 
155 	if (control != 9)
156 		nerrors++;
157 }
158 
159 /* Thread function */
threaded(void * arg)160 void *threaded(void *arg)
161 {
162 	int ret, status;
163 	pid_t child, ctl;
164 
165 	/* Wait main thread has registered the handler */
166 	ret = pthread_mutex_lock(&mtx);
167 
168 	if (ret != 0) {
169 		UNRESOLVED(ret, "Failed to lock mutex");
170 	}
171 
172 	ret = pthread_mutex_unlock(&mtx);
173 
174 	if (ret != 0) {
175 		UNRESOLVED(ret, "Failed to unlock mutex");
176 	}
177 
178 	/* fork */
179 	child = fork();
180 
181 	if (child == -1) {
182 		UNRESOLVED(errno, "Failed to fork");
183 	}
184 
185 	/* child */
186 	if (child == 0) {
187 		if (nerrors) {
188 			FAILED("Errors occured in the child");
189 		}
190 
191 		/* We're done */
192 		exit(PTS_PASS);
193 	}
194 
195 	/* Parent joins the child */
196 	ctl = waitpid(child, &status, 0);
197 
198 	if (ctl != child) {
199 		UNRESOLVED(errno, "Waitpid returned the wrong PID");
200 	}
201 
202 	if (!WIFEXITED(status) || (WEXITSTATUS(status) != PTS_PASS)) {
203 		FAILED("Child exited abnormally");
204 	}
205 
206 	if (nerrors) {
207 		FAILED("Errors occured in the parent (only)");
208 	}
209 
210 	/* quit */
211 	return NULL;
212 }
213 
214 /* The main test function. */
main(void)215 int main(void)
216 {
217 	int ret;
218 	pthread_t ch;
219 
220 	/* Initialize output */
221 	output_init();
222 
223 	ret = pthread_mutex_lock(&mtx);
224 
225 	if (ret != 0) {
226 		UNRESOLVED(ret, "Failed to lock mutex");
227 	}
228 
229 	ret = pthread_create(&ch, NULL, threaded, NULL);
230 
231 	if (ret != 0) {
232 		UNRESOLVED(ret, "Failed to create a thread");
233 	}
234 
235 	/* Register the handlers */
236 	ret = pthread_atfork(pre1, par1, chi1);
237 
238 	if (ret != 0) {
239 		UNRESOLVED(ret, "Failed to register the atfork handlers");
240 	}
241 
242 	ret = pthread_atfork(pre2, par2, chi2);
243 
244 	if (ret != 0) {
245 		UNRESOLVED(ret, "Failed to register the atfork handlers");
246 	}
247 
248 	ret = pthread_atfork(pre3, par3, chi3);
249 
250 	if (ret != 0) {
251 		UNRESOLVED(ret, "Failed to register the atfork handlers");
252 	}
253 
254 	/* Let the child go on */
255 	ret = pthread_mutex_unlock(&mtx);
256 
257 	if (ret != 0) {
258 		UNRESOLVED(ret, "Failed to unlock mutex");
259 	}
260 
261 	ret = pthread_join(ch, NULL);
262 
263 	if (ret != 0) {
264 		UNRESOLVED(ret, "Failed to join the thread");
265 	}
266 
267 	/* Test passed */
268 #if VERBOSE > 0
269 
270 	output("Test passed\n");
271 
272 #endif
273 
274 	PASSED;
275 }
276