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