Home | History | Annotate | Download | only in signalfd
      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 (at) 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
     79 int main(int argc, char **argv)
     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"
     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 
     97 int do_test1(int ntst, int 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=%" PRId32 ", expected-size=%" PRId32,
    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 
    190 void do_test2(int ntst, int fd, int 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=%" PRId32 ", expected-size= %" PRId32,
    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 
    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(lc, SIGUSR1);
    289 		if (sfd < 0)
    290 			continue;
    291 
    292 		do_test2(lc, 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  */
    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  */
    314 void cleanup(void)
    315 {
    316 
    317 }
    318 
    319 #endif
    320