xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/sigaction/sigaction01.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker /*
2*49cdfc7eSAndroid Build Coastguard Worker  *
3*49cdfc7eSAndroid Build Coastguard Worker  *   Copyright (c) International Business Machines  Corp., 2001
4*49cdfc7eSAndroid Build Coastguard Worker  *
5*49cdfc7eSAndroid Build Coastguard Worker  *   This program is free software;  you can redistribute it and/or modify
6*49cdfc7eSAndroid Build Coastguard Worker  *   it under the terms of the GNU General Public License as published by
7*49cdfc7eSAndroid Build Coastguard Worker  *   the Free Software Foundation; either version 2 of the License, or
8*49cdfc7eSAndroid Build Coastguard Worker  *   (at your option) any later version.
9*49cdfc7eSAndroid Build Coastguard Worker  *
10*49cdfc7eSAndroid Build Coastguard Worker  *   This program is distributed in the hope that it will be useful,
11*49cdfc7eSAndroid Build Coastguard Worker  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12*49cdfc7eSAndroid Build Coastguard Worker  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13*49cdfc7eSAndroid Build Coastguard Worker  *   the GNU General Public License for more details.
14*49cdfc7eSAndroid Build Coastguard Worker  *
15*49cdfc7eSAndroid Build Coastguard Worker  *   You should have received a copy of the GNU General Public License
16*49cdfc7eSAndroid Build Coastguard Worker  *   along with this program;  if not, write to the Free Software
17*49cdfc7eSAndroid Build Coastguard Worker  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*49cdfc7eSAndroid Build Coastguard Worker  */
19*49cdfc7eSAndroid Build Coastguard Worker 
20*49cdfc7eSAndroid Build Coastguard Worker /*
21*49cdfc7eSAndroid Build Coastguard Worker  * NAME
22*49cdfc7eSAndroid Build Coastguard Worker  * 	sigaction01.c
23*49cdfc7eSAndroid Build Coastguard Worker  *
24*49cdfc7eSAndroid Build Coastguard Worker  * DESCRIPTION
25*49cdfc7eSAndroid Build Coastguard Worker  * 	Test some features of sigaction (see below for more details)
26*49cdfc7eSAndroid Build Coastguard Worker  *
27*49cdfc7eSAndroid Build Coastguard Worker  * ALGORITHM
28*49cdfc7eSAndroid Build Coastguard Worker  * 	Use sigaction(2) to set a signal handler for SIGUSR1 with a certain
29*49cdfc7eSAndroid Build Coastguard Worker  * 	set of flags, set a global variable indicating the test case, and
30*49cdfc7eSAndroid Build Coastguard Worker  * 	finally send the signal to ourselves, causing the signal handler to
31*49cdfc7eSAndroid Build Coastguard Worker  * 	run. The signal handler then checks the signal handler to run. The
32*49cdfc7eSAndroid Build Coastguard Worker  * 	signal handler then checks certain conditions based on the test case
33*49cdfc7eSAndroid Build Coastguard Worker  * 	number.
34*49cdfc7eSAndroid Build Coastguard Worker  * 	There are 4 test cases:
35*49cdfc7eSAndroid Build Coastguard Worker  *
36*49cdfc7eSAndroid Build Coastguard Worker  * 	1) Set SA_RESETHAND and SA_SIGINFO. When the handler runs,
37*49cdfc7eSAndroid Build Coastguard Worker  * 	SA_SIGINFO should be set.
38*49cdfc7eSAndroid Build Coastguard Worker  *
39*49cdfc7eSAndroid Build Coastguard Worker  * 	2) Set SA_RESETHAND. When the handler runs, SIGUSR1 should be
40*49cdfc7eSAndroid Build Coastguard Worker  * 	masked (SA_RESETHAND makes sigaction behave as if SA_NODEFER was
41*49cdfc7eSAndroid Build Coastguard Worker  * 	not set).
42*49cdfc7eSAndroid Build Coastguard Worker  *
43*49cdfc7eSAndroid Build Coastguard Worker  * 	3) Same as case #2, but when the handler is established, sa_mask is
44*49cdfc7eSAndroid Build Coastguard Worker  * 	set to include SIGUSR1. Ensure that SIGUSR1 is indeed masked even if
45*49cdfc7eSAndroid Build Coastguard Worker  * 	SA_RESETHAND is set.
46*49cdfc7eSAndroid Build Coastguard Worker  *
47*49cdfc7eSAndroid Build Coastguard Worker  * 	4) A signal generated from an interface or condition that does not
48*49cdfc7eSAndroid Build Coastguard Worker  * 	provide siginfo (such as pthread_kill(3)) should invoke the handler
49*49cdfc7eSAndroid Build Coastguard Worker  * 	with a non-NULL siginfo pointer.
50*49cdfc7eSAndroid Build Coastguard Worker  *
51*49cdfc7eSAndroid Build Coastguard Worker  * USAGE:  <for command-line>
52*49cdfc7eSAndroid Build Coastguard Worker  * sigaction01 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
53*49cdfc7eSAndroid Build Coastguard Worker  *     where,  -c n : Run n copies concurrently.
54*49cdfc7eSAndroid Build Coastguard Worker  *             -f   : Turn off functionality Testing.
55*49cdfc7eSAndroid Build Coastguard Worker  *             -i n : Execute test n times.
56*49cdfc7eSAndroid Build Coastguard Worker  *             -I x : Execute test for x seconds.
57*49cdfc7eSAndroid Build Coastguard Worker  *             -P x : Pause for x seconds between iterations.
58*49cdfc7eSAndroid Build Coastguard Worker  *             -t   : Turn on syscall timing.
59*49cdfc7eSAndroid Build Coastguard Worker  *
60*49cdfc7eSAndroid Build Coastguard Worker  * HISTORY
61*49cdfc7eSAndroid Build Coastguard Worker  *	07/2001 Ported by Wayne Boyer
62*49cdfc7eSAndroid Build Coastguard Worker  *
63*49cdfc7eSAndroid Build Coastguard Worker  * RESTRICTIONS
64*49cdfc7eSAndroid Build Coastguard Worker  *	NONE
65*49cdfc7eSAndroid Build Coastguard Worker  */
66*49cdfc7eSAndroid Build Coastguard Worker #include <pthread.h>
67*49cdfc7eSAndroid Build Coastguard Worker #include <signal.h>
68*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
69*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
70*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
71*49cdfc7eSAndroid Build Coastguard Worker #include "test.h"
72*49cdfc7eSAndroid Build Coastguard Worker 
73*49cdfc7eSAndroid Build Coastguard Worker void setup();
74*49cdfc7eSAndroid Build Coastguard Worker void cleanup();
75*49cdfc7eSAndroid Build Coastguard Worker 
76*49cdfc7eSAndroid Build Coastguard Worker char *TCID = "sigaction01";
77*49cdfc7eSAndroid Build Coastguard Worker int TST_TOTAL = 4;
78*49cdfc7eSAndroid Build Coastguard Worker 
79*49cdfc7eSAndroid Build Coastguard Worker volatile sig_atomic_t testcase_no;
80*49cdfc7eSAndroid Build Coastguard Worker volatile sig_atomic_t pass;
81*49cdfc7eSAndroid Build Coastguard Worker 
82*49cdfc7eSAndroid Build Coastguard Worker /*
83*49cdfc7eSAndroid Build Coastguard Worker  * handler()
84*49cdfc7eSAndroid Build Coastguard Worker  *
85*49cdfc7eSAndroid Build Coastguard Worker  * 	A signal handler that understands which test case is currently
86*49cdfc7eSAndroid Build Coastguard Worker  * 	being executed and compares the current conditions to the ones it
87*49cdfc7eSAndroid Build Coastguard Worker  * 	expects (based on the test case number).
88*49cdfc7eSAndroid Build Coastguard Worker  */
handler(int sig,siginfo_t * sip,void * ucp)89*49cdfc7eSAndroid Build Coastguard Worker void handler(int sig, siginfo_t * sip, void *ucp)
90*49cdfc7eSAndroid Build Coastguard Worker {
91*49cdfc7eSAndroid Build Coastguard Worker 	struct sigaction oact;
92*49cdfc7eSAndroid Build Coastguard Worker 	int err;
93*49cdfc7eSAndroid Build Coastguard Worker 	sigset_t nmask, omask;
94*49cdfc7eSAndroid Build Coastguard Worker 
95*49cdfc7eSAndroid Build Coastguard Worker 	/*
96*49cdfc7eSAndroid Build Coastguard Worker 	 * Get sigaction setting
97*49cdfc7eSAndroid Build Coastguard Worker 	 */
98*49cdfc7eSAndroid Build Coastguard Worker 	err = sigaction(SIGUSR1, NULL, &oact);
99*49cdfc7eSAndroid Build Coastguard Worker 
100*49cdfc7eSAndroid Build Coastguard Worker 	if (err == -1) {
101*49cdfc7eSAndroid Build Coastguard Worker 		perror("sigaction");
102*49cdfc7eSAndroid Build Coastguard Worker 		return;
103*49cdfc7eSAndroid Build Coastguard Worker 	}
104*49cdfc7eSAndroid Build Coastguard Worker 
105*49cdfc7eSAndroid Build Coastguard Worker 	/*
106*49cdfc7eSAndroid Build Coastguard Worker 	 * Get current signal mask
107*49cdfc7eSAndroid Build Coastguard Worker 	 */
108*49cdfc7eSAndroid Build Coastguard Worker 	sigemptyset(&nmask);
109*49cdfc7eSAndroid Build Coastguard Worker 	sigemptyset(&omask);
110*49cdfc7eSAndroid Build Coastguard Worker 	err = sigprocmask(SIG_BLOCK, &nmask, &omask);
111*49cdfc7eSAndroid Build Coastguard Worker 	if (err == -1) {
112*49cdfc7eSAndroid Build Coastguard Worker 		perror("sigprocmask");
113*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TWARN, "sigprocmask() failed");
114*49cdfc7eSAndroid Build Coastguard Worker 		return;
115*49cdfc7eSAndroid Build Coastguard Worker 	}
116*49cdfc7eSAndroid Build Coastguard Worker 
117*49cdfc7eSAndroid Build Coastguard Worker 	switch (testcase_no) {
118*49cdfc7eSAndroid Build Coastguard Worker 	case 1:
119*49cdfc7eSAndroid Build Coastguard Worker 		/*
120*49cdfc7eSAndroid Build Coastguard Worker 		 * SA_RESETHAND and SA_SIGINFO were set. SA_SIGINFO should
121*49cdfc7eSAndroid Build Coastguard Worker 		 * be clear in Linux. In Linux kernel, SA_SIGINFO is not
122*49cdfc7eSAndroid Build Coastguard Worker 		 * cleared in psig().
123*49cdfc7eSAndroid Build Coastguard Worker 		 */
124*49cdfc7eSAndroid Build Coastguard Worker 		if (!(oact.sa_flags & SA_SIGINFO)) {
125*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TFAIL, "SA_RESETHAND should not "
126*49cdfc7eSAndroid Build Coastguard Worker 				 "cause SA_SIGINFO to be cleared, but it was.");
127*49cdfc7eSAndroid Build Coastguard Worker 			return;
128*49cdfc7eSAndroid Build Coastguard Worker 		}
129*49cdfc7eSAndroid Build Coastguard Worker 		if (sip == NULL) {
130*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TFAIL, "siginfo should not be NULL");
131*49cdfc7eSAndroid Build Coastguard Worker 			return;
132*49cdfc7eSAndroid Build Coastguard Worker 		}
133*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TPASS, "SA_RESETHAND did not "
134*49cdfc7eSAndroid Build Coastguard Worker 			 "cause SA_SIGINFO to be cleared");
135*49cdfc7eSAndroid Build Coastguard Worker 		break;
136*49cdfc7eSAndroid Build Coastguard Worker 
137*49cdfc7eSAndroid Build Coastguard Worker 	case 2:
138*49cdfc7eSAndroid Build Coastguard Worker 		/*
139*49cdfc7eSAndroid Build Coastguard Worker 		 * In Linux, SA_RESETHAND doesn't imply SA_NODEFER; sig
140*49cdfc7eSAndroid Build Coastguard Worker 		 * should not be masked.  The testcase should pass if
141*49cdfc7eSAndroid Build Coastguard Worker 		 * SA_NODEFER is not masked, ie. if SA_NODEFER is a member
142*49cdfc7eSAndroid Build Coastguard Worker 		 * of the signal list
143*49cdfc7eSAndroid Build Coastguard Worker 		 */
144*49cdfc7eSAndroid Build Coastguard Worker 		if (sigismember(&omask, sig) == 0) {
145*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TFAIL, "SA_RESETHAND should cause sig to "
146*49cdfc7eSAndroid Build Coastguard Worker 				 "be masked when the handler executes.");
147*49cdfc7eSAndroid Build Coastguard Worker 			return;
148*49cdfc7eSAndroid Build Coastguard Worker 		}
149*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TPASS, "SA_RESETHAND was masked when handler "
150*49cdfc7eSAndroid Build Coastguard Worker 			 "executed");
151*49cdfc7eSAndroid Build Coastguard Worker 		break;
152*49cdfc7eSAndroid Build Coastguard Worker 
153*49cdfc7eSAndroid Build Coastguard Worker 	case 3:
154*49cdfc7eSAndroid Build Coastguard Worker 		/*
155*49cdfc7eSAndroid Build Coastguard Worker 		 * SA_RESETHAND implies SA_NODEFER unless sa_mask already
156*49cdfc7eSAndroid Build Coastguard Worker 		 * included sig.
157*49cdfc7eSAndroid Build Coastguard Worker 		 */
158*49cdfc7eSAndroid Build Coastguard Worker 		if (!sigismember(&omask, sig)) {
159*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TFAIL, "sig should continue to be masked "
160*49cdfc7eSAndroid Build Coastguard Worker 				 "because sa_mask originally contained sig.");
161*49cdfc7eSAndroid Build Coastguard Worker 			return;
162*49cdfc7eSAndroid Build Coastguard Worker 		}
163*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TPASS, "sig has been masked "
164*49cdfc7eSAndroid Build Coastguard Worker 			 "because sa_mask originally contained sig");
165*49cdfc7eSAndroid Build Coastguard Worker 		break;
166*49cdfc7eSAndroid Build Coastguard Worker 
167*49cdfc7eSAndroid Build Coastguard Worker 	case 4:
168*49cdfc7eSAndroid Build Coastguard Worker 		/*
169*49cdfc7eSAndroid Build Coastguard Worker 		 * A signal generated from a mechanism that does not provide
170*49cdfc7eSAndroid Build Coastguard Worker 		 * siginfo should invoke the handler with a non-NULL siginfo
171*49cdfc7eSAndroid Build Coastguard Worker 		 * pointer.
172*49cdfc7eSAndroid Build Coastguard Worker 		 */
173*49cdfc7eSAndroid Build Coastguard Worker 		if (sip == NULL) {
174*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TFAIL, "siginfo pointer should not be NULL");
175*49cdfc7eSAndroid Build Coastguard Worker 			return;
176*49cdfc7eSAndroid Build Coastguard Worker 		}
177*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TPASS, "siginfo pointer non NULL");
178*49cdfc7eSAndroid Build Coastguard Worker 		break;
179*49cdfc7eSAndroid Build Coastguard Worker 
180*49cdfc7eSAndroid Build Coastguard Worker 	default:
181*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TFAIL, "invalid test case number: %d", testcase_no);
182*49cdfc7eSAndroid Build Coastguard Worker 		exit(1);
183*49cdfc7eSAndroid Build Coastguard Worker 	}
184*49cdfc7eSAndroid Build Coastguard Worker }
185*49cdfc7eSAndroid Build Coastguard Worker 
186*49cdfc7eSAndroid Build Coastguard Worker /*
187*49cdfc7eSAndroid Build Coastguard Worker  * set_handler()
188*49cdfc7eSAndroid Build Coastguard Worker  *
189*49cdfc7eSAndroid Build Coastguard Worker  * 	Establish a signal handler for SIGUSR1 with the specified flags and
190*49cdfc7eSAndroid Build Coastguard Worker  * 	signal to mask while the handler executes.
191*49cdfc7eSAndroid Build Coastguard Worker  */
set_handler(int flags,int sig_to_mask)192*49cdfc7eSAndroid Build Coastguard Worker int set_handler(int flags, int sig_to_mask)
193*49cdfc7eSAndroid Build Coastguard Worker {
194*49cdfc7eSAndroid Build Coastguard Worker 	struct sigaction sa;
195*49cdfc7eSAndroid Build Coastguard Worker 
196*49cdfc7eSAndroid Build Coastguard Worker 	sa.sa_sigaction = handler;
197*49cdfc7eSAndroid Build Coastguard Worker 	sa.sa_flags = flags;
198*49cdfc7eSAndroid Build Coastguard Worker 	sigemptyset(&sa.sa_mask);
199*49cdfc7eSAndroid Build Coastguard Worker 	sigaddset(&sa.sa_mask, sig_to_mask);
200*49cdfc7eSAndroid Build Coastguard Worker 
201*49cdfc7eSAndroid Build Coastguard Worker 	TEST(sigaction(SIGUSR1, &sa, NULL));
202*49cdfc7eSAndroid Build Coastguard Worker 	if (TEST_RETURN != 0) {
203*49cdfc7eSAndroid Build Coastguard Worker 		perror("sigaction");
204*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TFAIL, "call failed unexpectedly");
205*49cdfc7eSAndroid Build Coastguard Worker 		return 1;
206*49cdfc7eSAndroid Build Coastguard Worker 	}
207*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
208*49cdfc7eSAndroid Build Coastguard Worker }
209*49cdfc7eSAndroid Build Coastguard Worker 
210*49cdfc7eSAndroid Build Coastguard Worker /*
211*49cdfc7eSAndroid Build Coastguard Worker  * setup() - performs all ONE TIME setup for this test.
212*49cdfc7eSAndroid Build Coastguard Worker  */
setup(void)213*49cdfc7eSAndroid Build Coastguard Worker void setup(void)
214*49cdfc7eSAndroid Build Coastguard Worker {
215*49cdfc7eSAndroid Build Coastguard Worker 
216*49cdfc7eSAndroid Build Coastguard Worker 	TEST_PAUSE;
217*49cdfc7eSAndroid Build Coastguard Worker }
218*49cdfc7eSAndroid Build Coastguard Worker 
219*49cdfc7eSAndroid Build Coastguard Worker /*
220*49cdfc7eSAndroid Build Coastguard Worker  * cleanup() - performs all ONE TIME cleanup for this test at
221*49cdfc7eSAndroid Build Coastguard Worker  *	       completion or premature exit.
222*49cdfc7eSAndroid Build Coastguard Worker  */
cleanup(void)223*49cdfc7eSAndroid Build Coastguard Worker void cleanup(void)
224*49cdfc7eSAndroid Build Coastguard Worker {
225*49cdfc7eSAndroid Build Coastguard Worker 
226*49cdfc7eSAndroid Build Coastguard Worker }
227*49cdfc7eSAndroid Build Coastguard Worker 
main(int ac,char ** av)228*49cdfc7eSAndroid Build Coastguard Worker int main(int ac, char **av)
229*49cdfc7eSAndroid Build Coastguard Worker {
230*49cdfc7eSAndroid Build Coastguard Worker 	int lc;
231*49cdfc7eSAndroid Build Coastguard Worker 	int i;
232*49cdfc7eSAndroid Build Coastguard Worker 	int test_flags[] = { SA_RESETHAND | SA_SIGINFO, SA_RESETHAND,
233*49cdfc7eSAndroid Build Coastguard Worker 		SA_RESETHAND | SA_SIGINFO, SA_RESETHAND | SA_SIGINFO
234*49cdfc7eSAndroid Build Coastguard Worker 	};
235*49cdfc7eSAndroid Build Coastguard Worker 
236*49cdfc7eSAndroid Build Coastguard Worker 	tst_parse_opts(ac, av, NULL, NULL);
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 		/* reset tst_count in case we are looping */
243*49cdfc7eSAndroid Build Coastguard Worker 		tst_count = 0;
244*49cdfc7eSAndroid Build Coastguard Worker 
245*49cdfc7eSAndroid Build Coastguard Worker 		testcase_no = 0;
246*49cdfc7eSAndroid Build Coastguard Worker 
247*49cdfc7eSAndroid Build Coastguard Worker 		for (i = 0; i < TST_TOTAL; i++) {
248*49cdfc7eSAndroid Build Coastguard Worker 			if (set_handler(test_flags[i], 0) == 0) {
249*49cdfc7eSAndroid Build Coastguard Worker 				testcase_no++;
250*49cdfc7eSAndroid Build Coastguard Worker 				switch (i) {
251*49cdfc7eSAndroid Build Coastguard Worker 				case 0:
252*49cdfc7eSAndroid Build Coastguard Worker 				 /*FALLTHROUGH*/ case 1:
253*49cdfc7eSAndroid Build Coastguard Worker 					(void)kill(getpid(), SIGUSR1);
254*49cdfc7eSAndroid Build Coastguard Worker 					break;
255*49cdfc7eSAndroid Build Coastguard Worker 				case 2:
256*49cdfc7eSAndroid Build Coastguard Worker 				 /*FALLTHROUGH*/ case 3:
257*49cdfc7eSAndroid Build Coastguard Worker 					(void)
258*49cdfc7eSAndroid Build Coastguard Worker 					    pthread_kill(pthread_self(),
259*49cdfc7eSAndroid Build Coastguard Worker 							 SIGUSR1);
260*49cdfc7eSAndroid Build Coastguard Worker 					break;
261*49cdfc7eSAndroid Build Coastguard Worker 				default:
262*49cdfc7eSAndroid Build Coastguard Worker 					tst_brkm(TBROK, cleanup,
263*49cdfc7eSAndroid Build Coastguard Worker 						 "illegal case number");
264*49cdfc7eSAndroid Build Coastguard Worker 					break;
265*49cdfc7eSAndroid Build Coastguard Worker 				}
266*49cdfc7eSAndroid Build Coastguard Worker 			}
267*49cdfc7eSAndroid Build Coastguard Worker 		}
268*49cdfc7eSAndroid Build Coastguard Worker 	}
269*49cdfc7eSAndroid Build Coastguard Worker 
270*49cdfc7eSAndroid Build Coastguard Worker 	cleanup();
271*49cdfc7eSAndroid Build Coastguard Worker 	tst_exit();
272*49cdfc7eSAndroid Build Coastguard Worker }
273