robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 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 |
Wanlong Gao | fed9641 | 2012-10-24 10:10:29 +0800 | [diff] [blame] | 20 | * with this program; if not, write the Free Software Foundation, Inc., |
| 21 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 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 | */ |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 33 | /* $Id: kill10.c,v 1.7 2009/03/23 13:35:53 subrata_modak Exp $ */ |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 34 | /********************************************************** |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 35 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 36 | * OS Test - Silicon Graphics, Inc. |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 37 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 38 | * TEST IDENTIFIER : kill10 |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 39 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 40 | * EXECUTED BY : anyone |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 41 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 42 | * TEST TITLE : signal flooding test |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 43 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 44 | * TEST CASE TOTAL : 1 |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 45 | * |
| 46 | * WALL CLOCK TIME : |
| 47 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 48 | * CPU TYPES : ALL |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 49 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 50 | * AUTHOR : Nate Straz |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 51 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 52 | * DATE STARTED : 04/09/2001 |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 53 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 54 | * INITIAL RELEASE : Linux 2.4.x |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 55 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 56 | * TEST CASES |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 57 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 58 | * 1.) Create a large number of processes and signal between them. |
subrata_modak | bdbaec5 | 2009-02-26 12:14:51 +0000 | [diff] [blame] | 59 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 60 | * INPUT SPECIFICATIONS |
| 61 | * The standard options for system call tests are accepted. |
| 62 | * (See the parse_opts(3) man page). |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 63 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 64 | * OUTPUT SPECIFICATIONS |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 65 | *$ |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 66 | * DURATION |
| 67 | * Terminates - with frequency and infinite modes. |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 68 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 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 |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 75 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 76 | * ENVIRONMENTAL NEEDS |
| 77 | * No run-time environmental needs. |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 78 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 79 | * SPECIAL PROCEDURAL REQUIREMENTS |
| 80 | * None |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 81 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 82 | * INTERCASE DEPENDENCIES |
| 83 | * None |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 84 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 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 |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 98 | * SIGUSR1 -> |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 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 |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 125 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 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 |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 130 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 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 |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 145 | * |
| 146 | * |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 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" |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 159 | |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 160 | void setup(); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 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 */ |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 168 | void ack_ready(int sig, siginfo_t * si, void *data); |
| 169 | void ack_done(int sig, siginfo_t * si, void *data); |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 170 | void set_create_procs(int sig); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 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); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 176 | void reply_to_child(int sig, siginfo_t * si, void *data); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 177 | void wakeup(int sig); |
| 178 | |
| 179 | /* pid checklist management */ |
| 180 | struct pid_list_item { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 181 | pid_t pid; |
| 182 | short flag; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 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 | inline int k_sigaction(int sig, struct sigaction *sa, struct sigaction *osa); |
| 189 | |
Cyril Hrubis | fdce7d5 | 2013-04-04 18:35:48 +0200 | [diff] [blame] | 190 | char *TCID = "kill10"; |
| 191 | int TST_TOTAL = 1; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 192 | |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 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; |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 205 | int nflag = 0, gflag = 0, dflag = 0; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 206 | |
| 207 | /* for test specific parse_opts options */ |
| 208 | option_t options[] = { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 209 | {"n:", &nflag, &narg}, /* -n #procs */ |
| 210 | {"g:", &gflag, &garg}, /* -g #pgrps */ |
| 211 | {"d:", &dflag, &darg}, /* -d <debug level> */ |
| 212 | {NULL, NULL, NULL} |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 213 | }; |
| 214 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 215 | int main(int ac, char **av) |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 216 | { |
Cyril Hrubis | 89af32a | 2012-10-24 16:39:11 +0200 | [diff] [blame] | 217 | int lc; |
Cyril Hrubis | 0b9589f | 2014-05-27 17:40:33 +0200 | [diff] [blame] | 218 | const char *msg; |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 219 | int cnt; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 220 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 221 | if ((msg = parse_opts(ac, av, options, &help))) { |
Garrett Cooper | 5374050 | 2010-12-16 00:04:01 -0800 | [diff] [blame] | 222 | tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 223 | } |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 224 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 225 | if (nflag) { |
| 226 | if (sscanf(narg, "%i", &num_procs) != 1) { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 227 | tst_brkm(TBROK, NULL, "-n option arg is not a number"); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 228 | } |
| 229 | } |
| 230 | if (gflag) { |
| 231 | if (sscanf(garg, "%i", &num_pgrps) != 1) { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 232 | tst_brkm(TBROK, NULL, "-g option arg is not a number"); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 233 | } |
| 234 | } |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 235 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 236 | if (dflag) { |
| 237 | if (sscanf(darg, "%i", &debug_flag) != 1) { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 238 | tst_brkm(TBROK, NULL, "-d option arg is not a number"); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 239 | } |
| 240 | } |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 241 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 242 | setup(); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 243 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 244 | for (lc = 0; TEST_LOOPING(lc); lc++) { |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 245 | |
Caspar Zhang | d59a659 | 2013-03-07 14:59:12 +0800 | [diff] [blame] | 246 | tst_count = 0; |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 247 | child_signal_counter = 0; |
| 248 | pgrps_ready = 0; |
| 249 | checklist_reset(0x03); |
| 250 | |
| 251 | /* send SIGUSR1 to each pgroup */ |
| 252 | for (cnt = 0; cnt < child_checklist_total; ++cnt) { |
| 253 | if (debug_flag >= 2) |
| 254 | printf("%d: test_loop, SIGUSR1 -> %d\n", |
| 255 | mypid, -child_checklist[cnt].pid); |
| 256 | kill(-child_checklist[cnt].pid, SIGUSR1); |
| 257 | } |
| 258 | |
| 259 | /* wait for the managers to signal they are done */ |
| 260 | while (child_signal_counter < num_pgrps) { |
| 261 | alarm(1); |
| 262 | if (debug_flag >= 2) |
| 263 | printf("%d: Master pausing for done (%d/%d)\n", |
| 264 | mypid, child_signal_counter, num_pgrps); |
| 265 | pause(); |
| 266 | } |
| 267 | tst_resm(TPASS, "All %d pgrps received their signals", |
| 268 | child_signal_counter); |
| 269 | |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 270 | } |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 271 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 272 | cleanup(); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 273 | |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 274 | tst_exit(); |
| 275 | } |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 276 | |
Mike Frysinger | c57fba5 | 2014-04-09 18:56:30 -0400 | [diff] [blame] | 277 | void help(void) |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 278 | { |
| 279 | printf(" -g n Create n process groups (default: %d)\n", num_pgrps); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 280 | printf |
| 281 | (" -n n Create n children in each process group (default: %d)\n", |
| 282 | num_procs); |
| 283 | printf(" -d n Set debug level to n (default: %d)\n", debug_flag); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 284 | } |
| 285 | |
Mike Frysinger | c57fba5 | 2014-04-09 18:56:30 -0400 | [diff] [blame] | 286 | void setup(void) |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 287 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 288 | struct sigaction sa; |
| 289 | int i; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 290 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 291 | /* You will want to enable some signal handling so you can capture |
| 292 | * unexpected signals like SIGSEGV. |
| 293 | */ |
| 294 | tst_sig(FORK, DEF_HANDLER, cleanup); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 295 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 296 | /* One cavet that hasn't been fixed yet. TEST_PAUSE contains the code to |
| 297 | * fork the test with the -c option. You want to make sure you do this |
| 298 | * before you create your temporary directory. |
| 299 | */ |
| 300 | TEST_PAUSE; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 301 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 302 | mypid = getpid(); |
| 303 | sa.sa_handler = SIG_DFL; |
| 304 | sigemptyset(&sa.sa_mask); |
| 305 | sa.sa_flags = 0; |
| 306 | if (debug_flag >= 1) |
| 307 | printf("%d: setting SIGTRAP -> SIG_DFL\n", mypid); |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 308 | k_sigaction(SIGTRAP, &sa, NULL); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 309 | if (debug_flag >= 1) |
| 310 | printf("%d: setting SIGCONT -> SIG_DFL\n", mypid); |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 311 | k_sigaction(SIGCONT, &sa, NULL); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 312 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 313 | sa.sa_handler = set_create_procs; |
| 314 | if (debug_flag >= 4) |
| 315 | printf("%d: setting SIGALRM -> set_create_procs\n", mypid); |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 316 | k_sigaction(SIGALRM, &sa, NULL); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 317 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 318 | sa.sa_handler = NULL; |
| 319 | sa.sa_sigaction = ack_ready; |
| 320 | sa.sa_flags = SA_SIGINFO; |
| 321 | if (debug_flag >= 1) |
| 322 | printf("%d: setting SIGUSR1 -> ack_ready\n", mypid); |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 323 | k_sigaction(SIGUSR1, &sa, NULL); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 324 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 325 | fork_pgrps(num_pgrps); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 326 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 327 | /* wait for all pgrps to report in */ |
| 328 | if (debug_flag) |
| 329 | printf("Master: %d\n", mypid); |
| 330 | while (pgrps_ready < num_pgrps) { |
| 331 | if (debug_flag >= 3) |
| 332 | printf |
| 333 | ("%d: Master pausing for Managers to check in (%d/%d)\n", |
| 334 | mypid, pgrps_ready, num_pgrps); |
| 335 | /* |
| 336 | * We might recieve the signal from the (last manager) before |
| 337 | * we issue a pause. In that case we might hang even if we have |
| 338 | * all the managers reported in. So set an alarm so that we can |
| 339 | * wake up. |
| 340 | */ |
| 341 | alarm(1); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 342 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 343 | pause(); |
| 344 | } |
| 345 | checklist_reset(0x03); |
| 346 | if (debug_flag) { |
| 347 | printf("Managers: \n"); |
| 348 | for (i = 0; i < num_pgrps; i++) { |
| 349 | printf("%d ", child_checklist[i].pid); |
| 350 | } |
| 351 | printf("\n"); |
| 352 | } |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 353 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 354 | /* set up my signal processing */ |
| 355 | /* continue on ALRM */ |
| 356 | sa.sa_handler = wakeup; |
| 357 | if (debug_flag >= 4) |
| 358 | printf("%d: setting SIGALRM -> wakeup\n", mypid); |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 359 | k_sigaction(SIGALRM, &sa, NULL); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 360 | /* reply to child on USR2 */ |
| 361 | sa.sa_handler = NULL; |
| 362 | sa.sa_sigaction = ack_done; |
| 363 | sa.sa_flags = SA_SIGINFO; |
| 364 | if (debug_flag >= 1) |
| 365 | printf("%d: setting SIGUSR2 -> ack_done\n", mypid); |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 366 | k_sigaction(SIGUSR2, &sa, NULL); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 367 | } |
| 368 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 369 | void ack_ready(int sig, siginfo_t * si, void *data) |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 370 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 371 | struct pid_list_item findit, *result; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 372 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 373 | findit.pid = si->si_pid; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 374 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 375 | result = bsearch(&findit, child_checklist, child_checklist_total, |
| 376 | sizeof(*child_checklist), checklist_cmp); |
| 377 | if (result) { |
| 378 | if (!(result->flag & 0x01)) { |
| 379 | if (debug_flag >= 3) |
| 380 | printf("%d: ack_ready, SIGUSR1 -> %d\n", mypid, |
| 381 | si->si_pid); |
| 382 | kill(si->si_pid, SIGUSR1); |
| 383 | result->flag = result->flag | 0x01; |
| 384 | ++pgrps_ready; |
| 385 | } else { |
| 386 | if (debug_flag >= 3) |
| 387 | printf("%d: ack_ready, already acked %d\n", |
| 388 | mypid, si->si_pid); |
| 389 | } |
| 390 | } else { |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 391 | printf("received unexpected signal %d from %d", |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 392 | sig, si->si_pid); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 393 | } |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 394 | } |
| 395 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 396 | void ack_done(int sig, siginfo_t * si, void *data) |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 397 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 398 | struct pid_list_item findit, *result; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 399 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 400 | findit.pid = si->si_pid; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 401 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 402 | result = bsearch(&findit, child_checklist, child_checklist_total, |
| 403 | sizeof(*child_checklist), checklist_cmp); |
| 404 | if (result) { |
| 405 | if (!(result->flag & 0x02)) { |
| 406 | if (debug_flag >= 3) |
| 407 | printf("%d: ack_done, SIGHUP -> %d\n", mypid, |
| 408 | si->si_pid); |
| 409 | kill(si->si_pid, SIGHUP); |
| 410 | ++child_signal_counter; |
| 411 | result->flag = result->flag | 0x02; |
| 412 | } else { |
| 413 | if (debug_flag >= 3) |
| 414 | printf("%d: ack_done, already told %d\n", mypid, |
| 415 | si->si_pid); |
| 416 | } |
| 417 | } else { |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 418 | printf("received unexpected signal %d from %d", |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 419 | sig, si->si_pid); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 420 | } |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 421 | } |
| 422 | |
| 423 | /*************************************************************** |
| 424 | * cleanup() - performs all ONE TIME cleanup for this test at |
| 425 | * completion or premature exit. |
| 426 | ***************************************************************/ |
Mike Frysinger | c57fba5 | 2014-04-09 18:56:30 -0400 | [diff] [blame] | 427 | void cleanup(void) |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 428 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 429 | int i; |
| 430 | /* send SIGHUP to all pgroups */ |
| 431 | for (i = 0; i < num_pgrps; ++i) { |
| 432 | /* try to do this as nicely as possible */ |
| 433 | kill(-child_checklist[i].pid, SIGQUIT); |
| 434 | waitpid(child_checklist[i].pid, NULL, 0); |
| 435 | } |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 436 | free(child_checklist); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 437 | |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 438 | } |
| 439 | |
| 440 | /********************************************************************* |
| 441 | * fork_pgrps() forks off a child, changes it's pgrp, then continues |
| 442 | ********************************************************************/ |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 443 | void fork_pgrps(int pgrps_left) |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 444 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 445 | pid_t child; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 446 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 447 | if (!(child_checklist = calloc(pgrps_left, sizeof(*child_checklist)))) { |
| 448 | tst_brkm(TBROK, cleanup, |
| 449 | "%d: couldn't calloc child_checklist, errno=%d : %s", |
| 450 | mypid, errno, strerror(errno)); |
| 451 | } |
| 452 | child_checklist_total = 0; |
| 453 | while (pgrps_left) { |
| 454 | if (debug_flag >= 1) |
| 455 | printf("%d: forking new Manager\n", mypid); |
| 456 | switch (child = fork()) { |
| 457 | case -1: |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 458 | tst_brkm(TBROK | TERRNO, cleanup, |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 459 | "fork() failed in fork_pgrps(%d)", pgrps_left); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 460 | break; |
| 461 | case 0: |
| 462 | mypid = getpid(); |
| 463 | free(child_checklist); |
| 464 | child_checklist = NULL; |
| 465 | manager(num_procs); |
| 466 | break; |
| 467 | default: |
| 468 | child_checklist[child_checklist_total++].pid = child; |
| 469 | setpgid(child, child); |
| 470 | if (debug_flag >= 3) |
| 471 | printf("%d: fork_pgrps, SIGALRM -> %d\n", mypid, |
| 472 | child); |
| 473 | kill(child, SIGALRM); |
| 474 | } |
| 475 | --pgrps_left; |
| 476 | } |
| 477 | qsort(child_checklist, child_checklist_total, sizeof(*child_checklist), |
| 478 | checklist_cmp); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 479 | } |
| 480 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 481 | void set_create_procs(int sig) |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 482 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 483 | if (debug_flag >= 3) |
| 484 | printf("%d: Manager cleared to fork\n", getpid()); |
| 485 | create_procs_flag++; |
| 486 | return; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 487 | } |
| 488 | |
| 489 | /********************************************************************* |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 490 | * new_pgrg() - handle the creation of the pgrp managers and their |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 491 | * children |
| 492 | ********************************************************************/ |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 493 | void manager(int num_procs) |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 494 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 495 | struct sigaction sa; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 496 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 497 | /* Wait for the parent to change our pgid before we start forking */ |
| 498 | while (!create_procs_flag) { |
| 499 | alarm(1); |
| 500 | if (debug_flag >= 3) |
| 501 | printf("%d: Manager pausing, not cleared to fork\n", |
| 502 | mypid); |
| 503 | pause(); |
| 504 | } |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 505 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 506 | /* set up the signal handling the children will use */ |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 507 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 508 | /* ignore HUP */ |
| 509 | sa.sa_handler = SIG_IGN; |
| 510 | sigemptyset(&sa.sa_mask); |
| 511 | sa.sa_flags = 0; |
| 512 | if (debug_flag >= 4) |
| 513 | printf("%d: setting SIGHUP -> SIG_IGN\n", mypid); |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 514 | k_sigaction(SIGHUP, &sa, NULL); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 515 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 516 | /* We use ALRM to make sure that we don't miss the signal effects ! */ |
| 517 | sa.sa_handler = wakeup; |
| 518 | if (debug_flag >= 4) |
| 519 | printf("%d: setting SIGALRM -> wakeup\n", mypid); |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 520 | k_sigaction(SIGALRM, &sa, NULL); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 521 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 522 | /* exit on QUIT */ |
| 523 | sa.sa_handler = graceful_exit; |
| 524 | if (debug_flag >= 4) |
| 525 | printf("%d: setting SIGQUIT -> graceful_exit\n", mypid); |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 526 | k_sigaction(SIGQUIT, &sa, NULL); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 527 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 528 | /* start signaling on USR1 */ |
| 529 | sa.sa_handler = set_signal_parents; |
| 530 | sigfillset(&sa.sa_mask); |
| 531 | if (debug_flag >= 7) |
| 532 | printf("%d: setting SIGUSR1 -> set_signal_parents\n", mypid); |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 533 | k_sigaction(SIGUSR1, &sa, NULL); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 534 | /* stop signaling on USR2 */ |
| 535 | sa.sa_handler = clear_signal_parents; |
| 536 | if (debug_flag >= 7) |
| 537 | printf("%d: setting SIGUSR2 -> clear_signal_parents\n", mypid); |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 538 | k_sigaction(SIGUSR2, &sa, NULL); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 539 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 540 | fork_procs(num_procs); |
| 541 | sleep(1); /* wait a sec to let all the children pause */ |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 542 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 543 | /* now set up my signal handling */ |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 544 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 545 | /* continue on ALRM */ |
| 546 | sa.sa_handler = wakeup; |
| 547 | if (debug_flag >= 4) |
| 548 | printf("%d: setting SIGALRM -> wakeup\n", mypid); |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 549 | k_sigaction(SIGALRM, &sa, NULL); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 550 | /* mark ready confirmation on USR1 */ |
| 551 | sa.sa_handler = set_confirmed_ready; |
| 552 | if (debug_flag >= 4) |
| 553 | printf("%d: setting SIGUSR1 -> set_confirmed_ready\n", mypid); |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 554 | k_sigaction(SIGUSR1, &sa, NULL); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 555 | /* reset our counter on HUP */ |
| 556 | sa.sa_handler = reset_counter; |
| 557 | if (debug_flag >= 4) |
| 558 | printf("%d: setting SIGHUP -> reset_counter\n", mypid); |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 559 | k_sigaction(SIGHUP, &sa, NULL); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 560 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 561 | /* reply to child on USR2 */ |
| 562 | sa.sa_handler = NULL; |
| 563 | sa.sa_sigaction = reply_to_child; |
| 564 | sa.sa_flags = SA_SIGINFO; |
| 565 | if (debug_flag >= 4) |
| 566 | printf("%d: setting SIGUSR2 -> reply_to_child\n", mypid); |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 567 | k_sigaction(SIGUSR2, &sa, NULL); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 568 | |
| 569 | /* tell our parent that we are ready to rock */ |
| 570 | while (!confirmed_ready_flag) { |
| 571 | if (debug_flag >= 3) |
| 572 | printf("%d: Manager, SIGUSR1 -> %d\n", mypid, |
| 573 | getppid()); |
| 574 | if (kill(getppid(), SIGUSR1) == -1) { |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 575 | printf("%d: Couldn't signal master (%d) that we're " |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 576 | "ready. %d: %s", |
| 577 | mypid, getppid(), errno, strerror(errno)); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 578 | exit(errno); |
| 579 | } |
| 580 | usleep(100); |
| 581 | } |
| 582 | |
| 583 | /* handle pgroup management while the tests are running */ |
| 584 | while (1) { |
| 585 | alarm(1); |
| 586 | if (debug_flag >= 5) |
| 587 | printf("%d: Manager pausing (%d/%d)\n", |
| 588 | mypid, child_signal_counter, num_procs); |
| 589 | pause(); |
| 590 | if (child_signal_counter >= num_procs) { |
| 591 | confirmed_ready_flag = 0; |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 592 | printf("%d: All %d children reported in\n", |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 593 | mypid, child_signal_counter); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 594 | while (child_signal_counter) { |
| 595 | if (debug_flag >= 3) |
| 596 | printf("%d: Manager, SIGUSR2 -> %d\n", |
| 597 | mypid, getppid()); |
| 598 | if (kill(getppid(), SIGUSR2) == -1) { |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 599 | printf("%d: Couldn't signal master " |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 600 | "(%d) that we're ready. %d: %s\n", |
| 601 | mypid, getppid(), errno, |
| 602 | strerror(errno)); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 603 | exit(errno); |
| 604 | } |
| 605 | usleep(100); |
| 606 | } |
| 607 | } |
| 608 | } |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 609 | } |
| 610 | |
| 611 | /* some simple signal handlers for the kids */ |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 612 | void graceful_exit(int sig) |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 613 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 614 | exit(0); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 615 | } |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 616 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 617 | void set_signal_parents(int sig) |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 618 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 619 | if (debug_flag >= 8) |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 620 | printf("%d: Child start signaling\n", mypid); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 621 | signal_parents_flag = 1; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 622 | } |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 623 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 624 | void clear_signal_parents(int sig) |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 625 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 626 | if (debug_flag >= 8) |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 627 | printf("%d: Child stop signaling\n", mypid); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 628 | signal_parents_flag = 0; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 629 | } |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 630 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 631 | void set_confirmed_ready(int sig) |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 632 | { |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 633 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 634 | if (debug_flag >= 3) |
| 635 | printf("%d: Manager confirmed ready\n", mypid); |
| 636 | confirmed_ready_flag = 1; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 637 | } |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 638 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 639 | void reset_counter(int sig) |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 640 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 641 | checklist_reset(0xFF); |
| 642 | child_signal_counter = 0; |
| 643 | if (debug_flag >= 3) |
| 644 | printf("%d: reset_counter\n", mypid); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 645 | } |
| 646 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 647 | void reply_to_child(int sig, siginfo_t * si, void *data) |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 648 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 649 | struct pid_list_item findit, *result; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 650 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 651 | findit.pid = si->si_pid; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 652 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 653 | result = bsearch(&findit, child_checklist, child_checklist_total, |
| 654 | sizeof(*child_checklist), checklist_cmp); |
| 655 | if (result) { |
| 656 | if (!result->flag) { |
| 657 | if (debug_flag >= 6) |
| 658 | printf("%d: reply_to_child, SIGUSR1 -> %d\n", |
| 659 | mypid, si->si_pid); |
| 660 | kill(si->si_pid, SIGUSR2); |
| 661 | ++child_signal_counter; |
| 662 | result->flag = 1; |
| 663 | } else { |
| 664 | if (debug_flag >= 6) |
| 665 | printf("%d: reply_to_child, already told %d\n", |
| 666 | mypid, si->si_pid); |
| 667 | } |
| 668 | } else { |
| 669 | tst_brkm(TBROK, cleanup, |
| 670 | "received unexpected signal from %d", si->si_pid); |
| 671 | } |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 672 | } |
| 673 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 674 | void wakeup(int sig) |
| 675 | { |
| 676 | return; |
| 677 | } |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 678 | |
| 679 | /************************************************* |
| 680 | * fork_procs() - create all the children |
| 681 | ************************************************/ |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 682 | void fork_procs(int procs_left) |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 683 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 684 | pid_t child; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 685 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 686 | if (!(child_checklist = calloc(procs_left, sizeof(*child_checklist)))) { |
| 687 | tst_brkm(TBROK, cleanup, |
| 688 | "%d: couldn't calloc child_checklist, errno=%d : %s", |
| 689 | mypid, errno, strerror(errno)); |
| 690 | } |
| 691 | child_checklist_total = 0; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 692 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 693 | /* We are setting the flag for children, to avoid missing any signals */ |
| 694 | signal_parents_flag = 0; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 695 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 696 | while (procs_left) { |
| 697 | if (debug_flag >= 4) |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 698 | printf("%d: forking new child\n", mypid); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 699 | switch (child = fork()) { |
| 700 | case -1: |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 701 | tst_brkm(TBROK | TERRNO, cleanup, |
| 702 | "fork() failed in fork_procs(%d)", procs_left); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 703 | break; |
| 704 | case 0: |
| 705 | mypid = getpid(); |
| 706 | while (1) { |
| 707 | /* wait to start */ |
| 708 | if (debug_flag >= 8) |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 709 | printf("%d: child pausing\n", mypid); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 710 | /* |
| 711 | * If we have already recieved the signal, we dont |
| 712 | * want to pause for it ! |
| 713 | */ |
| 714 | while (!signal_parents_flag) { |
| 715 | alarm(2); |
| 716 | pause(); |
| 717 | } |
| 718 | |
| 719 | /* if we started, call mama */ |
| 720 | while (signal_parents_flag) { |
| 721 | if (debug_flag >= 6) |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 722 | printf("%d: child, SIGUSR2 " |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 723 | "-> %d\n", |
| 724 | mypid, getppid()); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 725 | if (kill(getppid(), SIGUSR2) == -1) { |
| 726 | /* something went wrong */ |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 727 | printf("%d: kill(ppid:%d, " |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 728 | "SIGUSR2) failed. %d: %s", |
| 729 | mypid, getppid(), errno, |
| 730 | strerror(errno)); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 731 | exit(errno); |
| 732 | } |
| 733 | usleep(100); |
| 734 | } |
| 735 | } |
| 736 | break; |
| 737 | default: |
| 738 | child_checklist[child_checklist_total++].pid = child; |
| 739 | } |
Garrett Cooper | d2f1667 | 2010-11-23 21:41:27 -0800 | [diff] [blame] | 740 | procs_left--; |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 741 | } |
| 742 | qsort(child_checklist, child_checklist_total, sizeof(*child_checklist), |
| 743 | checklist_cmp); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 744 | } |
| 745 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 746 | int checklist_cmp(const void *a, const void *b) |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 747 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 748 | const struct pid_list_item *pa = (const struct pid_list_item *)a; |
| 749 | const struct pid_list_item *pb = (const struct pid_list_item *)b; |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 750 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 751 | return (pa->pid > pb->pid) - (pa->pid < pb->pid); |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 752 | } |
| 753 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 754 | void checklist_reset(int bit) |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 755 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 756 | int i; |
| 757 | for (i = 0; i < child_checklist_total; i++) { |
| 758 | child_checklist[i].flag = child_checklist[i].flag & (~bit); |
| 759 | } |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 760 | |
| 761 | } |
| 762 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 763 | inline int k_sigaction(int sig, struct sigaction *sa, struct sigaction *osa) |
robbiew | c76bc8c | 2005-02-09 16:11:53 +0000 | [diff] [blame] | 764 | { |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 765 | int ret; |
| 766 | if ((ret = sigaction(sig, sa, osa)) == -1) { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 767 | tst_brkm(TBROK | TERRNO, cleanup, "sigaction(%d, ...) failed", |
| 768 | sig); |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 769 | } |
| 770 | return ret; |
Chris Dearman | ec6edca | 2012-10-17 19:54:01 -0700 | [diff] [blame] | 771 | } |