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