blob: 4faaa164dfd63408e91cc0ef11df5517dbb1e0a2 [file] [log] [blame]
subrata_modak89d3b4a2008-09-11 11:50:23 +00001/*
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
subrata_modak3d8666c2008-11-11 08:31:27 +000038#include "config.h"
39
subrata_modak89d3b4a2008-09-11 11:50:23 +000040#include "test.h"
41#include "usctest.h"
42
43#include <errno.h>
44#include <signal.h>
subrata_modak89d3b4a2008-09-11 11:50:23 +000045#include <unistd.h>
46#include <fcntl.h>
yaberauneya6b83f262009-11-26 12:43:45 +000047#include <inttypes.h>
48#include "ltp_signal.h"
subrata_modak89d3b4a2008-09-11 11:50:23 +000049
subrata_modak89d3b4a2008-09-11 11:50:23 +000050TCID_DEFINE(signalfd01);
51int TST_TOTAL = 1;
52extern int Tst_count;
53
subrata_modake94ba552008-11-20 09:35:07 +000054#ifndef HAVE_SIGNALFD
55#define USE_STUB
subrata_modak4bb656a2009-02-26 12:02:09 +000056#endif
subrata_modakec61b342008-10-23 06:54:59 +000057
subrata_modak3d8666c2008-11-11 08:31:27 +000058#if defined HAVE_SYS_SIGNALFD_H
subrata_modak89d3b4a2008-09-11 11:50:23 +000059#include <sys/signalfd.h>
subrata_modak3d8666c2008-11-11 08:31:27 +000060#elif defined HAVE_LINUX_SIGNALFD_H
subrata_modake94ba552008-11-20 09:35:07 +000061# if defined HAVE_LINUX_TYPES_H
62# include <linux/types.h>
63# endif
subrata_modak45d47502008-09-18 11:30:37 +000064#include <linux/signalfd.h>
subrata_modake94ba552008-11-20 09:35:07 +000065#define USE_OWNIMPL
subrata_modak3d8666c2008-11-11 08:31:27 +000066#elif defined HAVE_SIGNALFD_H
subrata_modak45d47502008-09-18 11:30:37 +000067#include <signalfd.h>
subrata_modak3d8666c2008-11-11 08:31:27 +000068#else
69#define USE_STUB
70#endif
subrata_modak45d47502008-09-18 11:30:37 +000071
subrata_modake94ba552008-11-20 09:35:07 +000072#if defined HAVE_STRUCT_SIGNALFD_SIGINFO_SSI_SIGNO
vapier48c51ee2008-11-12 19:27:33 +000073# define SIGNALFD_PREFIX(FIELD) ssi_##FIELD
subrata_modake94ba552008-11-20 09:35:07 +000074#elif defined HAVE_STRUCT_SIGNALFD_SIGINFO_SIGNO
vapier48c51ee2008-11-12 19:27:33 +000075# define SIGNALFD_PREFIX(FIELD) FIELD
subrata_modak3d8666c2008-11-11 08:31:27 +000076#else
subrata_modake94ba552008-11-20 09:35:07 +000077# define USE_STUB
subrata_modak3d8666c2008-11-11 08:31:27 +000078#endif
79
80#ifdef USE_STUB
vapier0dca7e52008-11-12 19:25:18 +000081int main(int argc, char **argv)
subrata_modak3d8666c2008-11-11 08:31:27 +000082{
vapier0dca7e52008-11-12 19:25:18 +000083 tst_resm(TCONF, "System doesn't support execution of the test");
84 return 0;
subrata_modak3d8666c2008-11-11 08:31:27 +000085}
subrata_modak3d8666c2008-11-11 08:31:27 +000086
subrata_modakc28532e2008-12-30 14:38:12 +000087#else
88#if defined USE_OWNIMPL
vapier2ba926e2008-11-14 07:39:21 +000089#include "linux_syscall_numbers.h"
90int signalfd(int fd, const sigset_t * mask, int flags)
91{
92 /* Taken from GLIBC. */
yaberauneya6b83f262009-11-26 12:43:45 +000093 return (syscall(__NR_signalfd, fd, mask, SIGSETSIZE));
vapier2ba926e2008-11-14 07:39:21 +000094}
subrata_modakc28532e2008-12-30 14:38:12 +000095#endif
vapier2ba926e2008-11-14 07:39:21 +000096
subrata_modak89d3b4a2008-09-11 11:50:23 +000097void cleanup(void);
98void setup(void);
99
vapier0dca7e52008-11-12 19:25:18 +0000100int do_test1(int ntst, int sig)
subrata_modak89d3b4a2008-09-11 11:50:23 +0000101{
102 int sfd_for_next;
103 int sfd;
104 sigset_t mask;
105 pid_t pid;
106 struct signalfd_siginfo fdsi;
vapier0dca7e52008-11-12 19:25:18 +0000107 ssize_t s;
108
subrata_modak89d3b4a2008-09-11 11:50:23 +0000109 sigemptyset(&mask);
110 sigaddset(&mask, sig);
111 if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
112 tst_brkm(TBROK, cleanup,
113 "sigprocmask() Failed: errno=%d : %s",
vapier0dca7e52008-11-12 19:25:18 +0000114 errno, strerror(errno));
subrata_modak89d3b4a2008-09-11 11:50:23 +0000115 }
vapier0dca7e52008-11-12 19:25:18 +0000116
subrata_modak89d3b4a2008-09-11 11:50:23 +0000117 TEST(signalfd(-1, &mask, 0));
vapier0dca7e52008-11-12 19:25:18 +0000118
subrata_modak89d3b4a2008-09-11 11:50:23 +0000119 if ((sfd = TEST_RETURN) == -1) {
120 tst_resm(TFAIL,
121 "signalfd() Failed, errno=%d : %s",
122 TEST_ERRNO, strerror(TEST_ERRNO));
123 sfd_for_next = -1;
124 return sfd_for_next;
vapier0dca7e52008-11-12 19:25:18 +0000125
subrata_modak89d3b4a2008-09-11 11:50:23 +0000126 } else if (!STD_FUNCTIONAL_TEST) {
127 tst_resm(TPASS, "signalfd is created successfully");
128 sfd_for_next = sfd;
129 goto out;
130 }
subrata_modak89d3b4a2008-09-11 11:50:23 +0000131
132 if (fcntl(sfd, F_SETFL, O_NONBLOCK) == -1) {
133 close(sfd);
134 tst_brkm(TBROK, cleanup,
135 "setting signalfd nonblocking mode failed: errno=%d : %s",
vapier0dca7e52008-11-12 19:25:18 +0000136 errno, strerror(errno));
subrata_modak89d3b4a2008-09-11 11:50:23 +0000137 }
138
subrata_modak89d3b4a2008-09-11 11:50:23 +0000139 pid = getpid();
140 if (kill(pid, sig) == -1) {
141 close(sfd);
142 tst_brkm(TBROK, cleanup,
143 "kill(self, %s) failed: errno=%d : %s",
vapier0dca7e52008-11-12 19:25:18 +0000144 strsignal(sig), errno, strerror(errno));
subrata_modak89d3b4a2008-09-11 11:50:23 +0000145 }
146
147 s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
148 if ((s > 0) && (s != sizeof(struct signalfd_siginfo))) {
149 tst_resm(TFAIL,
150 "getting incomplete signalfd_siginfo data: "
yaberauneya6b83f262009-11-26 12:43:45 +0000151 "actual-size=%"PRId32", expected-size=%"PRId32,
subrata_modak89d3b4a2008-09-11 11:50:23 +0000152 s, sizeof(struct signalfd_siginfo));
153 sfd_for_next = -1;
154 close(sfd);
155 goto out;
vapier0dca7e52008-11-12 19:25:18 +0000156 } else if (s < 0) {
subrata_modak89d3b4a2008-09-11 11:50:23 +0000157 if (errno == EAGAIN) {
158 tst_resm(TFAIL,
159 "signalfd_siginfo data is not delivered yet");
160 sfd_for_next = -1;
161 close(sfd);
162 goto out;
163 } else {
164 close(sfd);
165 tst_brkm(TBROK, cleanup,
166 "read signalfd_siginfo data failed: errno=%d : %s",
vapier0dca7e52008-11-12 19:25:18 +0000167 errno, strerror(errno));
subrata_modak89d3b4a2008-09-11 11:50:23 +0000168 }
vapier0dca7e52008-11-12 19:25:18 +0000169 } else if (s == 0) {
subrata_modak89d3b4a2008-09-11 11:50:23 +0000170 tst_resm(TFAIL, "got EOF unexpectedly");
171 sfd_for_next = -1;
172 close(sfd);
173 goto out;
174 }
vapier0dca7e52008-11-12 19:25:18 +0000175
vapier48c51ee2008-11-12 19:27:33 +0000176 if (fdsi.SIGNALFD_PREFIX(signo) == sig) {
subrata_modak89d3b4a2008-09-11 11:50:23 +0000177 tst_resm(TPASS, "got expected signal");
178 sfd_for_next = sfd;
179 goto out;
vapier0dca7e52008-11-12 19:25:18 +0000180 } else {
subrata_modak89d3b4a2008-09-11 11:50:23 +0000181 tst_resm(TFAIL, "got unexpected signal: signal=%d : %s",
subrata_modake94ba552008-11-20 09:35:07 +0000182 fdsi.SIGNALFD_PREFIX(signo),
vapier48c51ee2008-11-12 19:27:33 +0000183 strsignal(fdsi.SIGNALFD_PREFIX(signo)));
subrata_modak89d3b4a2008-09-11 11:50:23 +0000184 sfd_for_next = -1;
185 close(sfd);
186 goto out;
187 }
188
subrata_modak56207ce2009-03-23 13:35:39 +0000189 out:
subrata_modak89d3b4a2008-09-11 11:50:23 +0000190 return sfd_for_next;
191}
192
vapier0dca7e52008-11-12 19:25:18 +0000193void do_test2(int ntst, int fd, int sig)
subrata_modak89d3b4a2008-09-11 11:50:23 +0000194{
195 int sfd;
196 sigset_t mask;
197 pid_t pid;
198 struct signalfd_siginfo fdsi;
vapier0dca7e52008-11-12 19:25:18 +0000199 ssize_t s;
subrata_modak89d3b4a2008-09-11 11:50:23 +0000200
201 sigemptyset(&mask);
202 sigaddset(&mask, sig);
203 if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
204 close(fd);
205 tst_brkm(TBROK, cleanup,
206 "sigprocmask() Failed: errno=%d : %s",
vapier0dca7e52008-11-12 19:25:18 +0000207 errno, strerror(errno));
subrata_modak89d3b4a2008-09-11 11:50:23 +0000208 }
vapier0dca7e52008-11-12 19:25:18 +0000209
subrata_modak89d3b4a2008-09-11 11:50:23 +0000210 TEST(signalfd(fd, &mask, 0));
vapier0dca7e52008-11-12 19:25:18 +0000211
subrata_modak89d3b4a2008-09-11 11:50:23 +0000212 if ((sfd = TEST_RETURN) == -1) {
213 tst_resm(TFAIL,
214 "reassignment the file descriptor by signalfd() failed, errno=%d : %s",
215 TEST_ERRNO, strerror(TEST_ERRNO));
216 return;
217 } else if (sfd != fd) {
218 tst_resm(TFAIL,
219 "different fd is returned in reassignment: expected-fd=%d, actual-fd=%d",
220 fd, sfd);
221 close(sfd);
222 return;
vapier0dca7e52008-11-12 19:25:18 +0000223
subrata_modak89d3b4a2008-09-11 11:50:23 +0000224 } else if (!STD_FUNCTIONAL_TEST) {
225 tst_resm(TPASS, "signalfd is successfully reassigned");
226 goto out;
227 }
vapier0dca7e52008-11-12 19:25:18 +0000228
subrata_modak89d3b4a2008-09-11 11:50:23 +0000229 pid = getpid();
230 if (kill(pid, sig) == -1) {
231 close(sfd);
232 tst_brkm(TBROK, cleanup,
233 "kill(self, %s) failed: errno=%d : %s",
vapier0dca7e52008-11-12 19:25:18 +0000234 strsignal(sig), errno, strerror(errno));
subrata_modak89d3b4a2008-09-11 11:50:23 +0000235 }
236
237 s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
238 if ((s > 0) && (s != sizeof(struct signalfd_siginfo))) {
239 tst_resm(TFAIL,
240 "getting incomplete signalfd_siginfo data: "
yaberauneya6b83f262009-11-26 12:43:45 +0000241 "actual-size=%"PRId32", expected-size= %"PRId32,
subrata_modak89d3b4a2008-09-11 11:50:23 +0000242 s, sizeof(struct signalfd_siginfo));
243 goto out;
vapier0dca7e52008-11-12 19:25:18 +0000244 } else if (s < 0) {
subrata_modak89d3b4a2008-09-11 11:50:23 +0000245 if (errno == EAGAIN) {
246 tst_resm(TFAIL,
247 "signalfd_siginfo data is not delivered yet");
248 goto out;
249 } else {
250 close(sfd);
251 tst_brkm(TBROK, cleanup,
252 "read signalfd_siginfo data failed: errno=%d : %s",
vapier0dca7e52008-11-12 19:25:18 +0000253 errno, strerror(errno));
subrata_modak89d3b4a2008-09-11 11:50:23 +0000254 }
vapier0dca7e52008-11-12 19:25:18 +0000255 } else if (s == 0) {
subrata_modak89d3b4a2008-09-11 11:50:23 +0000256 tst_resm(TFAIL, "got EOF unexpectedly");
257 goto out;
258 }
vapier0dca7e52008-11-12 19:25:18 +0000259
vapier48c51ee2008-11-12 19:27:33 +0000260 if (fdsi.SIGNALFD_PREFIX(signo) == sig) {
subrata_modak89d3b4a2008-09-11 11:50:23 +0000261 tst_resm(TPASS, "got expected signal");
262 goto out;
vapier0dca7e52008-11-12 19:25:18 +0000263 } else {
subrata_modak89d3b4a2008-09-11 11:50:23 +0000264 tst_resm(TFAIL, "got unexpected signal: signal=%d : %s",
vapier48c51ee2008-11-12 19:27:33 +0000265 fdsi.SIGNALFD_PREFIX(signo),
266 strsignal(fdsi.SIGNALFD_PREFIX(signo)));
subrata_modak89d3b4a2008-09-11 11:50:23 +0000267 goto out;
268 }
vapier0dca7e52008-11-12 19:25:18 +0000269
subrata_modak56207ce2009-03-23 13:35:39 +0000270 out:
subrata_modak89d3b4a2008-09-11 11:50:23 +0000271 return;
272}
273
vapier0dca7e52008-11-12 19:25:18 +0000274int main(int argc, char **argv)
subrata_modak89d3b4a2008-09-11 11:50:23 +0000275{
276 int lc;
vapier0dca7e52008-11-12 19:25:18 +0000277 char *msg; /* message returned from parse_opts */
subrata_modak89d3b4a2008-09-11 11:50:23 +0000278 int sfd;
279
vapier0dca7e52008-11-12 19:25:18 +0000280 if ((tst_kvercmp(2, 6, 22)) < 0) {
281 tst_resm(TWARN,
282 "This test can only run on kernels that are 2.6.22 and higher");
subrata_modak89d3b4a2008-09-11 11:50:23 +0000283 exit(0);
284 }
subrata_modak89d3b4a2008-09-11 11:50:23 +0000285
286 if ((msg = parse_opts(argc, argv, NULL, NULL)) != NULL) {
287 tst_brkm(TBROK, cleanup, "OPTION PARSING ERROR - %s", msg);
288 }
289
vapier0dca7e52008-11-12 19:25:18 +0000290 setup();
subrata_modak89d3b4a2008-09-11 11:50:23 +0000291 for (lc = 0; TEST_LOOPING(lc); lc++) {
292 Tst_count = 0;
293
294 sfd = do_test1(lc, SIGUSR1);
295 if (sfd < 0)
296 continue;
vapier0dca7e52008-11-12 19:25:18 +0000297
subrata_modak89d3b4a2008-09-11 11:50:23 +0000298 do_test2(lc, sfd, SIGUSR2);
299 close(sfd);
300 }
vapier0dca7e52008-11-12 19:25:18 +0000301
subrata_modak89d3b4a2008-09-11 11:50:23 +0000302 cleanup();
303
304 return 0;
305}
306
307/*
308 * setup() - performs all the ONE TIME setup for this test.
309 */
vapier0dca7e52008-11-12 19:25:18 +0000310void setup(void)
subrata_modak89d3b4a2008-09-11 11:50:23 +0000311{
312 /* Pause if that option was specified */
313 TEST_PAUSE;
314}
315
316/*
317 * cleanup() - performs all the ONE TIME cleanup for this test at completion
318 * or premature exit.
319 */
vapier0dca7e52008-11-12 19:25:18 +0000320void cleanup(void)
subrata_modak89d3b4a2008-09-11 11:50:23 +0000321{
322 /*
323 * print timing stats if that option was specified.
324 * print errno log if that option was specified.
325 */
326 TEST_CLEANUP;
327
328 /* exit with return code appropriate for results */
329 tst_exit();
330}
331
subrata_modak3d8666c2008-11-11 08:31:27 +0000332#endif