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 "linux_syscall_numbers.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