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