1 /*
2 *
3 * Copyright (c) Red Hat Inc., 2008
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 * NAME
22 * signalfd01.c
23 *
24 * DESCRIPTION
25 * Check signalfd can receive signals
26 *
27 * USAGE
28 * signalfd01
29 *
30 * HISTORY
31 * 9/2008 Initial version by Masatake YAMATO <yamato@redhat.com>
32 *
33 * RESTRICTIONS
34 * None
35 */
36 #define _GNU_SOURCE
37
38 #include "config.h"
39
40 #include "test.h"
41
42 #include <errno.h>
43 #include <signal.h>
44 #include <unistd.h>
45 #include <fcntl.h>
46 #include <inttypes.h>
47 #include "ltp_signal.h"
48
49 TCID_DEFINE(signalfd01);
50 int TST_TOTAL = 1;
51
52 #ifndef HAVE_SIGNALFD
53 #define USE_STUB
54 #endif
55
56 #if defined HAVE_SYS_SIGNALFD_H
57 #include <sys/signalfd.h>
58 #elif defined HAVE_LINUX_SIGNALFD_H
59 #if defined HAVE_LINUX_TYPES_H
60 #include <linux/types.h>
61 #endif
62 #include <linux/signalfd.h>
63 #define USE_OWNIMPL
64 #elif defined HAVE_SIGNALFD_H
65 #include <signalfd.h>
66 #else
67 #define USE_STUB
68 #endif
69
70 #if defined HAVE_STRUCT_SIGNALFD_SIGINFO_SSI_SIGNO
71 #define SIGNALFD_PREFIX(FIELD) ssi_##FIELD
72 #elif defined HAVE_STRUCT_SIGNALFD_SIGINFO_SIGNO
73 #define SIGNALFD_PREFIX(FIELD) FIELD
74 #else
75 #define USE_STUB
76 #endif
77
78 #ifdef USE_STUB
main(void)79 int main(void)
80 {
81 tst_brkm(TCONF, NULL, "System doesn't support execution of the test");
82 }
83
84 #else
85 #if defined USE_OWNIMPL
86 #include "lapi/syscalls.h"
signalfd(int fd,const sigset_t * mask,int flags)87 int signalfd(int fd, const sigset_t * mask, int flags)
88 {
89 /* Taken from GLIBC. */
90 return ltp_syscall(__NR_signalfd, fd, mask, SIGSETSIZE);
91 }
92 #endif
93
94 void cleanup(void);
95 void setup(void);
96
do_test1(uint32_t sig)97 int do_test1(uint32_t sig)
98 {
99 int sfd_for_next;
100 int sfd;
101 sigset_t mask;
102 pid_t pid;
103 struct signalfd_siginfo fdsi;
104 ssize_t s;
105
106 sigemptyset(&mask);
107 sigaddset(&mask, sig);
108 if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
109 tst_brkm(TBROK, cleanup,
110 "sigprocmask() Failed: errno=%d : %s",
111 errno, strerror(errno));
112 }
113
114 TEST(signalfd(-1, &mask, 0));
115
116 if ((sfd = TEST_RETURN) == -1) {
117 tst_resm(TFAIL,
118 "signalfd() Failed, errno=%d : %s",
119 TEST_ERRNO, strerror(TEST_ERRNO));
120 sfd_for_next = -1;
121 return sfd_for_next;
122
123 } else {
124 tst_resm(TPASS, "signalfd is created successfully");
125 sfd_for_next = sfd;
126 goto out;
127 }
128
129 if (fcntl(sfd, F_SETFL, O_NONBLOCK) == -1) {
130 close(sfd);
131 tst_brkm(TBROK, cleanup,
132 "setting signalfd nonblocking mode failed: errno=%d : %s",
133 errno, strerror(errno));
134 }
135
136 pid = getpid();
137 if (kill(pid, sig) == -1) {
138 close(sfd);
139 tst_brkm(TBROK, cleanup,
140 "kill(self, %s) failed: errno=%d : %s",
141 strsignal(sig), errno, strerror(errno));
142 }
143
144 s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
145 if ((s > 0) && (s != sizeof(struct signalfd_siginfo))) {
146 tst_resm(TFAIL,
147 "getting incomplete signalfd_siginfo data: "
148 "actual-size=%zd, expected-size=%zu",
149 s, sizeof(struct signalfd_siginfo));
150 sfd_for_next = -1;
151 close(sfd);
152 goto out;
153 } else if (s < 0) {
154 if (errno == EAGAIN) {
155 tst_resm(TFAIL,
156 "signalfd_siginfo data is not delivered yet");
157 sfd_for_next = -1;
158 close(sfd);
159 goto out;
160 } else {
161 close(sfd);
162 tst_brkm(TBROK, cleanup,
163 "read signalfd_siginfo data failed: errno=%d : %s",
164 errno, strerror(errno));
165 }
166 } else if (s == 0) {
167 tst_resm(TFAIL, "got EOF unexpectedly");
168 sfd_for_next = -1;
169 close(sfd);
170 goto out;
171 }
172
173 if (fdsi.SIGNALFD_PREFIX(signo) == sig) {
174 tst_resm(TPASS, "got expected signal");
175 sfd_for_next = sfd;
176 goto out;
177 } else {
178 tst_resm(TFAIL, "got unexpected signal: signal=%d : %s",
179 fdsi.SIGNALFD_PREFIX(signo),
180 strsignal(fdsi.SIGNALFD_PREFIX(signo)));
181 sfd_for_next = -1;
182 close(sfd);
183 goto out;
184 }
185
186 out:
187 return sfd_for_next;
188 }
189
do_test2(int fd,uint32_t sig)190 void do_test2(int fd, uint32_t sig)
191 {
192 int sfd;
193 sigset_t mask;
194 pid_t pid;
195 struct signalfd_siginfo fdsi;
196 ssize_t s;
197
198 sigemptyset(&mask);
199 sigaddset(&mask, sig);
200 if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
201 close(fd);
202 tst_brkm(TBROK, cleanup,
203 "sigprocmask() Failed: errno=%d : %s",
204 errno, strerror(errno));
205 }
206
207 TEST(signalfd(fd, &mask, 0));
208
209 if ((sfd = TEST_RETURN) == -1) {
210 tst_resm(TFAIL,
211 "reassignment the file descriptor by signalfd() failed, errno=%d : %s",
212 TEST_ERRNO, strerror(TEST_ERRNO));
213 return;
214 } else if (sfd != fd) {
215 tst_resm(TFAIL,
216 "different fd is returned in reassignment: expected-fd=%d, actual-fd=%d",
217 fd, sfd);
218 close(sfd);
219 return;
220
221 } else {
222 tst_resm(TPASS, "signalfd is successfully reassigned");
223 goto out;
224 }
225
226 pid = getpid();
227 if (kill(pid, sig) == -1) {
228 close(sfd);
229 tst_brkm(TBROK, cleanup,
230 "kill(self, %s) failed: errno=%d : %s",
231 strsignal(sig), errno, strerror(errno));
232 }
233
234 s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
235 if ((s > 0) && (s != sizeof(struct signalfd_siginfo))) {
236 tst_resm(TFAIL,
237 "getting incomplete signalfd_siginfo data: "
238 "actual-size=%zd, expected-size= %zu",
239 s, sizeof(struct signalfd_siginfo));
240 goto out;
241 } else if (s < 0) {
242 if (errno == EAGAIN) {
243 tst_resm(TFAIL,
244 "signalfd_siginfo data is not delivered yet");
245 goto out;
246 } else {
247 close(sfd);
248 tst_brkm(TBROK, cleanup,
249 "read signalfd_siginfo data failed: errno=%d : %s",
250 errno, strerror(errno));
251 }
252 } else if (s == 0) {
253 tst_resm(TFAIL, "got EOF unexpectedly");
254 goto out;
255 }
256
257 if (fdsi.SIGNALFD_PREFIX(signo) == sig) {
258 tst_resm(TPASS, "got expected signal");
259 goto out;
260 } else {
261 tst_resm(TFAIL, "got unexpected signal: signal=%d : %s",
262 fdsi.SIGNALFD_PREFIX(signo),
263 strsignal(fdsi.SIGNALFD_PREFIX(signo)));
264 goto out;
265 }
266
267 out:
268 return;
269 }
270
main(int argc,char ** argv)271 int main(int argc, char **argv)
272 {
273 int lc;
274 int sfd;
275
276 if ((tst_kvercmp(2, 6, 22)) < 0) {
277 tst_resm(TWARN,
278 "This test can only run on kernels that are 2.6.22 and higher");
279 exit(0);
280 }
281
282 tst_parse_opts(argc, argv, NULL, NULL);
283
284 setup();
285 for (lc = 0; TEST_LOOPING(lc); lc++) {
286 tst_count = 0;
287
288 sfd = do_test1(SIGUSR1);
289 if (sfd < 0)
290 continue;
291
292 do_test2(sfd, SIGUSR2);
293 close(sfd);
294 }
295
296 cleanup();
297
298 tst_exit();
299 }
300
301 /*
302 * setup() - performs all the ONE TIME setup for this test.
303 */
setup(void)304 void setup(void)
305 {
306
307 TEST_PAUSE;
308 }
309
310 /*
311 * cleanup() - performs all the ONE TIME cleanup for this test at completion
312 * or premature exit.
313 */
cleanup(void)314 void cleanup(void)
315 {
316
317 }
318
319 #endif
320