Home | History | Annotate | Download | only in getpid
      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