1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci *
3f08c3bdfSopenharmony_ci *   Copyright (c) Red Hat Inc., 2008
4f08c3bdfSopenharmony_ci *
5f08c3bdfSopenharmony_ci *   This program is free software;  you can redistribute it and/or modify
6f08c3bdfSopenharmony_ci *   it under the terms of the GNU General Public License as published by
7f08c3bdfSopenharmony_ci *   the Free Software Foundation; either version 2 of the License, or
8f08c3bdfSopenharmony_ci *   (at your option) any later version.
9f08c3bdfSopenharmony_ci *
10f08c3bdfSopenharmony_ci *   This program is distributed in the hope that it will be useful,
11f08c3bdfSopenharmony_ci *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12f08c3bdfSopenharmony_ci *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13f08c3bdfSopenharmony_ci *   the GNU General Public License for more details.
14f08c3bdfSopenharmony_ci *
15f08c3bdfSopenharmony_ci *   You should have received a copy of the GNU General Public License
16f08c3bdfSopenharmony_ci *   along with this program;  if not, write to the Free Software
17f08c3bdfSopenharmony_ci *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18f08c3bdfSopenharmony_ci */
19f08c3bdfSopenharmony_ci
20f08c3bdfSopenharmony_ci/*
21f08c3bdfSopenharmony_ci * NAME
22f08c3bdfSopenharmony_ci *	signalfd01.c
23f08c3bdfSopenharmony_ci *
24f08c3bdfSopenharmony_ci * DESCRIPTION
25f08c3bdfSopenharmony_ci *	Check signalfd can receive signals
26f08c3bdfSopenharmony_ci *
27f08c3bdfSopenharmony_ci * USAGE
28f08c3bdfSopenharmony_ci * 	signalfd01
29f08c3bdfSopenharmony_ci *
30f08c3bdfSopenharmony_ci * HISTORY
31f08c3bdfSopenharmony_ci *	9/2008 Initial version by Masatake YAMATO <yamato@redhat.com>
32f08c3bdfSopenharmony_ci *
33f08c3bdfSopenharmony_ci * RESTRICTIONS
34f08c3bdfSopenharmony_ci * 	None
35f08c3bdfSopenharmony_ci */
36f08c3bdfSopenharmony_ci#define _GNU_SOURCE
37f08c3bdfSopenharmony_ci
38f08c3bdfSopenharmony_ci#include "config.h"
39f08c3bdfSopenharmony_ci
40f08c3bdfSopenharmony_ci#include "test.h"
41f08c3bdfSopenharmony_ci
42f08c3bdfSopenharmony_ci#include <errno.h>
43f08c3bdfSopenharmony_ci#include <signal.h>
44f08c3bdfSopenharmony_ci#include <unistd.h>
45f08c3bdfSopenharmony_ci#include <fcntl.h>
46f08c3bdfSopenharmony_ci#include <inttypes.h>
47f08c3bdfSopenharmony_ci#include "ltp_signal.h"
48f08c3bdfSopenharmony_ci
49f08c3bdfSopenharmony_ciTCID_DEFINE(signalfd01);
50f08c3bdfSopenharmony_ciint TST_TOTAL = 1;
51f08c3bdfSopenharmony_ci
52f08c3bdfSopenharmony_ci#ifndef HAVE_SIGNALFD
53f08c3bdfSopenharmony_ci#define  USE_STUB
54f08c3bdfSopenharmony_ci#endif
55f08c3bdfSopenharmony_ci
56f08c3bdfSopenharmony_ci#if defined HAVE_SYS_SIGNALFD_H
57f08c3bdfSopenharmony_ci#include <sys/signalfd.h>
58f08c3bdfSopenharmony_ci#elif defined HAVE_LINUX_SIGNALFD_H
59f08c3bdfSopenharmony_ci#include <linux/signalfd.h>
60f08c3bdfSopenharmony_ci#define USE_OWNIMPL
61f08c3bdfSopenharmony_ci#else
62f08c3bdfSopenharmony_ci#define  USE_STUB
63f08c3bdfSopenharmony_ci#endif
64f08c3bdfSopenharmony_ci
65f08c3bdfSopenharmony_ci#ifndef HAVE_STRUCT_SIGNALFD_SIGINFO_SSI_SIGNO
66f08c3bdfSopenharmony_ci#define USE_STUB
67f08c3bdfSopenharmony_ci#endif
68f08c3bdfSopenharmony_ci
69f08c3bdfSopenharmony_ci#ifdef USE_STUB
70f08c3bdfSopenharmony_ciint main(void)
71f08c3bdfSopenharmony_ci{
72f08c3bdfSopenharmony_ci	tst_brkm(TCONF, NULL, "System doesn't support execution of the test");
73f08c3bdfSopenharmony_ci}
74f08c3bdfSopenharmony_ci
75f08c3bdfSopenharmony_ci#else
76f08c3bdfSopenharmony_ci#if defined USE_OWNIMPL
77f08c3bdfSopenharmony_ci#include "lapi/syscalls.h"
78f08c3bdfSopenharmony_ciint signalfd(int fd, const sigset_t * mask, int flags)
79f08c3bdfSopenharmony_ci{
80f08c3bdfSopenharmony_ci	/* Taken from GLIBC. */
81f08c3bdfSopenharmony_ci	return tst_syscall(__NR_signalfd, fd, mask, SIGSETSIZE);
82f08c3bdfSopenharmony_ci}
83f08c3bdfSopenharmony_ci#endif
84f08c3bdfSopenharmony_ci
85f08c3bdfSopenharmony_civoid cleanup(void);
86f08c3bdfSopenharmony_civoid setup(void);
87f08c3bdfSopenharmony_ci
88f08c3bdfSopenharmony_ciint do_test1(uint32_t sig)
89f08c3bdfSopenharmony_ci{
90f08c3bdfSopenharmony_ci	int sfd_for_next;
91f08c3bdfSopenharmony_ci	int sfd;
92f08c3bdfSopenharmony_ci	sigset_t mask;
93f08c3bdfSopenharmony_ci	pid_t pid;
94f08c3bdfSopenharmony_ci	struct signalfd_siginfo fdsi;
95f08c3bdfSopenharmony_ci	ssize_t s;
96f08c3bdfSopenharmony_ci
97f08c3bdfSopenharmony_ci	sigemptyset(&mask);
98f08c3bdfSopenharmony_ci	sigaddset(&mask, sig);
99f08c3bdfSopenharmony_ci	if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
100f08c3bdfSopenharmony_ci		tst_brkm(TBROK, cleanup,
101f08c3bdfSopenharmony_ci			 "sigprocmask() Failed: errno=%d : %s",
102f08c3bdfSopenharmony_ci			 errno, strerror(errno));
103f08c3bdfSopenharmony_ci	}
104f08c3bdfSopenharmony_ci
105f08c3bdfSopenharmony_ci	TEST(signalfd(-1, &mask, 0));
106f08c3bdfSopenharmony_ci
107f08c3bdfSopenharmony_ci	if ((sfd = TEST_RETURN) == -1) {
108f08c3bdfSopenharmony_ci		tst_resm(TFAIL,
109f08c3bdfSopenharmony_ci			 "signalfd() Failed, errno=%d : %s",
110f08c3bdfSopenharmony_ci			 TEST_ERRNO, strerror(TEST_ERRNO));
111f08c3bdfSopenharmony_ci		sfd_for_next = -1;
112f08c3bdfSopenharmony_ci		return sfd_for_next;
113f08c3bdfSopenharmony_ci
114f08c3bdfSopenharmony_ci	} else {
115f08c3bdfSopenharmony_ci		tst_resm(TPASS, "signalfd is created successfully");
116f08c3bdfSopenharmony_ci		sfd_for_next = sfd;
117f08c3bdfSopenharmony_ci		goto out;
118f08c3bdfSopenharmony_ci	}
119f08c3bdfSopenharmony_ci
120f08c3bdfSopenharmony_ci	if (fcntl(sfd, F_SETFL, O_NONBLOCK) == -1) {
121f08c3bdfSopenharmony_ci		close(sfd);
122f08c3bdfSopenharmony_ci		tst_brkm(TBROK, cleanup,
123f08c3bdfSopenharmony_ci			 "setting signalfd nonblocking mode failed: errno=%d : %s",
124f08c3bdfSopenharmony_ci			 errno, strerror(errno));
125f08c3bdfSopenharmony_ci	}
126f08c3bdfSopenharmony_ci
127f08c3bdfSopenharmony_ci	pid = getpid();
128f08c3bdfSopenharmony_ci	if (kill(pid, sig) == -1) {
129f08c3bdfSopenharmony_ci		close(sfd);
130f08c3bdfSopenharmony_ci		tst_brkm(TBROK, cleanup,
131f08c3bdfSopenharmony_ci			 "kill(self, %s) failed: errno=%d : %s",
132f08c3bdfSopenharmony_ci			 strsignal(sig), errno, strerror(errno));
133f08c3bdfSopenharmony_ci	}
134f08c3bdfSopenharmony_ci
135f08c3bdfSopenharmony_ci	s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
136f08c3bdfSopenharmony_ci	if ((s > 0) && (s != sizeof(struct signalfd_siginfo))) {
137f08c3bdfSopenharmony_ci		tst_resm(TFAIL,
138f08c3bdfSopenharmony_ci			 "getting incomplete signalfd_siginfo data: "
139f08c3bdfSopenharmony_ci			 "actual-size=%zd, expected-size=%zu",
140f08c3bdfSopenharmony_ci			 s, sizeof(struct signalfd_siginfo));
141f08c3bdfSopenharmony_ci		sfd_for_next = -1;
142f08c3bdfSopenharmony_ci		close(sfd);
143f08c3bdfSopenharmony_ci		goto out;
144f08c3bdfSopenharmony_ci	} else if (s < 0) {
145f08c3bdfSopenharmony_ci		if (errno == EAGAIN) {
146f08c3bdfSopenharmony_ci			tst_resm(TFAIL,
147f08c3bdfSopenharmony_ci				 "signalfd_siginfo data is not delivered yet");
148f08c3bdfSopenharmony_ci			sfd_for_next = -1;
149f08c3bdfSopenharmony_ci			close(sfd);
150f08c3bdfSopenharmony_ci			goto out;
151f08c3bdfSopenharmony_ci		} else {
152f08c3bdfSopenharmony_ci			close(sfd);
153f08c3bdfSopenharmony_ci			tst_brkm(TBROK, cleanup,
154f08c3bdfSopenharmony_ci				 "read signalfd_siginfo data failed: errno=%d : %s",
155f08c3bdfSopenharmony_ci				 errno, strerror(errno));
156f08c3bdfSopenharmony_ci		}
157f08c3bdfSopenharmony_ci	} else if (s == 0) {
158f08c3bdfSopenharmony_ci		tst_resm(TFAIL, "got EOF unexpectedly");
159f08c3bdfSopenharmony_ci		sfd_for_next = -1;
160f08c3bdfSopenharmony_ci		close(sfd);
161f08c3bdfSopenharmony_ci		goto out;
162f08c3bdfSopenharmony_ci	}
163f08c3bdfSopenharmony_ci
164f08c3bdfSopenharmony_ci	if (fdsi.ssi_signo == sig) {
165f08c3bdfSopenharmony_ci		tst_resm(TPASS, "got expected signal");
166f08c3bdfSopenharmony_ci		sfd_for_next = sfd;
167f08c3bdfSopenharmony_ci		goto out;
168f08c3bdfSopenharmony_ci	} else {
169f08c3bdfSopenharmony_ci		tst_resm(TFAIL, "got unexpected signal: signal=%d : %s",
170f08c3bdfSopenharmony_ci			 fdsi.ssi_signo, strsignal(fdsi.ssi_signo));
171f08c3bdfSopenharmony_ci		sfd_for_next = -1;
172f08c3bdfSopenharmony_ci		close(sfd);
173f08c3bdfSopenharmony_ci		goto out;
174f08c3bdfSopenharmony_ci	}
175f08c3bdfSopenharmony_ci
176f08c3bdfSopenharmony_ciout:
177f08c3bdfSopenharmony_ci	return sfd_for_next;
178f08c3bdfSopenharmony_ci}
179f08c3bdfSopenharmony_ci
180f08c3bdfSopenharmony_civoid do_test2(int fd, uint32_t sig)
181f08c3bdfSopenharmony_ci{
182f08c3bdfSopenharmony_ci	int sfd;
183f08c3bdfSopenharmony_ci	sigset_t mask;
184f08c3bdfSopenharmony_ci	pid_t pid;
185f08c3bdfSopenharmony_ci	struct signalfd_siginfo fdsi;
186f08c3bdfSopenharmony_ci	ssize_t s;
187f08c3bdfSopenharmony_ci
188f08c3bdfSopenharmony_ci	sigemptyset(&mask);
189f08c3bdfSopenharmony_ci	sigaddset(&mask, sig);
190f08c3bdfSopenharmony_ci	if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
191f08c3bdfSopenharmony_ci		close(fd);
192f08c3bdfSopenharmony_ci		tst_brkm(TBROK, cleanup,
193f08c3bdfSopenharmony_ci			 "sigprocmask() Failed: errno=%d : %s",
194f08c3bdfSopenharmony_ci			 errno, strerror(errno));
195f08c3bdfSopenharmony_ci	}
196f08c3bdfSopenharmony_ci
197f08c3bdfSopenharmony_ci	TEST(signalfd(fd, &mask, 0));
198f08c3bdfSopenharmony_ci
199f08c3bdfSopenharmony_ci	if ((sfd = TEST_RETURN) == -1) {
200f08c3bdfSopenharmony_ci		tst_resm(TFAIL,
201f08c3bdfSopenharmony_ci			 "reassignment the file descriptor by signalfd() failed, errno=%d : %s",
202f08c3bdfSopenharmony_ci			 TEST_ERRNO, strerror(TEST_ERRNO));
203f08c3bdfSopenharmony_ci		return;
204f08c3bdfSopenharmony_ci	} else if (sfd != fd) {
205f08c3bdfSopenharmony_ci		tst_resm(TFAIL,
206f08c3bdfSopenharmony_ci			 "different fd is returned in reassignment: expected-fd=%d, actual-fd=%d",
207f08c3bdfSopenharmony_ci			 fd, sfd);
208f08c3bdfSopenharmony_ci		close(sfd);
209f08c3bdfSopenharmony_ci		return;
210f08c3bdfSopenharmony_ci
211f08c3bdfSopenharmony_ci	} else {
212f08c3bdfSopenharmony_ci		tst_resm(TPASS, "signalfd is successfully reassigned");
213f08c3bdfSopenharmony_ci		goto out;
214f08c3bdfSopenharmony_ci	}
215f08c3bdfSopenharmony_ci
216f08c3bdfSopenharmony_ci	pid = getpid();
217f08c3bdfSopenharmony_ci	if (kill(pid, sig) == -1) {
218f08c3bdfSopenharmony_ci		close(sfd);
219f08c3bdfSopenharmony_ci		tst_brkm(TBROK, cleanup,
220f08c3bdfSopenharmony_ci			 "kill(self, %s) failed: errno=%d : %s",
221f08c3bdfSopenharmony_ci			 strsignal(sig), errno, strerror(errno));
222f08c3bdfSopenharmony_ci	}
223f08c3bdfSopenharmony_ci
224f08c3bdfSopenharmony_ci	s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
225f08c3bdfSopenharmony_ci	if ((s > 0) && (s != sizeof(struct signalfd_siginfo))) {
226f08c3bdfSopenharmony_ci		tst_resm(TFAIL,
227f08c3bdfSopenharmony_ci			 "getting incomplete signalfd_siginfo data: "
228f08c3bdfSopenharmony_ci			 "actual-size=%zd, expected-size= %zu",
229f08c3bdfSopenharmony_ci			 s, sizeof(struct signalfd_siginfo));
230f08c3bdfSopenharmony_ci		goto out;
231f08c3bdfSopenharmony_ci	} else if (s < 0) {
232f08c3bdfSopenharmony_ci		if (errno == EAGAIN) {
233f08c3bdfSopenharmony_ci			tst_resm(TFAIL,
234f08c3bdfSopenharmony_ci				 "signalfd_siginfo data is not delivered yet");
235f08c3bdfSopenharmony_ci			goto out;
236f08c3bdfSopenharmony_ci		} else {
237f08c3bdfSopenharmony_ci			close(sfd);
238f08c3bdfSopenharmony_ci			tst_brkm(TBROK, cleanup,
239f08c3bdfSopenharmony_ci				 "read signalfd_siginfo data failed: errno=%d : %s",
240f08c3bdfSopenharmony_ci				 errno, strerror(errno));
241f08c3bdfSopenharmony_ci		}
242f08c3bdfSopenharmony_ci	} else if (s == 0) {
243f08c3bdfSopenharmony_ci		tst_resm(TFAIL, "got EOF unexpectedly");
244f08c3bdfSopenharmony_ci		goto out;
245f08c3bdfSopenharmony_ci	}
246f08c3bdfSopenharmony_ci
247f08c3bdfSopenharmony_ci	if (fdsi.ssi_signo == sig) {
248f08c3bdfSopenharmony_ci		tst_resm(TPASS, "got expected signal");
249f08c3bdfSopenharmony_ci		goto out;
250f08c3bdfSopenharmony_ci	} else {
251f08c3bdfSopenharmony_ci		tst_resm(TFAIL, "got unexpected signal: signal=%d : %s",
252f08c3bdfSopenharmony_ci			 fdsi.ssi_signo, strsignal(fdsi.ssi_signo));
253f08c3bdfSopenharmony_ci		goto out;
254f08c3bdfSopenharmony_ci	}
255f08c3bdfSopenharmony_ci
256f08c3bdfSopenharmony_ciout:
257f08c3bdfSopenharmony_ci	return;
258f08c3bdfSopenharmony_ci}
259f08c3bdfSopenharmony_ci
260f08c3bdfSopenharmony_ciint main(int argc, char **argv)
261f08c3bdfSopenharmony_ci{
262f08c3bdfSopenharmony_ci	int lc;
263f08c3bdfSopenharmony_ci	int sfd;
264f08c3bdfSopenharmony_ci
265f08c3bdfSopenharmony_ci	tst_parse_opts(argc, argv, NULL, NULL);
266f08c3bdfSopenharmony_ci
267f08c3bdfSopenharmony_ci	setup();
268f08c3bdfSopenharmony_ci	for (lc = 0; TEST_LOOPING(lc); lc++) {
269f08c3bdfSopenharmony_ci		tst_count = 0;
270f08c3bdfSopenharmony_ci
271f08c3bdfSopenharmony_ci		sfd = do_test1(SIGUSR1);
272f08c3bdfSopenharmony_ci		if (sfd < 0)
273f08c3bdfSopenharmony_ci			continue;
274f08c3bdfSopenharmony_ci
275f08c3bdfSopenharmony_ci		do_test2(sfd, SIGUSR2);
276f08c3bdfSopenharmony_ci		close(sfd);
277f08c3bdfSopenharmony_ci	}
278f08c3bdfSopenharmony_ci
279f08c3bdfSopenharmony_ci	cleanup();
280f08c3bdfSopenharmony_ci
281f08c3bdfSopenharmony_ci	tst_exit();
282f08c3bdfSopenharmony_ci}
283f08c3bdfSopenharmony_ci
284f08c3bdfSopenharmony_ci/*
285f08c3bdfSopenharmony_ci * setup() - performs all the ONE TIME setup for this test.
286f08c3bdfSopenharmony_ci */
287f08c3bdfSopenharmony_civoid setup(void)
288f08c3bdfSopenharmony_ci{
289f08c3bdfSopenharmony_ci
290f08c3bdfSopenharmony_ci	TEST_PAUSE;
291f08c3bdfSopenharmony_ci}
292f08c3bdfSopenharmony_ci
293f08c3bdfSopenharmony_ci/*
294f08c3bdfSopenharmony_ci * cleanup() - performs all the ONE TIME cleanup for this test at completion
295f08c3bdfSopenharmony_ci * 	       or premature exit.
296f08c3bdfSopenharmony_ci */
297f08c3bdfSopenharmony_civoid cleanup(void)
298f08c3bdfSopenharmony_ci{
299f08c3bdfSopenharmony_ci
300f08c3bdfSopenharmony_ci}
301f08c3bdfSopenharmony_ci
302f08c3bdfSopenharmony_ci#endif
303