blob: 9df912608eba7ecb65152b0013d38178cd248264 [file] [log] [blame]
robbiewc76bc8c2005-02-09 16:11:53 +00001/*
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 Gaofed96412012-10-24 10:10:29 +080020 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
robbiewc76bc8c2005-02-09 16:11:53 +000022 *
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_modak56207ce2009-03-23 13:35:39 +000033/* $Id: kill10.c,v 1.7 2009/03/23 13:35:53 subrata_modak Exp $ */
robbiewc76bc8c2005-02-09 16:11:53 +000034/**********************************************************
subrata_modak4bb656a2009-02-26 12:02:09 +000035 *
robbiewc76bc8c2005-02-09 16:11:53 +000036 * OS Test - Silicon Graphics, Inc.
subrata_modak4bb656a2009-02-26 12:02:09 +000037 *
robbiewc76bc8c2005-02-09 16:11:53 +000038 * TEST IDENTIFIER : kill10
subrata_modak4bb656a2009-02-26 12:02:09 +000039 *
robbiewc76bc8c2005-02-09 16:11:53 +000040 * EXECUTED BY : anyone
subrata_modak4bb656a2009-02-26 12:02:09 +000041 *
robbiewc76bc8c2005-02-09 16:11:53 +000042 * TEST TITLE : signal flooding test
subrata_modak4bb656a2009-02-26 12:02:09 +000043 *
robbiewc76bc8c2005-02-09 16:11:53 +000044 * TEST CASE TOTAL : 1
subrata_modak4bb656a2009-02-26 12:02:09 +000045 *
46 * WALL CLOCK TIME :
47 *
robbiewc76bc8c2005-02-09 16:11:53 +000048 * CPU TYPES : ALL
subrata_modak4bb656a2009-02-26 12:02:09 +000049 *
robbiewc76bc8c2005-02-09 16:11:53 +000050 * AUTHOR : Nate Straz
subrata_modak4bb656a2009-02-26 12:02:09 +000051 *
robbiewc76bc8c2005-02-09 16:11:53 +000052 * DATE STARTED : 04/09/2001
subrata_modak4bb656a2009-02-26 12:02:09 +000053 *
robbiewc76bc8c2005-02-09 16:11:53 +000054 * INITIAL RELEASE : Linux 2.4.x
subrata_modak4bb656a2009-02-26 12:02:09 +000055 *
robbiewc76bc8c2005-02-09 16:11:53 +000056 * TEST CASES
subrata_modak4bb656a2009-02-26 12:02:09 +000057 *
robbiewc76bc8c2005-02-09 16:11:53 +000058 * 1.) Create a large number of processes and signal between them.
subrata_modakbdbaec52009-02-26 12:14:51 +000059 *
robbiewc76bc8c2005-02-09 16:11:53 +000060 * INPUT SPECIFICATIONS
61 * The standard options for system call tests are accepted.
62 * (See the parse_opts(3) man page).
subrata_modak4bb656a2009-02-26 12:02:09 +000063 *
robbiewc76bc8c2005-02-09 16:11:53 +000064 * OUTPUT SPECIFICATIONS
subrata_modak56207ce2009-03-23 13:35:39 +000065 *$
robbiewc76bc8c2005-02-09 16:11:53 +000066 * DURATION
67 * Terminates - with frequency and infinite modes.
subrata_modak4bb656a2009-02-26 12:02:09 +000068 *
robbiewc76bc8c2005-02-09 16:11:53 +000069 * 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_modak4bb656a2009-02-26 12:02:09 +000075 *
robbiewc76bc8c2005-02-09 16:11:53 +000076 * ENVIRONMENTAL NEEDS
77 * No run-time environmental needs.
subrata_modak4bb656a2009-02-26 12:02:09 +000078 *
robbiewc76bc8c2005-02-09 16:11:53 +000079 * SPECIAL PROCEDURAL REQUIREMENTS
80 * None
subrata_modak4bb656a2009-02-26 12:02:09 +000081 *
robbiewc76bc8c2005-02-09 16:11:53 +000082 * INTERCASE DEPENDENCIES
83 * None
subrata_modak4bb656a2009-02-26 12:02:09 +000084 *
robbiewc76bc8c2005-02-09 16:11:53 +000085 * 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_modak4bb656a2009-02-26 12:02:09 +000098 * SIGUSR1 ->
robbiewc76bc8c2005-02-09 16:11:53 +000099 * 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_modak4bb656a2009-02-26 12:02:09 +0000125 *
robbiewc76bc8c2005-02-09 16:11:53 +0000126 * 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_modak4bb656a2009-02-26 12:02:09 +0000130 *
robbiewc76bc8c2005-02-09 16:11:53 +0000131 * 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_modak4bb656a2009-02-26 12:02:09 +0000145 *
146 *
robbiewc76bc8c2005-02-09 16:11:53 +0000147 *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
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"
robbiewc76bc8c2005-02-09 16:11:53 +0000159
subrata_modak4bb656a2009-02-26 12:02:09 +0000160void setup();
robbiewc76bc8c2005-02-09 16:11:53 +0000161void help();
162void cleanup();
163void fork_pgrps(int pgrps_left);
164void manager(int num_procs);
165void fork_procs(int procs_left);
166
167/* signal handlers */
subrata_modak56207ce2009-03-23 13:35:39 +0000168void ack_ready(int sig, siginfo_t * si, void *data);
169void ack_done(int sig, siginfo_t * si, void *data);
subrata_modak4bb656a2009-02-26 12:02:09 +0000170void set_create_procs(int sig);
robbiewc76bc8c2005-02-09 16:11:53 +0000171void graceful_exit(int sig);
172void set_signal_parents(int sig);
173void clear_signal_parents(int sig);
174void set_confirmed_ready(int sig);
175void reset_counter(int sig);
subrata_modak56207ce2009-03-23 13:35:39 +0000176void reply_to_child(int sig, siginfo_t * si, void *data);
robbiewc76bc8c2005-02-09 16:11:53 +0000177void wakeup(int sig);
178
179/* pid checklist management */
180struct pid_list_item {
subrata_modak56207ce2009-03-23 13:35:39 +0000181 pid_t pid;
182 short flag;
robbiewc76bc8c2005-02-09 16:11:53 +0000183} *child_checklist = NULL;
184int child_checklist_total = 0;
185int checklist_cmp(const void *a, const void *b);
186void checklist_reset(int bit);
187
188inline int k_sigaction(int sig, struct sigaction *sa, struct sigaction *osa);
189
Cyril Hrubisfdce7d52013-04-04 18:35:48 +0200190char *TCID = "kill10";
191int TST_TOTAL = 1;
robbiewc76bc8c2005-02-09 16:11:53 +0000192
robbiewc76bc8c2005-02-09 16:11:53 +0000193int num_procs = 10;
194int num_pgrps = 2;
195int pgrps_ready = 0;
196int child_signal_counter = 0;
197
198int create_procs_flag = 0;
199int signal_parents_flag = 0;
200int confirmed_ready_flag = 0;
201int debug_flag = 0;
202pid_t mypid = 0;
203
204char *narg, *garg, *darg;
subrata_modak56207ce2009-03-23 13:35:39 +0000205int nflag = 0, gflag = 0, dflag = 0;
robbiewc76bc8c2005-02-09 16:11:53 +0000206
207/* for test specific parse_opts options */
208option_t options[] = {
subrata_modak56207ce2009-03-23 13:35:39 +0000209 {"n:", &nflag, &narg}, /* -n #procs */
210 {"g:", &gflag, &garg}, /* -g #pgrps */
211 {"d:", &dflag, &darg}, /* -d <debug level> */
212 {NULL, NULL, NULL}
robbiewc76bc8c2005-02-09 16:11:53 +0000213};
214
subrata_modak56207ce2009-03-23 13:35:39 +0000215int main(int ac, char **av)
robbiewc76bc8c2005-02-09 16:11:53 +0000216{
Cyril Hrubis89af32a2012-10-24 16:39:11 +0200217 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +0200218 const char *msg;
subrata_modak56207ce2009-03-23 13:35:39 +0000219 int cnt;
robbiewc76bc8c2005-02-09 16:11:53 +0000220
subrata_modak56207ce2009-03-23 13:35:39 +0000221 if ((msg = parse_opts(ac, av, options, &help))) {
Garrett Cooper53740502010-12-16 00:04:01 -0800222 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
subrata_modak56207ce2009-03-23 13:35:39 +0000223 }
robbiewc76bc8c2005-02-09 16:11:53 +0000224
subrata_modak56207ce2009-03-23 13:35:39 +0000225 if (nflag) {
226 if (sscanf(narg, "%i", &num_procs) != 1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800227 tst_brkm(TBROK, NULL, "-n option arg is not a number");
subrata_modak56207ce2009-03-23 13:35:39 +0000228 }
229 }
230 if (gflag) {
231 if (sscanf(garg, "%i", &num_pgrps) != 1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800232 tst_brkm(TBROK, NULL, "-g option arg is not a number");
subrata_modak56207ce2009-03-23 13:35:39 +0000233 }
234 }
robbiewc76bc8c2005-02-09 16:11:53 +0000235
subrata_modak56207ce2009-03-23 13:35:39 +0000236 if (dflag) {
237 if (sscanf(darg, "%i", &debug_flag) != 1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800238 tst_brkm(TBROK, NULL, "-d option arg is not a number");
subrata_modak56207ce2009-03-23 13:35:39 +0000239 }
240 }
robbiewc76bc8c2005-02-09 16:11:53 +0000241
subrata_modak56207ce2009-03-23 13:35:39 +0000242 setup();
robbiewc76bc8c2005-02-09 16:11:53 +0000243
subrata_modak56207ce2009-03-23 13:35:39 +0000244 for (lc = 0; TEST_LOOPING(lc); lc++) {
robbiewc76bc8c2005-02-09 16:11:53 +0000245
Caspar Zhangd59a6592013-03-07 14:59:12 +0800246 tst_count = 0;
subrata_modak56207ce2009-03-23 13:35:39 +0000247 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 Cooper2c282152010-12-16 00:55:50 -0800270 }
robbiewc76bc8c2005-02-09 16:11:53 +0000271
subrata_modak56207ce2009-03-23 13:35:39 +0000272 cleanup();
robbiewc76bc8c2005-02-09 16:11:53 +0000273
Garrett Cooper2c282152010-12-16 00:55:50 -0800274 tst_exit();
275}
robbiewc76bc8c2005-02-09 16:11:53 +0000276
Mike Frysingerc57fba52014-04-09 18:56:30 -0400277void help(void)
robbiewc76bc8c2005-02-09 16:11:53 +0000278{
279 printf(" -g n Create n process groups (default: %d)\n", num_pgrps);
subrata_modak56207ce2009-03-23 13:35:39 +0000280 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);
robbiewc76bc8c2005-02-09 16:11:53 +0000284}
285
Mike Frysingerc57fba52014-04-09 18:56:30 -0400286void setup(void)
robbiewc76bc8c2005-02-09 16:11:53 +0000287{
subrata_modak56207ce2009-03-23 13:35:39 +0000288 struct sigaction sa;
289 int i;
robbiewc76bc8c2005-02-09 16:11:53 +0000290
subrata_modak56207ce2009-03-23 13:35:39 +0000291 /* 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);
robbiewc76bc8c2005-02-09 16:11:53 +0000295
subrata_modak56207ce2009-03-23 13:35:39 +0000296 /* 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;
robbiewc76bc8c2005-02-09 16:11:53 +0000301
subrata_modak56207ce2009-03-23 13:35:39 +0000302 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 Cooperd2f16672010-11-23 21:41:27 -0800308 k_sigaction(SIGTRAP, &sa, NULL);
subrata_modak56207ce2009-03-23 13:35:39 +0000309 if (debug_flag >= 1)
310 printf("%d: setting SIGCONT -> SIG_DFL\n", mypid);
Garrett Cooperd2f16672010-11-23 21:41:27 -0800311 k_sigaction(SIGCONT, &sa, NULL);
robbiewc76bc8c2005-02-09 16:11:53 +0000312
subrata_modak56207ce2009-03-23 13:35:39 +0000313 sa.sa_handler = set_create_procs;
314 if (debug_flag >= 4)
315 printf("%d: setting SIGALRM -> set_create_procs\n", mypid);
Garrett Cooperd2f16672010-11-23 21:41:27 -0800316 k_sigaction(SIGALRM, &sa, NULL);
robbiewc76bc8c2005-02-09 16:11:53 +0000317
subrata_modak56207ce2009-03-23 13:35:39 +0000318 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 Cooperd2f16672010-11-23 21:41:27 -0800323 k_sigaction(SIGUSR1, &sa, NULL);
robbiewc76bc8c2005-02-09 16:11:53 +0000324
subrata_modak56207ce2009-03-23 13:35:39 +0000325 fork_pgrps(num_pgrps);
robbiewc76bc8c2005-02-09 16:11:53 +0000326
subrata_modak56207ce2009-03-23 13:35:39 +0000327 /* 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);
robbiewc76bc8c2005-02-09 16:11:53 +0000342
subrata_modak56207ce2009-03-23 13:35:39 +0000343 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 }
robbiewc76bc8c2005-02-09 16:11:53 +0000353
subrata_modak56207ce2009-03-23 13:35:39 +0000354 /* 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 Cooperd2f16672010-11-23 21:41:27 -0800359 k_sigaction(SIGALRM, &sa, NULL);
subrata_modak56207ce2009-03-23 13:35:39 +0000360 /* 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 Cooperd2f16672010-11-23 21:41:27 -0800366 k_sigaction(SIGUSR2, &sa, NULL);
robbiewc76bc8c2005-02-09 16:11:53 +0000367}
368
subrata_modak56207ce2009-03-23 13:35:39 +0000369void ack_ready(int sig, siginfo_t * si, void *data)
robbiewc76bc8c2005-02-09 16:11:53 +0000370{
subrata_modak56207ce2009-03-23 13:35:39 +0000371 struct pid_list_item findit, *result;
robbiewc76bc8c2005-02-09 16:11:53 +0000372
subrata_modak56207ce2009-03-23 13:35:39 +0000373 findit.pid = si->si_pid;
robbiewc76bc8c2005-02-09 16:11:53 +0000374
subrata_modak56207ce2009-03-23 13:35:39 +0000375 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 Cooperd2f16672010-11-23 21:41:27 -0800391 printf("received unexpected signal %d from %d",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800392 sig, si->si_pid);
subrata_modak56207ce2009-03-23 13:35:39 +0000393 }
robbiewc76bc8c2005-02-09 16:11:53 +0000394}
395
subrata_modak56207ce2009-03-23 13:35:39 +0000396void ack_done(int sig, siginfo_t * si, void *data)
robbiewc76bc8c2005-02-09 16:11:53 +0000397{
subrata_modak56207ce2009-03-23 13:35:39 +0000398 struct pid_list_item findit, *result;
robbiewc76bc8c2005-02-09 16:11:53 +0000399
subrata_modak56207ce2009-03-23 13:35:39 +0000400 findit.pid = si->si_pid;
robbiewc76bc8c2005-02-09 16:11:53 +0000401
subrata_modak56207ce2009-03-23 13:35:39 +0000402 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 Cooperd2f16672010-11-23 21:41:27 -0800418 printf("received unexpected signal %d from %d",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800419 sig, si->si_pid);
subrata_modak56207ce2009-03-23 13:35:39 +0000420 }
robbiewc76bc8c2005-02-09 16:11:53 +0000421}
422
423/***************************************************************
424 * cleanup() - performs all ONE TIME cleanup for this test at
425 * completion or premature exit.
426 ***************************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400427void cleanup(void)
robbiewc76bc8c2005-02-09 16:11:53 +0000428{
subrata_modak56207ce2009-03-23 13:35:39 +0000429 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 Cooperd2f16672010-11-23 21:41:27 -0800436 free(child_checklist);
robbiewc76bc8c2005-02-09 16:11:53 +0000437
robbiewc76bc8c2005-02-09 16:11:53 +0000438}
439
440/*********************************************************************
441 * fork_pgrps() forks off a child, changes it's pgrp, then continues
442 ********************************************************************/
subrata_modak56207ce2009-03-23 13:35:39 +0000443void fork_pgrps(int pgrps_left)
robbiewc76bc8c2005-02-09 16:11:53 +0000444{
subrata_modak56207ce2009-03-23 13:35:39 +0000445 pid_t child;
robbiewc76bc8c2005-02-09 16:11:53 +0000446
subrata_modak56207ce2009-03-23 13:35:39 +0000447 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 Gao354ebb42012-12-07 10:10:04 +0800458 tst_brkm(TBROK | TERRNO, cleanup,
Garrett Cooperd2f16672010-11-23 21:41:27 -0800459 "fork() failed in fork_pgrps(%d)", pgrps_left);
subrata_modak56207ce2009-03-23 13:35:39 +0000460 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);
robbiewc76bc8c2005-02-09 16:11:53 +0000479}
480
subrata_modak56207ce2009-03-23 13:35:39 +0000481void set_create_procs(int sig)
robbiewc76bc8c2005-02-09 16:11:53 +0000482{
subrata_modak56207ce2009-03-23 13:35:39 +0000483 if (debug_flag >= 3)
484 printf("%d: Manager cleared to fork\n", getpid());
485 create_procs_flag++;
486 return;
robbiewc76bc8c2005-02-09 16:11:53 +0000487}
488
489/*********************************************************************
subrata_modak4bb656a2009-02-26 12:02:09 +0000490 * new_pgrg() - handle the creation of the pgrp managers and their
robbiewc76bc8c2005-02-09 16:11:53 +0000491 * children
492 ********************************************************************/
subrata_modak56207ce2009-03-23 13:35:39 +0000493void manager(int num_procs)
robbiewc76bc8c2005-02-09 16:11:53 +0000494{
subrata_modak56207ce2009-03-23 13:35:39 +0000495 struct sigaction sa;
robbiewc76bc8c2005-02-09 16:11:53 +0000496
subrata_modak56207ce2009-03-23 13:35:39 +0000497 /* 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 }
robbiewc76bc8c2005-02-09 16:11:53 +0000505
subrata_modak56207ce2009-03-23 13:35:39 +0000506 /* set up the signal handling the children will use */
robbiewc76bc8c2005-02-09 16:11:53 +0000507
subrata_modak56207ce2009-03-23 13:35:39 +0000508 /* 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 Cooperd2f16672010-11-23 21:41:27 -0800514 k_sigaction(SIGHUP, &sa, NULL);
robbiewc76bc8c2005-02-09 16:11:53 +0000515
subrata_modak56207ce2009-03-23 13:35:39 +0000516 /* 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 Cooperd2f16672010-11-23 21:41:27 -0800520 k_sigaction(SIGALRM, &sa, NULL);
robbiewc76bc8c2005-02-09 16:11:53 +0000521
subrata_modak56207ce2009-03-23 13:35:39 +0000522 /* exit on QUIT */
523 sa.sa_handler = graceful_exit;
524 if (debug_flag >= 4)
525 printf("%d: setting SIGQUIT -> graceful_exit\n", mypid);
Garrett Cooperd2f16672010-11-23 21:41:27 -0800526 k_sigaction(SIGQUIT, &sa, NULL);
robbiewc76bc8c2005-02-09 16:11:53 +0000527
subrata_modak56207ce2009-03-23 13:35:39 +0000528 /* 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 Cooperd2f16672010-11-23 21:41:27 -0800533 k_sigaction(SIGUSR1, &sa, NULL);
subrata_modak56207ce2009-03-23 13:35:39 +0000534 /* 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 Cooperd2f16672010-11-23 21:41:27 -0800538 k_sigaction(SIGUSR2, &sa, NULL);
robbiewc76bc8c2005-02-09 16:11:53 +0000539
subrata_modak56207ce2009-03-23 13:35:39 +0000540 fork_procs(num_procs);
541 sleep(1); /* wait a sec to let all the children pause */
robbiewc76bc8c2005-02-09 16:11:53 +0000542
subrata_modak56207ce2009-03-23 13:35:39 +0000543 /* now set up my signal handling */
robbiewc76bc8c2005-02-09 16:11:53 +0000544
subrata_modak56207ce2009-03-23 13:35:39 +0000545 /* continue on ALRM */
546 sa.sa_handler = wakeup;
547 if (debug_flag >= 4)
548 printf("%d: setting SIGALRM -> wakeup\n", mypid);
Garrett Cooperd2f16672010-11-23 21:41:27 -0800549 k_sigaction(SIGALRM, &sa, NULL);
subrata_modak56207ce2009-03-23 13:35:39 +0000550 /* 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 Cooperd2f16672010-11-23 21:41:27 -0800554 k_sigaction(SIGUSR1, &sa, NULL);
subrata_modak56207ce2009-03-23 13:35:39 +0000555 /* 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 Cooperd2f16672010-11-23 21:41:27 -0800559 k_sigaction(SIGHUP, &sa, NULL);
robbiewc76bc8c2005-02-09 16:11:53 +0000560
subrata_modak56207ce2009-03-23 13:35:39 +0000561 /* 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 Cooperd2f16672010-11-23 21:41:27 -0800567 k_sigaction(SIGUSR2, &sa, NULL);
subrata_modak56207ce2009-03-23 13:35:39 +0000568
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 Cooperd2f16672010-11-23 21:41:27 -0800575 printf("%d: Couldn't signal master (%d) that we're "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800576 "ready. %d: %s",
577 mypid, getppid(), errno, strerror(errno));
subrata_modak56207ce2009-03-23 13:35:39 +0000578 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 Cooperd2f16672010-11-23 21:41:27 -0800592 printf("%d: All %d children reported in\n",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800593 mypid, child_signal_counter);
subrata_modak56207ce2009-03-23 13:35:39 +0000594 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 Cooperd2f16672010-11-23 21:41:27 -0800599 printf("%d: Couldn't signal master "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800600 "(%d) that we're ready. %d: %s\n",
601 mypid, getppid(), errno,
602 strerror(errno));
subrata_modak56207ce2009-03-23 13:35:39 +0000603 exit(errno);
604 }
605 usleep(100);
606 }
607 }
608 }
robbiewc76bc8c2005-02-09 16:11:53 +0000609}
610
611/* some simple signal handlers for the kids */
subrata_modak56207ce2009-03-23 13:35:39 +0000612void graceful_exit(int sig)
subrata_modak4bb656a2009-02-26 12:02:09 +0000613{
subrata_modak56207ce2009-03-23 13:35:39 +0000614 exit(0);
robbiewc76bc8c2005-02-09 16:11:53 +0000615}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800616
subrata_modak56207ce2009-03-23 13:35:39 +0000617void set_signal_parents(int sig)
subrata_modak4bb656a2009-02-26 12:02:09 +0000618{
subrata_modak56207ce2009-03-23 13:35:39 +0000619 if (debug_flag >= 8)
Garrett Cooperd2f16672010-11-23 21:41:27 -0800620 printf("%d: Child start signaling\n", mypid);
subrata_modak56207ce2009-03-23 13:35:39 +0000621 signal_parents_flag = 1;
robbiewc76bc8c2005-02-09 16:11:53 +0000622}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800623
subrata_modak56207ce2009-03-23 13:35:39 +0000624void clear_signal_parents(int sig)
subrata_modak4bb656a2009-02-26 12:02:09 +0000625{
subrata_modak56207ce2009-03-23 13:35:39 +0000626 if (debug_flag >= 8)
Garrett Cooperd2f16672010-11-23 21:41:27 -0800627 printf("%d: Child stop signaling\n", mypid);
subrata_modak56207ce2009-03-23 13:35:39 +0000628 signal_parents_flag = 0;
robbiewc76bc8c2005-02-09 16:11:53 +0000629}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800630
subrata_modak56207ce2009-03-23 13:35:39 +0000631void set_confirmed_ready(int sig)
subrata_modak4bb656a2009-02-26 12:02:09 +0000632{
robbiewc76bc8c2005-02-09 16:11:53 +0000633
subrata_modak56207ce2009-03-23 13:35:39 +0000634 if (debug_flag >= 3)
635 printf("%d: Manager confirmed ready\n", mypid);
636 confirmed_ready_flag = 1;
robbiewc76bc8c2005-02-09 16:11:53 +0000637}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800638
subrata_modak56207ce2009-03-23 13:35:39 +0000639void reset_counter(int sig)
subrata_modak4bb656a2009-02-26 12:02:09 +0000640{
subrata_modak56207ce2009-03-23 13:35:39 +0000641 checklist_reset(0xFF);
642 child_signal_counter = 0;
643 if (debug_flag >= 3)
644 printf("%d: reset_counter\n", mypid);
robbiewc76bc8c2005-02-09 16:11:53 +0000645}
646
subrata_modak56207ce2009-03-23 13:35:39 +0000647void reply_to_child(int sig, siginfo_t * si, void *data)
robbiewc76bc8c2005-02-09 16:11:53 +0000648{
subrata_modak56207ce2009-03-23 13:35:39 +0000649 struct pid_list_item findit, *result;
robbiewc76bc8c2005-02-09 16:11:53 +0000650
subrata_modak56207ce2009-03-23 13:35:39 +0000651 findit.pid = si->si_pid;
robbiewc76bc8c2005-02-09 16:11:53 +0000652
subrata_modak56207ce2009-03-23 13:35:39 +0000653 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 }
robbiewc76bc8c2005-02-09 16:11:53 +0000672}
673
subrata_modak56207ce2009-03-23 13:35:39 +0000674void wakeup(int sig)
675{
676 return;
677}
robbiewc76bc8c2005-02-09 16:11:53 +0000678
679/*************************************************
680 * fork_procs() - create all the children
681 ************************************************/
subrata_modak56207ce2009-03-23 13:35:39 +0000682void fork_procs(int procs_left)
robbiewc76bc8c2005-02-09 16:11:53 +0000683{
subrata_modak56207ce2009-03-23 13:35:39 +0000684 pid_t child;
robbiewc76bc8c2005-02-09 16:11:53 +0000685
subrata_modak56207ce2009-03-23 13:35:39 +0000686 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;
robbiewc76bc8c2005-02-09 16:11:53 +0000692
subrata_modak56207ce2009-03-23 13:35:39 +0000693 /* We are setting the flag for children, to avoid missing any signals */
694 signal_parents_flag = 0;
robbiewc76bc8c2005-02-09 16:11:53 +0000695
subrata_modak56207ce2009-03-23 13:35:39 +0000696 while (procs_left) {
697 if (debug_flag >= 4)
Garrett Cooperd2f16672010-11-23 21:41:27 -0800698 printf("%d: forking new child\n", mypid);
subrata_modak56207ce2009-03-23 13:35:39 +0000699 switch (child = fork()) {
700 case -1:
Wanlong Gao354ebb42012-12-07 10:10:04 +0800701 tst_brkm(TBROK | TERRNO, cleanup,
702 "fork() failed in fork_procs(%d)", procs_left);
subrata_modak56207ce2009-03-23 13:35:39 +0000703 break;
704 case 0:
705 mypid = getpid();
706 while (1) {
707 /* wait to start */
708 if (debug_flag >= 8)
Garrett Cooperd2f16672010-11-23 21:41:27 -0800709 printf("%d: child pausing\n", mypid);
subrata_modak56207ce2009-03-23 13:35:39 +0000710 /*
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 Cooperd2f16672010-11-23 21:41:27 -0800722 printf("%d: child, SIGUSR2 "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800723 "-> %d\n",
724 mypid, getppid());
subrata_modak56207ce2009-03-23 13:35:39 +0000725 if (kill(getppid(), SIGUSR2) == -1) {
726 /* something went wrong */
Garrett Cooperd2f16672010-11-23 21:41:27 -0800727 printf("%d: kill(ppid:%d, "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800728 "SIGUSR2) failed. %d: %s",
729 mypid, getppid(), errno,
730 strerror(errno));
subrata_modak56207ce2009-03-23 13:35:39 +0000731 exit(errno);
732 }
733 usleep(100);
734 }
735 }
736 break;
737 default:
738 child_checklist[child_checklist_total++].pid = child;
739 }
Garrett Cooperd2f16672010-11-23 21:41:27 -0800740 procs_left--;
subrata_modak56207ce2009-03-23 13:35:39 +0000741 }
742 qsort(child_checklist, child_checklist_total, sizeof(*child_checklist),
743 checklist_cmp);
robbiewc76bc8c2005-02-09 16:11:53 +0000744}
745
subrata_modak56207ce2009-03-23 13:35:39 +0000746int checklist_cmp(const void *a, const void *b)
robbiewc76bc8c2005-02-09 16:11:53 +0000747{
subrata_modak56207ce2009-03-23 13:35:39 +0000748 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;
robbiewc76bc8c2005-02-09 16:11:53 +0000750
subrata_modak56207ce2009-03-23 13:35:39 +0000751 return (pa->pid > pb->pid) - (pa->pid < pb->pid);
robbiewc76bc8c2005-02-09 16:11:53 +0000752}
753
subrata_modak56207ce2009-03-23 13:35:39 +0000754void checklist_reset(int bit)
robbiewc76bc8c2005-02-09 16:11:53 +0000755{
subrata_modak56207ce2009-03-23 13:35:39 +0000756 int i;
757 for (i = 0; i < child_checklist_total; i++) {
758 child_checklist[i].flag = child_checklist[i].flag & (~bit);
759 }
robbiewc76bc8c2005-02-09 16:11:53 +0000760
761}
762
subrata_modak56207ce2009-03-23 13:35:39 +0000763inline int k_sigaction(int sig, struct sigaction *sa, struct sigaction *osa)
robbiewc76bc8c2005-02-09 16:11:53 +0000764{
subrata_modak56207ce2009-03-23 13:35:39 +0000765 int ret;
766 if ((ret = sigaction(sig, sa, osa)) == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800767 tst_brkm(TBROK | TERRNO, cleanup, "sigaction(%d, ...) failed",
768 sig);
subrata_modak56207ce2009-03-23 13:35:39 +0000769 }
770 return ret;
Chris Dearmanec6edca2012-10-17 19:54:01 -0700771}