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 recieve 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 recieved 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