Home | History | Annotate | Download | only in fork
      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