fork12.c revision 5262667a4c30c82180d439bae4d7787f45281289
1/* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 */ 19 20/* 21 * NAME 22 * fork12.c 23 * 24 * DESCRIPTION 25 * Check that all children inherit parent's file descriptor 26 * 27 * ALGORITHM 28 * Parent forks processes until -1 is returned.$ 29 *$ 30 * USAGE 31 * fork12 32 * ** CAUTION ** Can hang your machine, esp prior to 2.4.19 33 * 34 * HISTORY 35 * 07/2001 Ported by Wayne Boyer 36 * 07/2002 Split from fork07 as a test case to exhaust available pids. 37 * 38 * RESTRICTIONS 39 * Should be run as root to avoid resource limits.$ 40 * Should not be run with other test programs because it tries to 41 * use all available pids. 42 */ 43 44#include <stdio.h> 45#include <sys/wait.h> 46#include <errno.h> 47#include <string.h> 48#include "test.h" 49#include "usctest.h" 50 51char *TCID = "fork12"; 52int TST_TOTAL = 1; 53 54void setup(void); 55void cleanup(void); 56void fork12_sigs(int signum); 57 58char pbuf[10]; 59 60int main(int ac, char **av) 61{ 62 int forks, pid1, fork_errno, waitstatus; 63 int ret, status; 64 int lc; /* loop counter */ 65 char *msg; /* message returned from parse_opts */ 66 67 /* 68 * parse standard options 69 */ 70 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) { 71 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); 72 } 73 74 /* 75 * perform global setup for the test 76 */ 77 setup(); 78 79 /* 80 * check looping state if -i option is given 81 */ 82 for (lc = 0; TEST_LOOPING(lc); lc++) { 83 /* 84 * reset Tst_count in case we are looping. 85 */ 86 Tst_count = 0; 87 88 tst_resm(TINFO, "Forking as many kids as possible"); 89 forks = 0; 90 while ((pid1 = fork()) != -1) { 91 if (pid1 == 0) { /* child */ 92 pause(); 93 exit(0); 94 } 95 forks++; 96 ret = waitpid(-1, &status, WNOHANG); 97 if (ret < 0) 98 tst_brkm(TBROK, cleanup, 99 "waitpid failed %d: %s\n", errno, 100 strerror(errno)); 101 if (ret > 0) { 102 /* a child may be killed by OOM killer */ 103 if (WTERMSIG(status) == SIGKILL) 104 break; 105 tst_brkm(TBROK, cleanup, 106 "child exit with error code %d or signal %d", 107 WEXITSTATUS(status), WTERMSIG(status)); 108 } 109 } 110 fork_errno = errno; 111 112 /* parent */ 113 tst_resm(TINFO, "Number of processes forked is %d", forks); 114 tst_resm(TPASS, "fork() eventually failed with %d: %s", 115 fork_errno, strerror(fork_errno)); 116 /* collect our kids */ 117 sleep(3); //Introducing a sleep(3) to make sure all children are at pause() when SIGQUIT is sent to them 118 kill(0, SIGQUIT); 119 while (wait(&waitstatus) > 0) ; 120 121 } 122 cleanup(); 123 124 tst_exit(); 125} 126 127/* 128 * setup() - performs all ONE TIME setup for this test 129 */ 130void setup() 131{ 132 /* 133 * capture signals 134 */ 135 tst_sig(FORK, fork12_sigs, cleanup); 136 137 /* 138 * Pause if that option was specified 139 */ 140 TEST_PAUSE; 141} 142 143/* 144 * cleanup() - performs all ONE TIME cleanup for this test at 145 * completion or premature exit 146 */ 147void cleanup() 148{ 149 int waitstatus; 150 151 /* collect our kids */ 152 kill(0, SIGQUIT); 153 while (wait(&waitstatus) > 0) ; 154 /* 155 * print timing stats if that option was specified. 156 * print errno log if that option was specified. 157 */ 158 TEST_CLEANUP; 159 160} 161 162void fork12_sigs(int signum) 163{ 164 if (signum == SIGQUIT) { 165 /* Children will continue, parent will ignore */ 166 } else 167 tst_brkm(TBROK, cleanup, 168 "Unexpected signal %d received.", signum); 169} 170