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