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 */
child(void)55 static void child(void)
56 {
57 *sharedpid = getpid();
58 exit(0);
59 }
60
61 /* This will be executed by the child thread */
threaded(void * arg)62 static void *threaded(void *arg)
63 {
64 *(pid_t *) arg = getpid();
65 return NULL;
66 }
67
main(void)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 */
main(void)198 int main(void)
199 {
200 output_init();
201 UNTESTED("This test requires XSI features");
202 }
203 #endif
204