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: kill02.c,v 1.10 2009/08/28 13:20:15 vapier Exp $ */
     34 /***********************************************************************************
     35 
     36     OS Test -  Silicon Graphics, Inc.
     37 
     38     TEST IDENTIFIER :  kill02  Sending a signal to processes with the same process group ID.
     39 
     40     PARENT DOCUMENT :  kiltds01  Kill System Call.
     41 
     42     AUTHOR          :  Dave Baumgartner
     43 
     44     CO-PILOT        :  Barrie Kletscher
     45 
     46     DATE STARTED    :  12/30/85
     47 
     48     TEST ITEMS
     49 
     50 	1. Sending a signal to pid of zero sends to all processes whose process
     51 	   group ID is equal to the process group ID as the sender.
     52 
     53 	2. Sending a signal to pid of zero does not send to processes in another process group.
     54 
     55     OUTPUT SPECIFICATIONS
     56 
     57 	PASS :
     58 		kiltcs02 1 PASS The signal was sent to all processes in the process group.
     59 		kiltcs02 2 PASS The signal was not sent to selective processes that were not in the process group.
     60 
     61 	FAIL :
     62 		kiltcs02 1 FAIL The signal was not sent to all processes in the process group.
     63 		kiltcs02 2 FAIL The signal was sent to a process that was not in the process group.
     64 
     65 	BROK :
     66 		kiltcs02 # BROK System call XXX failed. Errno:X, Error message:XXX.
     67 		kiltcs02 # BROK Setting to catch unexpected signal %d failed. Errno: %d, Error message %s.
     68 		kiltcs02 # BROK Setting to ignore signal %d failed. Errno: %d, Error message %s.
     69 
     70 	WARN :
     71 		kiltcs02 0 WARN Unexpected signal X was caught.
     72 
     73     SPECIAL PROCEDURAL REQUIREMENTS
     74 
     75 	The program must be linked with tst_res.o.
     76 
     77     DETAILED DESCRIPTION
     78 
     79 	**Setup**
     80 	Set up unexpected signal handling.
     81 	Set up one pipe for each process to be created with no blocking for read.
     82 
     83 	**MAIN**
     84 	If setup fails exit.
     85 	Fork 2 children(1 & 2).
     86 	Wait for set up complete messages from the 1st and 2nd child.
     87 	Send the signal SIGUSR1 with pid equal to zero.
     88 	Sleep a reasonable amount of time so that each child has been swapped in
     89 	to process the signal.
     90 	Now decide the outcome of the test items by reading from each pipe to find
     91 	out if the child was interrupted by the signal and wrote to it.
     92 	Remove the second child.
     93 	Tell the first child it is time to remove it's child B because the decisions have been made.
     94 	Exit.
     95 
     96 	**First Child**
     97 	Set to catch SIGUSR1 with an int_rout1.
     98 	Set up to handle the message from the parent to remove child B.
     99 	Fork two children(A & B).
    100 	Wait for set up complete messages from child A & child B.
    101 	Send a set up complete message to the parent.
    102 	Pause until the signal SIGUSR1 comes in from the parent.
    103 	Pause until the parent says it is time to remove the child.
    104 	Exit.
    105 
    106 	**Second Child**
    107 	Set to catch SIGUSR1 with an int_rout2.
    108 	Set the process group to be something different than the parents.
    109 	Send a set up complete message to the parent.
    110 	Pause until killed by parent because this child shouldn't receive signal SIGUSR1.
    111 
    112 	**Child A**
    113 	Set to catch SIGUSR1 with an int_routA.
    114 	Send a set up complete message to the parent(First Child).
    115 	Pause until the signal SIGUSR1 comes in from the parent.
    116 	Exit.
    117 
    118 	**Child B**
    119 	Set to catch SIGUSR1 with an int_routB.
    120 	Set the process group to be something different than the parents(First Child's).
    121 	Send a set up complete message to the parent.
    122 	Pause until killed by parent because this child shouldn't receive signal SIGUSR1.
    123 
    124 	**usr1_rout-Used by all children**
    125 	Write to the appropriate pipe that the signal SIGUSR1 was caught.
    126 
    127 	**usr2_rout**
    128 	Remove child B.
    129 
    130 ******************************************************************************/
    131 #include <sys/param.h>
    132 #include <sys/wait.h>
    133 #include <errno.h>
    134 #include <fcntl.h>
    135 #include <signal.h>
    136 #include <string.h>
    137 #include <stdlib.h>
    138 #include "test.h"
    139 
    140 #define CHAR_SET_FAILED	"0"	/*Set up failing status transferred through the pipe.   */
    141 #define CHAR_SET_PASSED	"1"	/*Set up passing status transferred through the pipe.   */
    142 #define SIG_CAUGHT	"2"	/*Indicates that the signal SIGUSR1 was caught.         */
    143 #define SIG_RECEIVED	1	/*Integer value that indicates that the signal SIGUSR1  */
    144 				/*was caught.                                           */
    145 #define SIG_NOT_RECD	0	/*Integer value that indicates that the signal SIGUSR1  */
    146 				/*was caught.                                           */
    147 #define INT_SET_FAILED	0	/*Set up failing status transferred through the pipe.   */
    148 #define INT_SET_PASSED	1	/*Set up passing status transferred through the pipe.   */
    149 #define SLEEP_TIME	10	/*Amount of time the children get to catch the signal   */
    150 #define TRUE	 	40	/*Child exits with this if execution was as     */
    151 				/*expected.                                             */
    152 #define FALSE	 	50	/*Child exits with this if it timed out waiting for the         */
    153 				/*parents signal.                                       */
    154 #define TIMEOUT		60	/*Amount of time given in alarm calls.                  */
    155 #define CHILD_EXIT(VAR) ((VAR >> 8) & 0377)	/*Exit value from the child.               */
    156 #define CHILD_SIG(VAR) (VAR & 0377)	/*Signal value from the termination of child.       */
    157 				/*from the parent.                                      */
    158 
    159 int pid1;			/*Return value from 1st fork. Global so that it can be  */
    160 				/*used in interrupt handling routines.                  */
    161 int pid2;			/*Return value from 2nd fork. Global so that it can be  */
    162 				/*used in interrupt handling routines.                  */
    163 int pidA;			/*Return value from 1st fork in child 1. Global so that it      */
    164 				/*can be used in interrupt handling routines.           */
    165 int pidB;			/*Return value from 2nd fork in child 1. Global so that it      */
    166 				/*can be used in interrupt handling routines.           */
    167 int pipe1_fd[2];		/*Pipe file descriptors used for communication          */
    168 				/*between child 1 and the 1st parent.                   */
    169 int pipe2_fd[2];		/*Pipe file descriptors used for communication          */
    170 				/*between child 2 and the 1st parent.                   */
    171 int pipeA_fd[2];		/*Pipe file descriptors used for communication          */
    172 				/*between child A and the 1st parent.                   */
    173 int pipeB_fd[2];		/*Pipe file descriptors used for communication          */
    174 				/*between child B and the 1st parent.                   */
    175 char pipe_buf[10];		/*Pipe buffer.                                          */
    176 char buf_tmp1[2], buf_tmp2[2];	/*Temp hold for info read into pipe_buf.                */
    177 int read1_stat = 0;		/*Number of characters read from pipe 1.                */
    178 int read2_stat = 0;		/*Number of characters read from pipe 2.                */
    179 int readA_stat = 0;		/*Number of characters read from pipe A.                */
    180 int readB_stat = 0;		/*Number of characters read from pipe B.                */
    181 int alarm_flag = FALSE;		/*This flag indicates an alarm time out.                        */
    182 char who_am_i = '0';		/*This indicates which process is which when using      */
    183 				/*interrupt routine usr1_rout.                          */
    184 
    185 void notify_timeout();		/*Signal handler that the parent enters if it times out */
    186 				/*waiting for the child to indicate its set up status.  */
    187 void parent_rout();		/*This is the parents routine.                          */
    188 void child1_rout();		/*This is child 1's routine.                            */
    189 void child2_rout();		/*This is child 2's routine.                            */
    190 void childA_rout();		/*This is child A's routine.                            */
    191 void childB_rout();		/*This is child B's routine.                            */
    192 void usr1_rout();		/*This routine is used by all children to indicate that */
    193 				/*they have caught signal SIGUSR1.                      */
    194 void par_kill();		/*This routine is called by the original parent to      */
    195 				/*remove child 2 and to indicate to child 1 to          */
    196 				/*remove its children.                                  */
    197 void chld1_kill();		/*This routine is used by child 1 to remove itself and  */
    198 				/*its children A and B.                                 */
    199 
    200 void setup();
    201 void cleanup();
    202 
    203 char *TCID = "kill02";
    204 int TST_TOTAL = 2;
    205 
    206 #ifdef UCLINUX
    207 static char *argv0;
    208 void childA_rout_uclinux();
    209 void childB_rout_uclinux();
    210 #endif
    211 
    212 int main(int ac, char **av)
    213 {
    214 	int lc;
    215 
    216 	tst_parse_opts(ac, av, NULL, NULL);
    217 
    218 #ifdef UCLINUX
    219 	argv0 = av[0];
    220 
    221 	maybe_run_child(&childA_rout_uclinux, "nd", 1, &pipeA_fd[1]);
    222 	maybe_run_child(&childB_rout_uclinux, "nd", 2, &pipeB_fd[1]);
    223 	maybe_run_child(&child1_rout, "ndddddd", 3, &pipe1_fd[1], &pipe2_fd[1],
    224 			&pipeA_fd[0], &pipeA_fd[1], &pipeB_fd[0], &pipeB_fd[1]);
    225 	maybe_run_child(&child2_rout, "nd", 4, &pipe2_fd[1]);
    226 #endif
    227 
    228 	setup();
    229 
    230 	for (lc = 0; TEST_LOOPING(lc); lc++) {
    231 
    232 		tst_count = 0;
    233 
    234 		if ((pid1 = FORK_OR_VFORK()) > 0) {
    235 			if ((pid2 = FORK_OR_VFORK()) > 0) {
    236 				(void)parent_rout();
    237 			} else if (pid2 == 0) {
    238 #ifdef UCLINUX
    239 				if (self_exec(argv0, "nd", 4, pipe2_fd[1]) < 0) {
    240 					if (kill(pid1, SIGKILL) == -1
    241 					    && errno != ESRCH) {
    242 						tst_resm(TWARN,
    243 							 "Child process may not have been killed.");
    244 					}
    245 					tst_brkm(TBROK | TERRNO, cleanup,
    246 						 "fork failed");
    247 				}
    248 #else
    249 				(void)child2_rout();
    250 #endif
    251 			} else {
    252 				/*
    253 				 *  The second fork failed kill the first child.
    254 				 */
    255 				if (kill(pid1, SIGKILL) == -1 && errno != ESRCH) {
    256 					tst_resm(TWARN,
    257 						 "Child process may not have been killed.");
    258 				}
    259 				tst_brkm(TBROK | TERRNO, cleanup,
    260 					 "fork failed");
    261 			}
    262 
    263 		} else if (pid1 == 0) {
    264 			/*
    265 			 *  This is child 1.
    266 			 */
    267 #ifdef UCLINUX
    268 			if (self_exec
    269 			    (argv0, "ndddddd", 3, pipe1_fd[1], pipe2_fd[1],
    270 			     pipeA_fd[0], pipeA_fd[1], pipeB_fd[0],
    271 			     pipeB_fd[1]) < 0) {
    272 				tst_brkm(TBROK | TERRNO, cleanup,
    273 					 "self_exec() failed");
    274 			}
    275 #else
    276 			(void)child1_rout();
    277 #endif
    278 		} else {
    279 			/*
    280 			 * Fork failed.
    281 			 */
    282 			tst_brkm(TBROK | TERRNO, cleanup, "fork failed");
    283 		}
    284 	}
    285 
    286 	cleanup();
    287 	tst_exit();
    288 }				/* END OF MAIN. */
    289 
    290 /******************************************************************************
    291  *  This is the parents routine.  The parent waits for the children 1 and 2 to
    292  *  get set up. Then sends the signal and checks the outcome.
    293  *********************************************************************************/
    294 void parent_rout(void)
    295 {
    296 	/*
    297 	 *  Set to catch the alarm signal SIGALRM.
    298 	 */
    299 	if (signal(SIGALRM, notify_timeout) == SIG_ERR) {
    300 		(void)par_kill();
    301 		tst_brkm(TBROK, NULL,
    302 			 "Could not set to catch the parents time out alarm.");
    303 	}
    304 
    305 	/*
    306 	 *  Setting to catch the timeout alarm worked now let the children start up.
    307 	 *  Set an alarm which causes a time out on the read pipe loop.
    308 	 *  The children will notify the parent that set up is complete
    309 	 *  and the pass/fail status of set up.
    310 	 */
    311 	(void)alarm(TIMEOUT);
    312 
    313 	while ((read(pipe1_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
    314 		/*EMPTY*/;
    315 	strncpy(buf_tmp1, pipe_buf, 1);
    316 	(void)alarm(TIMEOUT);
    317 
    318 	while ((read(pipe2_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
    319 		/*EMPTY*/;
    320 	(void)alarm(0);		/*Reset the alarm clock. */
    321 	strncpy(buf_tmp2, pipe_buf, 1);
    322 
    323 	/*
    324 	 *  Check the alarm flag.
    325 	 */
    326 	if (alarm_flag == TRUE) {
    327 		tst_brkm(TBROK, NULL,
    328 			 "The set up of the children failed by timing out.");
    329 		(void)par_kill();
    330 		cleanup();
    331 	}
    332 
    333 	/*
    334 	 *  Check to see if either child failed in the set up.
    335 	 */
    336 	if ((strncmp(buf_tmp1, CHAR_SET_FAILED, 1) == 0) ||
    337 	    (strncmp(buf_tmp2, CHAR_SET_FAILED, 1) == 0)) {
    338 		/*
    339 		 * Problems were encountered in the set up of one of the children.
    340 		 * The error message has been displayed by the child.
    341 		 */
    342 		(void)par_kill();
    343 		cleanup();
    344 	}
    345 
    346 	/*
    347 	 *  Setup passed, now send SIGUSR1 to process id of zero.
    348 	 */
    349 	TEST(kill(0, SIGUSR1));
    350 
    351 	if (TEST_RETURN == -1) {
    352 		tst_brkm(TBROK | TERRNO, NULL, "kill() failed");
    353 		(void)par_kill();
    354 		cleanup();
    355 	}
    356 
    357 	/*
    358 	 *  Sleep for a while to allow the children to get a chance to
    359 	 *  catch the signal.
    360 	 */
    361 	(void)sleep(SLEEP_TIME);
    362 
    363 	/*
    364 	 *  The signal was sent above and time has run out for child response,
    365 	 *  check the outcomes.
    366 	 */
    367 	read1_stat = read(pipe1_fd[0], pipe_buf, 1);
    368 	if (read1_stat == -1 && errno == EAGAIN)
    369 		read1_stat = 0;
    370 	read2_stat = read(pipe2_fd[0], pipe_buf, 1);
    371 	if (read2_stat == -1 && errno == EAGAIN)
    372 		read2_stat = 0;
    373 	readA_stat = read(pipeA_fd[0], pipe_buf, 1);
    374 	if (readA_stat == -1 && errno == EAGAIN)
    375 		readA_stat = 0;
    376 	readB_stat = read(pipeB_fd[0], pipe_buf, 1);
    377 	if (readB_stat == -1 && errno == EAGAIN)
    378 		readB_stat = 0;
    379 
    380 	if (read1_stat == -1 || read2_stat == -1 ||
    381 	    readA_stat == -1 || readB_stat == -1) {
    382 		/*
    383 		 * The read system call failed.
    384 		 */
    385 		tst_brkm(TBROK | TERRNO, NULL, "read() failed");
    386 		(void)par_kill();
    387 		cleanup();
    388 	}
    389 
    390 	/*
    391 	 * Check the processes that were supposed to get the signal.
    392 	 */
    393 	if (read1_stat == SIG_RECEIVED) {
    394 		if (readA_stat == SIG_RECEIVED) {
    395 			/*
    396 			 *  Both processes, 1 and A, that were supposed to receive
    397 			 *  the signal did receive the signal.
    398 			 */
    399 			tst_resm(TPASS,
    400 				 "The signal was sent to all processes in the process group.");
    401 		} else {	/*Process A didn't receive the signal. */
    402 			tst_resm(TFAIL,
    403 				 "Process A did not receive the signal.");
    404 		}
    405 
    406 	} else {		/*Process 1 didn't receive the signal. */
    407 		tst_resm(TFAIL, "Process 1 did not receive the signal.");
    408 	}
    409 
    410 	/*
    411 	 * Check the processes that were not supposed to get the signal.
    412 	 */
    413 	if (read2_stat == SIG_NOT_RECD) {
    414 		if (readB_stat == SIG_NOT_RECD) {
    415 			/*
    416 			 *  Both processes, 2 and B did not receive the signal.
    417 			 */
    418 			tst_resm(TPASS,
    419 				 "The signal was not sent to selective processes that were not in the process group.");
    420 		} else {	/*Process B received the signal. */
    421 			tst_resm(TFAIL, "Process B received the signal.");
    422 		}
    423 
    424 	}
    425 
    426 	else {			/*Process 2 received the signal. */
    427 
    428 		tst_resm(TFAIL, "Process 2 received the signal.");
    429 	}
    430 
    431 	(void)par_kill();
    432 
    433 	(void)alarm(TIMEOUT);
    434 	while ((read(pipe1_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
    435 		strncpy(buf_tmp1, pipe_buf, 1);
    436 
    437 }				/*End of parent_rout */
    438 
    439 void child1_rout(void)
    440 {
    441 	who_am_i = '1';
    442 
    443 	/*
    444 	 *  Set to catch the SIGUSR1 with int1_rout.
    445 	 */
    446 	if (signal(SIGUSR1, usr1_rout) == SIG_ERR) {
    447 		tst_brkm(TBROK, NULL,
    448 			 "Could not set to catch the childrens signal.");
    449 		(void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
    450 		exit(0);
    451 	}
    452 	/*
    453 	 *  Create children A & B.
    454 	 */
    455 	if ((pidA = FORK_OR_VFORK()) > 0) {
    456 		/*
    457 		 *  This is the parent(child1), fork again to create child B.
    458 		 */
    459 		if ((pidB = FORK_OR_VFORK()) == 0) {
    460 			/* This is child B. */
    461 #ifdef UCLINUX
    462 			if (self_exec(argv0, "nd", 2, pipeB_fd[1]) < 0) {
    463 				tst_brkm(TBROK | TERRNO, NULL,
    464 					 "self_exec() failed");
    465 				(void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
    466 				exit(0);
    467 			}
    468 #else
    469 			(void)childB_rout();
    470 #endif
    471 		}
    472 
    473 		else if (pidB == -1) {
    474 			/*
    475 			 *  The fork of child B failed kill child A.
    476 			 */
    477 			if (kill(pidA, SIGKILL) == -1)
    478 				tst_resm(TWARN,
    479 					 "Child process may not have been killed.");
    480 			tst_brkm(TBROK | TERRNO, NULL, "fork failed");
    481 			(void)write(pipe2_fd[1], CHAR_SET_FAILED, 1);
    482 			exit(0);
    483 		}
    484 	}
    485 
    486 	else if (pidA == 0) {
    487 		/* This is child A. */
    488 #ifdef UCLINUX
    489 		if (self_exec(argv0, "nd", 1, pipeA_fd[1]) < 0) {
    490 			tst_brkm(TBROK | TERRNO, NULL, "self_exec() failed");
    491 			(void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
    492 			exit(0);
    493 		}
    494 #else
    495 		(void)childA_rout();
    496 #endif
    497 
    498 	}
    499 
    500 	else if (pidA == -1) {
    501 		/*
    502 		 *  The fork of child A failed.
    503 		 */
    504 		tst_brkm(TBROK | TERRNO, NULL, "fork failed");
    505 		(void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
    506 		exit(0);
    507 	}
    508 
    509 	/*
    510 	 *  Set to catch the SIGUSR2 with chld1_kill.
    511 	 */
    512 	if (signal(SIGUSR2, chld1_kill) == SIG_ERR) {
    513 		tst_brkm(TBROK, NULL,
    514 			 "Could not set to catch the parents signal.");
    515 		(void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
    516 		(void)chld1_kill();
    517 		exit(0);
    518 	}
    519 
    520 	/*
    521 	 *  Set to catch the alarm signal SIGALRM.
    522 	 */
    523 	if (signal(SIGALRM, notify_timeout) == SIG_ERR) {
    524 		tst_brkm(TBROK, NULL,
    525 			 "Could not set to catch the childs time out alarm.");
    526 		(void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
    527 		(void)chld1_kill();
    528 		exit(0);
    529 	}
    530 
    531 	/*
    532 	 *  Setting to catch the signals worked now let the children start up.
    533 	 *  Set an alarm which causes a time out on the pipe read loop.
    534 	 *  The children A & B will notify the parent(child1) that set up is complete
    535 	 *  and the pass/fail status of set up.
    536 	 */
    537 	(void)alarm(TIMEOUT - 40);
    538 
    539 	while ((read(pipeA_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
    540 		/*EMPTY*/;
    541 	(void)alarm(TIMEOUT - 40);
    542 
    543 	while ((read(pipeB_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
    544 		/*EMPTY*/;
    545 	(void)alarm(0);		/*Reset the alarm clock. */
    546 
    547 	/*
    548 	 *  Check the alarm flag.
    549 	 */
    550 	if (alarm_flag == TRUE) {
    551 		tst_brkm(TBROK, NULL,
    552 			 "The set up of the children failed by timing out.");
    553 		(void)chld1_kill();
    554 		(void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
    555 		exit(0);
    556 	}
    557 
    558 	/*
    559 	 *  Send a set up complete message to the parent.
    560 	 */
    561 	(void)write(pipe1_fd[1], CHAR_SET_PASSED, 1);
    562 
    563 	/*
    564 	 *  Pause until the signal SIGUSR1 or SIGUSR2 is sent from the parent.
    565 	 */
    566 	(void)pause();
    567 
    568 	/*
    569 	 *  Pause until signal SIGUSR2 is sent from the parent.
    570 	 *  This pause will only be executed if SIGUSR2 has not been received yet.
    571 	 */
    572 	while (1) {
    573 		sleep(1);
    574 	}
    575 
    576 }				/*End of child1_rout */
    577 
    578 /*******************************************************************************
    579  *  This is the routine for child 2, which should not receive the parents signal.
    580  ******************************************************************************/
    581 void child2_rout(void)
    582 {
    583 	who_am_i = '2';
    584 
    585 	/*
    586 	 * Set the process group of this process to be different
    587 	 * than the other processes.
    588 	 */
    589 	(void)setpgrp();
    590 
    591 	/*
    592 	 *  Set to catch the SIGUSR1 with usr1_rout.
    593 	 */
    594 	if (signal(SIGUSR1, usr1_rout) == SIG_ERR) {
    595 		tst_brkm(TBROK, cleanup,
    596 			 "Could not set to catch the parents signal.");
    597 		(void)write(pipe2_fd[1], CHAR_SET_FAILED, 1);
    598 		exit(0);
    599 	}
    600 
    601 	/* Send a set up complete message to parent. */
    602 	(void)write(pipe2_fd[1], CHAR_SET_PASSED, 1);
    603 
    604 	/*
    605 	 *  Pause until killed by the parent or SIGUSR1 is received.
    606 	 */
    607 	(void)pause();
    608 }
    609 
    610 /*******************************************************************************
    611  *  This is the routine for child A, which should receive the parents signal.
    612  ******************************************************************************/
    613 void childA_rout(void)
    614 {
    615 	who_am_i = 'A';
    616 
    617 	/* Send a set up complete message to parent. */
    618 	write(pipeA_fd[1], CHAR_SET_PASSED, 1);
    619 
    620 	/*
    621 	 *  Pause until killed by the parent or SIGUSR1 is received.
    622 	 */
    623 	(void)pause();
    624 
    625 	exit(0);
    626 }				/*End of childA_rout */
    627 
    628 #ifdef UCLINUX
    629 /*******************************************************************************
    630  *  This is the routine for child A after self_exec
    631  ******************************************************************************/
    632 void childA_rout_uclinux(void)
    633 {
    634 	/* Setup the signal handler again */
    635 	if (signal(SIGUSR1, usr1_rout) == SIG_ERR) {
    636 		tst_brkm(TBROK, NULL,
    637 			 "Could not set to catch the childrens signal.");
    638 		(void)write(pipeA_fd[1], CHAR_SET_FAILED, 1);
    639 		exit(0);
    640 	}
    641 
    642 	childA_rout();
    643 }
    644 #endif
    645 
    646 /*******************************************************************************
    647  *  This is the routine for child B, which should not receive the parents signal.
    648  ******************************************************************************/
    649 void childB_rout(void)
    650 {
    651 	who_am_i = 'B';
    652 
    653 	/*
    654 	 * Set the process group of this process to be different
    655 	 * than the other processes.
    656 	 */
    657 	(void)setpgrp();
    658 
    659 	/* Send a set up complete message to parent(child 1). */
    660 	write(pipeB_fd[1], CHAR_SET_PASSED, 1);
    661 
    662 	/*
    663 	 *  Pause until killed by the parent(child 1) or SIGUSR1 is received.
    664 	 */
    665 	(void)pause();
    666 
    667 	exit(0);
    668 }
    669 
    670 #ifdef UCLINUX
    671 /*******************************************************************************
    672  *  This is the routine for child B after self_exec
    673  ******************************************************************************/
    674 void childB_rout_uclinux(void)
    675 {
    676 	/* Setup the signal handler again */
    677 	if (signal(SIGUSR1, usr1_rout) == SIG_ERR) {
    678 		tst_brkm(TBROK, NULL,
    679 			 "Could not set to catch the childrens signal.");
    680 		(void)write(pipeB_fd[1], CHAR_SET_FAILED, 1);
    681 		exit(0);
    682 	}
    683 
    684 	childB_rout();
    685 }
    686 #endif
    687 
    688 /*******************************************************************************
    689  *  This routine sets up the interprocess communication pipes, signal handling,
    690  *  and process group information.
    691  ******************************************************************************/
    692 void setup(void)
    693 {
    694 	int errno_buf;		/*indicates the errno if pipe set up fails.             */
    695 	int err_flag = FALSE;	/*Indicates if an error has occurred in pipe set up.    */
    696 
    697 	/*
    698 	 *  Set the process group ID to be equal between the parent and children.
    699 	 */
    700 	(void)setpgrp();
    701 
    702 	/*
    703 	 *  Set to catch unexpected signals.
    704 	 *  SIGCHLD is set to be ignored because we do not wait for termination status.
    705 	 *  SIGUSR1 is set to be ignored because this is the signal we are using for
    706 	 *  the test and we are not concerned with the parent getting it.
    707 	 */
    708 
    709 	tst_sig(FORK, DEF_HANDLER, cleanup);
    710 
    711 	if (signal(SIGUSR1, SIG_IGN) == SIG_ERR) {
    712 		tst_brkm(TBROK | TFAIL, NULL,
    713 			 "signal(SIGUSR1, SIG_IGN) failed");
    714 	}
    715 
    716 	if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
    717 		tst_brkm(TBROK | TERRNO, NULL,
    718 			 "signal(SIGCHLD, SIG_IGN) failed");
    719 	}
    720 
    721 	TEST_PAUSE;
    722 
    723 	/*
    724 	 *  Set up pipe1, pipe2, pipeA, and pipeB.
    725 	 */
    726 	if ((pipe(pipe1_fd) == -1)
    727 	    || (fcntl(pipe1_fd[0], F_SETFL, O_NDELAY) == -1)) {
    728 		errno_buf = errno;
    729 		err_flag = TRUE;
    730 	}
    731 
    732 	if ((pipe(pipe2_fd) == -1)
    733 	    || (fcntl(pipe2_fd[0], F_SETFL, O_NDELAY) == -1)) {
    734 		errno_buf = errno;
    735 		err_flag = TRUE;
    736 	}
    737 
    738 	if ((pipe(pipeA_fd) == -1)
    739 	    || (fcntl(pipeA_fd[0], F_SETFL, O_NDELAY) == -1)) {
    740 		errno_buf = errno;
    741 		err_flag = TRUE;
    742 	}
    743 
    744 	if ((pipe(pipeB_fd) == -1)
    745 	    || (fcntl(pipeB_fd[0], F_SETFL, O_NDELAY) == -1)) {
    746 		errno_buf = errno;
    747 		err_flag = TRUE;
    748 	}
    749 
    750 	/*
    751 	 *  Check for errors.
    752 	 */
    753 	if (err_flag == TRUE) {
    754 		tst_brkm(TBROK | TERRNO, NULL, "pipe() failed");
    755 	}
    756 	return;
    757 
    758 }
    759 
    760 /***********************************************************
    761  *  This routine indicates that the process caught SIGUSR1.
    762  **********************************************************/
    763 void usr1_rout(void)
    764 {
    765 	switch (who_am_i) {
    766 	case '1':
    767 		if (write(pipe1_fd[1], SIG_CAUGHT, 1) == -1)
    768 			tst_resm(TWARN,
    769 				 "Writing signal catching status failed in child 1.");
    770 		break;
    771 	case '2':
    772 		if (write(pipe2_fd[1], SIG_CAUGHT, 1) == -1)
    773 			tst_resm(TWARN,
    774 				 "Writing signal catching status failed in child 2.");
    775 		break;
    776 	case 'A':
    777 		if (write(pipeA_fd[1], SIG_CAUGHT, 1) == -1)
    778 			tst_resm(TWARN,
    779 				 "Writing signal catching status failed in child A.");
    780 		break;
    781 	case 'B':
    782 		if (write(pipeB_fd[1], SIG_CAUGHT, 1) == -1)
    783 			tst_resm(TWARN,
    784 				 "Writing signal catching status failed in child B.");
    785 		break;
    786 	default:
    787 		tst_resm(TWARN,
    788 			 "Unexpected value %d for who_am_i in usr1_rout()",
    789 			 who_am_i);
    790 		break;
    791 	}
    792 
    793 }				/*End of usr1_rout */
    794 
    795 /***********************************************************
    796  *  This routine handles the timeout alarm in the parent,
    797  *  which occurs when the child fails to notify the parent
    798  *  the status of set up.
    799  **********************************************************/
    800 void notify_timeout(void)
    801 {
    802 	alarm_flag = TRUE;
    803 
    804 }				/*End of notify_timeout */
    805 
    806 /***********************************************************
    807  *  This routine handles the procedure for removing the
    808  *  children forked off during this test.
    809  **********************************************************/
    810 void par_kill(void)
    811 {
    812 	int status;
    813 
    814 	/*
    815 	 *  Indicate to child1 that it can remove it's children and itself now.
    816 	 */
    817 	if (kill(pid1, SIGUSR2) == -1 && errno != ESRCH) {
    818 		tst_resm(TWARN | TERRNO, "kill() failed");
    819 		tst_resm(TWARN,
    820 			 "Child 1 and it's children may still be alive.");
    821 	}
    822 
    823 	/*
    824 	 *  Remove child 2.
    825 	 */
    826 	if (kill(pid2, SIGKILL) == -1 && errno != ESRCH)
    827 		tst_resm(TWARN, "Child2 may still be alive.");
    828 
    829 	wait(&status);
    830 	return;
    831 
    832 }				/*End of par_kill */
    833 
    834 /*********************************************************************
    835  *  This routine is executed by child 1 when the parent tells it to
    836  *  remove it's children and itself.
    837  ********************************************************************/
    838 void chld1_kill(void)
    839 {
    840 	/*
    841 	 *  Remove children A & B.
    842 	 */
    843 	if (kill(pidA, SIGKILL) == -1 && errno != ESRCH)
    844 		tst_resm(TWARN | TERRNO,
    845 			 "kill(%d) failed; child 1's(A) child may still be alive",
    846 			 pidA);
    847 
    848 	(void)write(pipe1_fd[1], CHAR_SET_PASSED, 1);
    849 
    850 	if (kill(pidB, SIGKILL) == -1 && errno != ESRCH)
    851 		tst_resm(TWARN | TERRNO,
    852 			 "kill(%d) failed; child 1's(B) child may still be alive",
    853 			 pidB);
    854 
    855 	exit(0);
    856 
    857 }				/*End of chld1_kill */
    858 
    859 /***************************************************************
    860  * cleanup() - performs all ONE TIME cleanup for this test at
    861  *              completion or premature exit.
    862  ***************************************************************/
    863 void cleanup(void)
    864 {
    865 
    866 }
    867