1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
3f08c3bdfSopenharmony_ci *
4f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify it
5f08c3bdfSopenharmony_ci * under the terms of version 2 of the GNU General Public License as
6f08c3bdfSopenharmony_ci * published by the Free Software Foundation.
7f08c3bdfSopenharmony_ci *
8f08c3bdfSopenharmony_ci * This program is distributed in the hope that it would be useful, but
9f08c3bdfSopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of
10f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11f08c3bdfSopenharmony_ci *
12f08c3bdfSopenharmony_ci * Further, this software is distributed without any warranty that it is
13f08c3bdfSopenharmony_ci * free of the rightful claim of any third person regarding infringement
14f08c3bdfSopenharmony_ci * or the like.  Any license provided herein, whether implied or
15f08c3bdfSopenharmony_ci * otherwise, applies only to this software file.  Patent licenses, if
16f08c3bdfSopenharmony_ci * any, provided herein do not apply to combinations of this program with
17f08c3bdfSopenharmony_ci * other software, or any other product whatsoever.
18f08c3bdfSopenharmony_ci *
19f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License along
20f08c3bdfSopenharmony_ci * with this program; if not, write the Free Software Foundation, Inc.,
21f08c3bdfSopenharmony_ci * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22f08c3bdfSopenharmony_ci *
23f08c3bdfSopenharmony_ci * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24f08c3bdfSopenharmony_ci * Mountain View, CA  94043, or:
25f08c3bdfSopenharmony_ci *
26f08c3bdfSopenharmony_ci * http://www.sgi.com
27f08c3bdfSopenharmony_ci *
28f08c3bdfSopenharmony_ci * For further information regarding this notice, see:
29f08c3bdfSopenharmony_ci *
30f08c3bdfSopenharmony_ci * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31f08c3bdfSopenharmony_ci *
32f08c3bdfSopenharmony_ci */
33f08c3bdfSopenharmony_ci/* $Id: kill10.c,v 1.7 2009/03/23 13:35:53 subrata_modak Exp $ */
34f08c3bdfSopenharmony_ci/**********************************************************
35f08c3bdfSopenharmony_ci *
36f08c3bdfSopenharmony_ci *    OS Test - Silicon Graphics, Inc.
37f08c3bdfSopenharmony_ci *
38f08c3bdfSopenharmony_ci *    TEST IDENTIFIER	: kill10
39f08c3bdfSopenharmony_ci *
40f08c3bdfSopenharmony_ci *    EXECUTED BY	: anyone
41f08c3bdfSopenharmony_ci *
42f08c3bdfSopenharmony_ci *    TEST TITLE	: signal flooding test
43f08c3bdfSopenharmony_ci *
44f08c3bdfSopenharmony_ci *    TEST CASE TOTAL	: 1
45f08c3bdfSopenharmony_ci *
46f08c3bdfSopenharmony_ci *    WALL CLOCK TIME	:
47f08c3bdfSopenharmony_ci *
48f08c3bdfSopenharmony_ci *    CPU TYPES		: ALL
49f08c3bdfSopenharmony_ci *
50f08c3bdfSopenharmony_ci *    AUTHOR		: Nate Straz
51f08c3bdfSopenharmony_ci *
52f08c3bdfSopenharmony_ci *    DATE STARTED	: 04/09/2001
53f08c3bdfSopenharmony_ci *
54f08c3bdfSopenharmony_ci *    INITIAL RELEASE	: Linux 2.4.x
55f08c3bdfSopenharmony_ci *
56f08c3bdfSopenharmony_ci *    TEST CASES
57f08c3bdfSopenharmony_ci *
58f08c3bdfSopenharmony_ci * 	1.) Create a large number of processes and signal between them.
59f08c3bdfSopenharmony_ci *
60f08c3bdfSopenharmony_ci *    INPUT SPECIFICATIONS
61f08c3bdfSopenharmony_ci * 	The standard options for system call tests are accepted.
62f08c3bdfSopenharmony_ci *	(See the parse_opts(3) man page).
63f08c3bdfSopenharmony_ci *
64f08c3bdfSopenharmony_ci *    OUTPUT SPECIFICATIONS
65f08c3bdfSopenharmony_ci *$
66f08c3bdfSopenharmony_ci *    DURATION
67f08c3bdfSopenharmony_ci * 	Terminates - with frequency and infinite modes.
68f08c3bdfSopenharmony_ci *
69f08c3bdfSopenharmony_ci *    SIGNALS
70f08c3bdfSopenharmony_ci * 	Uses SIGUSR1 to pause before test if option set.
71f08c3bdfSopenharmony_ci * 	(See the parse_opts(3) man page).
72f08c3bdfSopenharmony_ci *
73f08c3bdfSopenharmony_ci *    RESOURCES
74f08c3bdfSopenharmony_ci * 	None
75f08c3bdfSopenharmony_ci *
76f08c3bdfSopenharmony_ci *    ENVIRONMENTAL NEEDS
77f08c3bdfSopenharmony_ci *      No run-time environmental needs.
78f08c3bdfSopenharmony_ci *
79f08c3bdfSopenharmony_ci *    SPECIAL PROCEDURAL REQUIREMENTS
80f08c3bdfSopenharmony_ci * 	None
81f08c3bdfSopenharmony_ci *
82f08c3bdfSopenharmony_ci *    INTERCASE DEPENDENCIES
83f08c3bdfSopenharmony_ci * 	None
84f08c3bdfSopenharmony_ci *
85f08c3bdfSopenharmony_ci *    DETAILED DESCRIPTION
86f08c3bdfSopenharmony_ci *  This test creates -g groups of -n processes each and prepares them to send
87f08c3bdfSopenharmony_ci *  large numbers of signals.  All process fall into three levels.
88f08c3bdfSopenharmony_ci *    * Level 1 - Master
89f08c3bdfSopenharmony_ci *                This is the parent of all processes.  It handles test looping
90f08c3bdfSopenharmony_ci *                and making sure that all level 2 Managers report in.
91f08c3bdfSopenharmony_ci *                SIGUSR1 -> ack Manager is ready
92f08c3bdfSopenharmony_ci *                SIGUSR2 -> ack Manager is done and sends reset
93f08c3bdfSopenharmony_ci *    * Level 2 - Managers
94f08c3bdfSopenharmony_ci *                There are -g (default 2) of these processes.  They handle
95f08c3bdfSopenharmony_ci *                forking off -n procs and setting up their signal handling.
96f08c3bdfSopenharmony_ci *                Managers are in a pgid with their Children.
97f08c3bdfSopenharmony_ci *                SIGALRM -> Process making your children
98f08c3bdfSopenharmony_ci *                SIGUSR1 ->
99f08c3bdfSopenharmony_ci *                SIGUSR2 -> Reply to Child to stop
100f08c3bdfSopenharmony_ci *                SIGHUP  -> Reset child signal counter
101f08c3bdfSopenharmony_ci *                SIGQUIT -> Exit gracefully
102f08c3bdfSopenharmony_ci *    * Level 3 - Child
103f08c3bdfSopenharmony_ci *                There are -n (default 10) of these process per Manager.  Their
104f08c3bdfSopenharmony_ci *                only job is to send signals to their Managers when told to by
105f08c3bdfSopenharmony_ci *                the Master.
106f08c3bdfSopenharmony_ci *                SIGUSR1 -> Start signaling Manager
107f08c3bdfSopenharmony_ci *                SIGUSR2 -> Stop signaling Manager
108f08c3bdfSopenharmony_ci *                SIGHUP  -> IGNORE
109f08c3bdfSopenharmony_ci *                SIGQUIT -> Exit gracefully
110f08c3bdfSopenharmony_ci *
111f08c3bdfSopenharmony_ci *  During each test loop, Master sends SIGUSR1 to the pgid of each Manager.
112f08c3bdfSopenharmony_ci *  This tells the Children to start signalling their manager.  They do this
113f08c3bdfSopenharmony_ci *  until the manager signals them to stop.  Once the manager finds that all
114f08c3bdfSopenharmony_ci *  children have been signaled (by checking them off in the checklist), the
115f08c3bdfSopenharmony_ci *  Manager signals the Master.  Once the Master acknowledges that all Managers
116f08c3bdfSopenharmony_ci *  have talked to all their Children, the test iteration is over.
117f08c3bdfSopenharmony_ci *
118f08c3bdfSopenharmony_ci * 	Setup:
119f08c3bdfSopenharmony_ci *	  Pause for SIGUSR1 if option specified.
120f08c3bdfSopenharmony_ci *	  Fork -g Managers
121f08c3bdfSopenharmony_ci *	    Set up signal handling for Children
122f08c3bdfSopenharmony_ci *	    Fork -n Children for each manager
123f08c3bdfSopenharmony_ci *	    Set up signal handling for Managers
124f08c3bdfSopenharmony_ci *	  Set up signal handling for Master
125f08c3bdfSopenharmony_ci *
126f08c3bdfSopenharmony_ci * 	Test:
127f08c3bdfSopenharmony_ci *	 Loop if the proper options are given.
128f08c3bdfSopenharmony_ci *	   Send SIGUSR1 to all Managers and their Children
129f08c3bdfSopenharmony_ci *	   Wait for Managers to send SIGUSR2
130f08c3bdfSopenharmony_ci *
131f08c3bdfSopenharmony_ci * 	Cleanup:
132f08c3bdfSopenharmony_ci * 	  Send SIGQUIT to all Manager process groups and wait for Manager to quit.
133f08c3bdfSopenharmony_ci * 	  Print errno log and/or timing stats if options given
134f08c3bdfSopenharmony_ci *
135f08c3bdfSopenharmony_ci *  Debugging:
136f08c3bdfSopenharmony_ci *    0 - normal operations
137f08c3bdfSopenharmony_ci *    1 - Master setup
138f08c3bdfSopenharmony_ci *    2 - Master processing
139f08c3bdfSopenharmony_ci *    3 - Master - Manager interaction
140f08c3bdfSopenharmony_ci *    4 - Manager setup
141f08c3bdfSopenharmony_ci *    5 - Manager processing
142f08c3bdfSopenharmony_ci *    6 - Manager - Child interaction
143f08c3bdfSopenharmony_ci *    7 - Child setup
144f08c3bdfSopenharmony_ci *    8 - Child processing
145f08c3bdfSopenharmony_ci *
146f08c3bdfSopenharmony_ci *
147f08c3bdfSopenharmony_ci *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
148f08c3bdfSopenharmony_ci
149f08c3bdfSopenharmony_ci#include <sys/types.h>
150f08c3bdfSopenharmony_ci#include <sys/wait.h>
151f08c3bdfSopenharmony_ci#include <fcntl.h>
152f08c3bdfSopenharmony_ci#include <dirent.h>
153f08c3bdfSopenharmony_ci#include <unistd.h>
154f08c3bdfSopenharmony_ci#include <stdlib.h>
155f08c3bdfSopenharmony_ci#include <errno.h>
156f08c3bdfSopenharmony_ci#include <string.h>
157f08c3bdfSopenharmony_ci#include <signal.h>
158f08c3bdfSopenharmony_ci#include "test.h"
159f08c3bdfSopenharmony_ci
160f08c3bdfSopenharmony_civoid setup();
161f08c3bdfSopenharmony_civoid help();
162f08c3bdfSopenharmony_civoid cleanup();
163f08c3bdfSopenharmony_civoid fork_pgrps(int pgrps_left);
164f08c3bdfSopenharmony_civoid manager(int num_procs);
165f08c3bdfSopenharmony_civoid fork_procs(int procs_left);
166f08c3bdfSopenharmony_ci
167f08c3bdfSopenharmony_ci/* signal handlers */
168f08c3bdfSopenharmony_civoid ack_ready(int sig, siginfo_t * si, void *data);
169f08c3bdfSopenharmony_civoid ack_done(int sig, siginfo_t * si, void *data);
170f08c3bdfSopenharmony_civoid set_create_procs(int sig);
171f08c3bdfSopenharmony_civoid graceful_exit(int sig);
172f08c3bdfSopenharmony_civoid set_signal_parents(int sig);
173f08c3bdfSopenharmony_civoid clear_signal_parents(int sig);
174f08c3bdfSopenharmony_civoid set_confirmed_ready(int sig);
175f08c3bdfSopenharmony_civoid reset_counter(int sig);
176f08c3bdfSopenharmony_civoid reply_to_child(int sig, siginfo_t * si, void *data);
177f08c3bdfSopenharmony_civoid wakeup(int sig);
178f08c3bdfSopenharmony_ci
179f08c3bdfSopenharmony_ci/* pid checklist management */
180f08c3bdfSopenharmony_cistruct pid_list_item {
181f08c3bdfSopenharmony_ci	pid_t pid;
182f08c3bdfSopenharmony_ci	short flag;
183f08c3bdfSopenharmony_ci} *child_checklist = NULL;
184f08c3bdfSopenharmony_ciint child_checklist_total = 0;
185f08c3bdfSopenharmony_ciint checklist_cmp(const void *a, const void *b);
186f08c3bdfSopenharmony_civoid checklist_reset(int bit);
187f08c3bdfSopenharmony_ci
188f08c3bdfSopenharmony_cistatic inline int k_sigaction(int sig, struct sigaction *sa, struct sigaction *osa);
189f08c3bdfSopenharmony_ci
190f08c3bdfSopenharmony_cichar *TCID = "kill10";
191f08c3bdfSopenharmony_ciint TST_TOTAL = 1;
192f08c3bdfSopenharmony_ci
193f08c3bdfSopenharmony_ciint num_procs = 10;
194f08c3bdfSopenharmony_ciint num_pgrps = 2;
195f08c3bdfSopenharmony_ciint pgrps_ready = 0;
196f08c3bdfSopenharmony_ciint child_signal_counter = 0;
197f08c3bdfSopenharmony_ci
198f08c3bdfSopenharmony_ciint create_procs_flag = 0;
199f08c3bdfSopenharmony_ciint signal_parents_flag = 0;
200f08c3bdfSopenharmony_ciint confirmed_ready_flag = 0;
201f08c3bdfSopenharmony_ciint debug_flag = 0;
202f08c3bdfSopenharmony_cipid_t mypid = 0;
203f08c3bdfSopenharmony_ci
204f08c3bdfSopenharmony_cichar *narg, *garg, *darg;
205f08c3bdfSopenharmony_ciint nflag = 0, gflag = 0, dflag = 0;
206f08c3bdfSopenharmony_ci
207f08c3bdfSopenharmony_cioption_t options[] = {
208f08c3bdfSopenharmony_ci	{"n:", &nflag, &narg},	/* -n #procs */
209f08c3bdfSopenharmony_ci	{"g:", &gflag, &garg},	/* -g #pgrps */
210f08c3bdfSopenharmony_ci	{"d:", &dflag, &darg},	/* -d <debug level>  */
211f08c3bdfSopenharmony_ci	{NULL, NULL, NULL}
212f08c3bdfSopenharmony_ci};
213f08c3bdfSopenharmony_ci
214f08c3bdfSopenharmony_ciint main(int ac, char **av)
215f08c3bdfSopenharmony_ci{
216f08c3bdfSopenharmony_ci	int lc;
217f08c3bdfSopenharmony_ci	int cnt;
218f08c3bdfSopenharmony_ci
219f08c3bdfSopenharmony_ci	tst_parse_opts(ac, av, options, &help);
220f08c3bdfSopenharmony_ci
221f08c3bdfSopenharmony_ci	if (nflag) {
222f08c3bdfSopenharmony_ci		if (sscanf(narg, "%i", &num_procs) != 1) {
223f08c3bdfSopenharmony_ci			tst_brkm(TBROK, NULL, "-n option arg is not a number");
224f08c3bdfSopenharmony_ci		}
225f08c3bdfSopenharmony_ci	}
226f08c3bdfSopenharmony_ci	if (gflag) {
227f08c3bdfSopenharmony_ci		if (sscanf(garg, "%i", &num_pgrps) != 1) {
228f08c3bdfSopenharmony_ci			tst_brkm(TBROK, NULL, "-g option arg is not a number");
229f08c3bdfSopenharmony_ci		}
230f08c3bdfSopenharmony_ci	}
231f08c3bdfSopenharmony_ci
232f08c3bdfSopenharmony_ci	if (dflag) {
233f08c3bdfSopenharmony_ci		if (sscanf(darg, "%i", &debug_flag) != 1) {
234f08c3bdfSopenharmony_ci			tst_brkm(TBROK, NULL, "-d option arg is not a number");
235f08c3bdfSopenharmony_ci		}
236f08c3bdfSopenharmony_ci	}
237f08c3bdfSopenharmony_ci
238f08c3bdfSopenharmony_ci	setup();
239f08c3bdfSopenharmony_ci
240f08c3bdfSopenharmony_ci	for (lc = 0; TEST_LOOPING(lc); lc++) {
241f08c3bdfSopenharmony_ci
242f08c3bdfSopenharmony_ci		tst_count = 0;
243f08c3bdfSopenharmony_ci		child_signal_counter = 0;
244f08c3bdfSopenharmony_ci		pgrps_ready = 0;
245f08c3bdfSopenharmony_ci		checklist_reset(0x03);
246f08c3bdfSopenharmony_ci
247f08c3bdfSopenharmony_ci		/* send SIGUSR1 to each pgroup */
248f08c3bdfSopenharmony_ci		for (cnt = 0; cnt < child_checklist_total; ++cnt) {
249f08c3bdfSopenharmony_ci			if (debug_flag >= 2)
250f08c3bdfSopenharmony_ci				printf("%d: test_loop, SIGUSR1 -> %d\n",
251f08c3bdfSopenharmony_ci				       mypid, -child_checklist[cnt].pid);
252f08c3bdfSopenharmony_ci			kill(-child_checklist[cnt].pid, SIGUSR1);
253f08c3bdfSopenharmony_ci		}
254f08c3bdfSopenharmony_ci
255f08c3bdfSopenharmony_ci		/* wait for the managers to signal they are done */
256f08c3bdfSopenharmony_ci		while (child_signal_counter < num_pgrps) {
257f08c3bdfSopenharmony_ci			alarm(1);
258f08c3bdfSopenharmony_ci			if (debug_flag >= 2)
259f08c3bdfSopenharmony_ci				printf("%d: Master pausing for done (%d/%d)\n",
260f08c3bdfSopenharmony_ci				       mypid, child_signal_counter, num_pgrps);
261f08c3bdfSopenharmony_ci			pause();
262f08c3bdfSopenharmony_ci		}
263f08c3bdfSopenharmony_ci		tst_resm(TPASS, "All %d pgrps received their signals",
264f08c3bdfSopenharmony_ci			 child_signal_counter);
265f08c3bdfSopenharmony_ci
266f08c3bdfSopenharmony_ci	}
267f08c3bdfSopenharmony_ci
268f08c3bdfSopenharmony_ci	cleanup();
269f08c3bdfSopenharmony_ci
270f08c3bdfSopenharmony_ci	tst_exit();
271f08c3bdfSopenharmony_ci}
272f08c3bdfSopenharmony_ci
273f08c3bdfSopenharmony_civoid help(void)
274f08c3bdfSopenharmony_ci{
275f08c3bdfSopenharmony_ci	printf("  -g n    Create n process groups (default: %d)\n", num_pgrps);
276f08c3bdfSopenharmony_ci	printf
277f08c3bdfSopenharmony_ci	    ("  -n n    Create n children in each process group (default: %d)\n",
278f08c3bdfSopenharmony_ci	     num_procs);
279f08c3bdfSopenharmony_ci	printf("  -d n    Set debug level to n (default: %d)\n", debug_flag);
280f08c3bdfSopenharmony_ci}
281f08c3bdfSopenharmony_ci
282f08c3bdfSopenharmony_civoid setup(void)
283f08c3bdfSopenharmony_ci{
284f08c3bdfSopenharmony_ci	struct sigaction sa;
285f08c3bdfSopenharmony_ci	int i;
286f08c3bdfSopenharmony_ci
287f08c3bdfSopenharmony_ci	/* You will want to enable some signal handling so you can capture
288f08c3bdfSopenharmony_ci	 * unexpected signals like SIGSEGV.
289f08c3bdfSopenharmony_ci	 */
290f08c3bdfSopenharmony_ci	tst_sig(FORK, DEF_HANDLER, cleanup);
291f08c3bdfSopenharmony_ci
292f08c3bdfSopenharmony_ci	/* One cavet that hasn't been fixed yet.  TEST_PAUSE contains the code to
293f08c3bdfSopenharmony_ci	 * fork the test with the -c option.  You want to make sure you do this
294f08c3bdfSopenharmony_ci	 * before you create your temporary directory.
295f08c3bdfSopenharmony_ci	 */
296f08c3bdfSopenharmony_ci	TEST_PAUSE;
297f08c3bdfSopenharmony_ci
298f08c3bdfSopenharmony_ci	mypid = getpid();
299f08c3bdfSopenharmony_ci	sa.sa_handler = SIG_DFL;
300f08c3bdfSopenharmony_ci	sigemptyset(&sa.sa_mask);
301f08c3bdfSopenharmony_ci	sa.sa_flags = 0;
302f08c3bdfSopenharmony_ci	if (debug_flag >= 1)
303f08c3bdfSopenharmony_ci		printf("%d: setting SIGTRAP -> SIG_DFL\n", mypid);
304f08c3bdfSopenharmony_ci	k_sigaction(SIGTRAP, &sa, NULL);
305f08c3bdfSopenharmony_ci	if (debug_flag >= 1)
306f08c3bdfSopenharmony_ci		printf("%d: setting SIGCONT -> SIG_DFL\n", mypid);
307f08c3bdfSopenharmony_ci	k_sigaction(SIGCONT, &sa, NULL);
308f08c3bdfSopenharmony_ci
309f08c3bdfSopenharmony_ci	sa.sa_handler = set_create_procs;
310f08c3bdfSopenharmony_ci	if (debug_flag >= 4)
311f08c3bdfSopenharmony_ci		printf("%d: setting SIGALRM -> set_create_procs\n", mypid);
312f08c3bdfSopenharmony_ci	k_sigaction(SIGALRM, &sa, NULL);
313f08c3bdfSopenharmony_ci
314f08c3bdfSopenharmony_ci	sa.sa_handler = NULL;
315f08c3bdfSopenharmony_ci	sa.sa_sigaction = ack_ready;
316f08c3bdfSopenharmony_ci	sa.sa_flags = SA_SIGINFO;
317f08c3bdfSopenharmony_ci	if (debug_flag >= 1)
318f08c3bdfSopenharmony_ci		printf("%d: setting SIGUSR1 -> ack_ready\n", mypid);
319f08c3bdfSopenharmony_ci	k_sigaction(SIGUSR1, &sa, NULL);
320f08c3bdfSopenharmony_ci
321f08c3bdfSopenharmony_ci	fork_pgrps(num_pgrps);
322f08c3bdfSopenharmony_ci
323f08c3bdfSopenharmony_ci	/* wait for all pgrps to report in */
324f08c3bdfSopenharmony_ci	if (debug_flag)
325f08c3bdfSopenharmony_ci		printf("Master: %d\n", mypid);
326f08c3bdfSopenharmony_ci	while (pgrps_ready < num_pgrps) {
327f08c3bdfSopenharmony_ci		if (debug_flag >= 3)
328f08c3bdfSopenharmony_ci			printf
329f08c3bdfSopenharmony_ci			    ("%d: Master pausing for Managers to check in (%d/%d)\n",
330f08c3bdfSopenharmony_ci			     mypid, pgrps_ready, num_pgrps);
331f08c3bdfSopenharmony_ci		/*
332f08c3bdfSopenharmony_ci		 * We might receive the signal from the (last manager) before
333f08c3bdfSopenharmony_ci		 * we issue a pause. In that case we might hang even if we have
334f08c3bdfSopenharmony_ci		 * all the managers reported in. So set an alarm so that we can
335f08c3bdfSopenharmony_ci		 * wake up.
336f08c3bdfSopenharmony_ci		 */
337f08c3bdfSopenharmony_ci		alarm(1);
338f08c3bdfSopenharmony_ci
339f08c3bdfSopenharmony_ci		pause();
340f08c3bdfSopenharmony_ci	}
341f08c3bdfSopenharmony_ci	checklist_reset(0x03);
342f08c3bdfSopenharmony_ci	if (debug_flag) {
343f08c3bdfSopenharmony_ci		printf("Managers: \n");
344f08c3bdfSopenharmony_ci		for (i = 0; i < num_pgrps; i++) {
345f08c3bdfSopenharmony_ci			printf("%d ", child_checklist[i].pid);
346f08c3bdfSopenharmony_ci		}
347f08c3bdfSopenharmony_ci		printf("\n");
348f08c3bdfSopenharmony_ci	}
349f08c3bdfSopenharmony_ci
350f08c3bdfSopenharmony_ci	/* set up my signal processing */
351f08c3bdfSopenharmony_ci	/* continue on ALRM */
352f08c3bdfSopenharmony_ci	sa.sa_handler = wakeup;
353f08c3bdfSopenharmony_ci	if (debug_flag >= 4)
354f08c3bdfSopenharmony_ci		printf("%d: setting SIGALRM -> wakeup\n", mypid);
355f08c3bdfSopenharmony_ci	k_sigaction(SIGALRM, &sa, NULL);
356f08c3bdfSopenharmony_ci	/* reply to child on USR2 */
357f08c3bdfSopenharmony_ci	sa.sa_handler = NULL;
358f08c3bdfSopenharmony_ci	sa.sa_sigaction = ack_done;
359f08c3bdfSopenharmony_ci	sa.sa_flags = SA_SIGINFO;
360f08c3bdfSopenharmony_ci	if (debug_flag >= 1)
361f08c3bdfSopenharmony_ci		printf("%d: setting SIGUSR2 -> ack_done\n", mypid);
362f08c3bdfSopenharmony_ci	k_sigaction(SIGUSR2, &sa, NULL);
363f08c3bdfSopenharmony_ci}
364f08c3bdfSopenharmony_ci
365f08c3bdfSopenharmony_civoid ack_ready(int sig, siginfo_t * si, void *data)
366f08c3bdfSopenharmony_ci{
367f08c3bdfSopenharmony_ci	struct pid_list_item findit, *result;
368f08c3bdfSopenharmony_ci
369f08c3bdfSopenharmony_ci	findit.pid = si->si_pid;
370f08c3bdfSopenharmony_ci
371f08c3bdfSopenharmony_ci	result = bsearch(&findit, child_checklist, child_checklist_total,
372f08c3bdfSopenharmony_ci			 sizeof(*child_checklist), checklist_cmp);
373f08c3bdfSopenharmony_ci	if (result) {
374f08c3bdfSopenharmony_ci		if (!(result->flag & 0x01)) {
375f08c3bdfSopenharmony_ci			if (debug_flag >= 3)
376f08c3bdfSopenharmony_ci				printf("%d: ack_ready, SIGUSR1 -> %d\n", mypid,
377f08c3bdfSopenharmony_ci				       si->si_pid);
378f08c3bdfSopenharmony_ci			kill(si->si_pid, SIGUSR1);
379f08c3bdfSopenharmony_ci			result->flag = result->flag | 0x01;
380f08c3bdfSopenharmony_ci			++pgrps_ready;
381f08c3bdfSopenharmony_ci		} else {
382f08c3bdfSopenharmony_ci			if (debug_flag >= 3)
383f08c3bdfSopenharmony_ci				printf("%d: ack_ready, already acked %d\n",
384f08c3bdfSopenharmony_ci				       mypid, si->si_pid);
385f08c3bdfSopenharmony_ci		}
386f08c3bdfSopenharmony_ci	} else {
387f08c3bdfSopenharmony_ci		printf("received unexpected signal %d from %d",
388f08c3bdfSopenharmony_ci		       sig, si->si_pid);
389f08c3bdfSopenharmony_ci	}
390f08c3bdfSopenharmony_ci}
391f08c3bdfSopenharmony_ci
392f08c3bdfSopenharmony_civoid ack_done(int sig, siginfo_t * si, void *data)
393f08c3bdfSopenharmony_ci{
394f08c3bdfSopenharmony_ci	struct pid_list_item findit, *result;
395f08c3bdfSopenharmony_ci
396f08c3bdfSopenharmony_ci	findit.pid = si->si_pid;
397f08c3bdfSopenharmony_ci
398f08c3bdfSopenharmony_ci	result = bsearch(&findit, child_checklist, child_checklist_total,
399f08c3bdfSopenharmony_ci			 sizeof(*child_checklist), checklist_cmp);
400f08c3bdfSopenharmony_ci	if (result) {
401f08c3bdfSopenharmony_ci		if (!(result->flag & 0x02)) {
402f08c3bdfSopenharmony_ci			if (debug_flag >= 3)
403f08c3bdfSopenharmony_ci				printf("%d: ack_done, SIGHUP -> %d\n", mypid,
404f08c3bdfSopenharmony_ci				       si->si_pid);
405f08c3bdfSopenharmony_ci			kill(si->si_pid, SIGHUP);
406f08c3bdfSopenharmony_ci			++child_signal_counter;
407f08c3bdfSopenharmony_ci			result->flag = result->flag | 0x02;
408f08c3bdfSopenharmony_ci		} else {
409f08c3bdfSopenharmony_ci			if (debug_flag >= 3)
410f08c3bdfSopenharmony_ci				printf("%d: ack_done, already told %d\n", mypid,
411f08c3bdfSopenharmony_ci				       si->si_pid);
412f08c3bdfSopenharmony_ci		}
413f08c3bdfSopenharmony_ci	} else {
414f08c3bdfSopenharmony_ci		printf("received unexpected signal %d from %d",
415f08c3bdfSopenharmony_ci		       sig, si->si_pid);
416f08c3bdfSopenharmony_ci	}
417f08c3bdfSopenharmony_ci}
418f08c3bdfSopenharmony_ci
419f08c3bdfSopenharmony_ci/***************************************************************
420f08c3bdfSopenharmony_ci * cleanup() - performs all ONE TIME cleanup for this test at
421f08c3bdfSopenharmony_ci *		completion or premature exit.
422f08c3bdfSopenharmony_ci ***************************************************************/
423f08c3bdfSopenharmony_civoid cleanup(void)
424f08c3bdfSopenharmony_ci{
425f08c3bdfSopenharmony_ci	int i;
426f08c3bdfSopenharmony_ci	/* send SIGHUP to all pgroups */
427f08c3bdfSopenharmony_ci	for (i = 0; i < num_pgrps; ++i) {
428f08c3bdfSopenharmony_ci		/* try to do this as nicely as possible */
429f08c3bdfSopenharmony_ci		kill(-child_checklist[i].pid, SIGQUIT);
430f08c3bdfSopenharmony_ci		waitpid(child_checklist[i].pid, NULL, 0);
431f08c3bdfSopenharmony_ci	}
432f08c3bdfSopenharmony_ci	free(child_checklist);
433f08c3bdfSopenharmony_ci
434f08c3bdfSopenharmony_ci}
435f08c3bdfSopenharmony_ci
436f08c3bdfSopenharmony_ci/*********************************************************************
437f08c3bdfSopenharmony_ci * fork_pgrps() forks off a child, changes it's pgrp, then continues
438f08c3bdfSopenharmony_ci ********************************************************************/
439f08c3bdfSopenharmony_civoid fork_pgrps(int pgrps_left)
440f08c3bdfSopenharmony_ci{
441f08c3bdfSopenharmony_ci	pid_t child;
442f08c3bdfSopenharmony_ci
443f08c3bdfSopenharmony_ci	if (!(child_checklist = calloc(pgrps_left, sizeof(*child_checklist)))) {
444f08c3bdfSopenharmony_ci		tst_brkm(TBROK, cleanup,
445f08c3bdfSopenharmony_ci			 "%d: couldn't calloc child_checklist, errno=%d : %s",
446f08c3bdfSopenharmony_ci			 mypid, errno, strerror(errno));
447f08c3bdfSopenharmony_ci	}
448f08c3bdfSopenharmony_ci	child_checklist_total = 0;
449f08c3bdfSopenharmony_ci	while (pgrps_left) {
450f08c3bdfSopenharmony_ci		if (debug_flag >= 1)
451f08c3bdfSopenharmony_ci			printf("%d: forking new Manager\n", mypid);
452f08c3bdfSopenharmony_ci		switch (child = fork()) {
453f08c3bdfSopenharmony_ci		case -1:
454f08c3bdfSopenharmony_ci			tst_brkm(TBROK | TERRNO, cleanup,
455f08c3bdfSopenharmony_ci				 "fork() failed in fork_pgrps(%d)", pgrps_left);
456f08c3bdfSopenharmony_ci			break;
457f08c3bdfSopenharmony_ci		case 0:
458f08c3bdfSopenharmony_ci			mypid = getpid();
459f08c3bdfSopenharmony_ci			free(child_checklist);
460f08c3bdfSopenharmony_ci			child_checklist = NULL;
461f08c3bdfSopenharmony_ci			manager(num_procs);
462f08c3bdfSopenharmony_ci			break;
463f08c3bdfSopenharmony_ci		default:
464f08c3bdfSopenharmony_ci			child_checklist[child_checklist_total++].pid = child;
465f08c3bdfSopenharmony_ci			setpgid(child, child);
466f08c3bdfSopenharmony_ci			if (debug_flag >= 3)
467f08c3bdfSopenharmony_ci				printf("%d: fork_pgrps, SIGALRM -> %d\n", mypid,
468f08c3bdfSopenharmony_ci				       child);
469f08c3bdfSopenharmony_ci			kill(child, SIGALRM);
470f08c3bdfSopenharmony_ci		}
471f08c3bdfSopenharmony_ci		--pgrps_left;
472f08c3bdfSopenharmony_ci	}
473f08c3bdfSopenharmony_ci	qsort(child_checklist, child_checklist_total, sizeof(*child_checklist),
474f08c3bdfSopenharmony_ci	      checklist_cmp);
475f08c3bdfSopenharmony_ci}
476f08c3bdfSopenharmony_ci
477f08c3bdfSopenharmony_civoid set_create_procs(int sig)
478f08c3bdfSopenharmony_ci{
479f08c3bdfSopenharmony_ci	if (debug_flag >= 3)
480f08c3bdfSopenharmony_ci		printf("%d: Manager cleared to fork\n", getpid());
481f08c3bdfSopenharmony_ci	create_procs_flag++;
482f08c3bdfSopenharmony_ci	return;
483f08c3bdfSopenharmony_ci}
484f08c3bdfSopenharmony_ci
485f08c3bdfSopenharmony_ci/*********************************************************************
486f08c3bdfSopenharmony_ci * new_pgrg() - handle the creation of the pgrp managers and their
487f08c3bdfSopenharmony_ci *              children
488f08c3bdfSopenharmony_ci ********************************************************************/
489f08c3bdfSopenharmony_civoid manager(int num_procs)
490f08c3bdfSopenharmony_ci{
491f08c3bdfSopenharmony_ci	struct sigaction sa;
492f08c3bdfSopenharmony_ci
493f08c3bdfSopenharmony_ci	/* Wait for the parent to change our pgid before we start forking */
494f08c3bdfSopenharmony_ci	while (!create_procs_flag) {
495f08c3bdfSopenharmony_ci		alarm(1);
496f08c3bdfSopenharmony_ci		if (debug_flag >= 3)
497f08c3bdfSopenharmony_ci			printf("%d: Manager pausing, not cleared to fork\n",
498f08c3bdfSopenharmony_ci			       mypid);
499f08c3bdfSopenharmony_ci		pause();
500f08c3bdfSopenharmony_ci	}
501f08c3bdfSopenharmony_ci
502f08c3bdfSopenharmony_ci	/* set up the signal handling the children will use */
503f08c3bdfSopenharmony_ci
504f08c3bdfSopenharmony_ci	/* ignore HUP */
505f08c3bdfSopenharmony_ci	sa.sa_handler = SIG_IGN;
506f08c3bdfSopenharmony_ci	sigemptyset(&sa.sa_mask);
507f08c3bdfSopenharmony_ci	sa.sa_flags = 0;
508f08c3bdfSopenharmony_ci	if (debug_flag >= 4)
509f08c3bdfSopenharmony_ci		printf("%d: setting SIGHUP -> SIG_IGN\n", mypid);
510f08c3bdfSopenharmony_ci	k_sigaction(SIGHUP, &sa, NULL);
511f08c3bdfSopenharmony_ci
512f08c3bdfSopenharmony_ci	/* We use ALRM to make sure that we don't miss the signal effects ! */
513f08c3bdfSopenharmony_ci	sa.sa_handler = wakeup;
514f08c3bdfSopenharmony_ci	if (debug_flag >= 4)
515f08c3bdfSopenharmony_ci		printf("%d: setting SIGALRM -> wakeup\n", mypid);
516f08c3bdfSopenharmony_ci	k_sigaction(SIGALRM, &sa, NULL);
517f08c3bdfSopenharmony_ci
518f08c3bdfSopenharmony_ci	/* exit on QUIT */
519f08c3bdfSopenharmony_ci	sa.sa_handler = graceful_exit;
520f08c3bdfSopenharmony_ci	if (debug_flag >= 4)
521f08c3bdfSopenharmony_ci		printf("%d: setting SIGQUIT -> graceful_exit\n", mypid);
522f08c3bdfSopenharmony_ci	k_sigaction(SIGQUIT, &sa, NULL);
523f08c3bdfSopenharmony_ci
524f08c3bdfSopenharmony_ci	/* start signaling on USR1 */
525f08c3bdfSopenharmony_ci	sa.sa_handler = set_signal_parents;
526f08c3bdfSopenharmony_ci	sigfillset(&sa.sa_mask);
527f08c3bdfSopenharmony_ci	if (debug_flag >= 7)
528f08c3bdfSopenharmony_ci		printf("%d: setting SIGUSR1 -> set_signal_parents\n", mypid);
529f08c3bdfSopenharmony_ci	k_sigaction(SIGUSR1, &sa, NULL);
530f08c3bdfSopenharmony_ci	/* stop signaling on USR2 */
531f08c3bdfSopenharmony_ci	sa.sa_handler = clear_signal_parents;
532f08c3bdfSopenharmony_ci	if (debug_flag >= 7)
533f08c3bdfSopenharmony_ci		printf("%d: setting SIGUSR2 -> clear_signal_parents\n", mypid);
534f08c3bdfSopenharmony_ci	k_sigaction(SIGUSR2, &sa, NULL);
535f08c3bdfSopenharmony_ci
536f08c3bdfSopenharmony_ci	fork_procs(num_procs);
537f08c3bdfSopenharmony_ci	sleep(1);		/* wait a sec to let all the children pause */
538f08c3bdfSopenharmony_ci
539f08c3bdfSopenharmony_ci	/* now set up my signal handling */
540f08c3bdfSopenharmony_ci
541f08c3bdfSopenharmony_ci	/* continue on ALRM */
542f08c3bdfSopenharmony_ci	sa.sa_handler = wakeup;
543f08c3bdfSopenharmony_ci	if (debug_flag >= 4)
544f08c3bdfSopenharmony_ci		printf("%d: setting SIGALRM -> wakeup\n", mypid);
545f08c3bdfSopenharmony_ci	k_sigaction(SIGALRM, &sa, NULL);
546f08c3bdfSopenharmony_ci	/* mark ready confirmation on USR1 */
547f08c3bdfSopenharmony_ci	sa.sa_handler = set_confirmed_ready;
548f08c3bdfSopenharmony_ci	if (debug_flag >= 4)
549f08c3bdfSopenharmony_ci		printf("%d: setting SIGUSR1 -> set_confirmed_ready\n", mypid);
550f08c3bdfSopenharmony_ci	k_sigaction(SIGUSR1, &sa, NULL);
551f08c3bdfSopenharmony_ci	/* reset our counter on HUP */
552f08c3bdfSopenharmony_ci	sa.sa_handler = reset_counter;
553f08c3bdfSopenharmony_ci	if (debug_flag >= 4)
554f08c3bdfSopenharmony_ci		printf("%d: setting SIGHUP -> reset_counter\n", mypid);
555f08c3bdfSopenharmony_ci	k_sigaction(SIGHUP, &sa, NULL);
556f08c3bdfSopenharmony_ci
557f08c3bdfSopenharmony_ci	/* reply to child on USR2 */
558f08c3bdfSopenharmony_ci	sa.sa_handler = NULL;
559f08c3bdfSopenharmony_ci	sa.sa_sigaction = reply_to_child;
560f08c3bdfSopenharmony_ci	sa.sa_flags = SA_SIGINFO;
561f08c3bdfSopenharmony_ci	if (debug_flag >= 4)
562f08c3bdfSopenharmony_ci		printf("%d: setting SIGUSR2 -> reply_to_child\n", mypid);
563f08c3bdfSopenharmony_ci	k_sigaction(SIGUSR2, &sa, NULL);
564f08c3bdfSopenharmony_ci
565f08c3bdfSopenharmony_ci	/* tell our parent that we are ready to rock */
566f08c3bdfSopenharmony_ci	while (!confirmed_ready_flag) {
567f08c3bdfSopenharmony_ci		if (debug_flag >= 3)
568f08c3bdfSopenharmony_ci			printf("%d: Manager, SIGUSR1 -> %d\n", mypid,
569f08c3bdfSopenharmony_ci			       getppid());
570f08c3bdfSopenharmony_ci		if (kill(getppid(), SIGUSR1) == -1) {
571f08c3bdfSopenharmony_ci			printf("%d: Couldn't signal master (%d) that we're "
572f08c3bdfSopenharmony_ci			       "ready. %d: %s",
573f08c3bdfSopenharmony_ci			       mypid, getppid(), errno, strerror(errno));
574f08c3bdfSopenharmony_ci			exit(errno);
575f08c3bdfSopenharmony_ci		}
576f08c3bdfSopenharmony_ci		usleep(100);
577f08c3bdfSopenharmony_ci	}
578f08c3bdfSopenharmony_ci
579f08c3bdfSopenharmony_ci	/* handle pgroup management while the tests are running */
580f08c3bdfSopenharmony_ci	while (1) {
581f08c3bdfSopenharmony_ci		alarm(1);
582f08c3bdfSopenharmony_ci		if (debug_flag >= 5)
583f08c3bdfSopenharmony_ci			printf("%d: Manager pausing (%d/%d)\n",
584f08c3bdfSopenharmony_ci			       mypid, child_signal_counter, num_procs);
585f08c3bdfSopenharmony_ci		pause();
586f08c3bdfSopenharmony_ci		if (child_signal_counter >= num_procs) {
587f08c3bdfSopenharmony_ci			confirmed_ready_flag = 0;
588f08c3bdfSopenharmony_ci			printf("%d: All %d children reported in\n",
589f08c3bdfSopenharmony_ci			       mypid, child_signal_counter);
590f08c3bdfSopenharmony_ci			while (child_signal_counter) {
591f08c3bdfSopenharmony_ci				if (debug_flag >= 3)
592f08c3bdfSopenharmony_ci					printf("%d: Manager, SIGUSR2 -> %d\n",
593f08c3bdfSopenharmony_ci					       mypid, getppid());
594f08c3bdfSopenharmony_ci				if (kill(getppid(), SIGUSR2) == -1) {
595f08c3bdfSopenharmony_ci					printf("%d: Couldn't signal master "
596f08c3bdfSopenharmony_ci					       "(%d) that we're ready. %d: %s\n",
597f08c3bdfSopenharmony_ci					       mypid, getppid(), errno,
598f08c3bdfSopenharmony_ci					       strerror(errno));
599f08c3bdfSopenharmony_ci					exit(errno);
600f08c3bdfSopenharmony_ci				}
601f08c3bdfSopenharmony_ci				usleep(100);
602f08c3bdfSopenharmony_ci			}
603f08c3bdfSopenharmony_ci		}
604f08c3bdfSopenharmony_ci	}
605f08c3bdfSopenharmony_ci}
606f08c3bdfSopenharmony_ci
607f08c3bdfSopenharmony_ci/* some simple signal handlers for the kids */
608f08c3bdfSopenharmony_civoid graceful_exit(int sig)
609f08c3bdfSopenharmony_ci{
610f08c3bdfSopenharmony_ci	exit(0);
611f08c3bdfSopenharmony_ci}
612f08c3bdfSopenharmony_ci
613f08c3bdfSopenharmony_civoid set_signal_parents(int sig)
614f08c3bdfSopenharmony_ci{
615f08c3bdfSopenharmony_ci	if (debug_flag >= 8)
616f08c3bdfSopenharmony_ci		printf("%d: Child start signaling\n", mypid);
617f08c3bdfSopenharmony_ci	signal_parents_flag = 1;
618f08c3bdfSopenharmony_ci}
619f08c3bdfSopenharmony_ci
620f08c3bdfSopenharmony_civoid clear_signal_parents(int sig)
621f08c3bdfSopenharmony_ci{
622f08c3bdfSopenharmony_ci	if (debug_flag >= 8)
623f08c3bdfSopenharmony_ci		printf("%d: Child stop signaling\n", mypid);
624f08c3bdfSopenharmony_ci	signal_parents_flag = 0;
625f08c3bdfSopenharmony_ci}
626f08c3bdfSopenharmony_ci
627f08c3bdfSopenharmony_civoid set_confirmed_ready(int sig)
628f08c3bdfSopenharmony_ci{
629f08c3bdfSopenharmony_ci
630f08c3bdfSopenharmony_ci	if (debug_flag >= 3)
631f08c3bdfSopenharmony_ci		printf("%d: Manager confirmed ready\n", mypid);
632f08c3bdfSopenharmony_ci	confirmed_ready_flag = 1;
633f08c3bdfSopenharmony_ci}
634f08c3bdfSopenharmony_ci
635f08c3bdfSopenharmony_civoid reset_counter(int sig)
636f08c3bdfSopenharmony_ci{
637f08c3bdfSopenharmony_ci	checklist_reset(0xFF);
638f08c3bdfSopenharmony_ci	child_signal_counter = 0;
639f08c3bdfSopenharmony_ci	if (debug_flag >= 3)
640f08c3bdfSopenharmony_ci		printf("%d: reset_counter\n", mypid);
641f08c3bdfSopenharmony_ci}
642f08c3bdfSopenharmony_ci
643f08c3bdfSopenharmony_civoid reply_to_child(int sig, siginfo_t * si, void *data)
644f08c3bdfSopenharmony_ci{
645f08c3bdfSopenharmony_ci	struct pid_list_item findit, *result;
646f08c3bdfSopenharmony_ci
647f08c3bdfSopenharmony_ci	findit.pid = si->si_pid;
648f08c3bdfSopenharmony_ci
649f08c3bdfSopenharmony_ci	result = bsearch(&findit, child_checklist, child_checklist_total,
650f08c3bdfSopenharmony_ci			 sizeof(*child_checklist), checklist_cmp);
651f08c3bdfSopenharmony_ci	if (result) {
652f08c3bdfSopenharmony_ci		if (!result->flag) {
653f08c3bdfSopenharmony_ci			if (debug_flag >= 6)
654f08c3bdfSopenharmony_ci				printf("%d: reply_to_child, SIGUSR1 -> %d\n",
655f08c3bdfSopenharmony_ci				       mypid, si->si_pid);
656f08c3bdfSopenharmony_ci			kill(si->si_pid, SIGUSR2);
657f08c3bdfSopenharmony_ci			++child_signal_counter;
658f08c3bdfSopenharmony_ci			result->flag = 1;
659f08c3bdfSopenharmony_ci		} else {
660f08c3bdfSopenharmony_ci			if (debug_flag >= 6)
661f08c3bdfSopenharmony_ci				printf("%d: reply_to_child, already told %d\n",
662f08c3bdfSopenharmony_ci				       mypid, si->si_pid);
663f08c3bdfSopenharmony_ci		}
664f08c3bdfSopenharmony_ci	} else {
665f08c3bdfSopenharmony_ci		tst_brkm(TBROK, cleanup,
666f08c3bdfSopenharmony_ci			 "received unexpected signal from %d", si->si_pid);
667f08c3bdfSopenharmony_ci	}
668f08c3bdfSopenharmony_ci}
669f08c3bdfSopenharmony_ci
670f08c3bdfSopenharmony_civoid wakeup(int sig)
671f08c3bdfSopenharmony_ci{
672f08c3bdfSopenharmony_ci	return;
673f08c3bdfSopenharmony_ci}
674f08c3bdfSopenharmony_ci
675f08c3bdfSopenharmony_ci/*************************************************
676f08c3bdfSopenharmony_ci * fork_procs() - create all the children
677f08c3bdfSopenharmony_ci ************************************************/
678f08c3bdfSopenharmony_civoid fork_procs(int procs_left)
679f08c3bdfSopenharmony_ci{
680f08c3bdfSopenharmony_ci	pid_t child;
681f08c3bdfSopenharmony_ci
682f08c3bdfSopenharmony_ci	if (!(child_checklist = calloc(procs_left, sizeof(*child_checklist)))) {
683f08c3bdfSopenharmony_ci		tst_brkm(TBROK, cleanup,
684f08c3bdfSopenharmony_ci			 "%d: couldn't calloc child_checklist, errno=%d : %s",
685f08c3bdfSopenharmony_ci			 mypid, errno, strerror(errno));
686f08c3bdfSopenharmony_ci	}
687f08c3bdfSopenharmony_ci	child_checklist_total = 0;
688f08c3bdfSopenharmony_ci
689f08c3bdfSopenharmony_ci	/* We are setting the flag for children, to avoid missing any signals */
690f08c3bdfSopenharmony_ci	signal_parents_flag = 0;
691f08c3bdfSopenharmony_ci
692f08c3bdfSopenharmony_ci	while (procs_left) {
693f08c3bdfSopenharmony_ci		if (debug_flag >= 4)
694f08c3bdfSopenharmony_ci			printf("%d: forking new child\n", mypid);
695f08c3bdfSopenharmony_ci		switch (child = fork()) {
696f08c3bdfSopenharmony_ci		case -1:
697f08c3bdfSopenharmony_ci			tst_brkm(TBROK | TERRNO, cleanup,
698f08c3bdfSopenharmony_ci				 "fork() failed in fork_procs(%d)", procs_left);
699f08c3bdfSopenharmony_ci			break;
700f08c3bdfSopenharmony_ci		case 0:
701f08c3bdfSopenharmony_ci			mypid = getpid();
702f08c3bdfSopenharmony_ci			while (1) {
703f08c3bdfSopenharmony_ci				/* wait to start */
704f08c3bdfSopenharmony_ci				if (debug_flag >= 8)
705f08c3bdfSopenharmony_ci					printf("%d: child pausing\n", mypid);
706f08c3bdfSopenharmony_ci				/*
707f08c3bdfSopenharmony_ci				 * If we have already received the signal, we dont
708f08c3bdfSopenharmony_ci				 * want to pause for it !
709f08c3bdfSopenharmony_ci				 */
710f08c3bdfSopenharmony_ci				while (!signal_parents_flag) {
711f08c3bdfSopenharmony_ci					alarm(2);
712f08c3bdfSopenharmony_ci					pause();
713f08c3bdfSopenharmony_ci				}
714f08c3bdfSopenharmony_ci
715f08c3bdfSopenharmony_ci				/* if we started, call mama */
716f08c3bdfSopenharmony_ci				while (signal_parents_flag) {
717f08c3bdfSopenharmony_ci					if (debug_flag >= 6)
718f08c3bdfSopenharmony_ci						printf("%d: child, SIGUSR2 "
719f08c3bdfSopenharmony_ci						       "-> %d\n",
720f08c3bdfSopenharmony_ci						       mypid, getppid());
721f08c3bdfSopenharmony_ci					if (kill(getppid(), SIGUSR2) == -1) {
722f08c3bdfSopenharmony_ci						/* something went wrong */
723f08c3bdfSopenharmony_ci						printf("%d: kill(ppid:%d, "
724f08c3bdfSopenharmony_ci						       "SIGUSR2) failed. %d: %s",
725f08c3bdfSopenharmony_ci						       mypid, getppid(), errno,
726f08c3bdfSopenharmony_ci						       strerror(errno));
727f08c3bdfSopenharmony_ci						exit(errno);
728f08c3bdfSopenharmony_ci					}
729f08c3bdfSopenharmony_ci					usleep(100);
730f08c3bdfSopenharmony_ci				}
731f08c3bdfSopenharmony_ci			}
732f08c3bdfSopenharmony_ci			break;
733f08c3bdfSopenharmony_ci		default:
734f08c3bdfSopenharmony_ci			child_checklist[child_checklist_total++].pid = child;
735f08c3bdfSopenharmony_ci		}
736f08c3bdfSopenharmony_ci		procs_left--;
737f08c3bdfSopenharmony_ci	}
738f08c3bdfSopenharmony_ci	qsort(child_checklist, child_checklist_total, sizeof(*child_checklist),
739f08c3bdfSopenharmony_ci	      checklist_cmp);
740f08c3bdfSopenharmony_ci}
741f08c3bdfSopenharmony_ci
742f08c3bdfSopenharmony_ciint checklist_cmp(const void *a, const void *b)
743f08c3bdfSopenharmony_ci{
744f08c3bdfSopenharmony_ci	const struct pid_list_item *pa = (const struct pid_list_item *)a;
745f08c3bdfSopenharmony_ci	const struct pid_list_item *pb = (const struct pid_list_item *)b;
746f08c3bdfSopenharmony_ci
747f08c3bdfSopenharmony_ci	return (pa->pid > pb->pid) - (pa->pid < pb->pid);
748f08c3bdfSopenharmony_ci}
749f08c3bdfSopenharmony_ci
750f08c3bdfSopenharmony_civoid checklist_reset(int bit)
751f08c3bdfSopenharmony_ci{
752f08c3bdfSopenharmony_ci	int i;
753f08c3bdfSopenharmony_ci	for (i = 0; i < child_checklist_total; i++) {
754f08c3bdfSopenharmony_ci		child_checklist[i].flag = child_checklist[i].flag & (~bit);
755f08c3bdfSopenharmony_ci	}
756f08c3bdfSopenharmony_ci
757f08c3bdfSopenharmony_ci}
758f08c3bdfSopenharmony_ci
759f08c3bdfSopenharmony_cistatic inline int k_sigaction(int sig, struct sigaction *sa, struct sigaction *osa)
760f08c3bdfSopenharmony_ci{
761f08c3bdfSopenharmony_ci	int ret;
762f08c3bdfSopenharmony_ci	if ((ret = sigaction(sig, sa, osa)) == -1) {
763f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, cleanup, "sigaction(%d, ...) failed",
764f08c3bdfSopenharmony_ci			 sig);
765f08c3bdfSopenharmony_ci	}
766f08c3bdfSopenharmony_ci	return ret;
767f08c3bdfSopenharmony_ci}
768