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