Home | History | Annotate | Download | only in pthread_atfork
      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