1 /* 2 * Copyright (c) International Business Machines Corp., 2001 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12 * the GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 * 18 * 19 * NAME 20 * fork12.c 21 * 22 * DESCRIPTION 23 * Check that all children inherit parent's file descriptor 24 * 25 * ALGORITHM 26 * Parent forks processes until -1 is returned.$ 27 * 28 * USAGE 29 * fork12 30 * ** CAUTION ** Can hang your machine, esp prior to 2.4.19 31 * 32 * HISTORY 33 * 07/2001 Ported by Wayne Boyer 34 * 07/2002 Split from fork07 as a test case to exhaust available pids. 35 * 36 * RESTRICTIONS 37 * Should be run as root to avoid resource limits.$ 38 * Should not be run with other test programs because it tries to 39 * use all available pids. 40 */ 41 42 #include <stdio.h> 43 #include <sys/wait.h> 44 #include <errno.h> 45 #include <string.h> 46 #include "test.h" 47 #include "safe_macros.h" 48 49 char *TCID = "fork12"; 50 int TST_TOTAL = 1; 51 52 static void setup(void); 53 static void cleanup(void); 54 static void fork12_sigs(int signum); 55 56 int main(int ac, char **av) 57 { 58 int forks, pid1, fork_errno, waitstatus; 59 int ret, status; 60 int lc; 61 62 tst_parse_opts(ac, av, NULL, NULL); 63 64 setup(); 65 66 for (lc = 0; TEST_LOOPING(lc); lc++) { 67 tst_count = 0; 68 69 tst_resm(TINFO, "Forking as many kids as possible"); 70 forks = 0; 71 while ((pid1 = fork()) != -1) { 72 if (pid1 == 0) { /* child */ 73 pause(); 74 exit(0); 75 } 76 forks++; 77 ret = SAFE_WAITPID(cleanup, -1, &status, WNOHANG); 78 if (ret > 0) { 79 /* a child may be killed by OOM killer */ 80 if (WTERMSIG(status) == SIGKILL) 81 break; 82 tst_brkm(TBROK, cleanup, 83 "child exit with error code %d or signal %d", 84 WEXITSTATUS(status), WTERMSIG(status)); 85 } 86 } 87 fork_errno = errno; 88 89 /* parent */ 90 tst_resm(TINFO, "Number of processes forked is %d", forks); 91 tst_resm(TPASS, "fork() eventually failed with %d: %s", 92 fork_errno, strerror(fork_errno)); 93 /* collect our kids */ 94 /* 95 * Introducing a sleep(3) to make sure all children are 96 * at pause() when SIGQUIT is sent to them 97 */ 98 sleep(3); 99 kill(0, SIGQUIT); 100 while (wait(&waitstatus) > 0) ; 101 102 } 103 104 cleanup(); 105 tst_exit(); 106 } 107 108 static void setup(void) 109 { 110 tst_sig(FORK, fork12_sigs, cleanup); 111 TEST_PAUSE; 112 } 113 114 static void cleanup(void) 115 { 116 int waitstatus; 117 118 /* collect our kids */ 119 kill(0, SIGQUIT); 120 while (wait(&waitstatus) > 0) ; 121 } 122 123 static void fork12_sigs(int signum) 124 { 125 if (signum == SIGQUIT) { 126 /* Children will continue, parent will ignore */ 127 } else { 128 tst_brkm(TBROK, cleanup, 129 "Unexpected signal %d received.", signum); 130 } 131 } 132