/*1* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 20092* The President and Fellows of Harvard College.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12* 3. Neither the name of the University nor the names of its contributors13* may be used to endorse or promote products derived from this software14* without specific prior written permission.15*16* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND17* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE18* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE19* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE20* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL21* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS22* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)23* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT24* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY25* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF26* SUCH DAMAGE.27*/2829/*30* forktest - test fork().31*32* This should work correctly when fork is implemented.33*34* It should also continue to work after subsequent assignments, most35* notably after implementing the virtual memory system.36*/3738#include <unistd.h>39#include <string.h>40#include <stdlib.h>41#include <stdio.h>42#include <err.h>4344/*45* This is used by all processes, to try to help make sure all46* processes have a distinct address space.47*/48static volatile int mypid;4950/*51* Helper function for fork that prints a warning on error.52*/53static54int55dofork(void)56{57int pid;58pid = fork();59if (pid < 0) {60warn("fork");61}62return pid;63}6465/*66* Check to make sure each process has its own address space. Write67* the pid into the data segment and read it back repeatedly, making68* sure it's correct every time.69*/70static71void72check(void)73{74int i;7576mypid = getpid();7778/* Make sure each fork has its own address space. */79for (i=0; i<800; i++) {80volatile int seenpid;81seenpid = mypid;82if (seenpid != getpid()) {83errx(1, "pid mismatch (%d, should be %d) "84"- your vm is broken!",85seenpid, getpid());86}87}88}8990/*91* Wait for a child process.92*93* This assumes dowait is called the same number of times as dofork94* and passed its results in reverse order. Any forks that fail send95* us -1 and are ignored. The first 0 we see indicates the fork that96* generated the current process; that means it's time to exit. Only97* the parent of all the processes returns from the chain of dowaits.98*/99static100void101dowait(int nowait, int pid)102{103int x;104105if (pid<0) {106/* fork in question failed; just return */107return;108}109if (pid==0) {110/* in the fork in question we were the child; exit */111exit(0);112}113114if (!nowait) {115if (waitpid(pid, &x, 0)<0) {116warn("waitpid");117}118else if (WIFSIGNALED(x)) {119warnx("pid %d: signal %d", pid, WTERMSIG(x));120}121else if (WEXITSTATUS(x) != 0) {122warnx("pid %d: exit %d", pid, WEXITSTATUS(x));123}124}125}126127/*128* Actually run the test.129*/130static131void132test(int nowait)133{134int pid0, pid1, pid2, pid3;135136/*137* Caution: This generates processes geometrically.138*139* It is unrolled to encourage gcc to registerize the pids,140* to prevent wait/exit problems if fork corrupts memory.141*/142143pid0 = dofork();144putchar('0');145check();146pid1 = dofork();147putchar('1');148check();149pid2 = dofork();150putchar('2');151check();152pid3 = dofork();153putchar('3');154check();155156/*157* These must be called in reverse order to avoid waiting158* improperly.159*/160dowait(nowait, pid3);161dowait(nowait, pid2);162dowait(nowait, pid1);163dowait(nowait, pid0);164165putchar('\n');166}167168int169main(int argc, char *argv[])170{171int nowait=0;172173if (argc==2 && !strcmp(argv[1], "-w")) {174nowait=1;175}176else if (argc!=1 && argc!=0) {177warnx("usage: forktest [-w]");178return 1;179}180warnx("Starting.");181182test(nowait);183184warnx("Complete.");185return 0;186}187188189