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 * getpid() always returns the process ID of the calling thread/process. 20 21 * The steps are: 22 * 23 * -> create two threads and check they get the same getpid() return value. 24 * -> create two processes and check they get different getpid() return value. 25 * -> check that the child process getpid() return value matchs the fork() return 26 value in the parent process. 27 28 * The test fails if any of the previous checks is not verified. 29 30 */ 31 32 #include <pthread.h> 33 #include <stdarg.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <unistd.h> 38 39 #include <errno.h> 40 #include <sys/wait.h> 41 #include <sys/mman.h> 42 43 #include "../testfrmw/testfrmw.h" 44 #include "../testfrmw/testfrmw.c" 45 46 #ifndef VERBOSE 47 #define VERBOSE 1 48 #endif 49 50 #ifndef WITHOUT_XOPEN 51 52 static pid_t *sharedpid; 53 54 /* This will be executed by the child process */ 55 static void child(void) 56 { 57 *sharedpid = getpid(); 58 exit(0); 59 } 60 61 /* This will be executed by the child thread */ 62 static void *threaded(void *arg) 63 { 64 *(pid_t *) arg = getpid(); 65 return NULL; 66 } 67 68 int main(void) 69 { 70 int ret, status; 71 long mf; /* Is memory mapping supported? */ 72 pid_t mypid, hispid, ctlpid; 73 pthread_t child_thread; 74 75 output_init(); 76 77 mypid = getpid(); 78 #if VERBOSE > 1 79 output("Main pid: %d\n", mypid); 80 #endif 81 82 ret = pthread_create(&child_thread, NULL, threaded, &hispid); 83 if (ret != 0) { 84 UNRESOLVED(ret, "Thread creation failed"); 85 } 86 ret = pthread_join(child_thread, NULL); 87 if (ret != 0) { 88 UNRESOLVED(ret, "Thread join failed"); 89 } 90 #if VERBOSE > 1 91 output("Thread pid: %d\n", hispid); 92 #endif 93 94 /* Compare threads PIDs */ 95 if (mypid != hispid) { 96 FAILED 97 ("Child thread got a different return value from getpid()\n"); 98 } 99 100 /* Test system abilities */ 101 mf = sysconf(_SC_MAPPED_FILES); 102 103 #if VERBOSE > 0 104 output("Test starting\n"); 105 output("System abilities:\n"); 106 output(" MF : %li\n", mf); 107 if (mf <= 0) 108 output("Unable to test without shared data\n"); 109 #endif 110 111 /* We need MF support for the process-cross testing */ 112 if (mf > 0) { 113 /* We will place the child pid in a mmaped file */ 114 char filename[] = "/tmp/getpid-1-XXXXXX"; 115 void *mmaped; 116 int fd; 117 118 /* We now create the temp files */ 119 fd = mkstemp(filename); 120 if (fd == -1) { 121 UNRESOLVED(errno, 122 "Temporary file could not be created"); 123 } 124 125 /* and make sure the file will be deleted when closed */ 126 unlink(filename); 127 128 #if VERBOSE > 1 129 output("Temp file created (%s).\n", filename); 130 #endif 131 132 /* Fill the file up to 1 pagesize */ 133 ret = ftruncate(fd, sysconf(_SC_PAGESIZE)); 134 if (ret != 0) { 135 UNRESOLVED(errno, "ftruncate operation failed"); 136 } 137 138 /* Now we can map the file in memory */ 139 mmaped = 140 mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, 141 MAP_SHARED, fd, 0); 142 if (mmaped == MAP_FAILED) { 143 UNRESOLVED(errno, "mmap failed"); 144 } 145 146 /* Set the sharedpid pointer to this mmaped area */ 147 sharedpid = (pid_t *) mmaped; 148 149 /* Our data is now in shared memory */ 150 #if VERBOSE > 1 151 output("Shared memory is ready.\n"); 152 #endif 153 154 /* Okay, let's create the child process */ 155 hispid = fork(); 156 if (hispid == (pid_t) - 1) { 157 UNRESOLVED(errno, "Fork failed"); 158 } 159 160 /* Child process : */ 161 if (hispid == (pid_t) 0) 162 child(); 163 164 /* Otherwise, we're the parent */ 165 ctlpid = waitpid(hispid, &status, 0); 166 if (ctlpid != hispid) { 167 UNRESOLVED(errno, 168 "waitpid waited for the wrong process"); 169 } 170 if (!WIFEXITED(status) || WEXITSTATUS(status)) { 171 UNRESOLVED(status, 172 "The child process did not terminate as expected"); 173 } 174 #if VERBOSE > 1 175 output("Child process pid: %d\n", hispid); 176 #endif 177 178 /* Check the child pid is the same as fork returned */ 179 if (hispid != *sharedpid) { 180 FAILED 181 ("getpid() in the child returned a different value than fork() in the parent"); 182 } 183 184 /* Check the child pid is different than the parent pid */ 185 if (hispid == mypid) { 186 FAILED 187 ("Both child and parent getpid() return values are equal"); 188 } 189 } 190 #if VERBOSE > 0 191 output("Test passed\n"); 192 #endif 193 194 PASSED; 195 } 196 197 #else /* WITHOUT_XOPEN */ 198 int main(void) 199 { 200 output_init(); 201 UNTESTED("This test requires XSI features"); 202 } 203 #endif 204