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: kill10.c,v 1.7 2009/03/23 13:35:53 subrata_modak Exp $ */ 34 /********************************************************** 35 * 36 * OS Test - Silicon Graphics, Inc. 37 * 38 * TEST IDENTIFIER : kill10 39 * 40 * EXECUTED BY : anyone 41 * 42 * TEST TITLE : signal flooding test 43 * 44 * TEST CASE TOTAL : 1 45 * 46 * WALL CLOCK TIME : 47 * 48 * CPU TYPES : ALL 49 * 50 * AUTHOR : Nate Straz 51 * 52 * DATE STARTED : 04/09/2001 53 * 54 * INITIAL RELEASE : Linux 2.4.x 55 * 56 * TEST CASES 57 * 58 * 1.) Create a large number of processes and signal between them. 59 * 60 * INPUT SPECIFICATIONS 61 * The standard options for system call tests are accepted. 62 * (See the parse_opts(3) man page). 63 * 64 * OUTPUT SPECIFICATIONS 65 *$ 66 * DURATION 67 * Terminates - with frequency and infinite modes. 68 * 69 * SIGNALS 70 * Uses SIGUSR1 to pause before test if option set. 71 * (See the parse_opts(3) man page). 72 * 73 * RESOURCES 74 * None 75 * 76 * ENVIRONMENTAL NEEDS 77 * No run-time environmental needs. 78 * 79 * SPECIAL PROCEDURAL REQUIREMENTS 80 * None 81 * 82 * INTERCASE DEPENDENCIES 83 * None 84 * 85 * DETAILED DESCRIPTION 86 * This test creates -g groups of -n processes each and prepares them to send 87 * large numbers of signals. All process fall into three levels. 88 * * Level 1 - Master 89 * This is the parent of all processes. It handles test looping 90 * and making sure that all level 2 Managers report in. 91 * SIGUSR1 -> ack Manager is ready 92 * SIGUSR2 -> ack Manager is done and sends reset 93 * * Level 2 - Managers 94 * There are -g (default 2) of these processes. They handle 95 * forking off -n procs and setting up their signal handling. 96 * Managers are in a pgid with their Children. 97 * SIGALRM -> Process making your children 98 * SIGUSR1 -> 99 * SIGUSR2 -> Reply to Child to stop 100 * SIGHUP -> Reset child signal counter 101 * SIGQUIT -> Exit gracefully 102 * * Level 3 - Child 103 * There are -n (default 10) of these process per Manager. Their 104 * only job is to send signals to their Managers when told to by 105 * the Master. 106 * SIGUSR1 -> Start signaling Manager 107 * SIGUSR2 -> Stop signaling Manager 108 * SIGHUP -> IGNORE 109 * SIGQUIT -> Exit gracefully 110 * 111 * During each test loop, Master sends SIGUSR1 to the pgid of each Manager. 112 * This tells the Children to start signalling their manager. They do this 113 * until the manager signals them to stop. Once the manager finds that all 114 * children have been signaled (by checking them off in the checklist), the 115 * Manager signals the Master. Once the Master acknowledges that all Managers 116 * have talked to all their Children, the test iteration is over. 117 * 118 * Setup: 119 * Pause for SIGUSR1 if option specified. 120 * Fork -g Managers 121 * Set up signal handling for Children 122 * Fork -n Children for each manager 123 * Set up signal handling for Managers 124 * Set up signal handling for Master 125 * 126 * Test: 127 * Loop if the proper options are given. 128 * Send SIGUSR1 to all Managers and their Children 129 * Wait for Managers to send SIGUSR2 130 * 131 * Cleanup: 132 * Send SIGQUIT to all Manager process groups and wait for Manager to quit. 133 * Print errno log and/or timing stats if options given 134 * 135 * Debugging: 136 * 0 - normal operations 137 * 1 - Master setup 138 * 2 - Master processing 139 * 3 - Master - Manager interaction 140 * 4 - Manager setup 141 * 5 - Manager processing 142 * 6 - Manager - Child interaction 143 * 7 - Child setup 144 * 8 - Child processing 145 * 146 * 147 *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/ 148 149 #include <sys/types.h> 150 #include <sys/wait.h> 151 #include <fcntl.h> 152 #include <dirent.h> 153 #include <unistd.h> 154 #include <stdlib.h> 155 #include <errno.h> 156 #include <string.h> 157 #include <signal.h> 158 #include "test.h" 159 160 void setup(); 161 void help(); 162 void cleanup(); 163 void fork_pgrps(int pgrps_left); 164 void manager(int num_procs); 165 void fork_procs(int procs_left); 166 167 /* signal handlers */ 168 void ack_ready(int sig, siginfo_t * si, void *data); 169 void ack_done(int sig, siginfo_t * si, void *data); 170 void set_create_procs(int sig); 171 void graceful_exit(int sig); 172 void set_signal_parents(int sig); 173 void clear_signal_parents(int sig); 174 void set_confirmed_ready(int sig); 175 void reset_counter(int sig); 176 void reply_to_child(int sig, siginfo_t * si, void *data); 177 void wakeup(int sig); 178 179 /* pid checklist management */ 180 struct pid_list_item { 181 pid_t pid; 182 short flag; 183 } *child_checklist = NULL; 184 int child_checklist_total = 0; 185 int checklist_cmp(const void *a, const void *b); 186 void checklist_reset(int bit); 187 188 static inline int k_sigaction(int sig, struct sigaction *sa, struct sigaction *osa); 189 190 char *TCID = "kill10"; 191 int TST_TOTAL = 1; 192 193 int num_procs = 10; 194 int num_pgrps = 2; 195 int pgrps_ready = 0; 196 int child_signal_counter = 0; 197 198 int create_procs_flag = 0; 199 int signal_parents_flag = 0; 200 int confirmed_ready_flag = 0; 201 int debug_flag = 0; 202 pid_t mypid = 0; 203 204 char *narg, *garg, *darg; 205 int nflag = 0, gflag = 0, dflag = 0; 206 207 option_t options[] = { 208 {"n:", &nflag, &narg}, /* -n #procs */ 209 {"g:", &gflag, &garg}, /* -g #pgrps */ 210 {"d:", &dflag, &darg}, /* -d <debug level> */ 211 {NULL, NULL, NULL} 212 }; 213 main(int ac,char ** av)214 int main(int ac, char **av) 215 { 216 int lc; 217 int cnt; 218 219 tst_parse_opts(ac, av, options, &help); 220 221 if (nflag) { 222 if (sscanf(narg, "%i", &num_procs) != 1) { 223 tst_brkm(TBROK, NULL, "-n option arg is not a number"); 224 } 225 } 226 if (gflag) { 227 if (sscanf(garg, "%i", &num_pgrps) != 1) { 228 tst_brkm(TBROK, NULL, "-g option arg is not a number"); 229 } 230 } 231 232 if (dflag) { 233 if (sscanf(darg, "%i", &debug_flag) != 1) { 234 tst_brkm(TBROK, NULL, "-d option arg is not a number"); 235 } 236 } 237 238 setup(); 239 240 for (lc = 0; TEST_LOOPING(lc); lc++) { 241 242 tst_count = 0; 243 child_signal_counter = 0; 244 pgrps_ready = 0; 245 checklist_reset(0x03); 246 247 /* send SIGUSR1 to each pgroup */ 248 for (cnt = 0; cnt < child_checklist_total; ++cnt) { 249 if (debug_flag >= 2) 250 printf("%d: test_loop, SIGUSR1 -> %d\n", 251 mypid, -child_checklist[cnt].pid); 252 kill(-child_checklist[cnt].pid, SIGUSR1); 253 } 254 255 /* wait for the managers to signal they are done */ 256 while (child_signal_counter < num_pgrps) { 257 alarm(1); 258 if (debug_flag >= 2) 259 printf("%d: Master pausing for done (%d/%d)\n", 260 mypid, child_signal_counter, num_pgrps); 261 pause(); 262 } 263 tst_resm(TPASS, "All %d pgrps received their signals", 264 child_signal_counter); 265 266 } 267 268 cleanup(); 269 270 tst_exit(); 271 } 272 help(void)273 void help(void) 274 { 275 printf(" -g n Create n process groups (default: %d)\n", num_pgrps); 276 printf 277 (" -n n Create n children in each process group (default: %d)\n", 278 num_procs); 279 printf(" -d n Set debug level to n (default: %d)\n", debug_flag); 280 } 281 setup(void)282 void setup(void) 283 { 284 struct sigaction sa; 285 int i; 286 287 /* You will want to enable some signal handling so you can capture 288 * unexpected signals like SIGSEGV. 289 */ 290 tst_sig(FORK, DEF_HANDLER, cleanup); 291 292 /* One cavet that hasn't been fixed yet. TEST_PAUSE contains the code to 293 * fork the test with the -c option. You want to make sure you do this 294 * before you create your temporary directory. 295 */ 296 TEST_PAUSE; 297 298 mypid = getpid(); 299 sa.sa_handler = SIG_DFL; 300 sigemptyset(&sa.sa_mask); 301 sa.sa_flags = 0; 302 if (debug_flag >= 1) 303 printf("%d: setting SIGTRAP -> SIG_DFL\n", mypid); 304 k_sigaction(SIGTRAP, &sa, NULL); 305 if (debug_flag >= 1) 306 printf("%d: setting SIGCONT -> SIG_DFL\n", mypid); 307 k_sigaction(SIGCONT, &sa, NULL); 308 309 sa.sa_handler = set_create_procs; 310 if (debug_flag >= 4) 311 printf("%d: setting SIGALRM -> set_create_procs\n", mypid); 312 k_sigaction(SIGALRM, &sa, NULL); 313 314 sa.sa_handler = NULL; 315 sa.sa_sigaction = ack_ready; 316 sa.sa_flags = SA_SIGINFO; 317 if (debug_flag >= 1) 318 printf("%d: setting SIGUSR1 -> ack_ready\n", mypid); 319 k_sigaction(SIGUSR1, &sa, NULL); 320 321 fork_pgrps(num_pgrps); 322 323 /* wait for all pgrps to report in */ 324 if (debug_flag) 325 printf("Master: %d\n", mypid); 326 while (pgrps_ready < num_pgrps) { 327 if (debug_flag >= 3) 328 printf 329 ("%d: Master pausing for Managers to check in (%d/%d)\n", 330 mypid, pgrps_ready, num_pgrps); 331 /* 332 * We might receive the signal from the (last manager) before 333 * we issue a pause. In that case we might hang even if we have 334 * all the managers reported in. So set an alarm so that we can 335 * wake up. 336 */ 337 alarm(1); 338 339 pause(); 340 } 341 checklist_reset(0x03); 342 if (debug_flag) { 343 printf("Managers: \n"); 344 for (i = 0; i < num_pgrps; i++) { 345 printf("%d ", child_checklist[i].pid); 346 } 347 printf("\n"); 348 } 349 350 /* set up my signal processing */ 351 /* continue on ALRM */ 352 sa.sa_handler = wakeup; 353 if (debug_flag >= 4) 354 printf("%d: setting SIGALRM -> wakeup\n", mypid); 355 k_sigaction(SIGALRM, &sa, NULL); 356 /* reply to child on USR2 */ 357 sa.sa_handler = NULL; 358 sa.sa_sigaction = ack_done; 359 sa.sa_flags = SA_SIGINFO; 360 if (debug_flag >= 1) 361 printf("%d: setting SIGUSR2 -> ack_done\n", mypid); 362 k_sigaction(SIGUSR2, &sa, NULL); 363 } 364 ack_ready(int sig,siginfo_t * si,void * data)365 void ack_ready(int sig, siginfo_t * si, void *data) 366 { 367 struct pid_list_item findit, *result; 368 369 findit.pid = si->si_pid; 370 371 result = bsearch(&findit, child_checklist, child_checklist_total, 372 sizeof(*child_checklist), checklist_cmp); 373 if (result) { 374 if (!(result->flag & 0x01)) { 375 if (debug_flag >= 3) 376 printf("%d: ack_ready, SIGUSR1 -> %d\n", mypid, 377 si->si_pid); 378 kill(si->si_pid, SIGUSR1); 379 result->flag = result->flag | 0x01; 380 ++pgrps_ready; 381 } else { 382 if (debug_flag >= 3) 383 printf("%d: ack_ready, already acked %d\n", 384 mypid, si->si_pid); 385 } 386 } else { 387 printf("received unexpected signal %d from %d", 388 sig, si->si_pid); 389 } 390 } 391 ack_done(int sig,siginfo_t * si,void * data)392 void ack_done(int sig, siginfo_t * si, void *data) 393 { 394 struct pid_list_item findit, *result; 395 396 findit.pid = si->si_pid; 397 398 result = bsearch(&findit, child_checklist, child_checklist_total, 399 sizeof(*child_checklist), checklist_cmp); 400 if (result) { 401 if (!(result->flag & 0x02)) { 402 if (debug_flag >= 3) 403 printf("%d: ack_done, SIGHUP -> %d\n", mypid, 404 si->si_pid); 405 kill(si->si_pid, SIGHUP); 406 ++child_signal_counter; 407 result->flag = result->flag | 0x02; 408 } else { 409 if (debug_flag >= 3) 410 printf("%d: ack_done, already told %d\n", mypid, 411 si->si_pid); 412 } 413 } else { 414 printf("received unexpected signal %d from %d", 415 sig, si->si_pid); 416 } 417 } 418 419 /*************************************************************** 420 * cleanup() - performs all ONE TIME cleanup for this test at 421 * completion or premature exit. 422 ***************************************************************/ cleanup(void)423 void cleanup(void) 424 { 425 int i; 426 /* send SIGHUP to all pgroups */ 427 for (i = 0; i < num_pgrps; ++i) { 428 /* try to do this as nicely as possible */ 429 kill(-child_checklist[i].pid, SIGQUIT); 430 waitpid(child_checklist[i].pid, NULL, 0); 431 } 432 free(child_checklist); 433 434 } 435 436 /********************************************************************* 437 * fork_pgrps() forks off a child, changes it's pgrp, then continues 438 ********************************************************************/ fork_pgrps(int pgrps_left)439 void fork_pgrps(int pgrps_left) 440 { 441 pid_t child; 442 443 if (!(child_checklist = calloc(pgrps_left, sizeof(*child_checklist)))) { 444 tst_brkm(TBROK, cleanup, 445 "%d: couldn't calloc child_checklist, errno=%d : %s", 446 mypid, errno, strerror(errno)); 447 } 448 child_checklist_total = 0; 449 while (pgrps_left) { 450 if (debug_flag >= 1) 451 printf("%d: forking new Manager\n", mypid); 452 switch (child = fork()) { 453 case -1: 454 tst_brkm(TBROK | TERRNO, cleanup, 455 "fork() failed in fork_pgrps(%d)", pgrps_left); 456 break; 457 case 0: 458 mypid = getpid(); 459 free(child_checklist); 460 child_checklist = NULL; 461 manager(num_procs); 462 break; 463 default: 464 child_checklist[child_checklist_total++].pid = child; 465 setpgid(child, child); 466 if (debug_flag >= 3) 467 printf("%d: fork_pgrps, SIGALRM -> %d\n", mypid, 468 child); 469 kill(child, SIGALRM); 470 } 471 --pgrps_left; 472 } 473 qsort(child_checklist, child_checklist_total, sizeof(*child_checklist), 474 checklist_cmp); 475 } 476 set_create_procs(int sig)477 void set_create_procs(int sig) 478 { 479 if (debug_flag >= 3) 480 printf("%d: Manager cleared to fork\n", getpid()); 481 create_procs_flag++; 482 return; 483 } 484 485 /********************************************************************* 486 * new_pgrg() - handle the creation of the pgrp managers and their 487 * children 488 ********************************************************************/ manager(int num_procs)489 void manager(int num_procs) 490 { 491 struct sigaction sa; 492 493 /* Wait for the parent to change our pgid before we start forking */ 494 while (!create_procs_flag) { 495 alarm(1); 496 if (debug_flag >= 3) 497 printf("%d: Manager pausing, not cleared to fork\n", 498 mypid); 499 pause(); 500 } 501 502 /* set up the signal handling the children will use */ 503 504 /* ignore HUP */ 505 sa.sa_handler = SIG_IGN; 506 sigemptyset(&sa.sa_mask); 507 sa.sa_flags = 0; 508 if (debug_flag >= 4) 509 printf("%d: setting SIGHUP -> SIG_IGN\n", mypid); 510 k_sigaction(SIGHUP, &sa, NULL); 511 512 /* We use ALRM to make sure that we don't miss the signal effects ! */ 513 sa.sa_handler = wakeup; 514 if (debug_flag >= 4) 515 printf("%d: setting SIGALRM -> wakeup\n", mypid); 516 k_sigaction(SIGALRM, &sa, NULL); 517 518 /* exit on QUIT */ 519 sa.sa_handler = graceful_exit; 520 if (debug_flag >= 4) 521 printf("%d: setting SIGQUIT -> graceful_exit\n", mypid); 522 k_sigaction(SIGQUIT, &sa, NULL); 523 524 /* start signaling on USR1 */ 525 sa.sa_handler = set_signal_parents; 526 sigfillset(&sa.sa_mask); 527 if (debug_flag >= 7) 528 printf("%d: setting SIGUSR1 -> set_signal_parents\n", mypid); 529 k_sigaction(SIGUSR1, &sa, NULL); 530 /* stop signaling on USR2 */ 531 sa.sa_handler = clear_signal_parents; 532 if (debug_flag >= 7) 533 printf("%d: setting SIGUSR2 -> clear_signal_parents\n", mypid); 534 k_sigaction(SIGUSR2, &sa, NULL); 535 536 fork_procs(num_procs); 537 sleep(1); /* wait a sec to let all the children pause */ 538 539 /* now set up my signal handling */ 540 541 /* continue on ALRM */ 542 sa.sa_handler = wakeup; 543 if (debug_flag >= 4) 544 printf("%d: setting SIGALRM -> wakeup\n", mypid); 545 k_sigaction(SIGALRM, &sa, NULL); 546 /* mark ready confirmation on USR1 */ 547 sa.sa_handler = set_confirmed_ready; 548 if (debug_flag >= 4) 549 printf("%d: setting SIGUSR1 -> set_confirmed_ready\n", mypid); 550 k_sigaction(SIGUSR1, &sa, NULL); 551 /* reset our counter on HUP */ 552 sa.sa_handler = reset_counter; 553 if (debug_flag >= 4) 554 printf("%d: setting SIGHUP -> reset_counter\n", mypid); 555 k_sigaction(SIGHUP, &sa, NULL); 556 557 /* reply to child on USR2 */ 558 sa.sa_handler = NULL; 559 sa.sa_sigaction = reply_to_child; 560 sa.sa_flags = SA_SIGINFO; 561 if (debug_flag >= 4) 562 printf("%d: setting SIGUSR2 -> reply_to_child\n", mypid); 563 k_sigaction(SIGUSR2, &sa, NULL); 564 565 /* tell our parent that we are ready to rock */ 566 while (!confirmed_ready_flag) { 567 if (debug_flag >= 3) 568 printf("%d: Manager, SIGUSR1 -> %d\n", mypid, 569 getppid()); 570 if (kill(getppid(), SIGUSR1) == -1) { 571 printf("%d: Couldn't signal master (%d) that we're " 572 "ready. %d: %s", 573 mypid, getppid(), errno, strerror(errno)); 574 exit(errno); 575 } 576 usleep(100); 577 } 578 579 /* handle pgroup management while the tests are running */ 580 while (1) { 581 alarm(1); 582 if (debug_flag >= 5) 583 printf("%d: Manager pausing (%d/%d)\n", 584 mypid, child_signal_counter, num_procs); 585 pause(); 586 if (child_signal_counter >= num_procs) { 587 confirmed_ready_flag = 0; 588 printf("%d: All %d children reported in\n", 589 mypid, child_signal_counter); 590 while (child_signal_counter) { 591 if (debug_flag >= 3) 592 printf("%d: Manager, SIGUSR2 -> %d\n", 593 mypid, getppid()); 594 if (kill(getppid(), SIGUSR2) == -1) { 595 printf("%d: Couldn't signal master " 596 "(%d) that we're ready. %d: %s\n", 597 mypid, getppid(), errno, 598 strerror(errno)); 599 exit(errno); 600 } 601 usleep(100); 602 } 603 } 604 } 605 } 606 607 /* some simple signal handlers for the kids */ graceful_exit(int sig)608 void graceful_exit(int sig) 609 { 610 exit(0); 611 } 612 set_signal_parents(int sig)613 void set_signal_parents(int sig) 614 { 615 if (debug_flag >= 8) 616 printf("%d: Child start signaling\n", mypid); 617 signal_parents_flag = 1; 618 } 619 clear_signal_parents(int sig)620 void clear_signal_parents(int sig) 621 { 622 if (debug_flag >= 8) 623 printf("%d: Child stop signaling\n", mypid); 624 signal_parents_flag = 0; 625 } 626 set_confirmed_ready(int sig)627 void set_confirmed_ready(int sig) 628 { 629 630 if (debug_flag >= 3) 631 printf("%d: Manager confirmed ready\n", mypid); 632 confirmed_ready_flag = 1; 633 } 634 reset_counter(int sig)635 void reset_counter(int sig) 636 { 637 checklist_reset(0xFF); 638 child_signal_counter = 0; 639 if (debug_flag >= 3) 640 printf("%d: reset_counter\n", mypid); 641 } 642 reply_to_child(int sig,siginfo_t * si,void * data)643 void reply_to_child(int sig, siginfo_t * si, void *data) 644 { 645 struct pid_list_item findit, *result; 646 647 findit.pid = si->si_pid; 648 649 result = bsearch(&findit, child_checklist, child_checklist_total, 650 sizeof(*child_checklist), checklist_cmp); 651 if (result) { 652 if (!result->flag) { 653 if (debug_flag >= 6) 654 printf("%d: reply_to_child, SIGUSR1 -> %d\n", 655 mypid, si->si_pid); 656 kill(si->si_pid, SIGUSR2); 657 ++child_signal_counter; 658 result->flag = 1; 659 } else { 660 if (debug_flag >= 6) 661 printf("%d: reply_to_child, already told %d\n", 662 mypid, si->si_pid); 663 } 664 } else { 665 tst_brkm(TBROK, cleanup, 666 "received unexpected signal from %d", si->si_pid); 667 } 668 } 669 wakeup(int sig)670 void wakeup(int sig) 671 { 672 return; 673 } 674 675 /************************************************* 676 * fork_procs() - create all the children 677 ************************************************/ fork_procs(int procs_left)678 void fork_procs(int procs_left) 679 { 680 pid_t child; 681 682 if (!(child_checklist = calloc(procs_left, sizeof(*child_checklist)))) { 683 tst_brkm(TBROK, cleanup, 684 "%d: couldn't calloc child_checklist, errno=%d : %s", 685 mypid, errno, strerror(errno)); 686 } 687 child_checklist_total = 0; 688 689 /* We are setting the flag for children, to avoid missing any signals */ 690 signal_parents_flag = 0; 691 692 while (procs_left) { 693 if (debug_flag >= 4) 694 printf("%d: forking new child\n", mypid); 695 switch (child = fork()) { 696 case -1: 697 tst_brkm(TBROK | TERRNO, cleanup, 698 "fork() failed in fork_procs(%d)", procs_left); 699 break; 700 case 0: 701 mypid = getpid(); 702 while (1) { 703 /* wait to start */ 704 if (debug_flag >= 8) 705 printf("%d: child pausing\n", mypid); 706 /* 707 * If we have already received the signal, we dont 708 * want to pause for it ! 709 */ 710 while (!signal_parents_flag) { 711 alarm(2); 712 pause(); 713 } 714 715 /* if we started, call mama */ 716 while (signal_parents_flag) { 717 if (debug_flag >= 6) 718 printf("%d: child, SIGUSR2 " 719 "-> %d\n", 720 mypid, getppid()); 721 if (kill(getppid(), SIGUSR2) == -1) { 722 /* something went wrong */ 723 printf("%d: kill(ppid:%d, " 724 "SIGUSR2) failed. %d: %s", 725 mypid, getppid(), errno, 726 strerror(errno)); 727 exit(errno); 728 } 729 usleep(100); 730 } 731 } 732 break; 733 default: 734 child_checklist[child_checklist_total++].pid = child; 735 } 736 procs_left--; 737 } 738 qsort(child_checklist, child_checklist_total, sizeof(*child_checklist), 739 checklist_cmp); 740 } 741 checklist_cmp(const void * a,const void * b)742 int checklist_cmp(const void *a, const void *b) 743 { 744 const struct pid_list_item *pa = (const struct pid_list_item *)a; 745 const struct pid_list_item *pb = (const struct pid_list_item *)b; 746 747 return (pa->pid > pb->pid) - (pa->pid < pb->pid); 748 } 749 checklist_reset(int bit)750 void checklist_reset(int bit) 751 { 752 int i; 753 for (i = 0; i < child_checklist_total; i++) { 754 child_checklist[i].flag = child_checklist[i].flag & (~bit); 755 } 756 757 } 758 k_sigaction(int sig,struct sigaction * sa,struct sigaction * osa)759 static inline int k_sigaction(int sig, struct sigaction *sa, struct sigaction *osa) 760 { 761 int ret; 762 if ((ret = sigaction(sig, sa, osa)) == -1) { 763 tst_brkm(TBROK | TERRNO, cleanup, "sigaction(%d, ...) failed", 764 sig); 765 } 766 return ret; 767 } 768