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