xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/kill/kill02.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
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 
main(int ac,char ** av)206 int main(int ac, char **av)
207 {
208 	int lc;
209 
210 	tst_parse_opts(ac, av, NULL, NULL);
211 
212 	setup();
213 
214 	for (lc = 0; TEST_LOOPING(lc); lc++) {
215 
216 		tst_count = 0;
217 
218 		if ((pid1 = tst_fork()) > 0) {
219 			if ((pid2 = tst_fork()) > 0) {
220 				(void)parent_rout();
221 			} else if (pid2 == 0) {
222 				(void)child2_rout();
223 			} else {
224 				/*
225 				 *  The second fork failed kill the first child.
226 				 */
227 				if (kill(pid1, SIGKILL) == -1 && errno != ESRCH) {
228 					tst_resm(TWARN,
229 						 "Child process may not have been killed.");
230 				}
231 				tst_brkm(TBROK | TERRNO, cleanup,
232 					 "fork failed");
233 			}
234 
235 		} else if (pid1 == 0) {
236 			/*
237 			 *  This is child 1.
238 			 */
239 			(void)child1_rout();
240 		} else {
241 			/*
242 			 * Fork failed.
243 			 */
244 			tst_brkm(TBROK | TERRNO, cleanup, "fork failed");
245 		}
246 	}
247 
248 	cleanup();
249 	tst_exit();
250 }				/* END OF MAIN. */
251 
252 /******************************************************************************
253  *  This is the parents routine.  The parent waits for the children 1 and 2 to
254  *  get set up. Then sends the signal and checks the outcome.
255  *********************************************************************************/
parent_rout(void)256 void parent_rout(void)
257 {
258 	/*
259 	 *  Set to catch the alarm signal SIGALRM.
260 	 */
261 	if (signal(SIGALRM, notify_timeout) == SIG_ERR) {
262 		(void)par_kill();
263 		tst_brkm(TBROK, NULL,
264 			 "Could not set to catch the parents time out alarm.");
265 	}
266 
267 	/*
268 	 *  Setting to catch the timeout alarm worked now let the children start up.
269 	 *  Set an alarm which causes a time out on the read pipe loop.
270 	 *  The children will notify the parent that set up is complete
271 	 *  and the pass/fail status of set up.
272 	 */
273 	(void)alarm(TIMEOUT);
274 
275 	while ((read(pipe1_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
276 		/*EMPTY*/;
277 	strncpy(buf_tmp1, pipe_buf, 1);
278 	(void)alarm(TIMEOUT);
279 
280 	while ((read(pipe2_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
281 		/*EMPTY*/;
282 	(void)alarm(0);		/*Reset the alarm clock. */
283 	strncpy(buf_tmp2, pipe_buf, 1);
284 
285 	/*
286 	 *  Check the alarm flag.
287 	 */
288 	if (alarm_flag == TRUE) {
289 		tst_brkm(TBROK, NULL,
290 			 "The set up of the children failed by timing out.");
291 		(void)par_kill();
292 		cleanup();
293 	}
294 
295 	/*
296 	 *  Check to see if either child failed in the set up.
297 	 */
298 	if ((strncmp(buf_tmp1, CHAR_SET_FAILED, 1) == 0) ||
299 	    (strncmp(buf_tmp2, CHAR_SET_FAILED, 1) == 0)) {
300 		/*
301 		 * Problems were encountered in the set up of one of the children.
302 		 * The error message has been displayed by the child.
303 		 */
304 		(void)par_kill();
305 		cleanup();
306 	}
307 
308 	/*
309 	 *  Setup passed, now send SIGUSR1 to process id of zero.
310 	 */
311 	TEST(kill(0, SIGUSR1));
312 
313 	if (TEST_RETURN == -1) {
314 		tst_brkm(TBROK | TTERRNO, NULL, "kill() failed");
315 		(void)par_kill();
316 		cleanup();
317 	}
318 
319 	/*
320 	 *  Sleep for a while to allow the children to get a chance to
321 	 *  catch the signal.
322 	 */
323 	(void)sleep(SLEEP_TIME);
324 
325 	/*
326 	 *  The signal was sent above and time has run out for child response,
327 	 *  check the outcomes.
328 	 */
329 	read1_stat = read(pipe1_fd[0], pipe_buf, 1);
330 	if (read1_stat == -1 && errno == EAGAIN)
331 		read1_stat = 0;
332 	read2_stat = read(pipe2_fd[0], pipe_buf, 1);
333 	if (read2_stat == -1 && errno == EAGAIN)
334 		read2_stat = 0;
335 	readA_stat = read(pipeA_fd[0], pipe_buf, 1);
336 	if (readA_stat == -1 && errno == EAGAIN)
337 		readA_stat = 0;
338 	readB_stat = read(pipeB_fd[0], pipe_buf, 1);
339 	if (readB_stat == -1 && errno == EAGAIN)
340 		readB_stat = 0;
341 
342 	if (read1_stat == -1 || read2_stat == -1 ||
343 	    readA_stat == -1 || readB_stat == -1) {
344 		/*
345 		 * The read system call failed.
346 		 */
347 		tst_brkm(TBROK | TERRNO, NULL, "read() failed");
348 		(void)par_kill();
349 		cleanup();
350 	}
351 
352 	/*
353 	 * Check the processes that were supposed to get the signal.
354 	 */
355 	if (read1_stat == SIG_RECEIVED) {
356 		if (readA_stat == SIG_RECEIVED) {
357 			/*
358 			 *  Both processes, 1 and A, that were supposed to receive
359 			 *  the signal did receive the signal.
360 			 */
361 			tst_resm(TPASS,
362 				 "The signal was sent to all processes in the process group.");
363 		} else {	/*Process A didn't receive the signal. */
364 			tst_resm(TFAIL,
365 				 "Process A did not receive the signal.");
366 		}
367 
368 	} else {		/*Process 1 didn't receive the signal. */
369 		tst_resm(TFAIL, "Process 1 did not receive the signal.");
370 	}
371 
372 	/*
373 	 * Check the processes that were not supposed to get the signal.
374 	 */
375 	if (read2_stat == SIG_NOT_RECD) {
376 		if (readB_stat == SIG_NOT_RECD) {
377 			/*
378 			 *  Both processes, 2 and B did not receive the signal.
379 			 */
380 			tst_resm(TPASS,
381 				 "The signal was not sent to selective processes that were not in the process group.");
382 		} else {	/*Process B received the signal. */
383 			tst_resm(TFAIL, "Process B received the signal.");
384 		}
385 
386 	}
387 
388 	else {			/*Process 2 received the signal. */
389 
390 		tst_resm(TFAIL, "Process 2 received the signal.");
391 	}
392 
393 	(void)par_kill();
394 
395 	(void)alarm(TIMEOUT);
396 	while ((read(pipe1_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
397 		strncpy(buf_tmp1, pipe_buf, 1);
398 
399 }				/*End of parent_rout */
400 
child1_rout(void)401 void child1_rout(void)
402 {
403 	who_am_i = '1';
404 
405 	/*
406 	 *  Set to catch the SIGUSR1 with int1_rout.
407 	 */
408 	if (signal(SIGUSR1, usr1_rout) == SIG_ERR) {
409 		tst_brkm(TBROK, NULL,
410 			 "Could not set to catch the childrens signal.");
411 		(void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
412 		exit(0);
413 	}
414 	/*
415 	 *  Create children A & B.
416 	 */
417 	if ((pidA = tst_fork()) > 0) {
418 		/*
419 		 *  This is the parent(child1), fork again to create child B.
420 		 */
421 
422 		if ((pidB = tst_fork()) == 0) {
423 			/* This is child B. */
424 			(void)childB_rout();
425 		}
426 
427 		else if (pidB == -1) {
428 			/*
429 			 *  The fork of child B failed kill child A.
430 			 */
431 			if (kill(pidA, SIGKILL) == -1)
432 				tst_resm(TWARN,
433 					 "Child process may not have been killed.");
434 			tst_brkm(TBROK | TERRNO, NULL, "fork failed");
435 			(void)write(pipe2_fd[1], CHAR_SET_FAILED, 1);
436 			exit(0);
437 		}
438 	}
439 
440 	else if (pidA == 0) {
441 		/* This is child A. */
442 		(void)childA_rout();
443 	}
444 
445 	else if (pidA == -1) {
446 		/*
447 		 *  The fork of child A failed.
448 		 */
449 		tst_brkm(TBROK | TERRNO, NULL, "fork failed");
450 		(void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
451 		exit(0);
452 	}
453 
454 	/*
455 	 *  Set to catch the SIGUSR2 with chld1_kill.
456 	 */
457 	if (signal(SIGUSR2, chld1_kill) == SIG_ERR) {
458 		tst_brkm(TBROK, NULL,
459 			 "Could not set to catch the parents signal.");
460 		(void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
461 		(void)chld1_kill();
462 		exit(0);
463 	}
464 
465 	/*
466 	 *  Set to catch the alarm signal SIGALRM.
467 	 */
468 	if (signal(SIGALRM, notify_timeout) == SIG_ERR) {
469 		tst_brkm(TBROK, NULL,
470 			 "Could not set to catch the childs time out alarm.");
471 		(void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
472 		(void)chld1_kill();
473 		exit(0);
474 	}
475 
476 	/*
477 	 *  Setting to catch the signals worked now let the children start up.
478 	 *  Set an alarm which causes a time out on the pipe read loop.
479 	 *  The children A & B will notify the parent(child1) that set up is complete
480 	 *  and the pass/fail status of set up.
481 	 */
482 	(void)alarm(TIMEOUT - 40);
483 
484 	while ((read(pipeA_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
485 		/*EMPTY*/;
486 	(void)alarm(TIMEOUT - 40);
487 
488 	while ((read(pipeB_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
489 		/*EMPTY*/;
490 	(void)alarm(0);		/*Reset the alarm clock. */
491 
492 	/*
493 	 *  Check the alarm flag.
494 	 */
495 	if (alarm_flag == TRUE) {
496 		tst_brkm(TBROK, NULL,
497 			 "The set up of the children failed by timing out.");
498 		(void)chld1_kill();
499 		(void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
500 		exit(0);
501 	}
502 
503 	/*
504 	 *  Send a set up complete message to the parent.
505 	 */
506 	(void)write(pipe1_fd[1], CHAR_SET_PASSED, 1);
507 
508 	/*
509 	 *  Pause until the signal SIGUSR1 or SIGUSR2 is sent from the parent.
510 	 */
511 	(void)pause();
512 
513 	/*
514 	 *  Pause until signal SIGUSR2 is sent from the parent.
515 	 *  This pause will only be executed if SIGUSR2 has not been received yet.
516 	 */
517 	while (1) {
518 		sleep(1);
519 	}
520 
521 }				/*End of child1_rout */
522 
523 /*******************************************************************************
524  *  This is the routine for child 2, which should not receive the parents signal.
525  ******************************************************************************/
child2_rout(void)526 void child2_rout(void)
527 {
528 	who_am_i = '2';
529 
530 	/*
531 	 * Set the process group of this process to be different
532 	 * than the other processes.
533 	 */
534 	(void)setpgrp();
535 
536 	/*
537 	 *  Set to catch the SIGUSR1 with usr1_rout.
538 	 */
539 	if (signal(SIGUSR1, usr1_rout) == SIG_ERR) {
540 		tst_brkm(TBROK, cleanup,
541 			 "Could not set to catch the parents signal.");
542 		(void)write(pipe2_fd[1], CHAR_SET_FAILED, 1);
543 		exit(0);
544 	}
545 
546 	/* Send a set up complete message to parent. */
547 	(void)write(pipe2_fd[1], CHAR_SET_PASSED, 1);
548 
549 	/*
550 	 *  Pause until killed by the parent or SIGUSR1 is received.
551 	 */
552 	(void)pause();
553 }
554 
555 /*******************************************************************************
556  *  This is the routine for child A, which should receive the parents signal.
557  ******************************************************************************/
childA_rout(void)558 void childA_rout(void)
559 {
560 	who_am_i = 'A';
561 
562 	/* Send a set up complete message to parent. */
563 	write(pipeA_fd[1], CHAR_SET_PASSED, 1);
564 
565 	/*
566 	 *  Pause until killed by the parent or SIGUSR1 is received.
567 	 */
568 	(void)pause();
569 
570 	exit(0);
571 }				/*End of childA_rout */
572 
573 /*******************************************************************************
574  *  This is the routine for child B, which should not receive the parents signal.
575  ******************************************************************************/
childB_rout(void)576 void childB_rout(void)
577 {
578 	who_am_i = 'B';
579 
580 	/*
581 	 * Set the process group of this process to be different
582 	 * than the other processes.
583 	 */
584 	(void)setpgrp();
585 
586 	/* Send a set up complete message to parent(child 1). */
587 	write(pipeB_fd[1], CHAR_SET_PASSED, 1);
588 
589 	/*
590 	 *  Pause until killed by the parent(child 1) or SIGUSR1 is received.
591 	 */
592 	(void)pause();
593 
594 	exit(0);
595 }
596 
597 /*******************************************************************************
598  *  This routine sets up the interprocess communication pipes, signal handling,
599  *  and process group information.
600  ******************************************************************************/
setup(void)601 void setup(void)
602 {
603 	int errno_buf;		/*indicates the errno if pipe set up fails.             */
604 	int err_flag = FALSE;	/*Indicates if an error has occurred in pipe set up.    */
605 
606 	/*
607 	 *  Set the process group ID to be equal between the parent and children.
608 	 */
609 	(void)setpgrp();
610 
611 	/*
612 	 *  Set to catch unexpected signals.
613 	 *  SIGCHLD is set to be ignored because we do not wait for termination status.
614 	 *  SIGUSR1 is set to be ignored because this is the signal we are using for
615 	 *  the test and we are not concerned with the parent getting it.
616 	 */
617 
618 	tst_sig(FORK, DEF_HANDLER, cleanup);
619 
620 	if (signal(SIGUSR1, SIG_IGN) == SIG_ERR) {
621 		tst_brkm(TBROK | TFAIL, NULL,
622 			 "signal(SIGUSR1, SIG_IGN) failed");
623 	}
624 
625 	if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
626 		tst_brkm(TBROK | TERRNO, NULL,
627 			 "signal(SIGCHLD, SIG_IGN) failed");
628 	}
629 
630 	TEST_PAUSE;
631 
632 	/*
633 	 *  Set up pipe1, pipe2, pipeA, and pipeB.
634 	 */
635 	if ((pipe(pipe1_fd) == -1)
636 	    || (fcntl(pipe1_fd[0], F_SETFL, O_NDELAY) == -1)) {
637 		errno_buf = errno;
638 		err_flag = TRUE;
639 	}
640 
641 	if ((pipe(pipe2_fd) == -1)
642 	    || (fcntl(pipe2_fd[0], F_SETFL, O_NDELAY) == -1)) {
643 		errno_buf = errno;
644 		err_flag = TRUE;
645 	}
646 
647 	if ((pipe(pipeA_fd) == -1)
648 	    || (fcntl(pipeA_fd[0], F_SETFL, O_NDELAY) == -1)) {
649 		errno_buf = errno;
650 		err_flag = TRUE;
651 	}
652 
653 	if ((pipe(pipeB_fd) == -1)
654 	    || (fcntl(pipeB_fd[0], F_SETFL, O_NDELAY) == -1)) {
655 		errno_buf = errno;
656 		err_flag = TRUE;
657 	}
658 
659 	/*
660 	 *  Check for errors.
661 	 */
662 	if (err_flag == TRUE) {
663 		tst_brkm(TBROK | TERRNO, NULL, "pipe() failed");
664 	}
665 	return;
666 
667 }
668 
669 /***********************************************************
670  *  This routine indicates that the process caught SIGUSR1.
671  **********************************************************/
usr1_rout(void)672 void usr1_rout(void)
673 {
674 	switch (who_am_i) {
675 	case '1':
676 		if (write(pipe1_fd[1], SIG_CAUGHT, 1) == -1)
677 			tst_resm(TWARN,
678 				 "Writing signal catching status failed in child 1.");
679 		break;
680 	case '2':
681 		if (write(pipe2_fd[1], SIG_CAUGHT, 1) == -1)
682 			tst_resm(TWARN,
683 				 "Writing signal catching status failed in child 2.");
684 		break;
685 	case 'A':
686 		if (write(pipeA_fd[1], SIG_CAUGHT, 1) == -1)
687 			tst_resm(TWARN,
688 				 "Writing signal catching status failed in child A.");
689 		break;
690 	case 'B':
691 		if (write(pipeB_fd[1], SIG_CAUGHT, 1) == -1)
692 			tst_resm(TWARN,
693 				 "Writing signal catching status failed in child B.");
694 		break;
695 	default:
696 		tst_resm(TWARN,
697 			 "Unexpected value %d for who_am_i in usr1_rout()",
698 			 who_am_i);
699 		break;
700 	}
701 
702 }				/*End of usr1_rout */
703 
704 /***********************************************************
705  *  This routine handles the timeout alarm in the parent,
706  *  which occurs when the child fails to notify the parent
707  *  the status of set up.
708  **********************************************************/
notify_timeout(void)709 void notify_timeout(void)
710 {
711 	alarm_flag = TRUE;
712 
713 }				/*End of notify_timeout */
714 
715 /***********************************************************
716  *  This routine handles the procedure for removing the
717  *  children forked off during this test.
718  **********************************************************/
par_kill(void)719 void par_kill(void)
720 {
721 	int status;
722 
723 	/*
724 	 *  Indicate to child1 that it can remove it's children and itself now.
725 	 */
726 	if (kill(pid1, SIGUSR2) == -1 && errno != ESRCH) {
727 		tst_resm(TWARN | TERRNO, "kill() failed");
728 		tst_resm(TWARN,
729 			 "Child 1 and it's children may still be alive.");
730 	}
731 
732 	/*
733 	 *  Remove child 2.
734 	 */
735 	if (kill(pid2, SIGKILL) == -1 && errno != ESRCH)
736 		tst_resm(TWARN, "Child2 may still be alive.");
737 
738 	wait(&status);
739 	return;
740 
741 }				/*End of par_kill */
742 
743 /*********************************************************************
744  *  This routine is executed by child 1 when the parent tells it to
745  *  remove it's children and itself.
746  ********************************************************************/
chld1_kill(void)747 void chld1_kill(void)
748 {
749 	/*
750 	 *  Remove children A & B.
751 	 */
752 	if (kill(pidA, SIGKILL) == -1 && errno != ESRCH)
753 		tst_resm(TWARN | TERRNO,
754 			 "kill(%d) failed; child 1's(A) child may still be alive",
755 			 pidA);
756 
757 	(void)write(pipe1_fd[1], CHAR_SET_PASSED, 1);
758 
759 	if (kill(pidB, SIGKILL) == -1 && errno != ESRCH)
760 		tst_resm(TWARN | TERRNO,
761 			 "kill(%d) failed; child 1's(B) child may still be alive",
762 			 pidB);
763 
764 	exit(0);
765 
766 }				/*End of chld1_kill */
767 
768 /***************************************************************
769  * cleanup() - performs all ONE TIME cleanup for this test at
770  *              completion or premature exit.
771  ***************************************************************/
cleanup(void)772 void cleanup(void)
773 {
774 
775 }
776