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