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