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 * Memory mappings created in the parent are retained in the child process.
     20 * If the mapping is MAP_PRIVATE, any modification done after the fork()
     21 * is visible only to the process doing the modification.
     22 
     23 * The steps are:
     24 * -> create two shared memory segments.
     25 * -> mmap both segment, one is MAP_SHARED and the other MAP_PRIVATE.
     26 * -> Write some data into the segment.
     27 * -> fork
     28 * -> The child checks that the data is visible in the segments, then modifies it.
     29 * -> child terminates
     30 * -> The parent checks that the modifications are visible only in the MAP_SHARED segment.
     31 
     32 * The test fails if one of the check is not verified.
     33 
     34 */
     35 
     36 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
     37 #define _POSIX_C_SOURCE 200112L
     38 
     39 #include <pthread.h>
     40 #include <stdarg.h>
     41 #include <stdio.h>
     42 #include <stdlib.h>
     43 #include <string.h>
     44 #include <unistd.h>
     45 
     46 #include <sys/wait.h>
     47 #include <errno.h>
     48 
     49 #include <sys/mman.h>
     50 #include <fcntl.h>
     51 #include <sys/stat.h>
     52 #include <sys/types.h>
     53 
     54 #include "../testfrmw/testfrmw.h"
     55 #include "../testfrmw/testfrmw.c"
     56 
     57 #ifndef VERBOSE
     58 #define VERBOSE 1
     59 #endif
     60 
     61 int main(void)
     62 {
     63 	int ret, status;
     64 	pid_t child, ctl;
     65 	int fd_s, fd_ns;
     66 	void *buf_s, *buf_ns;
     67 
     68 	output_init();
     69 
     70 	/* Create the shared memory segment */
     71 	fd_s = shm_open("/fork_16_1s", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
     72 
     73 	if (fd_s == -1) {
     74 		UNRESOLVED(errno, "Failed to open shared memory segment");
     75 	}
     76 
     77 	fd_ns = shm_open("/fork_16_1ns", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
     78 
     79 	if (fd_ns == -1) {
     80 		UNRESOLVED(errno, "Failed to open shared memory segment");
     81 	}
     82 
     83 	/* Size the memory segment to 1 page size. */
     84 	ret = ftruncate(fd_s, sysconf(_SC_PAGESIZE));
     85 
     86 	if (ret != 0) {
     87 		UNRESOLVED(errno, "Failed to size the shared memory segment");
     88 	}
     89 
     90 	ret = ftruncate(fd_ns, sysconf(_SC_PAGESIZE));
     91 
     92 	if (ret != 0) {
     93 		UNRESOLVED(errno, "Failed to size the shared memory segment");
     94 	}
     95 
     96 	/* Map these sengments in the process memory space */
     97 	buf_s =
     98 	    mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE,
     99 		 MAP_SHARED, fd_s, 0);
    100 
    101 	if (buf_s == MAP_FAILED) {
    102 		UNRESOLVED(errno, "Failed to mmap the shared memory segment");
    103 	}
    104 
    105 	buf_ns =
    106 	    mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE,
    107 		 MAP_PRIVATE, fd_ns, 0);
    108 
    109 	if (buf_ns == MAP_FAILED) {
    110 		UNRESOLVED(errno,
    111 			   "Failed to mmap the shared memory segment in MAP_PRIVATE mode");
    112 	}
    113 
    114 	/* Write some data into the buffers */
    115 	*(long *)buf_ns = 123456L;
    116 
    117 	*(long *)buf_s = 654321L;
    118 
    119 	/* Create the child */
    120 	child = fork();
    121 
    122 	if (child == -1) {
    123 		UNRESOLVED(errno, "Failed to fork");
    124 	}
    125 
    126 	if (child == 0) {
    127 		/* Check the values are read -- so that the mappings were inherited */
    128 
    129 		if ((*(long *)buf_ns != 123456L) || (*(long *)buf_s != 654321L)) {
    130 			output("Read values: %ld, %ld\n", *(long *)buf_ns,
    131 			       *(long *)buf_s);
    132 			FAILED
    133 			    ("The memory mappings were not inherited by the child process");
    134 		}
    135 
    136 		/* Now modify the values */
    137 		*(long *)buf_ns = 100000L;
    138 
    139 		*(long *)buf_s = 200000L;
    140 
    141 		/* We're done */
    142 		exit(PTS_PASS);
    143 	}
    144 
    145 	/* Parent joins the child */
    146 	ctl = waitpid(child, &status, 0);
    147 
    148 	if (ctl != child) {
    149 		UNRESOLVED(errno, "Waitpid returned the wrong PID");
    150 	}
    151 
    152 	if (!WIFEXITED(status) || (WEXITSTATUS(status) != PTS_PASS)) {
    153 		FAILED("Child exited abnormally");
    154 	}
    155 
    156 	/* Check that only the MAP_SHARED segment modification is visible */
    157 	if ((*(long *)buf_ns != 123456L) || (*(long *)buf_s != 200000L)) {
    158 		output("Read values: %ld, %ld\n", *(long *)buf_ns,
    159 		       *(long *)buf_s);
    160 		FAILED
    161 		    ("The memory mappings were not inherited by the child process");
    162 	}
    163 
    164 	/* Free resources (everything will be removed at destruction time) */
    165 	ret = shm_unlink("/fork_16_1ns");
    166 
    167 	if (ret != 0) {
    168 		UNRESOLVED(errno, "Failed to unlink the shared memory segment");
    169 	}
    170 
    171 	ret = shm_unlink("/fork_16_1s");
    172 
    173 	if (ret != 0) {
    174 		UNRESOLVED(errno, "Failed to unlink the shared memory segment");
    175 	}
    176 
    177 #if VERBOSE > 0
    178 	output("Test passed\n");
    179 #endif
    180 	PASSED;
    181 }
    182