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