00001 /* 00002 * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009 00003 * The President and Fellows of Harvard College. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the University nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 */ 00029 00030 /* 00031 * forktest - test fork(). 00032 * 00033 * This should work correctly when fork is implemented. 00034 * 00035 * It should also continue to work after subsequent assignments, most 00036 * notably after implementing the virtual memory system. 00037 */ 00038 00039 #include <unistd.h> 00040 #include <string.h> 00041 #include <stdlib.h> 00042 #include <stdio.h> 00043 #include <err.h> 00044 00045 /* 00046 * This is used by all processes, to try to help make sure all 00047 * processes have a distinct address space. 00048 */ 00049 static volatile int mypid; 00050 00051 /* 00052 * Helper function for fork that prints a warning on error. 00053 */ 00054 static 00055 int 00056 dofork(void) 00057 { 00058 int pid; 00059 pid = fork(); 00060 if (pid < 0) { 00061 warn("fork"); 00062 } 00063 return pid; 00064 } 00065 00066 /* 00067 * Check to make sure each process has its own address space. Write 00068 * the pid into the data segment and read it back repeatedly, making 00069 * sure it's correct every time. 00070 */ 00071 static 00072 void 00073 check(void) 00074 { 00075 int i; 00076 00077 mypid = getpid(); 00078 00079 /* Make sure each fork has its own address space. */ 00080 for (i=0; i<800; i++) { 00081 volatile int seenpid; 00082 seenpid = mypid; 00083 if (seenpid != getpid()) { 00084 errx(1, "pid mismatch (%d, should be %d) " 00085 "- your vm is broken!", 00086 seenpid, getpid()); 00087 } 00088 } 00089 } 00090 00091 /* 00092 * Wait for a child process. 00093 * 00094 * This assumes dowait is called the same number of times as dofork 00095 * and passed its results in reverse order. Any forks that fail send 00096 * us -1 and are ignored. The first 0 we see indicates the fork that 00097 * generated the current process; that means it's time to exit. Only 00098 * the parent of all the processes returns from the chain of dowaits. 00099 */ 00100 static 00101 void 00102 dowait(int nowait, int pid) 00103 { 00104 int x; 00105 00106 if (pid<0) { 00107 /* fork in question failed; just return */ 00108 return; 00109 } 00110 if (pid==0) { 00111 /* in the fork in question we were the child; exit */ 00112 exit(0); 00113 } 00114 00115 if (!nowait) { 00116 if (waitpid(pid, &x, 0)<0) { 00117 warn("waitpid"); 00118 } 00119 else if (WIFSIGNALED(x)) { 00120 warnx("pid %d: signal %d", pid, WTERMSIG(x)); 00121 } 00122 else if (WEXITSTATUS(x) != 0) { 00123 warnx("pid %d: exit %d", pid, WEXITSTATUS(x)); 00124 } 00125 } 00126 } 00127 00128 /* 00129 * Actually run the test. 00130 */ 00131 static 00132 void 00133 test(int nowait) 00134 { 00135 int pid0, pid1, pid2, pid3; 00136 00137 /* 00138 * Caution: This generates processes geometrically. 00139 * 00140 * It is unrolled to encourage gcc to registerize the pids, 00141 * to prevent wait/exit problems if fork corrupts memory. 00142 */ 00143 00144 pid0 = dofork(); 00145 putchar('0'); 00146 check(); 00147 pid1 = dofork(); 00148 putchar('1'); 00149 check(); 00150 pid2 = dofork(); 00151 putchar('2'); 00152 check(); 00153 pid3 = dofork(); 00154 putchar('3'); 00155 check(); 00156 00157 /* 00158 * These must be called in reverse order to avoid waiting 00159 * improperly. 00160 */ 00161 dowait(nowait, pid3); 00162 dowait(nowait, pid2); 00163 dowait(nowait, pid1); 00164 dowait(nowait, pid0); 00165 00166 putchar('\n'); 00167 } 00168 00169 int 00170 main(int argc, char *argv[]) 00171 { 00172 int nowait=0; 00173 00174 if (argc==2 && !strcmp(argv[1], "-w")) { 00175 nowait=1; 00176 } 00177 else if (argc!=1 && argc!=0) { 00178 warnx("usage: forktest [-w]"); 00179 return 1; 00180 } 00181 warnx("Starting."); 00182 00183 test(nowait); 00184 00185 warnx("Complete."); 00186 return 0; 00187 }