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