blob: 76df2b1c8e6ebb953d7e190d18562d11fb80d12d [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#include "usctest.h"
140
subrata_modak56207ce2009-03-23 13:35:39 +0000141#define CHAR_SET_FAILED "0" /*Set up failing status transferred through the pipe. */
142#define CHAR_SET_PASSED "1" /*Set up passing status transferred through the pipe. */
143#define SIG_CAUGHT "2" /*Indicates that the signal SIGUSR1 was caught. */
144#define SIG_RECEIVED 1 /*Integer value that indicates that the signal SIGUSR1 */
145 /*was caught. */
146#define SIG_NOT_RECD 0 /*Integer value that indicates that the signal SIGUSR1 */
147 /*was caught. */
148#define INT_SET_FAILED 0 /*Set up failing status transferred through the pipe. */
149#define INT_SET_PASSED 1 /*Set up passing status transferred through the pipe. */
150#define SLEEP_TIME 10 /*Amount of time the children get to catch the signal */
151#define TRUE 40 /*Child exits with this if execution was as */
152 /*expected. */
153#define FALSE 50 /*Child exits with this if it timed out waiting for the */
154 /*parents signal. */
155#define TIMEOUT 60 /*Amount of time given in alarm calls. */
156#define CHILD_EXIT(VAR) ((VAR >> 8) & 0377) /*Exit value from the child. */
157#define CHILD_SIG(VAR) (VAR & 0377) /*Signal value from the termination of child. */
158 /*from the parent. */
plars865695b2001-08-27 22:15:12 +0000159
subrata_modak56207ce2009-03-23 13:35:39 +0000160int pid1; /*Return value from 1st fork. Global so that it can be */
161 /*used in interrupt handling routines. */
162int pid2; /*Return value from 2nd fork. Global so that it can be */
163 /*used in interrupt handling routines. */
164int pidA; /*Return value from 1st fork in child 1. Global so that it */
165 /*can be used in interrupt handling routines. */
166int pidB; /*Return value from 2nd fork in child 1. Global so that it */
167 /*can be used in interrupt handling routines. */
168int pipe1_fd[2]; /*Pipe file descriptors used for communication */
169 /*between child 1 and the 1st parent. */
170int pipe2_fd[2]; /*Pipe file descriptors used for communication */
171 /*between child 2 and the 1st parent. */
172int pipeA_fd[2]; /*Pipe file descriptors used for communication */
173 /*between child A and the 1st parent. */
174int pipeB_fd[2]; /*Pipe file descriptors used for communication */
175 /*between child B and the 1st parent. */
176char pipe_buf[10]; /*Pipe buffer. */
177char buf_tmp1[2], buf_tmp2[2]; /*Temp hold for info read into pipe_buf. */
178int read1_stat = 0; /*Number of characters read from pipe 1. */
179int read2_stat = 0; /*Number of characters read from pipe 2. */
180int readA_stat = 0; /*Number of characters read from pipe A. */
181int readB_stat = 0; /*Number of characters read from pipe B. */
182int alarm_flag = FALSE; /*This flag indicates an alarm time out. */
183char who_am_i = '0'; /*This indicates which process is which when using */
184 /*interrupt routine usr1_rout. */
plars865695b2001-08-27 22:15:12 +0000185
subrata_modak56207ce2009-03-23 13:35:39 +0000186void notify_timeout(); /*Signal handler that the parent enters if it times out */
187 /*waiting for the child to indicate its set up status. */
188void parent_rout(); /*This is the parents routine. */
189void child1_rout(); /*This is child 1's routine. */
190void child2_rout(); /*This is child 2's routine. */
191void childA_rout(); /*This is child A's routine. */
192void childB_rout(); /*This is child B's routine. */
193void usr1_rout(); /*This routine is used by all children to indicate that */
194 /*they have caught signal SIGUSR1. */
195void par_kill(); /*This routine is called by the original parent to */
196 /*remove child 2 and to indicate to child 1 to */
197 /*remove its children. */
198void chld1_kill(); /*This routine is used by child 1 to remove itself and */
199 /*its children A and B. */
plars865695b2001-08-27 22:15:12 +0000200
201void setup();
202void cleanup();
203
subrata_modak56207ce2009-03-23 13:35:39 +0000204char *TCID = "kill02"; /* Test program identifier. */
205int TST_TOTAL = 2; /* Total number of test cases. */
plars865695b2001-08-27 22:15:12 +0000206
subrata_modak56207ce2009-03-23 13:35:39 +0000207int exp_enos[] = { 0 }; /* Array of expected errnos */
plars865695b2001-08-27 22:15:12 +0000208
robbiewd34d5812005-07-11 22:28:09 +0000209#ifdef UCLINUX
210static char *argv0;
211void childA_rout_uclinux();
212void childB_rout_uclinux();
213#endif
214
subrata_modak56207ce2009-03-23 13:35:39 +0000215int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +0000216{
subrata_modak56207ce2009-03-23 13:35:39 +0000217 int lc; /* loop counter */
218 char *msg; /* message returned from parse_opts */
plars865695b2001-08-27 22:15:12 +0000219
Garrett Cooper42b35382010-12-19 07:28:44 -0800220 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
subrata_modak56207ce2009-03-23 13:35:39 +0000221 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Garrett Cooper2c282152010-12-16 00:55:50 -0800222
robbiewd34d5812005-07-11 22:28:09 +0000223#ifdef UCLINUX
subrata_modak56207ce2009-03-23 13:35:39 +0000224 argv0 = av[0];
robbiewd34d5812005-07-11 22:28:09 +0000225
subrata_modak56207ce2009-03-23 13:35:39 +0000226 maybe_run_child(&childA_rout_uclinux, "nd", 1, &pipeA_fd[1]);
227 maybe_run_child(&childB_rout_uclinux, "nd", 2, &pipeB_fd[1]);
228 maybe_run_child(&child1_rout, "ndddddd", 3, &pipe1_fd[1], &pipe2_fd[1],
229 &pipeA_fd[0], &pipeA_fd[1], &pipeB_fd[0], &pipeB_fd[1]);
230 maybe_run_child(&child2_rout, "nd", 4, &pipe2_fd[1]);
robbiewd34d5812005-07-11 22:28:09 +0000231#endif
232
subrata_modak56207ce2009-03-23 13:35:39 +0000233 setup();
plars865695b2001-08-27 22:15:12 +0000234
subrata_modak56207ce2009-03-23 13:35:39 +0000235 for (lc = 0; TEST_LOOPING(lc); lc++) {
plars865695b2001-08-27 22:15:12 +0000236
subrata_modak56207ce2009-03-23 13:35:39 +0000237 Tst_count = 0;
plars865695b2001-08-27 22:15:12 +0000238
subrata_modak56207ce2009-03-23 13:35:39 +0000239 if ((pid1 = FORK_OR_VFORK()) > 0) {
subrata_modak56207ce2009-03-23 13:35:39 +0000240 if ((pid2 = FORK_OR_VFORK()) > 0) {
subrata_modak56207ce2009-03-23 13:35:39 +0000241 (void)parent_rout();
242 } else if (pid2 == 0) {
robbiewd34d5812005-07-11 22:28:09 +0000243#ifdef UCLINUX
subrata_modak56207ce2009-03-23 13:35:39 +0000244 if (self_exec(argv0, "nd", 4, pipe2_fd[1]) < 0) {
245 if (kill(pid1, SIGKILL) == -1
246 && errno != ESRCH) {
247 tst_resm(TWARN,
248 "Child process may not have been killed.");
249 }
Garrett Cooper42b35382010-12-19 07:28:44 -0800250 tst_brkm(TBROK|TERRNO, cleanup, "fork failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000251 }
robbiewd34d5812005-07-11 22:28:09 +0000252#else
subrata_modak56207ce2009-03-23 13:35:39 +0000253 (void)child2_rout();
robbiewd34d5812005-07-11 22:28:09 +0000254#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000255 } else {
256 /*
257 * The second fork failed kill the first child.
258 */
259 if (kill(pid1, SIGKILL) == -1 && errno != ESRCH) {
260 tst_resm(TWARN,
261 "Child process may not have been killed.");
262 }
Garrett Cooper42b35382010-12-19 07:28:44 -0800263 tst_brkm(TBROK|TERRNO, cleanup, "fork failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000264 }
plars865695b2001-08-27 22:15:12 +0000265
subrata_modak56207ce2009-03-23 13:35:39 +0000266 } else if (pid1 == 0) {
267 /*
268 * This is child 1.
269 */
robbiewd34d5812005-07-11 22:28:09 +0000270#ifdef UCLINUX
subrata_modak56207ce2009-03-23 13:35:39 +0000271 if (self_exec
272 (argv0, "ndddddd", 3, pipe1_fd[1], pipe2_fd[1],
273 pipeA_fd[0], pipeA_fd[1], pipeB_fd[0],
274 pipeB_fd[1]) < 0) {
vapiere7a6ab52009-08-28 13:20:15 +0000275 tst_brkm(TBROK|TERRNO, cleanup, "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 */
Garrett Cooper42b35382010-12-19 07:28:44 -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 *********************************************************************************/
296void parent_rout()
297{
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.");
305 tst_exit();
306 }
plars865695b2001-08-27 22:15:12 +0000307
plars865695b2001-08-27 22:15:12 +0000308 /*
subrata_modak56207ce2009-03-23 13:35:39 +0000309 * Setting to catch the timeout alarm worked now let the children start up.
310 * Set an alarm which causes a time out on the read pipe loop.
311 * The children will notify the parent that set up is complete
312 * and the pass/fail status of set up.
plars865695b2001-08-27 22:15:12 +0000313 */
subrata_modak56207ce2009-03-23 13:35:39 +0000314 (void)alarm(TIMEOUT);
plars865695b2001-08-27 22:15:12 +0000315
subrata_modak56207ce2009-03-23 13:35:39 +0000316 while ((read(pipe1_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
317 /*EMPTY*/;
318 strncpy(buf_tmp1, pipe_buf, 1);
319 (void)alarm(TIMEOUT);
320
321 while ((read(pipe2_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
322 /*EMPTY*/;
323 (void)alarm(0); /*Reset the alarm clock. */
324 strncpy(buf_tmp2, pipe_buf, 1);
325
326 /*
327 * Check the alarm flag.
328 */
329 if (alarm_flag == TRUE) {
330 tst_brkm(TBROK, NULL,
331 "The set up of the children failed by timing out.");
332 (void)par_kill();
333 cleanup();
plars865695b2001-08-27 22:15:12 +0000334 }
335
subrata_modak56207ce2009-03-23 13:35:39 +0000336 /*
337 * Check to see if either child failed in the set up.
338 */
339 if ((strncmp(buf_tmp1, CHAR_SET_FAILED, 1) == 0) ||
340 (strncmp(buf_tmp2, CHAR_SET_FAILED, 1) == 0)) {
341 /*
342 * Problems were encountered in the set up of one of the children.
343 * The error message has been displayed by the child.
344 */
345 (void)par_kill();
346 cleanup();
plars865695b2001-08-27 22:15:12 +0000347 }
348
subrata_modak56207ce2009-03-23 13:35:39 +0000349 /*
350 * Setup passed, now send SIGUSR1 to process id of zero.
351 */
352 TEST(kill(0, SIGUSR1));
plars865695b2001-08-27 22:15:12 +0000353
subrata_modak56207ce2009-03-23 13:35:39 +0000354 if (TEST_RETURN == -1) {
vapiere7a6ab52009-08-28 13:20:15 +0000355 tst_brkm(TBROK|TERRNO, NULL, "kill() failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000356 (void)par_kill();
357 cleanup();
358 }
plars865695b2001-08-27 22:15:12 +0000359
subrata_modak56207ce2009-03-23 13:35:39 +0000360 /*
361 * Sleep for a while to allow the children to get a chance to
362 * catch the signal.
363 */
364 (void)sleep(SLEEP_TIME);
mreed1062091702006-09-06 16:45:02 +0000365
subrata_modak56207ce2009-03-23 13:35:39 +0000366 /*
367 * The signal was sent above and time has run out for child response,
368 * check the outcomes.
369 */
370 read1_stat = read(pipe1_fd[0], pipe_buf, 1);
371 if (read1_stat == -1 && errno == EAGAIN)
372 read1_stat = 0;
373 read2_stat = read(pipe2_fd[0], pipe_buf, 1);
374 if (read2_stat == -1 && errno == EAGAIN)
375 read2_stat = 0;
376 readA_stat = read(pipeA_fd[0], pipe_buf, 1);
377 if (readA_stat == -1 && errno == EAGAIN)
378 readA_stat = 0;
379 readB_stat = read(pipeB_fd[0], pipe_buf, 1);
380 if (readB_stat == -1 && errno == EAGAIN)
381 readB_stat = 0;
mreed1062091702006-09-06 16:45:02 +0000382
subrata_modak56207ce2009-03-23 13:35:39 +0000383 if (read1_stat == -1 || read2_stat == -1 ||
384 readA_stat == -1 || readB_stat == -1) {
385 /*
386 * The read system call failed.
387 */
vapiere7a6ab52009-08-28 13:20:15 +0000388 tst_brkm(TBROK|TERRNO, NULL, "read() failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000389 (void)par_kill();
390 cleanup();
391 }
mreed1062091702006-09-06 16:45:02 +0000392
subrata_modak56207ce2009-03-23 13:35:39 +0000393 /*
394 * Check the processes that were supposed to get the signal.
395 */
396 if (read1_stat == SIG_RECEIVED) {
397 if (readA_stat == SIG_RECEIVED) {
398 /*
399 * Both processes, 1 and A, that were supposed to receive
400 * the signal did receive the signal.
401 */
402 if (STD_FUNCTIONAL_TEST)
403 tst_resm(TPASS,
404 "The signal was sent to all processes in the process group.");
405 else
406 Tst_count++;
407 } else { /*Process A didn't receive the signal. */
408 tst_resm(TFAIL,
409 "Process A did not receive the signal.");
410 }
mreed1062091702006-09-06 16:45:02 +0000411
subrata_modak56207ce2009-03-23 13:35:39 +0000412 } else { /*Process 1 didn't receive the signal. */
413 tst_resm(TFAIL, "Process 1 did not receive the signal.");
414 }
415
416 /*
417 * Check the processes that were not supposed to get the signal.
418 */
419 if (read2_stat == SIG_NOT_RECD) {
420 if (readB_stat == SIG_NOT_RECD) {
421 /*
422 * Both processes, 2 and B did not receive the signal.
423 */
424 if (STD_FUNCTIONAL_TEST)
425 tst_resm(TPASS,
426 "The signal was not sent to selective processes that were not in the process group.");
427 else
428 Tst_count++;
429 } else { /*Process B received the signal. */
430 tst_resm(TFAIL, "Process B received the signal.");
431 }
432
433 }
434
435 else { /*Process 2 received the signal. */
436
437 tst_resm(TFAIL, "Process 2 received the signal.");
438 }
439
440 (void)par_kill();
441
442 (void)alarm(TIMEOUT);
443 while ((read(pipe1_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
444 strncpy(buf_tmp1, pipe_buf, 1);
445
subrata_modak56207ce2009-03-23 13:35:39 +0000446} /*End of parent_rout */
mreed1062091702006-09-06 16:45:02 +0000447
plars865695b2001-08-27 22:15:12 +0000448void child1_rout()
449{
subrata_modak56207ce2009-03-23 13:35:39 +0000450 who_am_i = '1';
plars865695b2001-08-27 22:15:12 +0000451
plars865695b2001-08-27 22:15:12 +0000452 /*
subrata_modak56207ce2009-03-23 13:35:39 +0000453 * Set to catch the SIGUSR1 with int1_rout.
plars865695b2001-08-27 22:15:12 +0000454 */
subrata_modak56207ce2009-03-23 13:35:39 +0000455 if (signal(SIGUSR1, usr1_rout) == SIG_ERR) {
456 tst_brkm(TBROK, NULL,
457 "Could not set to catch the childrens signal.");
458 (void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
robbiewd34d5812005-07-11 22:28:09 +0000459 exit(0);
460 }
subrata_modak56207ce2009-03-23 13:35:39 +0000461 /*
462 * Create children A & B.
463 */
464 if ((pidA = FORK_OR_VFORK()) > 0) {
465 /*
466 * This is the parent(child1), fork again to create child B.
467 */
468 if ((pidB = FORK_OR_VFORK()) == 0) {
469 /* This is child B. */
470#ifdef UCLINUX
471 if (self_exec(argv0, "nd", 2, pipeB_fd[1]) < 0) {
vapiere7a6ab52009-08-28 13:20:15 +0000472 tst_brkm(TBROK|TERRNO, NULL, "self_exec() failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000473 (void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
474 exit(0);
475 }
robbiewd34d5812005-07-11 22:28:09 +0000476#else
subrata_modak56207ce2009-03-23 13:35:39 +0000477 (void)childB_rout();
478#endif
479 }
480
481 else if (pidB == -1) {
482 /*
483 * The fork of child B failed kill child A.
484 */
485 if (kill(pidA, SIGKILL) == -1)
486 tst_resm(TWARN,
487 "Child process may not have been killed.");
Garrett Cooper42b35382010-12-19 07:28:44 -0800488 tst_brkm(TBROK|TERRNO, NULL, "fork failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000489 (void)write(pipe2_fd[1], CHAR_SET_FAILED, 1);
490 exit(0);
491 }
492 }
493
494 else if (pidA == 0) {
495 /* This is child A. */
496#ifdef UCLINUX
497 if (self_exec(argv0, "nd", 1, pipeA_fd[1]) < 0) {
vapiere7a6ab52009-08-28 13:20:15 +0000498 tst_brkm(TBROK|TERRNO, NULL, "self_exec() failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000499 (void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
500 exit(0);
501 }
502#else
503 (void)childA_rout();
robbiewd34d5812005-07-11 22:28:09 +0000504#endif
plars865695b2001-08-27 22:15:12 +0000505
subrata_modak56207ce2009-03-23 13:35:39 +0000506 }
plars865695b2001-08-27 22:15:12 +0000507
subrata_modak56207ce2009-03-23 13:35:39 +0000508 else if (pidA == -1) {
509 /*
510 * The fork of child A failed.
511 */
Garrett Cooper42b35382010-12-19 07:28:44 -0800512 tst_brkm(TBROK|TERRNO, NULL, "fork failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000513 (void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
514 exit(0);
515 }
516
plars865695b2001-08-27 22:15:12 +0000517 /*
subrata_modak56207ce2009-03-23 13:35:39 +0000518 * Set to catch the SIGUSR2 with chld1_kill.
plars865695b2001-08-27 22:15:12 +0000519 */
subrata_modak56207ce2009-03-23 13:35:39 +0000520 if (signal(SIGUSR2, chld1_kill) == SIG_ERR) {
521 tst_brkm(TBROK, NULL,
522 "Could not set to catch the parents signal.");
523 (void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
524 (void)chld1_kill();
525 exit(0);
526 }
plars865695b2001-08-27 22:15:12 +0000527
subrata_modak56207ce2009-03-23 13:35:39 +0000528 /*
529 * Set to catch the alarm signal SIGALRM.
530 */
531 if (signal(SIGALRM, notify_timeout) == SIG_ERR) {
532 tst_brkm(TBROK, NULL,
533 "Could not set to catch the childs time out alarm.");
534 (void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
535 (void)chld1_kill();
536 exit(0);
537 }
plars865695b2001-08-27 22:15:12 +0000538
subrata_modak56207ce2009-03-23 13:35:39 +0000539 /*
540 * Setting to catch the signals worked now let the children start up.
541 * Set an alarm which causes a time out on the pipe read loop.
542 * The children A & B will notify the parent(child1) that set up is complete
543 * and the pass/fail status of set up.
544 */
545 (void)alarm(TIMEOUT - 40);
plars865695b2001-08-27 22:15:12 +0000546
subrata_modak56207ce2009-03-23 13:35:39 +0000547 while ((read(pipeA_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
548 /*EMPTY*/;
549 (void)alarm(TIMEOUT - 40);
plars865695b2001-08-27 22:15:12 +0000550
subrata_modak56207ce2009-03-23 13:35:39 +0000551 while ((read(pipeB_fd[0], pipe_buf, 1) != 1) && (alarm_flag == FALSE))
552 /*EMPTY*/;
553 (void)alarm(0); /*Reset the alarm clock. */
plars865695b2001-08-27 22:15:12 +0000554
subrata_modak56207ce2009-03-23 13:35:39 +0000555 /*
556 * Check the alarm flag.
557 */
558 if (alarm_flag == TRUE) {
559 tst_brkm(TBROK, NULL,
560 "The set up of the children failed by timing out.");
561 (void)chld1_kill();
562 (void)write(pipe1_fd[1], CHAR_SET_FAILED, 1);
563 exit(0);
564 }
plars865695b2001-08-27 22:15:12 +0000565
subrata_modak56207ce2009-03-23 13:35:39 +0000566 /*
567 * Send a set up complete message to the parent.
568 */
569 (void)write(pipe1_fd[1], CHAR_SET_PASSED, 1);
plars865695b2001-08-27 22:15:12 +0000570
subrata_modak56207ce2009-03-23 13:35:39 +0000571 /*
572 * Pause until the signal SIGUSR1 or SIGUSR2 is sent from the parent.
573 */
574 (void)pause();
plars865695b2001-08-27 22:15:12 +0000575
subrata_modak56207ce2009-03-23 13:35:39 +0000576 /*
577 * Pause until signal SIGUSR2 is sent from the parent.
578 * This pause will only be executed if SIGUSR2 has not been received yet.
579 */
580 while (1) {
581 sleep(1);
582 }
plars865695b2001-08-27 22:15:12 +0000583
subrata_modak56207ce2009-03-23 13:35:39 +0000584} /*End of child1_rout */
plars865695b2001-08-27 22:15:12 +0000585
586/*******************************************************************************
587 * This is the routine for child 2, which should not receive the parents signal.
588 ******************************************************************************/
589void child2_rout()
590{
subrata_modak56207ce2009-03-23 13:35:39 +0000591 who_am_i = '2';
plars865695b2001-08-27 22:15:12 +0000592
subrata_modak56207ce2009-03-23 13:35:39 +0000593 /*
594 * Set the process group of this process to be different
595 * than the other processes.
596 */
597 (void)setpgrp();
plars865695b2001-08-27 22:15:12 +0000598
subrata_modak56207ce2009-03-23 13:35:39 +0000599 /*
600 * Set to catch the SIGUSR1 with usr1_rout.
601 */
602 if (signal(SIGUSR1, usr1_rout) == SIG_ERR) {
603 tst_brkm(TBROK, cleanup,
604 "Could not set to catch the parents signal.");
605 (void)write(pipe2_fd[1], CHAR_SET_FAILED, 1);
606 exit(0);
607 }
plars865695b2001-08-27 22:15:12 +0000608
subrata_modak56207ce2009-03-23 13:35:39 +0000609 /* Send a set up complete message to parent. */
610 (void)write(pipe2_fd[1], CHAR_SET_PASSED, 1);
plars865695b2001-08-27 22:15:12 +0000611
subrata_modak56207ce2009-03-23 13:35:39 +0000612 /*
613 * Pause until killed by the parent or SIGUSR1 is received.
614 */
615 (void)pause();
plars865695b2001-08-27 22:15:12 +0000616}
617
plars865695b2001-08-27 22:15:12 +0000618/*******************************************************************************
619 * This is the routine for child A, which should receive the parents signal.
620 ******************************************************************************/
621void childA_rout()
622{
subrata_modak56207ce2009-03-23 13:35:39 +0000623 who_am_i = 'A';
plars865695b2001-08-27 22:15:12 +0000624
subrata_modak56207ce2009-03-23 13:35:39 +0000625 /* Send a set up complete message to parent. */
626 write(pipeA_fd[1], CHAR_SET_PASSED, 1);
plars865695b2001-08-27 22:15:12 +0000627
subrata_modak56207ce2009-03-23 13:35:39 +0000628 /*
629 * Pause until killed by the parent or SIGUSR1 is received.
630 */
631 (void)pause();
plars865695b2001-08-27 22:15:12 +0000632
subrata_modak56207ce2009-03-23 13:35:39 +0000633 exit(0);
634} /*End of childA_rout */
plars865695b2001-08-27 22:15:12 +0000635
robbiewd34d5812005-07-11 22:28:09 +0000636#ifdef UCLINUX
637/*******************************************************************************
638 * This is the routine for child A after self_exec
639 ******************************************************************************/
640void childA_rout_uclinux()
641{
subrata_modak56207ce2009-03-23 13:35:39 +0000642 /* Setup the signal handler again */
643 if (signal(SIGUSR1, usr1_rout) == SIG_ERR) {
644 tst_brkm(TBROK, NULL,
645 "Could not set to catch the childrens signal.");
646 (void)write(pipeA_fd[1], CHAR_SET_FAILED, 1);
647 exit(0);
648 }
robbiewd34d5812005-07-11 22:28:09 +0000649
subrata_modak56207ce2009-03-23 13:35:39 +0000650 childA_rout();
robbiewd34d5812005-07-11 22:28:09 +0000651}
652#endif
653
plars865695b2001-08-27 22:15:12 +0000654/*******************************************************************************
655 * This is the routine for child B, which should not receive the parents signal.
656 ******************************************************************************/
657void childB_rout()
658{
subrata_modak56207ce2009-03-23 13:35:39 +0000659 who_am_i = 'B';
plars865695b2001-08-27 22:15:12 +0000660
subrata_modak56207ce2009-03-23 13:35:39 +0000661 /*
662 * Set the process group of this process to be different
663 * than the other processes.
664 */
665 (void)setpgrp();
plars865695b2001-08-27 22:15:12 +0000666
subrata_modak56207ce2009-03-23 13:35:39 +0000667 /* Send a set up complete message to parent(child 1). */
668 write(pipeB_fd[1], CHAR_SET_PASSED, 1);
plars865695b2001-08-27 22:15:12 +0000669
subrata_modak56207ce2009-03-23 13:35:39 +0000670 /*
671 * Pause until killed by the parent(child 1) or SIGUSR1 is received.
672 */
673 (void)pause();
plars865695b2001-08-27 22:15:12 +0000674
subrata_modak56207ce2009-03-23 13:35:39 +0000675 exit(0);
plars865695b2001-08-27 22:15:12 +0000676}
robbiewd34d5812005-07-11 22:28:09 +0000677
678#ifdef UCLINUX
679/*******************************************************************************
680 * This is the routine for child B after self_exec
681 ******************************************************************************/
682void childB_rout_uclinux()
683{
subrata_modak56207ce2009-03-23 13:35:39 +0000684 /* Setup the signal handler again */
685 if (signal(SIGUSR1, usr1_rout) == SIG_ERR) {
686 tst_brkm(TBROK, NULL,
687 "Could not set to catch the childrens signal.");
688 (void)write(pipeB_fd[1], CHAR_SET_FAILED, 1);
689 exit(0);
690 }
robbiewd34d5812005-07-11 22:28:09 +0000691
subrata_modak56207ce2009-03-23 13:35:39 +0000692 childB_rout();
robbiewd34d5812005-07-11 22:28:09 +0000693}
694#endif
Garrett Cooper2c282152010-12-16 00:55:50 -0800695
plars865695b2001-08-27 22:15:12 +0000696/*******************************************************************************
697 * This routine sets up the interprocess communication pipes, signal handling,
698 * and process group information.
699 ******************************************************************************/
subrata_modak56207ce2009-03-23 13:35:39 +0000700void setup()
plars865695b2001-08-27 22:15:12 +0000701{
subrata_modak56207ce2009-03-23 13:35:39 +0000702 int errno_buf; /*indicates the errno if pipe set up fails. */
703 int err_flag = FALSE; /*Indicates if an error has occurred in pipe set up. */
plars865695b2001-08-27 22:15:12 +0000704
subrata_modak56207ce2009-03-23 13:35:39 +0000705 /*
706 * Set the process group ID to be equal between the parent and children.
707 */
708 (void)setpgrp();
plars865695b2001-08-27 22:15:12 +0000709
subrata_modak56207ce2009-03-23 13:35:39 +0000710 /*
711 * Set to catch unexpected signals.
712 * SIGCLD is set to be ignored because we do not wait for termination status.
713 * SIGUSR1 is set to be ignored because this is the signal we are using for
714 * the test and we are not concerned with the parent getting it.
715 */
Garrett Cooper2c282152010-12-16 00:55:50 -0800716
subrata_modak56207ce2009-03-23 13:35:39 +0000717 tst_sig(FORK, DEF_HANDLER, cleanup);
plars865695b2001-08-27 22:15:12 +0000718
subrata_modak56207ce2009-03-23 13:35:39 +0000719 if (signal(SIGUSR1, SIG_IGN) == SIG_ERR) {
vapiere7a6ab52009-08-28 13:20:15 +0000720 tst_brkm(TBROK|TFAIL, NULL, "signal(SIGUSR1, SIG_IGN) failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000721 tst_exit();
plars865695b2001-08-27 22:15:12 +0000722 }
723
subrata_modak56207ce2009-03-23 13:35:39 +0000724 if (signal(SIGCLD, SIG_IGN) == SIG_ERR) {
vapiere7a6ab52009-08-28 13:20:15 +0000725 tst_brkm(TBROK|TERRNO, NULL, "signal(SIGCLD, SIG_IGN) failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000726 tst_exit();
plars865695b2001-08-27 22:15:12 +0000727 }
728
subrata_modak56207ce2009-03-23 13:35:39 +0000729 /* Indicate which errnos are expected */
730 TEST_EXP_ENOS(exp_enos);
plars865695b2001-08-27 22:15:12 +0000731
subrata_modak56207ce2009-03-23 13:35:39 +0000732 TEST_PAUSE;
plars865695b2001-08-27 22:15:12 +0000733
subrata_modak56207ce2009-03-23 13:35:39 +0000734 /*
735 * Set up pipe1, pipe2, pipeA, and pipeB.
736 */
737 if ((pipe(pipe1_fd) == -1)
738 || (fcntl(pipe1_fd[0], F_SETFL, O_NDELAY) == -1)) {
739 errno_buf = errno;
740 err_flag = TRUE;
741 }
plars865695b2001-08-27 22:15:12 +0000742
subrata_modak56207ce2009-03-23 13:35:39 +0000743 if ((pipe(pipe2_fd) == -1)
744 || (fcntl(pipe2_fd[0], F_SETFL, O_NDELAY) == -1)) {
745 errno_buf = errno;
746 err_flag = TRUE;
747 }
plars865695b2001-08-27 22:15:12 +0000748
subrata_modak56207ce2009-03-23 13:35:39 +0000749 if ((pipe(pipeA_fd) == -1)
750 || (fcntl(pipeA_fd[0], F_SETFL, O_NDELAY) == -1)) {
751 errno_buf = errno;
752 err_flag = TRUE;
753 }
plars865695b2001-08-27 22:15:12 +0000754
subrata_modak56207ce2009-03-23 13:35:39 +0000755 if ((pipe(pipeB_fd) == -1)
756 || (fcntl(pipeB_fd[0], F_SETFL, O_NDELAY) == -1)) {
757 errno_buf = errno;
758 err_flag = TRUE;
759 }
plars865695b2001-08-27 22:15:12 +0000760
subrata_modak56207ce2009-03-23 13:35:39 +0000761 /*
762 * Check for errors.
763 */
764 if (err_flag == TRUE) {
vapiere7a6ab52009-08-28 13:20:15 +0000765 tst_brkm(TBROK|TERRNO, NULL, "pipe() failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000766 tst_exit();
767 }
768 return;
plars865695b2001-08-27 22:15:12 +0000769
770}
771
772/***********************************************************
773 * This routine indicates that the process caught SIGUSR1.
774 **********************************************************/
775void usr1_rout()
776{
subrata_modak56207ce2009-03-23 13:35:39 +0000777 switch (who_am_i) {
778 case '1':
779 if (write(pipe1_fd[1], SIG_CAUGHT, 1) == -1)
780 tst_resm(TWARN,
781 "Writing signal catching status failed in child 1.");
782 break;
783 case '2':
784 if (write(pipe2_fd[1], SIG_CAUGHT, 1) == -1)
785 tst_resm(TWARN,
786 "Writing signal catching status failed in child 2.");
787 break;
788 case 'A':
789 if (write(pipeA_fd[1], SIG_CAUGHT, 1) == -1)
790 tst_resm(TWARN,
791 "Writing signal catching status failed in child A.");
792 break;
793 case 'B':
794 if (write(pipeB_fd[1], SIG_CAUGHT, 1) == -1)
795 tst_resm(TWARN,
796 "Writing signal catching status failed in child B.");
797 break;
plars865695b2001-08-27 22:15:12 +0000798 default:
vapiere7a6ab52009-08-28 13:20:15 +0000799 tst_resm(TWARN,
800 "Unexpected value %d for who_am_i in usr1_rout()",
subrata_modak56207ce2009-03-23 13:35:39 +0000801 who_am_i);
subrata_modak56207ce2009-03-23 13:35:39 +0000802 break;
803 }
plars865695b2001-08-27 22:15:12 +0000804
subrata_modak56207ce2009-03-23 13:35:39 +0000805} /*End of usr1_rout */
plars865695b2001-08-27 22:15:12 +0000806
807/***********************************************************
808 * This routine handles the timeout alarm in the parent,
809 * which occurs when the child fails to notify the parent
810 * the status of set up.
811 **********************************************************/
812void notify_timeout()
813{
subrata_modak56207ce2009-03-23 13:35:39 +0000814 alarm_flag = TRUE;
plars865695b2001-08-27 22:15:12 +0000815
subrata_modak56207ce2009-03-23 13:35:39 +0000816} /*End of notify_timeout */
Garrett Cooper2c282152010-12-16 00:55:50 -0800817
plars865695b2001-08-27 22:15:12 +0000818/***********************************************************
subrata_modak4bb656a2009-02-26 12:02:09 +0000819 * This routine handles the procedure for removing the
plars865695b2001-08-27 22:15:12 +0000820 * children forked off during this test.
821 **********************************************************/
822void par_kill()
823{
robbiew8f837d72005-06-15 15:47:04 +0000824 int status;
825
subrata_modak56207ce2009-03-23 13:35:39 +0000826 /*
827 * Indicate to child1 that it can remove it's children and itself now.
828 */
829 if (kill(pid1, SIGUSR2) == -1 && errno != ESRCH) {
vapiere7a6ab52009-08-28 13:20:15 +0000830 tst_resm(TWARN|TERRNO, "kill() failed");
831 tst_resm(TWARN, "Child 1 and it's children may still be alive.");
subrata_modak56207ce2009-03-23 13:35:39 +0000832 }
plars865695b2001-08-27 22:15:12 +0000833
subrata_modak56207ce2009-03-23 13:35:39 +0000834 /*
835 * Remove child 2.
836 */
837 if (kill(pid2, SIGKILL) == -1 && errno != ESRCH)
838 tst_resm(TWARN, "Child2 may still be alive.");
plars865695b2001-08-27 22:15:12 +0000839
subrata_modak56207ce2009-03-23 13:35:39 +0000840 wait(&status);
841 return;
subrata_modakbdbaec52009-02-26 12:14:51 +0000842
subrata_modak56207ce2009-03-23 13:35:39 +0000843} /*End of par_kill */
plars865695b2001-08-27 22:15:12 +0000844
845/*********************************************************************
846 * This routine is executed by child 1 when the parent tells it to
847 * remove it's children and itself.
848 ********************************************************************/
849void chld1_kill()
850{
subrata_modak56207ce2009-03-23 13:35:39 +0000851 /*
852 * Remove children A & B.
853 */
vapiere7a6ab52009-08-28 13:20:15 +0000854 if (kill(pidA, SIGKILL) == -1 && errno != ESRCH)
855 tst_resm(TWARN|TERRNO, "kill(%d) failed; child 1's(A) child may still be alive", pidA);
mreed1062091702006-09-06 16:45:02 +0000856
subrata_modak56207ce2009-03-23 13:35:39 +0000857 (void)write(pipe1_fd[1], CHAR_SET_PASSED, 1);
mreed1062091702006-09-06 16:45:02 +0000858
vapiere7a6ab52009-08-28 13:20:15 +0000859 if (kill(pidB, SIGKILL) == -1 && errno != ESRCH)
860 tst_resm(TWARN|TERRNO, "kill(%d) failed; child 1's(B) child may still be alive", pidB);
mreed1062091702006-09-06 16:45:02 +0000861
subrata_modak56207ce2009-03-23 13:35:39 +0000862 exit(0);
plars865695b2001-08-27 22:15:12 +0000863
subrata_modak56207ce2009-03-23 13:35:39 +0000864} /*End of chld1_kill */
plars865695b2001-08-27 22:15:12 +0000865
866/***************************************************************
867 * cleanup() - performs all ONE TIME cleanup for this test at
868 * completion or premature exit.
869 ***************************************************************/
subrata_modak56207ce2009-03-23 13:35:39 +0000870void cleanup()
plars865695b2001-08-27 22:15:12 +0000871{
subrata_modak56207ce2009-03-23 13:35:39 +0000872 /*
873 * print timing stats if that option was specified.
874 * print errno log if that option was specified.
875 */
876 TEST_CLEANUP;
plars865695b2001-08-27 22:15:12 +0000877
Chris Dearmanec6edca2012-10-17 19:54:01 -0700878}