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 #include <pthread.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42
43 #include <sys/wait.h>
44 #include <errno.h>
45
46 #include <signal.h>
47
48 #include "posixtest.h"
49 #include "mem_pattern.h"
50
51 struct test_struct {
52 char one;
53 short two;
54 int three;
55 void *four;
56 };
57
handler(int sig)58 static void handler(int sig)
59 {
60 (void)sig;
61 }
62
main(void)63 int main(void)
64 {
65 int ret, status;
66 pid_t child, ctl;
67 void *malloced;
68 struct sigaction sa_ori, sa_child;
69 struct test_struct mystruct = { 1, 2, 3, (void *)4 };
70 size_t page_size = sysconf(_SC_PAGESIZE);
71
72 malloced = malloc(page_size);
73
74 if (malloced == NULL) {
75 perror("malloc() failed");
76 return PTS_UNRESOLVED;
77 }
78
79 fill_mem(malloced, page_size);
80
81 /* Initialize an environment variable */
82 ret = setenv("OPTS_FORK_TC", "2-1.c", 1);
83
84 if (ret != 0) {
85 perror("setenv() failed");
86 return PTS_UNRESOLVED;
87 }
88
89 /* Initialize the signal handler */
90 sa_ori.sa_handler = handler;
91
92 ret = sigemptyset(&sa_ori.sa_mask);
93
94 if (ret != 0) {
95 perror("sigemptyset() failed");
96 return PTS_UNRESOLVED;
97 }
98
99 ret = sigaddset(&sa_ori.sa_mask, SIGUSR2);
100
101 if (ret != 0) {
102 perror("sigaddset() failed");
103 return PTS_UNRESOLVED;
104 }
105
106 sa_ori.sa_flags = SA_NOCLDSTOP;
107 ret = sigaction(SIGUSR1, &sa_ori, NULL);
108
109 if (ret != 0) {
110 perror("sigaction() failed");
111 return PTS_UNRESOLVED;
112 }
113
114 /* Create the child */
115 child = fork();
116
117 if (child == -1) {
118 perror("fork() failed");
119 return PTS_UNRESOLVED;
120 }
121
122 /* child */
123 if (child == 0) {
124 /* Check the struct was copied */
125 if ((mystruct.one != 1) || (mystruct.two != 2) ||
126 (mystruct.three != 3) || (mystruct.four != (void *)4)) {
127 printf("On-the-stack structure not copied correctly\n");
128 return PTS_FAIL;
129 }
130
131 /* Check the malloc'ed memory is copied */
132 if (check_mem(malloced, page_size)) {
133 printf("Allocated page not copied correctly\n");
134 return PTS_FAIL;
135 }
136
137 /* Free the memory -- this should suceed */
138 free(malloced);
139
140 /* Check the env variable */
141 if (strncmp("2-1.c", getenv("OPTS_FORK_TC"), 6) != 0) {
142 printf("Enviroment variable not copied correctly\n");
143 return PTS_FAIL;
144 }
145
146 /* Check the signal handler stuff */
147 ret = sigaction(SIGUSR1, NULL, &sa_child);
148
149 if (ret != 0) {
150 perror("sigaction() failed in child");
151 return PTS_UNRESOLVED;
152 }
153
154 if (sa_child.sa_handler != handler) {
155 printf("Signal handler function is different\n");
156 return PTS_FAIL;
157 }
158
159 ret = sigismember(&sa_child.sa_mask, SIGUSR2);
160
161 if (ret == 0) {
162 printf("Signal handler mask is different\n");
163 return PTS_FAIL;
164 }
165
166 if (ret != 1) {
167 printf("Unexpected return code from sigismember\n");
168 return PTS_UNRESOLVED;
169 }
170
171 if (((sa_child.sa_flags & SA_NOCLDSTOP) != SA_NOCLDSTOP)
172 #ifndef WITHOUT_XOPEN
173 || ((sa_child.sa_flags & SA_ONSTACK) != 0)
174 || ((sa_child.sa_flags & SA_RESETHAND) != 0)
175 || ((sa_child.sa_flags & SA_RESTART) != 0)
176 || ((sa_child.sa_flags & SA_SIGINFO) != 0)
177 || ((sa_child.sa_flags & SA_NOCLDWAIT) != 0)
178 || ((sa_child.sa_flags & SA_NODEFER) != 0)
179 #endif
180 ) {
181 printf("The sigaction flags are different\n");
182 return PTS_FAIL;
183 }
184
185 return PTS_PASS;
186 }
187
188 /* Parent joins the child */
189 ctl = waitpid(child, &status, 0);
190
191 if (ctl != child) {
192 printf("Waitpid returned wrong PID\n");
193 return PTS_UNRESOLVED;
194 }
195
196 if (!WIFEXITED(status)) {
197 printf("Child exited abnormally\n");
198 return PTS_UNRESOLVED;
199 }
200
201 if (WEXITSTATUS(status) == PTS_PASS) {
202 printf("Test PASSED\n");
203 return PTS_PASS;
204 }
205
206 return WEXITSTATUS(status);
207 }
208