• 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 * 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