os161-1.99
 All Data Structures
bad_waitpid.c
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  * bad calls to waitpid()
00032  */
00033 
00034 #include <sys/types.h>
00035 #include <stdlib.h>
00036 #include <unistd.h>
00037 #include <errno.h>
00038 #include <err.h>
00039 
00040 #include "config.h"
00041 #include "test.h"
00042 
00043 static
00044 void
00045 wait_badpid(int pid, const char *desc)
00046 {
00047         int rv, x;
00048         rv = waitpid(pid, &x, 0);
00049         report_test2(rv, errno, EINVAL, NOSUCHPID_ERROR, desc);
00050 }
00051 
00052 static
00053 void
00054 wait_badstatus(void *ptr, const char *desc)
00055 {
00056         int rv, pid, x;
00057 
00058         pid = fork();
00059         if (pid<0) {
00060                 warn("UH-OH: fork failed");
00061                 return;
00062         }
00063         if (pid==0) {
00064                 exit(0);
00065         }
00066 
00067         rv = waitpid(pid, ptr, 0);
00068         report_test(rv, errno, EFAULT, desc);
00069         waitpid(pid, &x, 0);
00070 }
00071 
00072 static
00073 void
00074 wait_unaligned(void)
00075 {
00076         int rv, pid, x;
00077         int status[2];  /* will have integer alignment */
00078         char *ptr;
00079 
00080         pid = fork();
00081         if (pid<0) {
00082                 warn("UH-OH: fork failed");
00083                 return;
00084         }
00085         if (pid==0) {
00086                 exit(0);
00087         }
00088 
00089         /* start with proper integer alignment */
00090         ptr = (char *)(&status[0]);
00091 
00092         /* generate improper alignment on platforms with restrictions*/
00093         ptr++;
00094 
00095         rv = waitpid(pid, (int *)ptr, 0);
00096         report_survival(rv, errno, "wait with unaligned status");
00097         if (rv<0) {
00098                 waitpid(pid, &x, 0);
00099         }
00100 }
00101 
00102 static
00103 void
00104 wait_badflags(void)
00105 {
00106         int rv, x, pid;
00107 
00108         pid = fork();
00109         if (pid<0) {
00110                 warn("UH-OH: fork failed");
00111                 return;
00112         }
00113         if (pid==0) {
00114                 exit(0);
00115         }
00116 
00117         rv = waitpid(pid, &x, 309429);
00118         report_test(rv, errno, EINVAL, "wait with bad flags");
00119         waitpid(pid, &x, 0);
00120 }
00121 
00122 static
00123 void
00124 wait_self(void)
00125 {
00126         int rv, x;
00127         rv = waitpid(getpid(), &x, 0);
00128         report_survival(rv, errno, "wait for self");
00129 }
00130 
00131 static
00132 void
00133 wait_parent(void)
00134 {
00135         int mypid, childpid, rv, x;
00136 
00137         mypid = getpid();
00138         childpid = fork();
00139         if (childpid<0) {
00140                 warn("UH-OH: can't fork");
00141                 return;
00142         }
00143         if (childpid==0) {
00144                 /* Child. Wait for parent. */
00145                 rv = waitpid(mypid, &x, 0);
00146                 report_survival(rv, errno, "wait for parent (from child)");
00147                 _exit(0);
00148         }
00149         rv = waitpid(childpid, &x, 0);
00150         report_survival(rv, errno, "wait for parent test (from parent)");
00151 }
00152 
00153 ////////////////////////////////////////////////////////////
00154 
00155 static
00156 void
00157 wait_siblings_child(void)
00158 {
00159         int pids[2], mypid, otherpid, fd, rv, x;
00160 
00161         mypid = getpid();
00162 
00163         fd = open(TESTFILE, O_RDONLY);
00164         if (fd<0) {
00165                 warn("UH-OH: child process (pid %d) can't open %s",
00166                      mypid, TESTFILE);
00167                 return;
00168         }
00169 
00170         /*
00171          * Busy-wait until the parent writes the pids into the file.
00172          * This sucks, but there's not a whole lot else we can do.
00173          */
00174         do {
00175                 rv = lseek(fd, 0, SEEK_SET);
00176                 if (rv<0) {
00177                         warn("UH-OH: child process (pid %d) lseek error",
00178                              mypid);
00179                         return;
00180                 }
00181                 rv = read(fd, pids, sizeof(pids));
00182                 if (rv<0) {
00183                         warn("UH-OH: child process (pid %d) read error",
00184                              mypid);
00185                         return;
00186                 }
00187         } while (rv < (int)sizeof(pids));
00188 
00189         if (mypid==pids[0]) {
00190                 otherpid = pids[1];
00191         }
00192         else if (mypid==pids[1]) {
00193                 otherpid = pids[0];
00194         }
00195         else {
00196                 warn("UH-OH: child process (pid %d) got garbage in comm file",
00197                      mypid);
00198                 return;
00199         }
00200         close(fd);
00201 
00202         rv = waitpid(otherpid, &x, 0);
00203         report_survival(rv, errno, "sibling wait");
00204 }
00205 
00206 static
00207 void
00208 wait_siblings(void)
00209 {
00210         int pids[2], fd, rv, x;
00211 
00212         /* Note: this may also blow up if FS synchronization is substandard */
00213 
00214         fd = open_testfile(NULL);
00215         if (fd<0) {
00216                 return;
00217         }
00218 
00219         pids[0] = fork();
00220         if (pids[0]<0) {
00221                 warn("UH-OH: can't fork");
00222                 return;
00223         }
00224         if (pids[0]==0) {
00225                 close(fd);
00226                 wait_siblings_child();
00227                 _exit(0);
00228         }
00229 
00230         pids[1] = fork();
00231         if (pids[1]<0) {
00232                 warn("UH-OH: can't fork");
00233                 /* abandon the other child process :( */
00234                 return;
00235         }
00236         if (pids[1]==0) {
00237                 close(fd);
00238                 wait_siblings_child();
00239                 _exit(0);
00240         }
00241 
00242         rv = write(fd, pids, sizeof(pids));
00243         if (rv < 0) {
00244                 warn("UH-OH: write error on %s", TESTFILE);
00245                 /* abandon child procs :( */
00246                 return;
00247         }
00248         if (rv != (int)sizeof(pids)) {
00249                 warnx("UH-OH: write error on %s: short count", TESTFILE);
00250                 /* abandon child procs :( */
00251                 return;
00252         }
00253 
00254         rv = waitpid(pids[0], &x, 0);
00255         if (rv<0) {
00256                 warn("UH-OH: error waiting for child 0 (pid %d)", pids[0]);
00257         }
00258         rv = waitpid(pids[1], &x, 0);
00259         if (rv<0) {
00260                 warn("UH-OH: error waiting for child 1 (pid %d)", pids[1]);
00261         }
00262         warnx("passed: siblings wait for each other");
00263         close(fd);
00264         remove(TESTFILE);
00265 }
00266 
00267 ////////////////////////////////////////////////////////////
00268 
00269 void
00270 test_waitpid(void)
00271 {
00272         wait_badpid(-8, "wait for pid -8");
00273         wait_badpid(-1, "wait for pid -1");
00274         wait_badpid(0, "pid zero");
00275         wait_badpid(NONEXIST_PID, "nonexistent pid");
00276 
00277         wait_badstatus(NULL, "wait with NULL status");
00278         wait_badstatus(INVAL_PTR, "wait with invalid pointer status");
00279         wait_badstatus(KERN_PTR, "wait with kernel pointer status");
00280 
00281         wait_unaligned();
00282 
00283         wait_badflags();
00284 
00285         wait_self();
00286         wait_parent();
00287         wait_siblings();
00288 }
 All Data Structures