• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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