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 /* 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