blob: e47d6b0432c3c0f7e2593141c99a820905547d33 [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
plars865695b2001-08-27 22:15:12 +000018 */
19
20/*
21 * NAME
22 * sigaction01.c
23 *
24 * DESCRIPTION
25 * Test some features of sigaction (see below for more details)
26 *
27 * ALGORITHM
28 * Use sigaction(2) to set a signal handler for SIGUSR1 with a certain
29 * set of flags, set a global variable indicating the test case, and
30 * finally send the signal to ourselves, causing the signal handler to
31 * run. The signal handler then checks the signal handler to run. The
32 * signal handler then checks certain conditions based on the test case
33 * number.
34 * There are 4 test cases:
35 *
36 * 1) Set SA_RESETHAND and SA_SIGINFO. When the handler runs,
37 * SA_SIGINFO should be set.
38 *
39 * 2) Set SA_RESETHAND. When the handler runs, SIGUSR1 should be
40 * masked (SA_RESETHAND makes sigaction behave as if SA_NODEFER was
41 * not set).
42 *
43 * 3) Same as case #2, but when the handler is established, sa_mask is
44 * set to include SIGUSR1. Ensure that SIGUSR1 is indeed masked even if
45 * SA_RESETHAND is set.
46 *
47 * 4) A signal generated from an interface or condition that does not
48 * provide siginfo (such as pthread_kill(3)) should invoke the handler
49 * with a non-NULL siginfo pointer.
50 *
51 * USAGE: <for command-line>
52 * sigaction01 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
53 * where, -c n : Run n copies concurrently.
54 * -f : Turn off functionality Testing.
55 * -i n : Execute test n times.
56 * -I x : Execute test for x seconds.
57 * -P x : Pause for x seconds between iterations.
58 * -t : Turn on syscall timing.
59 *
60 * HISTORY
61 * 07/2001 Ported by Wayne Boyer
62 *
63 * RESTRICTIONS
64 * NONE
65 */
66#include <pthread.h>
67#include <signal.h>
68#include <errno.h>
69#include <stdlib.h>
subrata_modak4bb656a2009-02-26 12:02:09 +000070#include <unistd.h>
plars865695b2001-08-27 22:15:12 +000071#include "test.h"
plars865695b2001-08-27 22:15:12 +000072
73void setup();
74void cleanup();
75
76char *TCID = "sigaction01";
77int TST_TOTAL = 4;
plars865695b2001-08-27 22:15:12 +000078
79volatile sig_atomic_t testcase_no;
80volatile sig_atomic_t pass;
81
plars865695b2001-08-27 22:15:12 +000082/*
83 * handler()
84 *
85 * A signal handler that understands which test case is currently
86 * being executed and compares the current conditions to the ones it
87 * expects (based on the test case number).
88 */
subrata_modak56207ce2009-03-23 13:35:39 +000089void handler(int sig, siginfo_t * sip, void *ucp)
plars865695b2001-08-27 22:15:12 +000090{
91 struct sigaction oact;
92 int err;
93 sigset_t nmask, omask;
94
95 /*
96 * Get sigaction setting
97 */
98 err = sigaction(SIGUSR1, NULL, &oact);
99
100 if (err == -1) {
101 perror("sigaction");
102 return;
103 }
104
105 /*
106 * Get current signal mask
107 */
108 sigemptyset(&nmask);
109 sigemptyset(&omask);
110 err = sigprocmask(SIG_BLOCK, &nmask, &omask);
111 if (err == -1) {
112 perror("sigprocmask");
113 tst_resm(TWARN, "sigprocmask() failed");
114 return;
115 }
116
117 switch (testcase_no) {
118 case 1:
119 /*
120 * SA_RESETHAND and SA_SIGINFO were set. SA_SIGINFO should
121 * be clear in Linux. In Linux kernel, SA_SIGINFO is not
122 * cleared in psig().
123 */
124 if (!(oact.sa_flags & SA_SIGINFO)) {
125 tst_resm(TFAIL, "SA_RESETHAND should not "
126 "cause SA_SIGINFO to be cleared, but it was.");
127 return;
128 }
129 if (sip == NULL) {
130 tst_resm(TFAIL, "siginfo should not be NULL");
131 return;
132 }
133 tst_resm(TPASS, "SA_RESETHAND did not "
134 "cause SA_SIGINFO to be cleared");
135 break;
136
137 case 2:
138 /*
139 * In Linux, SA_RESETHAND doesn't imply SA_NODEFER; sig
subrata_modak4bb656a2009-02-26 12:02:09 +0000140 * should not be masked. The testcase should pass if
plars865695b2001-08-27 22:15:12 +0000141 * SA_NODEFER is not masked, ie. if SA_NODEFER is a member
142 * of the signal list
143 */
144 if (sigismember(&omask, sig) == 0) {
145 tst_resm(TFAIL, "SA_RESETHAND should cause sig to"
146 "be masked when the handler executes.");
147 return;
148 }
149 tst_resm(TPASS, "SA_RESETHAND was masked when handler "
subrata_modak56207ce2009-03-23 13:35:39 +0000150 "executed");
plars865695b2001-08-27 22:15:12 +0000151 break;
152
153 case 3:
154 /*
155 * SA_RESETHAND implies SA_NODEFER unless sa_mask already
156 * included sig.
157 */
158 if (!sigismember(&omask, sig)) {
159 tst_resm(TFAIL, "sig should continue to be masked"
160 "because sa_mask originally contained sig.");
161 return;
162 }
163 tst_resm(TPASS, "sig has been masked "
164 "because sa_mask originally contained sig");
165 break;
166
167 case 4:
168 /*
169 * A signal generated from a mechanism that does not provide
170 * siginfo should invoke the handler with a non-NULL siginfo
171 * pointer.
172 */
173 if (sip == NULL) {
174 tst_resm(TFAIL, "siginfo pointer should not be NULL");
175 return;
176 }
177 tst_resm(TPASS, "siginfo pointer non NULL");
178 break;
179
180 default:
181 tst_resm(TFAIL, "invalid test case number: %d", testcase_no);
182 exit(1);
183 }
184}
185
186/*
187 * set_handler()
188 *
189 * Establish a signal handler for SIGUSR1 with the specified flags and
190 * signal to mask while the handler executes.
191 */
subrata_modak56207ce2009-03-23 13:35:39 +0000192int set_handler(int flags, int sig_to_mask)
plars865695b2001-08-27 22:15:12 +0000193{
194 struct sigaction sa;
195
196 sa.sa_sigaction = handler;
197 sa.sa_flags = flags;
198 sigemptyset(&sa.sa_mask);
199 sigaddset(&sa.sa_mask, sig_to_mask);
200
201 TEST(sigaction(SIGUSR1, &sa, NULL));
202 if (TEST_RETURN != 0) {
203 perror("sigaction");
204 tst_resm(TFAIL, "call failed unexpectedly");
205 return 1;
206 }
207 return 0;
208}
209
210/*
211 * setup() - performs all ONE TIME setup for this test.
212 */
Mike Frysingerc57fba52014-04-09 18:56:30 -0400213void setup(void)
plars865695b2001-08-27 22:15:12 +0000214{
Garrett Cooper2c282152010-12-16 00:55:50 -0800215
plars865695b2001-08-27 22:15:12 +0000216 TEST_PAUSE;
217}
218
219/*
220 * cleanup() - performs all ONE TIME cleanup for this test at
221 * completion or premature exit.
222 */
Mike Frysingerc57fba52014-04-09 18:56:30 -0400223void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000224{
plars865695b2001-08-27 22:15:12 +0000225
plars865695b2001-08-27 22:15:12 +0000226}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800227
robbiewfa451a12003-03-27 20:52:36 +0000228int main(int ac, char **av)
229{
Cyril Hrubis89af32a2012-10-24 16:39:11 +0200230 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +0200231 const char *msg; /* message got from parse_opts */
robbiewfa451a12003-03-27 20:52:36 +0000232 int i;
subrata_modak56207ce2009-03-23 13:35:39 +0000233 int test_flags[] = { SA_RESETHAND | SA_SIGINFO, SA_RESETHAND,
234 SA_RESETHAND | SA_SIGINFO, SA_RESETHAND | SA_SIGINFO
235 };
robbiewfa451a12003-03-27 20:52:36 +0000236
Garrett Cooper45e285d2010-11-22 12:19:25 -0800237 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) {
Garrett Cooper60fa8012010-11-22 13:50:58 -0800238 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
robbiewfa451a12003-03-27 20:52:36 +0000239 }
240
241 setup();
242
robbiewfa451a12003-03-27 20:52:36 +0000243 for (lc = 0; TEST_LOOPING(lc); lc++) {
244
Caspar Zhangd59a6592013-03-07 14:59:12 +0800245 /* reset tst_count in case we are looping */
246 tst_count = 0;
robbiewfa451a12003-03-27 20:52:36 +0000247
248 testcase_no = 0;
249
subrata_modak56207ce2009-03-23 13:35:39 +0000250 for (i = 0; i < TST_TOTAL; i++) {
robbiewfa451a12003-03-27 20:52:36 +0000251 if (set_handler(test_flags[i], 0) == 0) {
Cyril Hrubise38b9612014-06-02 17:20:57 +0200252 testcase_no++;
253 switch (i) {
254 case 0:
255 /*FALLTHROUGH*/ case 1:
256 (void)kill(getpid(), SIGUSR1);
257 break;
258 case 2:
259 /*FALLTHROUGH*/ case 3:
260 (void)
261 pthread_kill(pthread_self(),
262 SIGUSR1);
263 break;
264 default:
265 tst_brkm(TBROK, cleanup,
266 "illegal case number");
267 break;
robbiewfa451a12003-03-27 20:52:36 +0000268 }
269 }
270 }
271 }
robbiewfa451a12003-03-27 20:52:36 +0000272
Cyril Hrubise38b9612014-06-02 17:20:57 +0200273 cleanup();
Garrett Cooper53740502010-12-16 00:04:01 -0800274 tst_exit();
Chris Dearmanec6edca2012-10-17 19:54:01 -0700275}