xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/sigrelse/sigrelse01.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
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: sigrelse01.c,v 1.14 2009/08/28 14:10:16 vapier Exp $ */
34*49cdfc7eSAndroid Build Coastguard Worker /*****************************************************************************
35*49cdfc7eSAndroid Build Coastguard Worker  * OS Test - Silicon Graphics, Inc.  Eagan, Minnesota
36*49cdfc7eSAndroid Build Coastguard Worker  *
37*49cdfc7eSAndroid Build Coastguard Worker  * TEST IDENTIFIER : sigrelse01 Releasing held signals.
38*49cdfc7eSAndroid Build Coastguard Worker  *
39*49cdfc7eSAndroid Build Coastguard Worker  * PARENT DOCUMENT : sgrtds01  sigrelse system call
40*49cdfc7eSAndroid Build Coastguard Worker  *
41*49cdfc7eSAndroid Build Coastguard Worker  * AUTHOR          : Bob Clark
42*49cdfc7eSAndroid Build Coastguard Worker  *		   : Rewrote 12/92 by Richard Logan
43*49cdfc7eSAndroid Build Coastguard Worker  *
44*49cdfc7eSAndroid Build Coastguard Worker  * CO-PILOT        : Dave Baumgartner
45*49cdfc7eSAndroid Build Coastguard Worker  *
46*49cdfc7eSAndroid Build Coastguard Worker  * DATE STARTED    : 10/08/86
47*49cdfc7eSAndroid Build Coastguard Worker  *
48*49cdfc7eSAndroid Build Coastguard Worker  * TEST ITEMS
49*49cdfc7eSAndroid Build Coastguard Worker  *
50*49cdfc7eSAndroid Build Coastguard Worker  * 	1. sigrelse turns on the receipt of signals held by sighold.
51*49cdfc7eSAndroid Build Coastguard Worker  *
52*49cdfc7eSAndroid Build Coastguard Worker  * SPECIAL PROCEDURAL REQUIRMENTS
53*49cdfc7eSAndroid Build Coastguard Worker  * 	None
54*49cdfc7eSAndroid Build Coastguard Worker  *
55*49cdfc7eSAndroid Build Coastguard Worker  * DETAILED DESCRIPTION
56*49cdfc7eSAndroid Build Coastguard Worker  * 	set up pipe for parent/child communications
57*49cdfc7eSAndroid Build Coastguard Worker  * 	fork off a child process
58*49cdfc7eSAndroid Build Coastguard Worker  *
59*49cdfc7eSAndroid Build Coastguard Worker  * 	parent():
60*49cdfc7eSAndroid Build Coastguard Worker  * 		set up for unexpected signals
61*49cdfc7eSAndroid Build Coastguard Worker  * 		wait for child to send ready message over pipe
62*49cdfc7eSAndroid Build Coastguard Worker  * 		send all catchable signals to child process
63*49cdfc7eSAndroid Build Coastguard Worker  *		send alarm signal to speed up timeout
64*49cdfc7eSAndroid Build Coastguard Worker  * 		wait for child to terminate and check exit value
65*49cdfc7eSAndroid Build Coastguard Worker  *
66*49cdfc7eSAndroid Build Coastguard Worker  * 		if exit value is EXIT_OK
67*49cdfc7eSAndroid Build Coastguard Worker  * 		  get message from pipe (contains array of signal counters)
68*49cdfc7eSAndroid Build Coastguard Worker  * 		  loop through array of signal counters and record any
69*49cdfc7eSAndroid Build Coastguard Worker  * 			signals which were not caught once.
70*49cdfc7eSAndroid Build Coastguard Worker  * 		  record PASS or FAIL depending on what was found in the array.
71*49cdfc7eSAndroid Build Coastguard Worker  *
72*49cdfc7eSAndroid Build Coastguard Worker  * 		else if exit is SIG_CAUGHT then BROK (signal caught
73*49cdfc7eSAndroid Build Coastguard Worker  *		  before released)
74*49cdfc7eSAndroid Build Coastguard Worker  * 		else if exit is WRITE_BROK then BROK (write() to pipe failed)
75*49cdfc7eSAndroid Build Coastguard Worker  * 		else if exit is HANDLE_ERR then BROK (error in child's
76*49cdfc7eSAndroid Build Coastguard Worker  *		  signal handler)
77*49cdfc7eSAndroid Build Coastguard Worker  * 		else unexpected exit value - BROK
78*49cdfc7eSAndroid Build Coastguard Worker  *
79*49cdfc7eSAndroid Build Coastguard Worker  * 	child():
80*49cdfc7eSAndroid Build Coastguard Worker  * 	  phase 1:
81*49cdfc7eSAndroid Build Coastguard Worker  * 		set up to catch all catchable signals (exit SIG_CAUGHT
82*49cdfc7eSAndroid Build Coastguard Worker  *		  if caught)
83*49cdfc7eSAndroid Build Coastguard Worker  * 		hold each signal with sighold()
84*49cdfc7eSAndroid Build Coastguard Worker  * 		send parent ready message if setup went ok.
85*49cdfc7eSAndroid Build Coastguard Worker  * 		wait for signals to arrive - timeout if they don't
86*49cdfc7eSAndroid Build Coastguard Worker  *
87*49cdfc7eSAndroid Build Coastguard Worker  * 	  phase 2:
88*49cdfc7eSAndroid Build Coastguard Worker  * 		release each signal and wait a second for the handler to
89*49cdfc7eSAndroid Build Coastguard Worker  *		  catch it.
90*49cdfc7eSAndroid Build Coastguard Worker  * 		(the handler will record each signal it catches in an array
91*49cdfc7eSAndroid Build Coastguard Worker  * 		and exit HANDLE_ERR if an error occurs)
92*49cdfc7eSAndroid Build Coastguard Worker  *
93*49cdfc7eSAndroid Build Coastguard Worker  * 		send array of counters back to parent for processing.
94*49cdfc7eSAndroid Build Coastguard Worker  * 		exit EXIT_OK
95*49cdfc7eSAndroid Build Coastguard Worker  * NOTES
96*49cdfc7eSAndroid Build Coastguard Worker  *	since child is executing system calls under test, no
97*49cdfc7eSAndroid Build Coastguard Worker  *	system call times are printed.
98*49cdfc7eSAndroid Build Coastguard Worker  *
99*49cdfc7eSAndroid Build Coastguard Worker ***************************************************************************/
100*49cdfc7eSAndroid Build Coastguard Worker 
101*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
102*49cdfc7eSAndroid Build Coastguard Worker #include <sys/wait.h>
103*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
104*49cdfc7eSAndroid Build Coastguard Worker #include <fcntl.h>
105*49cdfc7eSAndroid Build Coastguard Worker #include <signal.h>
106*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
107*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
108*49cdfc7eSAndroid Build Coastguard Worker #include <time.h>
109*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
110*49cdfc7eSAndroid Build Coastguard Worker #include "test.h"
111*49cdfc7eSAndroid Build Coastguard Worker #include "safe_macros.h"
112*49cdfc7eSAndroid Build Coastguard Worker 
113*49cdfc7eSAndroid Build Coastguard Worker #ifdef __linux__
114*49cdfc7eSAndroid Build Coastguard Worker /* glibc2.2 definition needs -D_XOPEN_SOURCE, which breaks other things. */
115*49cdfc7eSAndroid Build Coastguard Worker extern int sighold(int __sig);
116*49cdfc7eSAndroid Build Coastguard Worker extern int sigrelse(int __sig);
117*49cdfc7eSAndroid Build Coastguard Worker #endif
118*49cdfc7eSAndroid Build Coastguard Worker 
119*49cdfc7eSAndroid Build Coastguard Worker /* Needed for NPTL */
120*49cdfc7eSAndroid Build Coastguard Worker #define SIGCANCEL 32
121*49cdfc7eSAndroid Build Coastguard Worker #define SIGTIMER 33
122*49cdfc7eSAndroid Build Coastguard Worker 
123*49cdfc7eSAndroid Build Coastguard Worker void setup(void);
124*49cdfc7eSAndroid Build Coastguard Worker void cleanup(void);
125*49cdfc7eSAndroid Build Coastguard Worker static void parent(void);
126*49cdfc7eSAndroid Build Coastguard Worker static void child(void);
127*49cdfc7eSAndroid Build Coastguard Worker static void timeout(int sig);
128*49cdfc7eSAndroid Build Coastguard Worker static int setup_sigs(void);
129*49cdfc7eSAndroid Build Coastguard Worker static void handler(int sig);
130*49cdfc7eSAndroid Build Coastguard Worker static void wait_a_while(void);
131*49cdfc7eSAndroid Build Coastguard Worker static char *read_pipe(int fd);
132*49cdfc7eSAndroid Build Coastguard Worker static int write_pipe(int fd, char *msg);
133*49cdfc7eSAndroid Build Coastguard Worker static int set_timeout(void);
134*49cdfc7eSAndroid Build Coastguard Worker static void clear_timeout(void);
135*49cdfc7eSAndroid Build Coastguard Worker static void getout(void);
136*49cdfc7eSAndroid Build Coastguard Worker int choose_sig(int sig);
137*49cdfc7eSAndroid Build Coastguard Worker 
138*49cdfc7eSAndroid Build Coastguard Worker #define TRUE  1
139*49cdfc7eSAndroid Build Coastguard Worker #define FALSE 0
140*49cdfc7eSAndroid Build Coastguard Worker 
141*49cdfc7eSAndroid Build Coastguard Worker #ifndef DEBUG
142*49cdfc7eSAndroid Build Coastguard Worker #define DEBUG 0
143*49cdfc7eSAndroid Build Coastguard Worker #endif
144*49cdfc7eSAndroid Build Coastguard Worker 
145*49cdfc7eSAndroid Build Coastguard Worker #define CHILD_EXIT(VAL) ((VAL >> 8) & 0377)	/* exit value of child process */
146*49cdfc7eSAndroid Build Coastguard Worker #define CHILD_SIG(VAL)   (VAL & 0377)	/* signal value of child proc */
147*49cdfc7eSAndroid Build Coastguard Worker 
148*49cdfc7eSAndroid Build Coastguard Worker #define MAXMESG 512		/* the size of the message string */
149*49cdfc7eSAndroid Build Coastguard Worker 
150*49cdfc7eSAndroid Build Coastguard Worker #define READY "ready"		/* signal to parent that child is set up */
151*49cdfc7eSAndroid Build Coastguard Worker 
152*49cdfc7eSAndroid Build Coastguard Worker #define TIMEOUT 30		/* time (sec) used in the alarm calls */
153*49cdfc7eSAndroid Build Coastguard Worker 
154*49cdfc7eSAndroid Build Coastguard Worker /* child exit values */
155*49cdfc7eSAndroid Build Coastguard Worker #define EXIT_OK    0
156*49cdfc7eSAndroid Build Coastguard Worker #define SIG_CAUGHT 8
157*49cdfc7eSAndroid Build Coastguard Worker #define WRITE_BROK 16
158*49cdfc7eSAndroid Build Coastguard Worker #define HANDLE_ERR 32
159*49cdfc7eSAndroid Build Coastguard Worker 
160*49cdfc7eSAndroid Build Coastguard Worker int TST_TOTAL = 1;		/* number of test items */
161*49cdfc7eSAndroid Build Coastguard Worker 
162*49cdfc7eSAndroid Build Coastguard Worker char *TCID = "sigrelse01";	/* test case identifier */
163*49cdfc7eSAndroid Build Coastguard Worker static char mesg[MAXMESG];	/* message buffer for tst_res */
164*49cdfc7eSAndroid Build Coastguard Worker static int pid;			/* process id of child */
165*49cdfc7eSAndroid Build Coastguard Worker static int pipe_fd[2];		/* file descriptors for pipe parent read */
166*49cdfc7eSAndroid Build Coastguard Worker static int pipe_fd2[2];		/* file descriptors for pipe child read */
167*49cdfc7eSAndroid Build Coastguard Worker static int phase;		/* flag for phase1 or phase2 of */
168*49cdfc7eSAndroid Build Coastguard Worker 				/* signal handler */
169*49cdfc7eSAndroid Build Coastguard Worker static int sig_caught;		/* flag TRUE if signal caught */
170*49cdfc7eSAndroid Build Coastguard Worker 				/* (see wait_a_while ()) */
171*49cdfc7eSAndroid Build Coastguard Worker 
172*49cdfc7eSAndroid Build Coastguard Worker /* ensure that NUMSIGS is defined. */
173*49cdfc7eSAndroid Build Coastguard Worker #ifndef NUMSIGS
174*49cdfc7eSAndroid Build Coastguard Worker #define NUMSIGS NSIG
175*49cdfc7eSAndroid Build Coastguard Worker #endif
176*49cdfc7eSAndroid Build Coastguard Worker 
177*49cdfc7eSAndroid Build Coastguard Worker /* array of counters for signals caught by handler() */
178*49cdfc7eSAndroid Build Coastguard Worker static int sig_array[NUMSIGS];
179*49cdfc7eSAndroid Build Coastguard Worker 
180*49cdfc7eSAndroid Build Coastguard Worker /***********************************************************************
181*49cdfc7eSAndroid Build Coastguard Worker  *   M A I N
182*49cdfc7eSAndroid Build Coastguard Worker  ***********************************************************************/
main(int argc,char ** argv)183*49cdfc7eSAndroid Build Coastguard Worker int main(int argc, char **argv)
184*49cdfc7eSAndroid Build Coastguard Worker {
185*49cdfc7eSAndroid Build Coastguard Worker 	int lc;
186*49cdfc7eSAndroid Build Coastguard Worker 
187*49cdfc7eSAndroid Build Coastguard Worker 	/* gcc -Wall complains about sig_caught not being ref'd because of the
188*49cdfc7eSAndroid Build Coastguard Worker 	   external declarations. */
189*49cdfc7eSAndroid Build Coastguard Worker 	sig_caught = FALSE;
190*49cdfc7eSAndroid Build Coastguard Worker 
191*49cdfc7eSAndroid Build Coastguard Worker 	/*
192*49cdfc7eSAndroid Build Coastguard Worker 	 * parse standard options
193*49cdfc7eSAndroid Build Coastguard Worker 	 */
194*49cdfc7eSAndroid Build Coastguard Worker 	tst_parse_opts(argc, argv, NULL, NULL);
195*49cdfc7eSAndroid Build Coastguard Worker 
196*49cdfc7eSAndroid Build Coastguard Worker 	/*
197*49cdfc7eSAndroid Build Coastguard Worker 	 * perform global setup for test
198*49cdfc7eSAndroid Build Coastguard Worker 	 */
199*49cdfc7eSAndroid Build Coastguard Worker 	setup();
200*49cdfc7eSAndroid Build Coastguard Worker 
201*49cdfc7eSAndroid Build Coastguard Worker 	for (lc = 0; TEST_LOOPING(lc); lc++) {
202*49cdfc7eSAndroid Build Coastguard Worker 
203*49cdfc7eSAndroid Build Coastguard Worker 		tst_count = 0;
204*49cdfc7eSAndroid Build Coastguard Worker 
205*49cdfc7eSAndroid Build Coastguard Worker 		/*
206*49cdfc7eSAndroid Build Coastguard Worker 		 * fork off a child process
207*49cdfc7eSAndroid Build Coastguard Worker 		 */
208*49cdfc7eSAndroid Build Coastguard Worker 		if ((pid = tst_fork()) < 0)
209*49cdfc7eSAndroid Build Coastguard Worker 			tst_brkm(TBROK | TERRNO, cleanup, "fork() failed");
210*49cdfc7eSAndroid Build Coastguard Worker 		else if (pid > 0)
211*49cdfc7eSAndroid Build Coastguard Worker 			parent();
212*49cdfc7eSAndroid Build Coastguard Worker 		else
213*49cdfc7eSAndroid Build Coastguard Worker 			child();
214*49cdfc7eSAndroid Build Coastguard Worker 
215*49cdfc7eSAndroid Build Coastguard Worker 	}
216*49cdfc7eSAndroid Build Coastguard Worker 
217*49cdfc7eSAndroid Build Coastguard Worker 	cleanup();
218*49cdfc7eSAndroid Build Coastguard Worker 	tst_exit();
219*49cdfc7eSAndroid Build Coastguard Worker 
220*49cdfc7eSAndroid Build Coastguard Worker }				/* end main */
221*49cdfc7eSAndroid Build Coastguard Worker 
222*49cdfc7eSAndroid Build Coastguard Worker /****************************************************************************
223*49cdfc7eSAndroid Build Coastguard Worker  * parent() : wait for "ready" from child, send signals to child, wait for
224*49cdfc7eSAndroid Build Coastguard Worker  *    child to exit and report what happened.
225*49cdfc7eSAndroid Build Coastguard Worker  ***************************************************************************/
parent(void)226*49cdfc7eSAndroid Build Coastguard Worker static void parent(void)
227*49cdfc7eSAndroid Build Coastguard Worker {
228*49cdfc7eSAndroid Build Coastguard Worker 	int term_stat;		/* child return status */
229*49cdfc7eSAndroid Build Coastguard Worker 	int rv;			/* function return value */
230*49cdfc7eSAndroid Build Coastguard Worker 	int sig;		/* current signal number */
231*49cdfc7eSAndroid Build Coastguard Worker 	char *str;		/* string returned from read_pipe() */
232*49cdfc7eSAndroid Build Coastguard Worker 	int *array;		/* pointer to sig_array returned from child */
233*49cdfc7eSAndroid Build Coastguard Worker 	int fail = FALSE;	/* flag indicating test item failure */
234*49cdfc7eSAndroid Build Coastguard Worker 	char big_mesg[MAXMESG * 6];	/* storage for big failure message */
235*49cdfc7eSAndroid Build Coastguard Worker 	int caught_sigs;
236*49cdfc7eSAndroid Build Coastguard Worker 
237*49cdfc7eSAndroid Build Coastguard Worker 	/* wait for "ready" message from child */
238*49cdfc7eSAndroid Build Coastguard Worker 	if ((str = read_pipe(pipe_fd[0])) == NULL) {
239*49cdfc7eSAndroid Build Coastguard Worker 		/* read_pipe() failed. */
240*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK, getout, "%s", mesg);
241*49cdfc7eSAndroid Build Coastguard Worker 	}
242*49cdfc7eSAndroid Build Coastguard Worker 
243*49cdfc7eSAndroid Build Coastguard Worker 	if (strcmp(str, READY) != 0) {
244*49cdfc7eSAndroid Build Coastguard Worker 		/* child setup did not go well */
245*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK, getout, "%s", str);
246*49cdfc7eSAndroid Build Coastguard Worker 	}
247*49cdfc7eSAndroid Build Coastguard Worker 
248*49cdfc7eSAndroid Build Coastguard Worker 	/*
249*49cdfc7eSAndroid Build Coastguard Worker 	 * send signals to child and see if it holds them
250*49cdfc7eSAndroid Build Coastguard Worker 	 */
251*49cdfc7eSAndroid Build Coastguard Worker 
252*49cdfc7eSAndroid Build Coastguard Worker 	for (sig = 1; sig < NUMSIGS; sig++) {
253*49cdfc7eSAndroid Build Coastguard Worker 		if (choose_sig(sig)) {
254*49cdfc7eSAndroid Build Coastguard Worker 			if (kill(pid, sig) < 0) {
255*49cdfc7eSAndroid Build Coastguard Worker 				if (errno == ESRCH) {
256*49cdfc7eSAndroid Build Coastguard Worker 					if (kill(pid, SIGTERM) < 0)
257*49cdfc7eSAndroid Build Coastguard Worker 						tst_brkm(TBROK | TERRNO, getout,
258*49cdfc7eSAndroid Build Coastguard Worker 							 "kill(%d, %d) and kill(%d, SIGTERM) failed",
259*49cdfc7eSAndroid Build Coastguard Worker 							 pid, sig, pid);
260*49cdfc7eSAndroid Build Coastguard Worker 					else
261*49cdfc7eSAndroid Build Coastguard Worker 						tst_brkm(TBROK | TERRNO, getout,
262*49cdfc7eSAndroid Build Coastguard Worker 							 "kill(%d, %d) failed, but kill(%d, SIGTERM) worked",
263*49cdfc7eSAndroid Build Coastguard Worker 							 pid, sig, pid);
264*49cdfc7eSAndroid Build Coastguard Worker 				} else
265*49cdfc7eSAndroid Build Coastguard Worker 					tst_brkm(TBROK | TERRNO, getout,
266*49cdfc7eSAndroid Build Coastguard Worker 						 "kill(%d, %d) failed", pid,
267*49cdfc7eSAndroid Build Coastguard Worker 						 sig);
268*49cdfc7eSAndroid Build Coastguard Worker 			}
269*49cdfc7eSAndroid Build Coastguard Worker 		}
270*49cdfc7eSAndroid Build Coastguard Worker 	}
271*49cdfc7eSAndroid Build Coastguard Worker 
272*49cdfc7eSAndroid Build Coastguard Worker 	if (write_pipe(pipe_fd2[1], READY) < 0) {
273*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK | TERRNO, getout,
274*49cdfc7eSAndroid Build Coastguard Worker 			 "Unable to tell child to go, write to pipe failed");
275*49cdfc7eSAndroid Build Coastguard Worker 	}
276*49cdfc7eSAndroid Build Coastguard Worker 
277*49cdfc7eSAndroid Build Coastguard Worker 	/*
278*49cdfc7eSAndroid Build Coastguard Worker 	 * child is now releasing signals, wait and check exit value
279*49cdfc7eSAndroid Build Coastguard Worker 	 */
280*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_WAIT(getout, &term_stat);
281*49cdfc7eSAndroid Build Coastguard Worker 
282*49cdfc7eSAndroid Build Coastguard Worker 	/* check child's signal exit value */
283*49cdfc7eSAndroid Build Coastguard Worker 	if ((sig = CHILD_SIG(term_stat)) != 0)
284*49cdfc7eSAndroid Build Coastguard Worker 		/* the child was zapped by a signal */
285*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK, cleanup, "Unexpected signal %d killed child",
286*49cdfc7eSAndroid Build Coastguard Worker 			 sig);
287*49cdfc7eSAndroid Build Coastguard Worker 
288*49cdfc7eSAndroid Build Coastguard Worker 	/* get child exit value */
289*49cdfc7eSAndroid Build Coastguard Worker 
290*49cdfc7eSAndroid Build Coastguard Worker 	rv = CHILD_EXIT(term_stat);
291*49cdfc7eSAndroid Build Coastguard Worker 
292*49cdfc7eSAndroid Build Coastguard Worker 	switch (rv) {
293*49cdfc7eSAndroid Build Coastguard Worker 	case EXIT_OK:
294*49cdfc7eSAndroid Build Coastguard Worker 		/* sig_array sent back on pipe, check it out */
295*49cdfc7eSAndroid Build Coastguard Worker 		if ((array = (int *)read_pipe(pipe_fd[0])) == NULL) {
296*49cdfc7eSAndroid Build Coastguard Worker 			/* read_pipe() failed. */
297*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TBROK, "%s", mesg);
298*49cdfc7eSAndroid Build Coastguard Worker 			break;
299*49cdfc7eSAndroid Build Coastguard Worker 		}
300*49cdfc7eSAndroid Build Coastguard Worker #if DEBUG > 1
301*49cdfc7eSAndroid Build Coastguard Worker 		for (sig = 1; sig < NUMSIGS; sig++) {
302*49cdfc7eSAndroid Build Coastguard Worker 			printf("array[%d] = %d\n", sig, array[sig]);
303*49cdfc7eSAndroid Build Coastguard Worker 		}
304*49cdfc7eSAndroid Build Coastguard Worker #endif
305*49cdfc7eSAndroid Build Coastguard Worker 		caught_sigs = 0;
306*49cdfc7eSAndroid Build Coastguard Worker 		for (sig = 1; sig < NUMSIGS; sig++) {
307*49cdfc7eSAndroid Build Coastguard Worker 			if (choose_sig(sig)) {
308*49cdfc7eSAndroid Build Coastguard Worker 				if (array[sig] != 1) {
309*49cdfc7eSAndroid Build Coastguard Worker 					/* sig was not caught or caught too many times */
310*49cdfc7eSAndroid Build Coastguard Worker 					(void)sprintf(mesg,
311*49cdfc7eSAndroid Build Coastguard Worker 						      "\tsignal %d caught %d times (expected 1).\n",
312*49cdfc7eSAndroid Build Coastguard Worker 						      sig, array[sig]);
313*49cdfc7eSAndroid Build Coastguard Worker 					(void)strcat(big_mesg, mesg);
314*49cdfc7eSAndroid Build Coastguard Worker 					fail = TRUE;
315*49cdfc7eSAndroid Build Coastguard Worker 				} else {
316*49cdfc7eSAndroid Build Coastguard Worker 					caught_sigs++;
317*49cdfc7eSAndroid Build Coastguard Worker 				}
318*49cdfc7eSAndroid Build Coastguard Worker 			}
319*49cdfc7eSAndroid Build Coastguard Worker 		}		/* endfor */
320*49cdfc7eSAndroid Build Coastguard Worker 
321*49cdfc7eSAndroid Build Coastguard Worker 		if (fail == TRUE)
322*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TFAIL, "%s", big_mesg);
323*49cdfc7eSAndroid Build Coastguard Worker 		else
324*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TPASS,
325*49cdfc7eSAndroid Build Coastguard Worker 				 "sigrelse() released all %d signals under test.",
326*49cdfc7eSAndroid Build Coastguard Worker 				 caught_sigs);
327*49cdfc7eSAndroid Build Coastguard Worker 		break;
328*49cdfc7eSAndroid Build Coastguard Worker 
329*49cdfc7eSAndroid Build Coastguard Worker 	case TBROK:
330*49cdfc7eSAndroid Build Coastguard Worker 		/* get BROK message from pipe */
331*49cdfc7eSAndroid Build Coastguard Worker 		if ((str = read_pipe(pipe_fd[0])) == NULL) {
332*49cdfc7eSAndroid Build Coastguard Worker 			/* read_pipe() failed. */
333*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TBROK, "%s", mesg);
334*49cdfc7eSAndroid Build Coastguard Worker 			break;
335*49cdfc7eSAndroid Build Coastguard Worker 		}
336*49cdfc7eSAndroid Build Coastguard Worker 
337*49cdfc7eSAndroid Build Coastguard Worker 		/* call tst_res: str contains the message */
338*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TBROK, "%s", str);
339*49cdfc7eSAndroid Build Coastguard Worker 		break;
340*49cdfc7eSAndroid Build Coastguard Worker 	case SIG_CAUGHT:
341*49cdfc7eSAndroid Build Coastguard Worker 		/* a signal was caught before it was released */
342*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TBROK, "A signal was caught before being released.");
343*49cdfc7eSAndroid Build Coastguard Worker 		break;
344*49cdfc7eSAndroid Build Coastguard Worker 	case WRITE_BROK:
345*49cdfc7eSAndroid Build Coastguard Worker 		/* the write() call failed in child's write_pipe */
346*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TBROK, "write() pipe failed for child.");
347*49cdfc7eSAndroid Build Coastguard Worker 		break;
348*49cdfc7eSAndroid Build Coastguard Worker 	case HANDLE_ERR:
349*49cdfc7eSAndroid Build Coastguard Worker 		/* more than one signal tried to be handled at the same time */
350*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TBROK, "Error occured in signal handler.");
351*49cdfc7eSAndroid Build Coastguard Worker 		break;
352*49cdfc7eSAndroid Build Coastguard Worker 	default:
353*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TBROK, "Unexpected exit code %d from child", rv);
354*49cdfc7eSAndroid Build Coastguard Worker 		break;
355*49cdfc7eSAndroid Build Coastguard Worker 	}
356*49cdfc7eSAndroid Build Coastguard Worker 
357*49cdfc7eSAndroid Build Coastguard Worker }				/* end of parent */
358*49cdfc7eSAndroid Build Coastguard Worker 
359*49cdfc7eSAndroid Build Coastguard Worker /****************************************************************************
360*49cdfc7eSAndroid Build Coastguard Worker  * child() : hold signals, notify parent and wait for parent to send signals.
361*49cdfc7eSAndroid Build Coastguard Worker  *   If none were caught (sighold worked), release the signals one at a time
362*49cdfc7eSAndroid Build Coastguard Worker  *   and wait for them to be caught.  Send results back to parent
363*49cdfc7eSAndroid Build Coastguard Worker  *   for processing.
364*49cdfc7eSAndroid Build Coastguard Worker  ***************************************************************************/
child(void)365*49cdfc7eSAndroid Build Coastguard Worker static void child(void)
366*49cdfc7eSAndroid Build Coastguard Worker {
367*49cdfc7eSAndroid Build Coastguard Worker 	int rv;			/* return value from sighold() and sigrelse() */
368*49cdfc7eSAndroid Build Coastguard Worker 	int sig;		/* signal value */
369*49cdfc7eSAndroid Build Coastguard Worker 	int exit_val;		/* exit value to send to parent */
370*49cdfc7eSAndroid Build Coastguard Worker 	char note[MAXMESG];	/* message buffer for pipe */
371*49cdfc7eSAndroid Build Coastguard Worker 	char *str;
372*49cdfc7eSAndroid Build Coastguard Worker 
373*49cdfc7eSAndroid Build Coastguard Worker 	phase = 1;		/* tell handler that we do not want to catch signals */
374*49cdfc7eSAndroid Build Coastguard Worker 
375*49cdfc7eSAndroid Build Coastguard Worker 	/* set note to READY and if an error occurs, overwrite it */
376*49cdfc7eSAndroid Build Coastguard Worker 	(void)strcpy(note, READY);
377*49cdfc7eSAndroid Build Coastguard Worker 
378*49cdfc7eSAndroid Build Coastguard Worker 	/* set alarm in case something hangs */
379*49cdfc7eSAndroid Build Coastguard Worker 	if (set_timeout() < 0) {
380*49cdfc7eSAndroid Build Coastguard Worker 		/* an error occured - put mesg in note and send it back to parent */
381*49cdfc7eSAndroid Build Coastguard Worker 		(void)strcpy(note, mesg);
382*49cdfc7eSAndroid Build Coastguard Worker 
383*49cdfc7eSAndroid Build Coastguard Worker 	} else if (setup_sigs() < 0) {
384*49cdfc7eSAndroid Build Coastguard Worker 		/* an error occured - put mesg in note and send it back to parent */
385*49cdfc7eSAndroid Build Coastguard Worker 		(void)strcpy(note, mesg);
386*49cdfc7eSAndroid Build Coastguard Worker 
387*49cdfc7eSAndroid Build Coastguard Worker 	} else {
388*49cdfc7eSAndroid Build Coastguard Worker 		/* all set up to catch signals, now hold them */
389*49cdfc7eSAndroid Build Coastguard Worker 
390*49cdfc7eSAndroid Build Coastguard Worker 		for (sig = 1; sig < NUMSIGS; sig++) {
391*49cdfc7eSAndroid Build Coastguard Worker 			if (choose_sig(sig)) {
392*49cdfc7eSAndroid Build Coastguard Worker 				if ((rv = sighold(sig)) != 0) {
393*49cdfc7eSAndroid Build Coastguard Worker 					/* THEY say sighold ALWAYS returns 0 */
394*49cdfc7eSAndroid Build Coastguard Worker 					(void)sprintf(note,
395*49cdfc7eSAndroid Build Coastguard Worker 						      "sighold did not return 0. rv:%d",
396*49cdfc7eSAndroid Build Coastguard Worker 						      rv);
397*49cdfc7eSAndroid Build Coastguard Worker 					break;
398*49cdfc7eSAndroid Build Coastguard Worker 				}
399*49cdfc7eSAndroid Build Coastguard Worker 			}
400*49cdfc7eSAndroid Build Coastguard Worker 		}
401*49cdfc7eSAndroid Build Coastguard Worker 
402*49cdfc7eSAndroid Build Coastguard Worker 	}
403*49cdfc7eSAndroid Build Coastguard Worker 
404*49cdfc7eSAndroid Build Coastguard Worker 	/*
405*49cdfc7eSAndroid Build Coastguard Worker 	 * send note to parent (if not READY, parent will BROK) and
406*49cdfc7eSAndroid Build Coastguard Worker 	 * wait for parent to send signals.  The timeout clock is set so
407*49cdfc7eSAndroid Build Coastguard Worker 	 * that we will not wait forever - if sighold() did its job, we
408*49cdfc7eSAndroid Build Coastguard Worker 	 * will not receive the signals.  If sighold() blew it we will
409*49cdfc7eSAndroid Build Coastguard Worker 	 * catch a signal and the interrupt handler will exit with a
410*49cdfc7eSAndroid Build Coastguard Worker 	 * value of SIG_CAUGHT.
411*49cdfc7eSAndroid Build Coastguard Worker 	 */
412*49cdfc7eSAndroid Build Coastguard Worker 	if (write_pipe(pipe_fd[1], note) < 0) {
413*49cdfc7eSAndroid Build Coastguard Worker 		/*
414*49cdfc7eSAndroid Build Coastguard Worker 		 * write_pipe() failed.  Set exit value to WRITE_BROK to let
415*49cdfc7eSAndroid Build Coastguard Worker 		 * parent know what happened
416*49cdfc7eSAndroid Build Coastguard Worker 		 */
417*49cdfc7eSAndroid Build Coastguard Worker 		clear_timeout();
418*49cdfc7eSAndroid Build Coastguard Worker 		exit(WRITE_BROK);
419*49cdfc7eSAndroid Build Coastguard Worker 	}
420*49cdfc7eSAndroid Build Coastguard Worker 
421*49cdfc7eSAndroid Build Coastguard Worker 	/*
422*49cdfc7eSAndroid Build Coastguard Worker 	 * if we get to this point, all signals have been held and the
423*49cdfc7eSAndroid Build Coastguard Worker 	 * timer has expired.  Now what we want to do is release each
424*49cdfc7eSAndroid Build Coastguard Worker 	 * signal and see if we catch it.  If we catch all signals,
425*49cdfc7eSAndroid Build Coastguard Worker 	 * sigrelse passed, else it failed.
426*49cdfc7eSAndroid Build Coastguard Worker 	 */
427*49cdfc7eSAndroid Build Coastguard Worker 
428*49cdfc7eSAndroid Build Coastguard Worker 	phase = 2;		/* let handler know we are now expecting signals */
429*49cdfc7eSAndroid Build Coastguard Worker 
430*49cdfc7eSAndroid Build Coastguard Worker #if DEBUG > 0
431*49cdfc7eSAndroid Build Coastguard Worker 	printf("child: PHASE II\n");
432*49cdfc7eSAndroid Build Coastguard Worker #endif
433*49cdfc7eSAndroid Build Coastguard Worker 
434*49cdfc7eSAndroid Build Coastguard Worker 	/* assume success and overwrite exit_val if an error occurs */
435*49cdfc7eSAndroid Build Coastguard Worker 	exit_val = EXIT_OK;
436*49cdfc7eSAndroid Build Coastguard Worker 
437*49cdfc7eSAndroid Build Coastguard Worker #if DEBUG > 0
438*49cdfc7eSAndroid Build Coastguard Worker 	printf("child: pid=%d waiting for parent's ready...\n", getpid());
439*49cdfc7eSAndroid Build Coastguard Worker #endif
440*49cdfc7eSAndroid Build Coastguard Worker 
441*49cdfc7eSAndroid Build Coastguard Worker 	/*
442*49cdfc7eSAndroid Build Coastguard Worker 	 * wait for parent to tell us that sigals were all sent
443*49cdfc7eSAndroid Build Coastguard Worker 	 */
444*49cdfc7eSAndroid Build Coastguard Worker 
445*49cdfc7eSAndroid Build Coastguard Worker 	/* wait for "ready" message from parent */
446*49cdfc7eSAndroid Build Coastguard Worker 	if ((str = read_pipe(pipe_fd2[0])) == NULL) {
447*49cdfc7eSAndroid Build Coastguard Worker 		/* read_pipe() failed. */
448*49cdfc7eSAndroid Build Coastguard Worker 		printf(" child: read_pipe failed\n");
449*49cdfc7eSAndroid Build Coastguard Worker 		exit(TBROK);
450*49cdfc7eSAndroid Build Coastguard Worker 	}
451*49cdfc7eSAndroid Build Coastguard Worker 
452*49cdfc7eSAndroid Build Coastguard Worker 	if (strcmp(str, READY) != 0) {
453*49cdfc7eSAndroid Build Coastguard Worker 		/* parent/pipe problem */
454*49cdfc7eSAndroid Build Coastguard Worker 		printf("child: didn't proper ready message\n");
455*49cdfc7eSAndroid Build Coastguard Worker 		exit(TBROK);
456*49cdfc7eSAndroid Build Coastguard Worker 	}
457*49cdfc7eSAndroid Build Coastguard Worker 
458*49cdfc7eSAndroid Build Coastguard Worker 	for (sig = 1; sig < NUMSIGS; sig++) {
459*49cdfc7eSAndroid Build Coastguard Worker 		if (choose_sig(sig)) {
460*49cdfc7eSAndroid Build Coastguard Worker 
461*49cdfc7eSAndroid Build Coastguard Worker 			/* all set up, release and catch a signal */
462*49cdfc7eSAndroid Build Coastguard Worker 
463*49cdfc7eSAndroid Build Coastguard Worker 			sig_caught = FALSE;	/* handler sets it to TRUE when caught */
464*49cdfc7eSAndroid Build Coastguard Worker #if DEBUG > 1
465*49cdfc7eSAndroid Build Coastguard Worker 			printf("child: releasing sig %d...\n", sig);
466*49cdfc7eSAndroid Build Coastguard Worker #endif
467*49cdfc7eSAndroid Build Coastguard Worker 			if ((rv = sigrelse(sig)) != 0) {
468*49cdfc7eSAndroid Build Coastguard Worker 				/* THEY say sigrelse ALWAYS returns 0 */
469*49cdfc7eSAndroid Build Coastguard Worker 				(void)sprintf(note,
470*49cdfc7eSAndroid Build Coastguard Worker 					      "sigrelse did not return 0. rv:%d",
471*49cdfc7eSAndroid Build Coastguard Worker 					      rv);
472*49cdfc7eSAndroid Build Coastguard Worker 				exit_val = TBROK;
473*49cdfc7eSAndroid Build Coastguard Worker 				break;
474*49cdfc7eSAndroid Build Coastguard Worker 			}
475*49cdfc7eSAndroid Build Coastguard Worker 
476*49cdfc7eSAndroid Build Coastguard Worker 			/* give signal handler some time to process signal */
477*49cdfc7eSAndroid Build Coastguard Worker 			wait_a_while();
478*49cdfc7eSAndroid Build Coastguard Worker 		}
479*49cdfc7eSAndroid Build Coastguard Worker 
480*49cdfc7eSAndroid Build Coastguard Worker 	}			/* endfor */
481*49cdfc7eSAndroid Build Coastguard Worker 
482*49cdfc7eSAndroid Build Coastguard Worker 	/*
483*49cdfc7eSAndroid Build Coastguard Worker 	 * If we are error free so far...
484*49cdfc7eSAndroid Build Coastguard Worker 	 * check the sig_array array for one occurence of
485*49cdfc7eSAndroid Build Coastguard Worker 	 * each of the catchable signals.  If this is true,
486*49cdfc7eSAndroid Build Coastguard Worker 	 * then PASS, otherwise FAIL.
487*49cdfc7eSAndroid Build Coastguard Worker 	 */
488*49cdfc7eSAndroid Build Coastguard Worker 
489*49cdfc7eSAndroid Build Coastguard Worker 	if (exit_val == EXIT_OK) {
490*49cdfc7eSAndroid Build Coastguard Worker 		(void)memcpy(note, (char *)sig_array,
491*49cdfc7eSAndroid Build Coastguard Worker                             sizeof(note) < sizeof(sig_array) ?
492*49cdfc7eSAndroid Build Coastguard Worker                             sizeof(note) : sizeof(sig_array));
493*49cdfc7eSAndroid Build Coastguard Worker 	}
494*49cdfc7eSAndroid Build Coastguard Worker 
495*49cdfc7eSAndroid Build Coastguard Worker 	/* send note to parent and exit */
496*49cdfc7eSAndroid Build Coastguard Worker 	if (write_pipe(pipe_fd[1], note) < 0) {
497*49cdfc7eSAndroid Build Coastguard Worker 		/*
498*49cdfc7eSAndroid Build Coastguard Worker 		 * write_pipe() failed.  Set exit value to WRITE_BROK to let
499*49cdfc7eSAndroid Build Coastguard Worker 		 * parent know what happened
500*49cdfc7eSAndroid Build Coastguard Worker 		 */
501*49cdfc7eSAndroid Build Coastguard Worker 		exit(WRITE_BROK);
502*49cdfc7eSAndroid Build Coastguard Worker 	}
503*49cdfc7eSAndroid Build Coastguard Worker 
504*49cdfc7eSAndroid Build Coastguard Worker 	exit(exit_val);
505*49cdfc7eSAndroid Build Coastguard Worker 
506*49cdfc7eSAndroid Build Coastguard Worker }				/* end of child */
507*49cdfc7eSAndroid Build Coastguard Worker 
508*49cdfc7eSAndroid Build Coastguard Worker /*****************************************************************************
509*49cdfc7eSAndroid Build Coastguard Worker  *  setup_sigs() : set child up to catch all signals.  If there is
510*49cdfc7eSAndroid Build Coastguard Worker  *       trouble, write message in mesg and return -1, else return 0.
511*49cdfc7eSAndroid Build Coastguard Worker  *       The signal handler has two functions depending on which phase
512*49cdfc7eSAndroid Build Coastguard Worker  *       of the test we are in.  The first section is executed after the
513*49cdfc7eSAndroid Build Coastguard Worker  *       signals have been held (should not ever be used).  The second
514*49cdfc7eSAndroid Build Coastguard Worker  *       section is executed after the signals have been released (should
515*49cdfc7eSAndroid Build Coastguard Worker  *       be executed for each signal).
516*49cdfc7eSAndroid Build Coastguard Worker  ****************************************************************************/
setup_sigs(void)517*49cdfc7eSAndroid Build Coastguard Worker static int setup_sigs(void)
518*49cdfc7eSAndroid Build Coastguard Worker {
519*49cdfc7eSAndroid Build Coastguard Worker 	int sig;
520*49cdfc7eSAndroid Build Coastguard Worker 
521*49cdfc7eSAndroid Build Coastguard Worker 	/* set up signal handler routine */
522*49cdfc7eSAndroid Build Coastguard Worker 	for (sig = 1; sig < NUMSIGS; sig++) {
523*49cdfc7eSAndroid Build Coastguard Worker 		if (choose_sig(sig)) {
524*49cdfc7eSAndroid Build Coastguard Worker 			if (signal(sig, handler) == SIG_ERR) {
525*49cdfc7eSAndroid Build Coastguard Worker 				/* set up mesg to send back to parent */
526*49cdfc7eSAndroid Build Coastguard Worker 				(void)sprintf(mesg,
527*49cdfc7eSAndroid Build Coastguard Worker 					      "signal() failed for signal %d. error:%d %s.",
528*49cdfc7eSAndroid Build Coastguard Worker 					      sig, errno, strerror(errno));
529*49cdfc7eSAndroid Build Coastguard Worker 				return (-1);
530*49cdfc7eSAndroid Build Coastguard Worker 			}
531*49cdfc7eSAndroid Build Coastguard Worker 		}
532*49cdfc7eSAndroid Build Coastguard Worker 	}
533*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
534*49cdfc7eSAndroid Build Coastguard Worker 
535*49cdfc7eSAndroid Build Coastguard Worker }				/* end of setup_sigs  */
536*49cdfc7eSAndroid Build Coastguard Worker 
537*49cdfc7eSAndroid Build Coastguard Worker /*****************************************************************************
538*49cdfc7eSAndroid Build Coastguard Worker  *  handler() : child's interrupt handler for all signals.  The phase variable
539*49cdfc7eSAndroid Build Coastguard Worker  *      is set in the child process indicating what action is to be taken.
540*49cdfc7eSAndroid Build Coastguard Worker  *    The phase 1 section will be run if the child process catches a signal
541*49cdfc7eSAndroid Build Coastguard Worker  *      after the signal has been held resulting in a test item BROK.
542*49cdfc7eSAndroid Build Coastguard Worker  *      The parent detects this situation by a child exit value of SIG_CAUGHT.
543*49cdfc7eSAndroid Build Coastguard Worker  *    The phase 2 section will be run if the child process catches a
544*49cdfc7eSAndroid Build Coastguard Worker  *      signal after the signal has been released.  All signals must be
545*49cdfc7eSAndroid Build Coastguard Worker  *      caught in order for a PASS.
546*49cdfc7eSAndroid Build Coastguard Worker  ****************************************************************************/
handler(int sig)547*49cdfc7eSAndroid Build Coastguard Worker static void handler(int sig)
548*49cdfc7eSAndroid Build Coastguard Worker {
549*49cdfc7eSAndroid Build Coastguard Worker 	static int s = 0;	/* semaphore so that we don't handle 2 */
550*49cdfc7eSAndroid Build Coastguard Worker 	/* sigs at once */
551*49cdfc7eSAndroid Build Coastguard Worker #if DEBUG > 1
552*49cdfc7eSAndroid Build Coastguard Worker 	printf("child: handler phase%d: caught signal %d.\n", phase, sig);
553*49cdfc7eSAndroid Build Coastguard Worker #endif
554*49cdfc7eSAndroid Build Coastguard Worker 
555*49cdfc7eSAndroid Build Coastguard Worker 	if (phase == 1) {
556*49cdfc7eSAndroid Build Coastguard Worker 		/* exit the child process with a value of -1 */
557*49cdfc7eSAndroid Build Coastguard Worker 		exit(SIG_CAUGHT);
558*49cdfc7eSAndroid Build Coastguard Worker 
559*49cdfc7eSAndroid Build Coastguard Worker 	} else {
560*49cdfc7eSAndroid Build Coastguard Worker 		/* phase 2 (error if s gets incremented twice) */
561*49cdfc7eSAndroid Build Coastguard Worker 		++s;
562*49cdfc7eSAndroid Build Coastguard Worker 
563*49cdfc7eSAndroid Build Coastguard Worker 		if (s > 1) {
564*49cdfc7eSAndroid Build Coastguard Worker 			exit(HANDLE_ERR);
565*49cdfc7eSAndroid Build Coastguard Worker 		}
566*49cdfc7eSAndroid Build Coastguard Worker 
567*49cdfc7eSAndroid Build Coastguard Worker 		/* increment the array element for this signal */
568*49cdfc7eSAndroid Build Coastguard Worker 		++sig_array[sig];
569*49cdfc7eSAndroid Build Coastguard Worker 		sig_caught = TRUE;	/* flag for wait_a_while () */
570*49cdfc7eSAndroid Build Coastguard Worker 		--s;
571*49cdfc7eSAndroid Build Coastguard Worker 	}
572*49cdfc7eSAndroid Build Coastguard Worker 
573*49cdfc7eSAndroid Build Coastguard Worker 	return;
574*49cdfc7eSAndroid Build Coastguard Worker 
575*49cdfc7eSAndroid Build Coastguard Worker }				/* end of handler */
576*49cdfc7eSAndroid Build Coastguard Worker 
577*49cdfc7eSAndroid Build Coastguard Worker /*****************************************************************************
578*49cdfc7eSAndroid Build Coastguard Worker  *  read_pipe() : read data from pipe and return in buf.  If an error occurs
579*49cdfc7eSAndroid Build Coastguard Worker  *      put message in mesg and return NULL.  Note: this routine sets a
580*49cdfc7eSAndroid Build Coastguard Worker  *      timeout signal in case the pipe is blocked.
581*49cdfc7eSAndroid Build Coastguard Worker  ****************************************************************************/
read_pipe(int fd)582*49cdfc7eSAndroid Build Coastguard Worker static char *read_pipe(int fd)
583*49cdfc7eSAndroid Build Coastguard Worker {
584*49cdfc7eSAndroid Build Coastguard Worker 	static char buf[MAXMESG];	/* buffer for pipe read */
585*49cdfc7eSAndroid Build Coastguard Worker 	int ret;
586*49cdfc7eSAndroid Build Coastguard Worker 
587*49cdfc7eSAndroid Build Coastguard Worker #if DEBUG > 0
588*49cdfc7eSAndroid Build Coastguard Worker 	printf("read_pipe: pid=%d waiting...\n", getpid());
589*49cdfc7eSAndroid Build Coastguard Worker #endif
590*49cdfc7eSAndroid Build Coastguard Worker 
591*49cdfc7eSAndroid Build Coastguard Worker 	/* set timeout alarm in case the pipe is blocked */
592*49cdfc7eSAndroid Build Coastguard Worker 	if (set_timeout() < 0) {
593*49cdfc7eSAndroid Build Coastguard Worker 		/* an error occured, message in mesg */
594*49cdfc7eSAndroid Build Coastguard Worker 		return NULL;
595*49cdfc7eSAndroid Build Coastguard Worker 	}
596*49cdfc7eSAndroid Build Coastguard Worker 
597*49cdfc7eSAndroid Build Coastguard Worker 	ret = -1;
598*49cdfc7eSAndroid Build Coastguard Worker 	while (ret == -1) {	/* while empty reads */
599*49cdfc7eSAndroid Build Coastguard Worker 		if ((ret = read(fd, buf, MAXMESG)) == 0) {
600*49cdfc7eSAndroid Build Coastguard Worker 			(void)sprintf(mesg, "read() pipe failed. error:%d %s.",
601*49cdfc7eSAndroid Build Coastguard Worker 				      errno, strerror(errno));
602*49cdfc7eSAndroid Build Coastguard Worker 
603*49cdfc7eSAndroid Build Coastguard Worker 			clear_timeout();
604*49cdfc7eSAndroid Build Coastguard Worker 			return NULL;
605*49cdfc7eSAndroid Build Coastguard Worker 		}
606*49cdfc7eSAndroid Build Coastguard Worker 	}
607*49cdfc7eSAndroid Build Coastguard Worker 	clear_timeout();
608*49cdfc7eSAndroid Build Coastguard Worker 
609*49cdfc7eSAndroid Build Coastguard Worker #if DEBUG > 0
610*49cdfc7eSAndroid Build Coastguard Worker 	printf("read_pipe: pid=%d received: %s.\n", getpid(), buf);
611*49cdfc7eSAndroid Build Coastguard Worker #endif
612*49cdfc7eSAndroid Build Coastguard Worker 	return (buf);
613*49cdfc7eSAndroid Build Coastguard Worker 
614*49cdfc7eSAndroid Build Coastguard Worker }				/* end of read_pipe */
615*49cdfc7eSAndroid Build Coastguard Worker 
616*49cdfc7eSAndroid Build Coastguard Worker /*****************************************************************************
617*49cdfc7eSAndroid Build Coastguard Worker  *  write_pipe(msg) : write msg to pipe.  If it fails, put message in
618*49cdfc7eSAndroid Build Coastguard Worker  *       mesg and return -1, else return 0.
619*49cdfc7eSAndroid Build Coastguard Worker  ****************************************************************************/
write_pipe(int fd,char * msg)620*49cdfc7eSAndroid Build Coastguard Worker static int write_pipe(int fd, char *msg)
621*49cdfc7eSAndroid Build Coastguard Worker {
622*49cdfc7eSAndroid Build Coastguard Worker 
623*49cdfc7eSAndroid Build Coastguard Worker #if DEBUG > 0
624*49cdfc7eSAndroid Build Coastguard Worker 	printf("write_pipe: pid=%d, sending %s.\n", getpid(), msg);
625*49cdfc7eSAndroid Build Coastguard Worker #endif
626*49cdfc7eSAndroid Build Coastguard Worker 
627*49cdfc7eSAndroid Build Coastguard Worker 	if (write(fd, msg, MAXMESG) < 0) {
628*49cdfc7eSAndroid Build Coastguard Worker 		(void)sprintf(mesg, "write() pipe failed. error:%d %s.",
629*49cdfc7eSAndroid Build Coastguard Worker 			      errno, strerror(errno));
630*49cdfc7eSAndroid Build Coastguard Worker 
631*49cdfc7eSAndroid Build Coastguard Worker 		return (-1);
632*49cdfc7eSAndroid Build Coastguard Worker 	}
633*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
634*49cdfc7eSAndroid Build Coastguard Worker 
635*49cdfc7eSAndroid Build Coastguard Worker }				/* end of write_pipe */
636*49cdfc7eSAndroid Build Coastguard Worker 
637*49cdfc7eSAndroid Build Coastguard Worker /*****************************************************************************
638*49cdfc7eSAndroid Build Coastguard Worker  *  set_timeout() : set alarm to signal process after the period of time
639*49cdfc7eSAndroid Build Coastguard Worker  *       indicated by TIMEOUT.  If the signal occurs, the routine timeout()
640*49cdfc7eSAndroid Build Coastguard Worker  *       will be executed.  If all goes ok, return 0, else load message
641*49cdfc7eSAndroid Build Coastguard Worker  *       into mesg and return -1.
642*49cdfc7eSAndroid Build Coastguard Worker  ****************************************************************************/
set_timeout(void)643*49cdfc7eSAndroid Build Coastguard Worker static int set_timeout(void)
644*49cdfc7eSAndroid Build Coastguard Worker {
645*49cdfc7eSAndroid Build Coastguard Worker 	if (signal(SIGALRM, timeout) == SIG_ERR) {
646*49cdfc7eSAndroid Build Coastguard Worker 		(void)sprintf(mesg,
647*49cdfc7eSAndroid Build Coastguard Worker 			      "signal() failed for signal %d. error:%d %s.",
648*49cdfc7eSAndroid Build Coastguard Worker 			      SIGALRM, errno, strerror(errno));
649*49cdfc7eSAndroid Build Coastguard Worker 		return (-1);
650*49cdfc7eSAndroid Build Coastguard Worker 	}
651*49cdfc7eSAndroid Build Coastguard Worker 
652*49cdfc7eSAndroid Build Coastguard Worker 	(void)alarm(TIMEOUT);
653*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
654*49cdfc7eSAndroid Build Coastguard Worker 
655*49cdfc7eSAndroid Build Coastguard Worker }				/* end of set_timeout */
656*49cdfc7eSAndroid Build Coastguard Worker 
657*49cdfc7eSAndroid Build Coastguard Worker /*****************************************************************************
658*49cdfc7eSAndroid Build Coastguard Worker  *  clear_timeout() : turn off the alarm so that SIGALRM will not get sent.
659*49cdfc7eSAndroid Build Coastguard Worker  ****************************************************************************/
clear_timeout(void)660*49cdfc7eSAndroid Build Coastguard Worker static void clear_timeout(void)
661*49cdfc7eSAndroid Build Coastguard Worker {
662*49cdfc7eSAndroid Build Coastguard Worker 	(void)alarm(0);
663*49cdfc7eSAndroid Build Coastguard Worker 
664*49cdfc7eSAndroid Build Coastguard Worker }				/* end of clear_timeout */
665*49cdfc7eSAndroid Build Coastguard Worker 
666*49cdfc7eSAndroid Build Coastguard Worker /*****************************************************************************
667*49cdfc7eSAndroid Build Coastguard Worker  *  timeout() : this routine is executed when the SIGALRM signal is
668*49cdfc7eSAndroid Build Coastguard Worker  *      caught.  It does nothing but return - the read() on the pipe
669*49cdfc7eSAndroid Build Coastguard Worker  *      will fail.
670*49cdfc7eSAndroid Build Coastguard Worker  ****************************************************************************/
timeout(int sig)671*49cdfc7eSAndroid Build Coastguard Worker static void timeout(int sig)
672*49cdfc7eSAndroid Build Coastguard Worker {
673*49cdfc7eSAndroid Build Coastguard Worker #if DEBUG > 0
674*49cdfc7eSAndroid Build Coastguard Worker 	printf("timeout: pid=%d sigalrm caught.\n", getpid());
675*49cdfc7eSAndroid Build Coastguard Worker #endif
676*49cdfc7eSAndroid Build Coastguard Worker }
677*49cdfc7eSAndroid Build Coastguard Worker 
678*49cdfc7eSAndroid Build Coastguard Worker /*****************************************************************************
679*49cdfc7eSAndroid Build Coastguard Worker  *  wait_a_while () : wait a while before returning.
680*49cdfc7eSAndroid Build Coastguard Worker  ****************************************************************************/
wait_a_while(void)681*49cdfc7eSAndroid Build Coastguard Worker static void wait_a_while(void)
682*49cdfc7eSAndroid Build Coastguard Worker {
683*49cdfc7eSAndroid Build Coastguard Worker 	long btime;
684*49cdfc7eSAndroid Build Coastguard Worker 
685*49cdfc7eSAndroid Build Coastguard Worker 	btime = time(NULL);
686*49cdfc7eSAndroid Build Coastguard Worker 	while (time(NULL) - btime < TIMEOUT) {
687*49cdfc7eSAndroid Build Coastguard Worker 		if (sig_caught == TRUE)
688*49cdfc7eSAndroid Build Coastguard Worker 			break;
689*49cdfc7eSAndroid Build Coastguard Worker 	}
690*49cdfc7eSAndroid Build Coastguard Worker }				/* end of wait_a_while */
691*49cdfc7eSAndroid Build Coastguard Worker 
getout(void)692*49cdfc7eSAndroid Build Coastguard Worker static void getout(void)
693*49cdfc7eSAndroid Build Coastguard Worker {
694*49cdfc7eSAndroid Build Coastguard Worker 	if (pid > 0 && kill(pid, SIGKILL) < 0)
695*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TWARN, "kill(%d, SIGKILL) failed", pid);
696*49cdfc7eSAndroid Build Coastguard Worker 	cleanup();
697*49cdfc7eSAndroid Build Coastguard Worker 
698*49cdfc7eSAndroid Build Coastguard Worker }				/* end of getout */
699*49cdfc7eSAndroid Build Coastguard Worker 
700*49cdfc7eSAndroid Build Coastguard Worker #ifdef VAX
sighold(int signo)701*49cdfc7eSAndroid Build Coastguard Worker static int sighold(int signo)
702*49cdfc7eSAndroid Build Coastguard Worker {
703*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
704*49cdfc7eSAndroid Build Coastguard Worker }
705*49cdfc7eSAndroid Build Coastguard Worker 
sigrelse(signo)706*49cdfc7eSAndroid Build Coastguard Worker static int sigrelse(signo)
707*49cdfc7eSAndroid Build Coastguard Worker int signo;
708*49cdfc7eSAndroid Build Coastguard Worker {
709*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
710*49cdfc7eSAndroid Build Coastguard Worker }
711*49cdfc7eSAndroid Build Coastguard Worker #endif
712*49cdfc7eSAndroid Build Coastguard Worker 
choose_sig(int sig)713*49cdfc7eSAndroid Build Coastguard Worker int choose_sig(int sig)
714*49cdfc7eSAndroid Build Coastguard Worker {
715*49cdfc7eSAndroid Build Coastguard Worker 	switch (sig) {
716*49cdfc7eSAndroid Build Coastguard Worker 
717*49cdfc7eSAndroid Build Coastguard Worker 	case SIGKILL:
718*49cdfc7eSAndroid Build Coastguard Worker 	case SIGSTOP:
719*49cdfc7eSAndroid Build Coastguard Worker 	case SIGTSTP:
720*49cdfc7eSAndroid Build Coastguard Worker 	case SIGCONT:
721*49cdfc7eSAndroid Build Coastguard Worker 	case SIGALRM:
722*49cdfc7eSAndroid Build Coastguard Worker 	case SIGCANCEL:
723*49cdfc7eSAndroid Build Coastguard Worker 	case SIGTIMER:
724*49cdfc7eSAndroid Build Coastguard Worker #ifdef SIGNOBDM
725*49cdfc7eSAndroid Build Coastguard Worker 	case SIGNOBDM:
726*49cdfc7eSAndroid Build Coastguard Worker #endif
727*49cdfc7eSAndroid Build Coastguard Worker #ifdef SIGTTIN
728*49cdfc7eSAndroid Build Coastguard Worker 	case SIGTTIN:
729*49cdfc7eSAndroid Build Coastguard Worker #endif
730*49cdfc7eSAndroid Build Coastguard Worker #ifdef SIGTTOU
731*49cdfc7eSAndroid Build Coastguard Worker 	case SIGTTOU:
732*49cdfc7eSAndroid Build Coastguard Worker #endif
733*49cdfc7eSAndroid Build Coastguard Worker #ifdef  SIGPTINTR
734*49cdfc7eSAndroid Build Coastguard Worker 	case SIGPTINTR:
735*49cdfc7eSAndroid Build Coastguard Worker #endif
736*49cdfc7eSAndroid Build Coastguard Worker #ifdef  SIGSWAP
737*49cdfc7eSAndroid Build Coastguard Worker 	case SIGSWAP:
738*49cdfc7eSAndroid Build Coastguard Worker #endif
739*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
740*49cdfc7eSAndroid Build Coastguard Worker 
741*49cdfc7eSAndroid Build Coastguard Worker 	}
742*49cdfc7eSAndroid Build Coastguard Worker 
743*49cdfc7eSAndroid Build Coastguard Worker 	return 1;
744*49cdfc7eSAndroid Build Coastguard Worker 
745*49cdfc7eSAndroid Build Coastguard Worker }
746*49cdfc7eSAndroid Build Coastguard Worker 
setup(void)747*49cdfc7eSAndroid Build Coastguard Worker void setup(void)
748*49cdfc7eSAndroid Build Coastguard Worker {
749*49cdfc7eSAndroid Build Coastguard Worker 
750*49cdfc7eSAndroid Build Coastguard Worker 	tst_sig(FORK, DEF_HANDLER, cleanup);
751*49cdfc7eSAndroid Build Coastguard Worker 
752*49cdfc7eSAndroid Build Coastguard Worker 	TEST_PAUSE;
753*49cdfc7eSAndroid Build Coastguard Worker 
754*49cdfc7eSAndroid Build Coastguard Worker 	tst_tmpdir();
755*49cdfc7eSAndroid Build Coastguard Worker 
756*49cdfc7eSAndroid Build Coastguard Worker 	/* set up pipe for parent/child communications */
757*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_PIPE(cleanup, pipe_fd);
758*49cdfc7eSAndroid Build Coastguard Worker 
759*49cdfc7eSAndroid Build Coastguard Worker 	/*
760*49cdfc7eSAndroid Build Coastguard Worker 	 * Cause the read to return 0 once EOF is encountered and the
761*49cdfc7eSAndroid Build Coastguard Worker 	 * read to return -1 if pipe is empty.
762*49cdfc7eSAndroid Build Coastguard Worker 	 */
763*49cdfc7eSAndroid Build Coastguard Worker 	if (fcntl(pipe_fd[0], F_SETFL, O_NONBLOCK) == -1)
764*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK | TERRNO, cleanup,
765*49cdfc7eSAndroid Build Coastguard Worker 			 "fcntl(Fds[0], F_SETFL, O_NONBLOCK) failed");
766*49cdfc7eSAndroid Build Coastguard Worker 
767*49cdfc7eSAndroid Build Coastguard Worker 	/* set up pipe for parent/child communications */
768*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_PIPE(cleanup, pipe_fd2);
769*49cdfc7eSAndroid Build Coastguard Worker 
770*49cdfc7eSAndroid Build Coastguard Worker 	/*
771*49cdfc7eSAndroid Build Coastguard Worker 	 * Cause the read to return 0 once EOF is encountered and the
772*49cdfc7eSAndroid Build Coastguard Worker 	 * read to return -1 if pipe is empty.
773*49cdfc7eSAndroid Build Coastguard Worker 	 */
774*49cdfc7eSAndroid Build Coastguard Worker 	if (fcntl(pipe_fd2[0], F_SETFL, O_NONBLOCK) == -1)
775*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK | TERRNO, cleanup,
776*49cdfc7eSAndroid Build Coastguard Worker 			 "fcntl(Fds[0], F_SETFL, O_NONBLOCK) failed");
777*49cdfc7eSAndroid Build Coastguard Worker }
778*49cdfc7eSAndroid Build Coastguard Worker 
cleanup(void)779*49cdfc7eSAndroid Build Coastguard Worker void cleanup(void)
780*49cdfc7eSAndroid Build Coastguard Worker {
781*49cdfc7eSAndroid Build Coastguard Worker 	tst_rmdir();
782*49cdfc7eSAndroid Build Coastguard Worker 
783*49cdfc7eSAndroid Build Coastguard Worker }
784