blob: c918e62c3df9f07cee5007d27d6b8bf771da638a [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
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
Wanlong Gaofed96412012-10-24 10:10:29 +080020 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
plars865695b2001-08-27 22:15:12 +000022 *
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 */
vapiere7a6ab52009-08-28 13:20:15 +000033/* $Id: kill02.c,v 1.10 2009/08/28 13:20:15 vapier Exp $ */
plars865695b2001-08-27 22:15:12 +000034/***********************************************************************************
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.
Garrett Cooper2c282152010-12-16 00:55:50 -080041
plars865695b2001-08-27 22:15:12 +000042 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
plars865695b2001-08-27 22:15:12 +000055 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.
subrata_modakbdbaec52009-02-26 12:14:51 +000082
plars865695b2001-08-27 22:15:12 +000083 **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>
robbiewe93a3242005-08-31 20:27:12 +0000132#include <sys/wait.h>
subrata_modak56207ce2009-03-23 13:35:39 +0000133#include <errno.h>
plars865695b2001-08-27 22:15:12 +0000134#include <fcntl.h>
Garrett Cooper42b35382010-12-19 07:28:44 -0800135#include <signal.h>
plars865695b2001-08-27 22:15:12 +0000136#include <string.h>
137#include <stdlib.h>
subrata_modak56207ce2009-03-23 13:35:39 +0000138#include "test.h"
plars865695b2001-08-27 22:15:12 +0000139
subrata_modak56207ce2009-03-23 13:35:39 +0000140#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. */
plars865695b2001-08-27 22:15:12 +0000158
subrata_modak56207ce2009-03-23 13:35:39 +0000159int pid1; /*Return value from 1st fork. Global so that it can be */
160 /*used in interrupt handling routines. */
161int pid2; /*Return value from 2nd fork. Global so that it can be */
162 /*used in interrupt handling routines. */
163int pidA; /*Return value from 1st fork in child 1. Global so that it */
164 /*can be used in interrupt handling routines. */
165int pidB; /*Return value from 2nd fork in child 1. Global so that it */
166 /*can be used in interrupt handling routines. */
167int pipe1_fd[2]; /*Pipe file descriptors used for communication */
168 /*between child 1 and the 1st parent. */
169int pipe2_fd[2]; /*Pipe file descriptors used for communication */
170 /*between child 2 and the 1st parent. */
171int pipeA_fd[2]; /*Pipe file descriptors used for communication */
172 /*between child A and the 1st parent. */
173int pipeB_fd[2]; /*Pipe file descriptors used for communication */
174 /*between child B and the 1st parent. */
175char pipe_buf[10]; /*Pipe buffer. */
176char buf_tmp1[2], buf_tmp2[2]; /*Temp hold for info read into pipe_buf. */
177int read1_stat = 0; /*Number of characters read from pipe 1. */
178int read2_stat = 0; /*Number of characters read from pipe 2. */
179int readA_stat = 0; /*Number of characters read from pipe A. */
180int readB_stat = 0; /*Number of characters read from pipe B. */
181int alarm_flag = FALSE; /*This flag indicates an alarm time out. */
182char who_am_i = '0'; /*This indicates which process is which when using */
183 /*interrupt routine usr1_rout. */
plars865695b2001-08-27 22:15:12 +0000184
subrata_modak56207ce2009-03-23 13:35:39 +0000185void notify_timeout(); /*Signal handler that the parent enters if it times out */
186 /*waiting for the child to indicate its set up status. */
187void parent_rout(); /*This is the parents routine. */
188void child1_rout(); /*This is child 1's routine. */
189void child2_rout(); /*This is child 2's routine. */
190void childA_rout(); /*This is child A's routine. */
191void childB_rout(); /*This is child B's routine. */
192void usr1_rout(); /*This routine is used by all children to indicate that */
193 /*they have caught signal SIGUSR1. */
194void 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. */
197void chld1_kill(); /*This routine is used by child 1 to remove itself and */
198 /*its children A and B. */
plars865695b2001-08-27 22:15:12 +0000199
200void setup();
201void cleanup();
202
Cyril Hrubisfdce7d52013-04-04 18:35:48 +0200203char *TCID = "kill02";
204int TST_TOTAL = 2;
plars865695b2001-08-27 22:15:12 +0000205
robbiewd34d5812005-07-11 22:28:09 +0000206#ifdef UCLINUX
207static char *argv0;
208void childA_rout_uclinux();
209void childB_rout_uclinux();
210#endif
211
subrata_modak56207ce2009-03-23 13:35:39 +0000212int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +0000213{
Cyril Hrubis89af32a2012-10-24 16:39:11 +0200214 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +0200215 const char *msg;
plars865695b2001-08-27 22:15:12 +0000216
Garrett Cooper42b35382010-12-19 07:28:44 -0800217 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
subrata_modak56207ce2009-03-23 13:35:39 +0000218 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Garrett Cooper2c282152010-12-16 00:55:50 -0800219
robbiewd34d5812005-07-11 22:28:09 +0000220#ifdef UCLINUX
subrata_modak56207ce2009-03-23 13:35:39 +0000221 argv0 = av[0];
robbiewd34d5812005-07-11 22:28:09 +0000222
subrata_modak56207ce2009-03-23 13:35:39 +0000223 maybe_run_child(&childA_rout_uclinux, "nd", 1, &pipeA_fd[1]);
224 maybe_run_child(&childB_rout_uclinux, "nd", 2, &pipeB_fd[1]);
225 maybe_run_child(&child1_rout, "ndddddd", 3, &pipe1_fd[1], &pipe2_fd[1],
226 &pipeA_fd[0], &pipeA_fd[1], &pipeB_fd[0], &pipeB_fd[1]);
227 maybe_run_child(&child2_rout, "nd", 4, &pipe2_fd[1]);
robbiewd34d5812005-07-11 22:28:09 +0000228#endif
229
subrata_modak56207ce2009-03-23 13:35:39 +0000230 setup();
plars865695b2001-08-27 22:15:12 +0000231
subrata_modak56207ce2009-03-23 13:35:39 +0000232 for (lc = 0; TEST_LOOPING(lc); lc++) {
plars865695b2001-08-27 22:15:12 +0000233
Caspar Zhangd59a6592013-03-07 14:59:12 +0800234 tst_count = 0;
plars865695b2001-08-27 22:15:12 +0000235
subrata_modak56207ce2009-03-23 13:35:39 +0000236 if ((pid1 = FORK_OR_VFORK()) > 0) {
subrata_modak56207ce2009-03-23 13:35:39 +0000237 if ((pid2 = FORK_OR_VFORK()) > 0) {
subrata_modak56207ce2009-03-23 13:35:39 +0000238 (void)parent_rout();
239 } else if (pid2 == 0) {
robbiewd34d5812005-07-11 22:28:09 +0000240#ifdef UCLINUX
subrata_modak56207ce2009-03-23 13:35:39 +0000241 if (self_exec(argv0, "nd", 4, pipe2_fd[1]) < 0) {
242 if (kill(pid1, SIGKILL) == -1
243 && errno != ESRCH) {
244 tst_resm(TWARN,
245 "Child process may not have been killed.");
246 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800247 tst_brkm(TBROK | TERRNO, cleanup,
248 "fork failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000249 }
robbiewd34d5812005-07-11 22:28:09 +0000250#else
subrata_modak56207ce2009-03-23 13:35:39 +0000251 (void)child2_rout();
robbiewd34d5812005-07-11 22:28:09 +0000252#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000253 } else {
254 /*
255 * The second fork failed kill the first child.
256 */
257 if (kill(pid1, SIGKILL) == -1 && errno != ESRCH) {
258 tst_resm(TWARN,
259 "Child process may not have been killed.");
260 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800261 tst_brkm(TBROK | TERRNO, cleanup,
262 "fork failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000263 }
plars865695b2001-08-27 22:15:12 +0000264
subrata_modak56207ce2009-03-23 13:35:39 +0000265 } else if (pid1 == 0) {
266 /*
267 * This is child 1.
268 */
robbiewd34d5812005-07-11 22:28:09 +0000269#ifdef UCLINUX
subrata_modak56207ce2009-03-23 13:35:39 +0000270 if (self_exec
271 (argv0, "ndddddd", 3, pipe1_fd[1], pipe2_fd[1],
272 pipeA_fd[0], pipeA_fd[1], pipeB_fd[0],
273 pipeB_fd[1]) < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800274 tst_brkm(TBROK | TERRNO, cleanup,
275 "self_exec() failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000276 }
robbiewd34d5812005-07-11 22:28:09 +0000277#else
subrata_modak56207ce2009-03-23 13:35:39 +0000278 (void)child1_rout();
robbiewd34d5812005-07-11 22:28:09 +0000279#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000280 } else {
281 /*
282 * Fork failed.
283 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800284 tst_brkm(TBROK | TERRNO, cleanup, "fork failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000285 }
plars865695b2001-08-27 22:15:12 +0000286 }
plars865695b2001-08-27 22:15:12 +0000287
subrata_modak56207ce2009-03-23 13:35:39 +0000288 cleanup();
Garrett Cooper42b35382010-12-19 07:28:44 -0800289 tst_exit();
subrata_modak56207ce2009-03-23 13:35:39 +0000290} /* END OF MAIN. */
plars865695b2001-08-27 22:15:12 +0000291
292/******************************************************************************
293 * This is the parents routine. The parent waits for the children 1 and 2 to
294 * get set up. Then sends the signal and checks the outcome.
295 *********************************************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400296void parent_rout(void)
plars865695b2001-08-27 22:15:12 +0000297{
plars865695b2001-08-27 22:15:12 +0000298 /*
subrata_modak56207ce2009-03-23 13:35:39 +0000299 * Set to catch the alarm signal SIGALRM.
plars865695b2001-08-27 22:15:12 +0000300 */
subrata_modak56207ce2009-03-23 13:35:39 +0000301 if (signal(SIGALRM, notify_timeout) == SIG_ERR) {
302 (void)par_kill();
303 tst_brkm(TBROK, NULL,
304 "Could not set to catch the parents time out alarm.");
subrata_modak56207ce2009-03-23 13:35:39 +0000305 }
plars865695b2001-08-27 22:15:12 +0000306
plars865695b2001-08-27 22:15:12 +0000307 /*
subrata_modak56207ce2009-03-23 13:35:39 +0000308 * Setting to catch the timeout alarm worked now let the children start up.
309 * Set an alarm which causes a time out on the read pipe loop.
310 * The children will notify the parent that set up is complete
311 * and the pass/fail status of set up.
plars865695b2001-08-27 22:15:12 +0000312 */
subrata_modak56207ce2009-03-23 13:35:39 +0000313 (void)alarm(TIMEOUT);
plars865695b2001-08-27 22:15:12 +0000314
subrata_modak56207ce2009-03-23 13:35:39 +0000315 while ((read(pipe1_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
316 /*EMPTY*/;
317 strncpy(buf_tmp1, pipe_buf, 1);
318 (void)alarm(TIMEOUT);
319
320 while ((read(pipe2_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
321 /*EMPTY*/;
322 (void)alarm(0); /*Reset the alarm clock. */
323 strncpy(buf_tmp2, pipe_buf, 1);
324
325 /*
326 * Check the alarm flag.
327 */
328 if (alarm_flag == TRUE) {
329 tst_brkm(TBROK, NULL,
330 "The set up of the children failed by timing out.");
331 (void)par_kill();
332 cleanup();
plars865695b2001-08-27 22:15:12 +0000333 }
334
subrata_modak56207ce2009-03-23 13:35:39 +0000335 /*
336 * Check to see if either child failed in the set up.
337 */
338 if ((strncmp(buf_tmp1, CHAR_SET_FAILED, 1) == 0) ||
339 (strncmp(buf_tmp2, CHAR_SET_FAILED, 1) == 0)) {
340 /*
341 * Problems were encountered in the set up of one of the children.
342 * The error message has been displayed by the child.
343 */
344 (void)par_kill();
345 cleanup();
plars865695b2001-08-27 22:15:12 +0000346 }
347
subrata_modak56207ce2009-03-23 13:35:39 +0000348 /*
349 * Setup passed, now send SIGUSR1 to process id of zero.
350 */
351 TEST(kill(0, SIGUSR1));
plars865695b2001-08-27 22:15:12 +0000352
subrata_modak56207ce2009-03-23 13:35:39 +0000353 if (TEST_RETURN == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800354 tst_brkm(TBROK | TERRNO, NULL, "kill() failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000355 (void)par_kill();
356 cleanup();
357 }
plars865695b2001-08-27 22:15:12 +0000358
subrata_modak56207ce2009-03-23 13:35:39 +0000359 /*
360 * Sleep for a while to allow the children to get a chance to
361 * catch the signal.
362 */
363 (void)sleep(SLEEP_TIME);
mreed1062091702006-09-06 16:45:02 +0000364
subrata_modak56207ce2009-03-23 13:35:39 +0000365 /*
366 * The signal was sent above and time has run out for child response,
367 * check the outcomes.
368 */
369 read1_stat = read(pipe1_fd[0], pipe_buf, 1);
370 if (read1_stat == -1 && errno == EAGAIN)
371 read1_stat = 0;
372 read2_stat = read(pipe2_fd[0], pipe_buf, 1);
373 if (read2_stat == -1 && errno == EAGAIN)
374 read2_stat = 0;
375 readA_stat = read(pipeA_fd[0], pipe_buf, 1);
376 if (readA_stat == -1 && errno == EAGAIN)
377 readA_stat = 0;
378 readB_stat = read(pipeB_fd[0], pipe_buf, 1);
379 if (readB_stat == -1 && errno == EAGAIN)
380 readB_stat = 0;
mreed1062091702006-09-06 16:45:02 +0000381
subrata_modak56207ce2009-03-23 13:35:39 +0000382 if (read1_stat == -1 || read2_stat == -1 ||
383 readA_stat == -1 || readB_stat == -1) {
384 /*
385 * The read system call failed.
386 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800387 tst_brkm(TBROK | TERRNO, NULL, "read() failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000388 (void)par_kill();
389 cleanup();
390 }
mreed1062091702006-09-06 16:45:02 +0000391
subrata_modak56207ce2009-03-23 13:35:39 +0000392 /*
393 * Check the processes that were supposed to get the signal.
394 */
395 if (read1_stat == SIG_RECEIVED) {
396 if (readA_stat == SIG_RECEIVED) {
397 /*
398 * Both processes, 1 and A, that were supposed to receive
399 * the signal did receive the signal.
400 */
Cyril Hrubise38b9612014-06-02 17:20:57 +0200401 tst_resm(TPASS,
402 "The signal was sent to all processes in the process group.");
subrata_modak56207ce2009-03-23 13:35:39 +0000403 } else { /*Process A didn't receive the signal. */
404 tst_resm(TFAIL,
405 "Process A did not receive the signal.");
406 }
mreed1062091702006-09-06 16:45:02 +0000407
subrata_modak56207ce2009-03-23 13:35:39 +0000408 } else { /*Process 1 didn't receive the signal. */
409 tst_resm(TFAIL, "Process 1 did not receive the signal.");
410 }
411
412 /*
413 * Check the processes that were not supposed to get the signal.
414 */
415 if (read2_stat == SIG_NOT_RECD) {
416 if (readB_stat == SIG_NOT_RECD) {
417 /*
418 * Both processes, 2 and B did not receive the signal.
419 */
Cyril Hrubise38b9612014-06-02 17:20:57 +0200420 tst_resm(TPASS,
421 "The signal was not sent to selective processes that were not in the process group.");
subrata_modak56207ce2009-03-23 13:35:39 +0000422 } else { /*Process B received the signal. */
423 tst_resm(TFAIL, "Process B received the signal.");
424 }
425
426 }
427
428 else { /*Process 2 received the signal. */
429
430 tst_resm(TFAIL, "Process 2 received the signal.");
431 }
432
433 (void)par_kill();
434
435 (void)alarm(TIMEOUT);
436 while ((read(pipe1_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
437 strncpy(buf_tmp1, pipe_buf, 1);
438
subrata_modak56207ce2009-03-23 13:35:39 +0000439} /*End of parent_rout */
mreed1062091702006-09-06 16:45:02 +0000440
Mike Frysingerc57fba52014-04-09 18:56:30 -0400441void child1_rout(void)
plars865695b2001-08-27 22:15:12 +0000442{
subrata_modak56207ce2009-03-23 13:35:39 +0000443 who_am_i = '1';
plars865695b2001-08-27 22:15:12 +0000444
plars865695b2001-08-27 22:15:12 +0000445 /*
subrata_modak56207ce2009-03-23 13:35:39 +0000446 * Set to catch the SIGUSR1 with int1_rout.
plars865695b2001-08-27 22:15:12 +0000447 */
subrata_modak56207ce2009-03-23 13:35:39 +0000448 if (signal(SIGUSR1, usr1_rout) == SIG_ERR) {
449 tst_brkm(TBROK, NULL,
450 "Could not set to catch the childrens signal.");
451 (void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
robbiewd34d5812005-07-11 22:28:09 +0000452 exit(0);
453 }
subrata_modak56207ce2009-03-23 13:35:39 +0000454 /*
455 * Create children A & B.
456 */
457 if ((pidA = FORK_OR_VFORK()) > 0) {
458 /*
459 * This is the parent(child1), fork again to create child B.
460 */
461 if ((pidB = FORK_OR_VFORK()) == 0) {
462 /* This is child B. */
463#ifdef UCLINUX
464 if (self_exec(argv0, "nd", 2, pipeB_fd[1]) < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800465 tst_brkm(TBROK | TERRNO, NULL,
466 "self_exec() failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000467 (void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
468 exit(0);
469 }
robbiewd34d5812005-07-11 22:28:09 +0000470#else
subrata_modak56207ce2009-03-23 13:35:39 +0000471 (void)childB_rout();
472#endif
473 }
474
475 else if (pidB == -1) {
476 /*
477 * The fork of child B failed kill child A.
478 */
479 if (kill(pidA, SIGKILL) == -1)
480 tst_resm(TWARN,
481 "Child process may not have been killed.");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800482 tst_brkm(TBROK | TERRNO, NULL, "fork failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000483 (void)write(pipe2_fd[1], CHAR_SET_FAILED, 1);
484 exit(0);
485 }
486 }
487
488 else if (pidA == 0) {
489 /* This is child A. */
490#ifdef UCLINUX
491 if (self_exec(argv0, "nd", 1, pipeA_fd[1]) < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800492 tst_brkm(TBROK | TERRNO, NULL, "self_exec() failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000493 (void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
494 exit(0);
495 }
496#else
497 (void)childA_rout();
robbiewd34d5812005-07-11 22:28:09 +0000498#endif
plars865695b2001-08-27 22:15:12 +0000499
subrata_modak56207ce2009-03-23 13:35:39 +0000500 }
plars865695b2001-08-27 22:15:12 +0000501
subrata_modak56207ce2009-03-23 13:35:39 +0000502 else if (pidA == -1) {
503 /*
504 * The fork of child A failed.
505 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800506 tst_brkm(TBROK | TERRNO, NULL, "fork failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000507 (void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
508 exit(0);
509 }
510
plars865695b2001-08-27 22:15:12 +0000511 /*
subrata_modak56207ce2009-03-23 13:35:39 +0000512 * Set to catch the SIGUSR2 with chld1_kill.
plars865695b2001-08-27 22:15:12 +0000513 */
subrata_modak56207ce2009-03-23 13:35:39 +0000514 if (signal(SIGUSR2, chld1_kill) == SIG_ERR) {
515 tst_brkm(TBROK, NULL,
516 "Could not set to catch the parents signal.");
517 (void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
518 (void)chld1_kill();
519 exit(0);
520 }
plars865695b2001-08-27 22:15:12 +0000521
subrata_modak56207ce2009-03-23 13:35:39 +0000522 /*
523 * Set to catch the alarm signal SIGALRM.
524 */
525 if (signal(SIGALRM, notify_timeout) == SIG_ERR) {
526 tst_brkm(TBROK, NULL,
527 "Could not set to catch the childs time out alarm.");
528 (void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
529 (void)chld1_kill();
530 exit(0);
531 }
plars865695b2001-08-27 22:15:12 +0000532
subrata_modak56207ce2009-03-23 13:35:39 +0000533 /*
534 * Setting to catch the signals worked now let the children start up.
535 * Set an alarm which causes a time out on the pipe read loop.
536 * The children A & B will notify the parent(child1) that set up is complete
537 * and the pass/fail status of set up.
538 */
539 (void)alarm(TIMEOUT - 40);
plars865695b2001-08-27 22:15:12 +0000540
subrata_modak56207ce2009-03-23 13:35:39 +0000541 while ((read(pipeA_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
542 /*EMPTY*/;
543 (void)alarm(TIMEOUT - 40);
plars865695b2001-08-27 22:15:12 +0000544
subrata_modak56207ce2009-03-23 13:35:39 +0000545 while ((read(pipeB_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
546 /*EMPTY*/;
547 (void)alarm(0); /*Reset the alarm clock. */
plars865695b2001-08-27 22:15:12 +0000548
subrata_modak56207ce2009-03-23 13:35:39 +0000549 /*
550 * Check the alarm flag.
551 */
552 if (alarm_flag == TRUE) {
553 tst_brkm(TBROK, NULL,
554 "The set up of the children failed by timing out.");
555 (void)chld1_kill();
556 (void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
557 exit(0);
558 }
plars865695b2001-08-27 22:15:12 +0000559
subrata_modak56207ce2009-03-23 13:35:39 +0000560 /*
561 * Send a set up complete message to the parent.
562 */
563 (void)write(pipe1_fd[1], CHAR_SET_PASSED, 1);
plars865695b2001-08-27 22:15:12 +0000564
subrata_modak56207ce2009-03-23 13:35:39 +0000565 /*
566 * Pause until the signal SIGUSR1 or SIGUSR2 is sent from the parent.
567 */
568 (void)pause();
plars865695b2001-08-27 22:15:12 +0000569
subrata_modak56207ce2009-03-23 13:35:39 +0000570 /*
571 * Pause until signal SIGUSR2 is sent from the parent.
572 * This pause will only be executed if SIGUSR2 has not been received yet.
573 */
574 while (1) {
575 sleep(1);
576 }
plars865695b2001-08-27 22:15:12 +0000577
subrata_modak56207ce2009-03-23 13:35:39 +0000578} /*End of child1_rout */
plars865695b2001-08-27 22:15:12 +0000579
580/*******************************************************************************
581 * This is the routine for child 2, which should not receive the parents signal.
582 ******************************************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400583void child2_rout(void)
plars865695b2001-08-27 22:15:12 +0000584{
subrata_modak56207ce2009-03-23 13:35:39 +0000585 who_am_i = '2';
plars865695b2001-08-27 22:15:12 +0000586
subrata_modak56207ce2009-03-23 13:35:39 +0000587 /*
588 * Set the process group of this process to be different
589 * than the other processes.
590 */
591 (void)setpgrp();
plars865695b2001-08-27 22:15:12 +0000592
subrata_modak56207ce2009-03-23 13:35:39 +0000593 /*
594 * Set to catch the SIGUSR1 with usr1_rout.
595 */
596 if (signal(SIGUSR1, usr1_rout) == SIG_ERR) {
597 tst_brkm(TBROK, cleanup,
598 "Could not set to catch the parents signal.");
599 (void)write(pipe2_fd[1], CHAR_SET_FAILED, 1);
600 exit(0);
601 }
plars865695b2001-08-27 22:15:12 +0000602
subrata_modak56207ce2009-03-23 13:35:39 +0000603 /* Send a set up complete message to parent. */
604 (void)write(pipe2_fd[1], CHAR_SET_PASSED, 1);
plars865695b2001-08-27 22:15:12 +0000605
subrata_modak56207ce2009-03-23 13:35:39 +0000606 /*
607 * Pause until killed by the parent or SIGUSR1 is received.
608 */
609 (void)pause();
plars865695b2001-08-27 22:15:12 +0000610}
611
plars865695b2001-08-27 22:15:12 +0000612/*******************************************************************************
613 * This is the routine for child A, which should receive the parents signal.
614 ******************************************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400615void childA_rout(void)
plars865695b2001-08-27 22:15:12 +0000616{
subrata_modak56207ce2009-03-23 13:35:39 +0000617 who_am_i = 'A';
plars865695b2001-08-27 22:15:12 +0000618
subrata_modak56207ce2009-03-23 13:35:39 +0000619 /* Send a set up complete message to parent. */
620 write(pipeA_fd[1], CHAR_SET_PASSED, 1);
plars865695b2001-08-27 22:15:12 +0000621
subrata_modak56207ce2009-03-23 13:35:39 +0000622 /*
623 * Pause until killed by the parent or SIGUSR1 is received.
624 */
625 (void)pause();
plars865695b2001-08-27 22:15:12 +0000626
subrata_modak56207ce2009-03-23 13:35:39 +0000627 exit(0);
628} /*End of childA_rout */
plars865695b2001-08-27 22:15:12 +0000629
robbiewd34d5812005-07-11 22:28:09 +0000630#ifdef UCLINUX
631/*******************************************************************************
632 * This is the routine for child A after self_exec
633 ******************************************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400634void childA_rout_uclinux(void)
robbiewd34d5812005-07-11 22:28:09 +0000635{
subrata_modak56207ce2009-03-23 13:35:39 +0000636 /* Setup the signal handler again */
637 if (signal(SIGUSR1, usr1_rout) == SIG_ERR) {
638 tst_brkm(TBROK, NULL,
639 "Could not set to catch the childrens signal.");
640 (void)write(pipeA_fd[1], CHAR_SET_FAILED, 1);
641 exit(0);
642 }
robbiewd34d5812005-07-11 22:28:09 +0000643
subrata_modak56207ce2009-03-23 13:35:39 +0000644 childA_rout();
robbiewd34d5812005-07-11 22:28:09 +0000645}
646#endif
647
plars865695b2001-08-27 22:15:12 +0000648/*******************************************************************************
649 * This is the routine for child B, which should not receive the parents signal.
650 ******************************************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400651void childB_rout(void)
plars865695b2001-08-27 22:15:12 +0000652{
subrata_modak56207ce2009-03-23 13:35:39 +0000653 who_am_i = 'B';
plars865695b2001-08-27 22:15:12 +0000654
subrata_modak56207ce2009-03-23 13:35:39 +0000655 /*
656 * Set the process group of this process to be different
657 * than the other processes.
658 */
659 (void)setpgrp();
plars865695b2001-08-27 22:15:12 +0000660
subrata_modak56207ce2009-03-23 13:35:39 +0000661 /* Send a set up complete message to parent(child 1). */
662 write(pipeB_fd[1], CHAR_SET_PASSED, 1);
plars865695b2001-08-27 22:15:12 +0000663
subrata_modak56207ce2009-03-23 13:35:39 +0000664 /*
665 * Pause until killed by the parent(child 1) or SIGUSR1 is received.
666 */
667 (void)pause();
plars865695b2001-08-27 22:15:12 +0000668
subrata_modak56207ce2009-03-23 13:35:39 +0000669 exit(0);
plars865695b2001-08-27 22:15:12 +0000670}
robbiewd34d5812005-07-11 22:28:09 +0000671
672#ifdef UCLINUX
673/*******************************************************************************
674 * This is the routine for child B after self_exec
675 ******************************************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400676void childB_rout_uclinux(void)
robbiewd34d5812005-07-11 22:28:09 +0000677{
subrata_modak56207ce2009-03-23 13:35:39 +0000678 /* Setup the signal handler again */
679 if (signal(SIGUSR1, usr1_rout) == SIG_ERR) {
680 tst_brkm(TBROK, NULL,
681 "Could not set to catch the childrens signal.");
682 (void)write(pipeB_fd[1], CHAR_SET_FAILED, 1);
683 exit(0);
684 }
robbiewd34d5812005-07-11 22:28:09 +0000685
subrata_modak56207ce2009-03-23 13:35:39 +0000686 childB_rout();
robbiewd34d5812005-07-11 22:28:09 +0000687}
688#endif
Garrett Cooper2c282152010-12-16 00:55:50 -0800689
plars865695b2001-08-27 22:15:12 +0000690/*******************************************************************************
691 * This routine sets up the interprocess communication pipes, signal handling,
692 * and process group information.
693 ******************************************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400694void setup(void)
plars865695b2001-08-27 22:15:12 +0000695{
subrata_modak56207ce2009-03-23 13:35:39 +0000696 int errno_buf; /*indicates the errno if pipe set up fails. */
697 int err_flag = FALSE; /*Indicates if an error has occurred in pipe set up. */
plars865695b2001-08-27 22:15:12 +0000698
subrata_modak56207ce2009-03-23 13:35:39 +0000699 /*
700 * Set the process group ID to be equal between the parent and children.
701 */
702 (void)setpgrp();
plars865695b2001-08-27 22:15:12 +0000703
subrata_modak56207ce2009-03-23 13:35:39 +0000704 /*
705 * Set to catch unexpected signals.
706 * SIGCLD is set to be ignored because we do not wait for termination status.
707 * SIGUSR1 is set to be ignored because this is the signal we are using for
708 * the test and we are not concerned with the parent getting it.
709 */
Garrett Cooper2c282152010-12-16 00:55:50 -0800710
subrata_modak56207ce2009-03-23 13:35:39 +0000711 tst_sig(FORK, DEF_HANDLER, cleanup);
plars865695b2001-08-27 22:15:12 +0000712
subrata_modak56207ce2009-03-23 13:35:39 +0000713 if (signal(SIGUSR1, SIG_IGN) == SIG_ERR) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800714 tst_brkm(TBROK | TFAIL, NULL,
715 "signal(SIGUSR1, SIG_IGN) failed");
plars865695b2001-08-27 22:15:12 +0000716 }
717
subrata_modak56207ce2009-03-23 13:35:39 +0000718 if (signal(SIGCLD, SIG_IGN) == SIG_ERR) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800719 tst_brkm(TBROK | TERRNO, NULL,
720 "signal(SIGCLD, SIG_IGN) failed");
plars865695b2001-08-27 22:15:12 +0000721 }
722
subrata_modak56207ce2009-03-23 13:35:39 +0000723 TEST_PAUSE;
plars865695b2001-08-27 22:15:12 +0000724
subrata_modak56207ce2009-03-23 13:35:39 +0000725 /*
726 * Set up pipe1, pipe2, pipeA, and pipeB.
727 */
728 if ((pipe(pipe1_fd) == -1)
729 || (fcntl(pipe1_fd[0], F_SETFL, O_NDELAY) == -1)) {
730 errno_buf = errno;
731 err_flag = TRUE;
732 }
plars865695b2001-08-27 22:15:12 +0000733
subrata_modak56207ce2009-03-23 13:35:39 +0000734 if ((pipe(pipe2_fd) == -1)
735 || (fcntl(pipe2_fd[0], F_SETFL, O_NDELAY) == -1)) {
736 errno_buf = errno;
737 err_flag = TRUE;
738 }
plars865695b2001-08-27 22:15:12 +0000739
subrata_modak56207ce2009-03-23 13:35:39 +0000740 if ((pipe(pipeA_fd) == -1)
741 || (fcntl(pipeA_fd[0], F_SETFL, O_NDELAY) == -1)) {
742 errno_buf = errno;
743 err_flag = TRUE;
744 }
plars865695b2001-08-27 22:15:12 +0000745
subrata_modak56207ce2009-03-23 13:35:39 +0000746 if ((pipe(pipeB_fd) == -1)
747 || (fcntl(pipeB_fd[0], F_SETFL, O_NDELAY) == -1)) {
748 errno_buf = errno;
749 err_flag = TRUE;
750 }
plars865695b2001-08-27 22:15:12 +0000751
subrata_modak56207ce2009-03-23 13:35:39 +0000752 /*
753 * Check for errors.
754 */
755 if (err_flag == TRUE) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800756 tst_brkm(TBROK | TERRNO, NULL, "pipe() failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000757 }
758 return;
plars865695b2001-08-27 22:15:12 +0000759
760}
761
762/***********************************************************
763 * This routine indicates that the process caught SIGUSR1.
764 **********************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400765void usr1_rout(void)
plars865695b2001-08-27 22:15:12 +0000766{
subrata_modak56207ce2009-03-23 13:35:39 +0000767 switch (who_am_i) {
768 case '1':
769 if (write(pipe1_fd[1], SIG_CAUGHT, 1) == -1)
770 tst_resm(TWARN,
771 "Writing signal catching status failed in child 1.");
772 break;
773 case '2':
774 if (write(pipe2_fd[1], SIG_CAUGHT, 1) == -1)
775 tst_resm(TWARN,
776 "Writing signal catching status failed in child 2.");
777 break;
778 case 'A':
779 if (write(pipeA_fd[1], SIG_CAUGHT, 1) == -1)
780 tst_resm(TWARN,
781 "Writing signal catching status failed in child A.");
782 break;
783 case 'B':
784 if (write(pipeB_fd[1], SIG_CAUGHT, 1) == -1)
785 tst_resm(TWARN,
786 "Writing signal catching status failed in child B.");
787 break;
plars865695b2001-08-27 22:15:12 +0000788 default:
vapiere7a6ab52009-08-28 13:20:15 +0000789 tst_resm(TWARN,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800790 "Unexpected value %d for who_am_i in usr1_rout()",
791 who_am_i);
subrata_modak56207ce2009-03-23 13:35:39 +0000792 break;
793 }
plars865695b2001-08-27 22:15:12 +0000794
subrata_modak56207ce2009-03-23 13:35:39 +0000795} /*End of usr1_rout */
plars865695b2001-08-27 22:15:12 +0000796
797/***********************************************************
798 * This routine handles the timeout alarm in the parent,
799 * which occurs when the child fails to notify the parent
800 * the status of set up.
801 **********************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400802void notify_timeout(void)
plars865695b2001-08-27 22:15:12 +0000803{
subrata_modak56207ce2009-03-23 13:35:39 +0000804 alarm_flag = TRUE;
plars865695b2001-08-27 22:15:12 +0000805
subrata_modak56207ce2009-03-23 13:35:39 +0000806} /*End of notify_timeout */
Garrett Cooper2c282152010-12-16 00:55:50 -0800807
plars865695b2001-08-27 22:15:12 +0000808/***********************************************************
subrata_modak4bb656a2009-02-26 12:02:09 +0000809 * This routine handles the procedure for removing the
plars865695b2001-08-27 22:15:12 +0000810 * children forked off during this test.
811 **********************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400812void par_kill(void)
plars865695b2001-08-27 22:15:12 +0000813{
robbiew8f837d72005-06-15 15:47:04 +0000814 int status;
815
subrata_modak56207ce2009-03-23 13:35:39 +0000816 /*
817 * Indicate to child1 that it can remove it's children and itself now.
818 */
819 if (kill(pid1, SIGUSR2) == -1 && errno != ESRCH) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800820 tst_resm(TWARN | TERRNO, "kill() failed");
821 tst_resm(TWARN,
822 "Child 1 and it's children may still be alive.");
subrata_modak56207ce2009-03-23 13:35:39 +0000823 }
plars865695b2001-08-27 22:15:12 +0000824
subrata_modak56207ce2009-03-23 13:35:39 +0000825 /*
826 * Remove child 2.
827 */
828 if (kill(pid2, SIGKILL) == -1 && errno != ESRCH)
829 tst_resm(TWARN, "Child2 may still be alive.");
plars865695b2001-08-27 22:15:12 +0000830
subrata_modak56207ce2009-03-23 13:35:39 +0000831 wait(&status);
832 return;
subrata_modakbdbaec52009-02-26 12:14:51 +0000833
subrata_modak56207ce2009-03-23 13:35:39 +0000834} /*End of par_kill */
plars865695b2001-08-27 22:15:12 +0000835
836/*********************************************************************
837 * This routine is executed by child 1 when the parent tells it to
838 * remove it's children and itself.
839 ********************************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400840void chld1_kill(void)
plars865695b2001-08-27 22:15:12 +0000841{
subrata_modak56207ce2009-03-23 13:35:39 +0000842 /*
843 * Remove children A & B.
844 */
vapiere7a6ab52009-08-28 13:20:15 +0000845 if (kill(pidA, SIGKILL) == -1 && errno != ESRCH)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800846 tst_resm(TWARN | TERRNO,
847 "kill(%d) failed; child 1's(A) child may still be alive",
848 pidA);
mreed1062091702006-09-06 16:45:02 +0000849
subrata_modak56207ce2009-03-23 13:35:39 +0000850 (void)write(pipe1_fd[1], CHAR_SET_PASSED, 1);
mreed1062091702006-09-06 16:45:02 +0000851
vapiere7a6ab52009-08-28 13:20:15 +0000852 if (kill(pidB, SIGKILL) == -1 && errno != ESRCH)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800853 tst_resm(TWARN | TERRNO,
854 "kill(%d) failed; child 1's(B) child may still be alive",
855 pidB);
mreed1062091702006-09-06 16:45:02 +0000856
subrata_modak56207ce2009-03-23 13:35:39 +0000857 exit(0);
plars865695b2001-08-27 22:15:12 +0000858
subrata_modak56207ce2009-03-23 13:35:39 +0000859} /*End of chld1_kill */
plars865695b2001-08-27 22:15:12 +0000860
861/***************************************************************
862 * cleanup() - performs all ONE TIME cleanup for this test at
863 * completion or premature exit.
864 ***************************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400865void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000866{
plars865695b2001-08-27 22:15:12 +0000867
Chris Dearmanec6edca2012-10-17 19:54:01 -0700868}