Home | History | Annotate | Download | only in fork
      1 /*
      2 * Copyright (c) 2004, 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 * The new process is a copy of the original one -- with few exceptions.
     20 
     21 * The steps are:
     22 * -> set up some data in process memory space
     23 * -> create a new process
     24 * -> check in this new process that the memory space was copied.
     25 *
     26 * We check that:
     27 * -> a structure object is copied.
     28 * -> a malloc'ed memory block is copied and can be freed in child.
     29 * -> the environment is copied
     30 * -> signal handlers are copied
     31 
     32 * The test fails if a difference is detected.
     33 
     34 */
     35 
     36 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
     37 #define _POSIX_C_SOURCE 200112L
     38 
     39 /* We can use XSI features in case it is allowed */
     40 #ifndef WITHOUT_XOPEN
     41 #define _XOPEN_SOURCE 600
     42 #endif
     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 #include <signal.h>
     55 
     56 #include "posixtest.h"
     57 #include "mem_pattern.h"
     58 
     59 struct test_struct {
     60 	char one;
     61 	short two;
     62 	int three;
     63 	void *four;
     64 };
     65 
     66 void handler(int sig)
     67 {
     68 	(void)sig;
     69 }
     70 
     71 int main(void)
     72 {
     73 	int ret, status;
     74 	pid_t child, ctl;
     75 	void *malloced;
     76 	struct sigaction sa_ori, sa_child;
     77 	struct test_struct mystruct = { 1, 2, 3, (void *)4 };
     78 	size_t page_size = sysconf(_SC_PAGESIZE);
     79 
     80 	malloced = malloc(page_size);
     81 
     82 	if (malloced == NULL) {
     83 		perror("malloc() failed");
     84 		return PTS_UNRESOLVED;
     85 	}
     86 
     87 	fill_mem(malloced, page_size);
     88 
     89 	/* Initialize an environment variable */
     90 	ret = setenv("OPTS_FORK_TC", "2-1.c", 1);
     91 
     92 	if (ret != 0) {
     93 		perror("setenv() failed");
     94 		return PTS_UNRESOLVED;
     95 	}
     96 
     97 	/* Initialize the signal handler */
     98 	sa_ori.sa_handler = handler;
     99 
    100 	ret = sigemptyset(&sa_ori.sa_mask);
    101 
    102 	if (ret != 0) {
    103 		perror("sigemptyset() failed");
    104 		return PTS_UNRESOLVED;
    105 	}
    106 
    107 	ret = sigaddset(&sa_ori.sa_mask, SIGUSR2);
    108 
    109 	if (ret != 0) {
    110 		perror("sigaddset() failed");
    111 		return PTS_UNRESOLVED;
    112 	}
    113 
    114 	sa_ori.sa_flags = SA_NOCLDSTOP;
    115 	ret = sigaction(SIGUSR1, &sa_ori, NULL);
    116 
    117 	if (ret != 0) {
    118 		perror("sigaction() failed");
    119 		return PTS_UNRESOLVED;
    120 	}
    121 
    122 	/* Create the child */
    123 	child = fork();
    124 
    125 	if (child == -1) {
    126 		perror("fork() failed");
    127 		return PTS_UNRESOLVED;
    128 	}
    129 
    130 	/* child */
    131 	if (child == 0) {
    132 		/* Check the struct was copied */
    133 		if ((mystruct.one != 1) || (mystruct.two != 2) ||
    134 		    (mystruct.three != 3) || (mystruct.four != (void *)4)) {
    135 			printf("On-the-stack structure not copied correctly\n");
    136 			return PTS_FAIL;
    137 		}
    138 
    139 		/* Check the malloc'ed memory is copied */
    140 		if (check_mem(malloced, page_size)) {
    141 			printf("Allocated page not copied correctly\n");
    142 			return PTS_FAIL;
    143 		}
    144 
    145 		/* Free the memory -- this should suceed */
    146 		free(malloced);
    147 
    148 		/* Check the env variable */
    149 		if (strncmp("2-1.c", getenv("OPTS_FORK_TC"), 6) != 0) {
    150 			printf("Enviroment variable not copied correctly\n");
    151 			return PTS_FAIL;
    152 		}
    153 
    154 		/* Check the signal handler stuff */
    155 		ret = sigaction(SIGUSR1, NULL, &sa_child);
    156 
    157 		if (ret != 0) {
    158 			perror("sigaction() failed in child");
    159 			return PTS_UNRESOLVED;
    160 		}
    161 
    162 		if (sa_child.sa_handler != handler) {
    163 			printf("Signal handler function is different\n");
    164 			return PTS_FAIL;
    165 		}
    166 
    167 		ret = sigismember(&sa_child.sa_mask, SIGUSR2);
    168 
    169 		if (ret == 0) {
    170 			printf("Signal handler mask is different\n");
    171 			return PTS_FAIL;
    172 		}
    173 
    174 		if (ret != 1) {
    175 			printf("Unexpected return code from sigismember\n");
    176 			return PTS_UNRESOLVED;
    177 		}
    178 
    179 		if (((sa_child.sa_flags & SA_NOCLDSTOP) != SA_NOCLDSTOP)
    180 #ifndef WITHOUT_XOPEN
    181 		    || ((sa_child.sa_flags & SA_ONSTACK) != 0)
    182 		    || ((sa_child.sa_flags & SA_RESETHAND) != 0)
    183 		    || ((sa_child.sa_flags & SA_RESTART) != 0)
    184 		    || ((sa_child.sa_flags & SA_SIGINFO) != 0)
    185 		    || ((sa_child.sa_flags & SA_NOCLDWAIT) != 0)
    186 		    || ((sa_child.sa_flags & SA_NODEFER) != 0)
    187 #endif
    188 		    ) {
    189 			printf("The sigaction flags are different\n");
    190 			return PTS_FAIL;
    191 		}
    192 
    193 		return PTS_PASS;
    194 	}
    195 
    196 	/* Parent joins the child */
    197 	ctl = waitpid(child, &status, 0);
    198 
    199 	if (ctl != child) {
    200 		printf("Waitpid returned wrong PID\n");
    201 		return PTS_UNRESOLVED;
    202 	}
    203 
    204 	if (!WIFEXITED(status)) {
    205 		printf("Child exited abnormally\n");
    206 		return PTS_UNRESOLVED;
    207 	}
    208 
    209 	if (WEXITSTATUS(status) == PTS_PASS) {
    210 		printf("Test PASSED\n");
    211 		return PTS_PASS;
    212 	}
    213 
    214 	return WEXITSTATUS(status);
    215 }
    216