1 /*
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
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /*
21 * Test Name: sigprocmask01
22 *
23 * Test Description:
24 * Verify that sigprocmask() succeeds to examine and change the calling
25 * process's signal mask.
26 * Also, verify that sigpending() succeeds to store signal mask that are
27 * blocked from delivery and pending for the calling process.
28 *
29 * Expected Result:
30 * - sigprocmask() should return value 0 on successs and succeed to change
31 * calling process's set of blocked/unblocked signals.
32 * - sigpending() should succeed to store the signal mask of pending signal.
33 *
34 * Algorithm:
35 * Setup:
36 * Setup signal handling.
37 * Create temporary directory.
38 * Pause for SIGUSR1 if option specified.
39 *
40 * Test:
41 * Loop if the proper options are given.
42 * Execute system call
43 * Check return code, if system call failed (return=-1)
44 * Log the errno and Issue a FAIL message.
45 * Otherwise,
46 * Verify the Functionality of system call
47 * if successful,
48 * Issue Functionality-Pass message.
49 * Otherwise,
50 * Issue Functionality-Fail message.
51 * Cleanup:
52 * Print errno log and/or timing stats if options given
53 * Delete the temporary directory created.
54 *
55 * Usage: <for command-line>
56 * sigprocmask01 [-c n] [-e] [-f] [-i n] [-I x] [-p x] [-t]
57 * where, -c n : Run n copies concurrently.
58 * -e : Turn on errno logging.
59 * -f : Turn off functionality Testing.
60 * -i n : Execute test n times.
61 * -I x : Execute test for x seconds.
62 * -P x : Pause for x seconds between iterations.
63 * -t : Turn on syscall timing.
64 *
65 * History
66 * 07/2001 John George
67 * -Ported
68 *
69 * Restrictions:
70 * None.
71 */
72
73 #include <stdio.h>
74 #include <unistd.h>
75 #include <sys/types.h>
76 #include <errno.h>
77 #include <fcntl.h>
78 #include <string.h>
79 #include <signal.h>
80 #include <ucontext.h>
81
82 #include "test.h"
83
84 void setup(); /* Main setup function of test */
85 void cleanup(); /* cleanup function for the test */
86 void sig_handler(int sig); /* signal catching function */
87
88 char *TCID = "sigprocmask01";
89 int TST_TOTAL = 1;
90
91 int sig_catch = 0; /* variable to blocked/unblocked signals */
92
93 struct sigaction sa_new; /* struct to hold signal info */
94 sigset_t set; /* signal set to hold signal lists */
95 sigset_t sigset2;
96
main(int ac,char ** av)97 int main(int ac, char **av)
98 {
99 int lc;
100 pid_t my_pid; /* test process id */
101
102 tst_parse_opts(ac, av, NULL, NULL);
103
104 setup();
105
106 for (lc = 0; TEST_LOOPING(lc); lc++) {
107
108 tst_count = 0;
109
110 /*
111 * Call sigprocmask() to block (SIGINT) signal
112 * so that, signal will not be delivered to
113 * the test process.
114 */
115 TEST(sigprocmask(SIG_BLOCK, &set, 0));
116
117 /* Get the process id of test process */
118 my_pid = getpid();
119
120 /* Send SIGINT signal to the process */
121 kill(my_pid, SIGINT);
122
123 if (TEST_RETURN == -1) {
124 tst_resm(TFAIL,
125 "sigprocmask() Failed, errno=%d : %s",
126 TEST_ERRNO, strerror(TEST_ERRNO));
127 } else {
128 /*
129 * Check whether process received the signal.
130 * If yes! signal handler was executed and
131 * incremented 'sig_catch' variable.
132 */
133 if (sig_catch) {
134 tst_resm(TFAIL, "sigprocmask fails to "
135 "change process's signal mask");
136 } else {
137 /*
138 * Check whether specified signal
139 * 'SIGINT' is pending for the process.
140 */
141 errno = 0;
142 if (sigpending(&sigset2) == -1) {
143 tst_brkm(TFAIL, cleanup,
144 "blocked signal not "
145 "in pending state, "
146 "error:%d", errno);
147 }
148
149 /*
150 * Check whether specified signal
151 * is the member of signal set.
152 */
153 errno = 0;
154 if (!sigismember(&sigset2, SIGINT)) {
155 tst_brkm(TFAIL, cleanup,
156 "sigismember() failed, "
157 "error:%d", errno);
158 }
159
160 /*
161 * Invoke sigprocmask() again to
162 * unblock the specified signal.
163 * so that, signal is delivered and
164 * signal handler executed.
165 */
166 errno = 0;
167 if (sigprocmask(SIG_UNBLOCK,
168 &set, 0) == -1) {
169 tst_brkm(TFAIL, cleanup,
170 "sigprocmask() failed "
171 "to unblock signal, "
172 "error=%d", errno);
173 }
174 if (sig_catch) {
175 tst_resm(TPASS, "Functionality "
176 "of sigprocmask() "
177 "Successful");
178 } else {
179 tst_resm(TFAIL, "Functionality "
180 "of sigprocmask() "
181 "Failed");
182 }
183 /* set sig_catch back to 0 */
184 sig_catch = 0;
185 }
186 }
187
188 tst_count++; /* incr TEST_LOOP counter */
189 }
190
191 cleanup();
192 tst_exit();
193 }
194
195 /*
196 * void
197 * setup() - performs all ONE TIME setup for this test.
198 * Initialise signal set with the list that includes/excludes
199 * all system-defined signals.
200 * Set the signal handler to catch SIGINT signal.
201 * Add the signal SIGINT to the exclude list of system-defined
202 * signals for the test process.
203 */
setup(void)204 void setup(void)
205 {
206
207 tst_sig(FORK, DEF_HANDLER, cleanup);
208
209 TEST_PAUSE;
210
211 /*
212 * Initialise the signal sets with the list that
213 * excludes/includes all system-defined signals.
214 */
215 if (sigemptyset(&set) == -1) {
216 tst_brkm(TFAIL, cleanup,
217 "sigemptyset() failed, errno=%d : %s",
218 errno, strerror(errno));
219 }
220 if (sigfillset(&sigset2) == -1) {
221 tst_brkm(TFAIL, cleanup,
222 "sigfillset() failed, errno=%d : %s",
223 errno, strerror(errno));
224 }
225
226 /* Set the signal handler function to catch the signal */
227 sa_new.sa_handler = sig_handler;
228 if (sigaction(SIGINT, &sa_new, 0) == -1) {
229 tst_brkm(TFAIL, cleanup,
230 "sigaction() failed, errno=%d : %s",
231 errno, strerror(errno));
232 }
233
234 /*
235 * Add specified signal (SIGINT) to the signal set
236 * which excludes system-defined signals.
237 */
238 if (sigaddset(&set, SIGINT) == -1) {
239 tst_brkm(TFAIL, cleanup,
240 "sigaddset() failed, errno=%d : %s",
241 errno, strerror(errno));
242 }
243 }
244
245 /*
246 * void
247 * sig_handler(int sig) - Signal catching function.
248 * This function gets executed when the signal SIGINT is delivered
249 * to the test process and the signal was trapped by sigaction()
250 * to execute this function.
251 * This function when executed, increments a global variable value
252 * which will be accessed in the test.
253 */
sig_handler(int sig)254 void sig_handler(int sig)
255 {
256 /* Increment the sig_catch variable */
257 sig_catch++;
258 }
259
260 /*
261 * void
262 * cleanup() - performs all ONE TIME cleanup for this test at
263 * completion or premature exit.
264 */
cleanup(void)265 void cleanup(void)
266 {
267
268 }
269