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