1 /* 2 * Copyright (c) 2016 Fujitsu Ltd. 3 * Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> 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. 17 */ 18 19 /* 20 * Description: 21 * Basic test for epoll_pwait(2). 22 * 1) epoll_pwait(2) with sigmask argument allows the caller to 23 * safely wait until either a file descriptor becomes ready 24 * or the timeout expires. 25 * 2) epoll_pwait(2) with NULL sigmask argument fails if 26 * interrupted by a signal handler, epoll_pwait(2) should 27 * return -1 and set errno to EINTR. 28 */ 29 30 #include <sys/epoll.h> 31 #include <sys/types.h> 32 #include <unistd.h> 33 #include <string.h> 34 #include <errno.h> 35 36 #include "test.h" 37 #include "epoll_pwait.h" 38 #include "safe_macros.h" 39 40 char *TCID = "epoll_pwait01"; 41 int TST_TOTAL = 2; 42 43 static int epfd, fds[2]; 44 static sigset_t signalset; 45 static struct epoll_event epevs; 46 static struct sigaction sa; 47 48 static void setup(void); 49 static void verify_sigmask(void); 50 static void verify_nonsigmask(void); 51 static void sighandler(int sig LTP_ATTRIBUTE_UNUSED); 52 static void do_test(sigset_t *); 53 static void do_child(void); 54 static void cleanup(void); 55 56 int main(int ac, char **av) 57 { 58 int lc; 59 60 tst_parse_opts(ac, av, NULL, NULL); 61 62 setup(); 63 64 for (lc = 0; TEST_LOOPING(lc); lc++) { 65 tst_count = 0; 66 67 do_test(&signalset); 68 do_test(NULL); 69 } 70 71 cleanup(); 72 tst_exit(); 73 } 74 75 static void setup(void) 76 { 77 if ((tst_kvercmp(2, 6, 19)) < 0) { 78 tst_brkm(TCONF, NULL, "This test can only run on kernels " 79 "that are 2.6.19 or higher"); 80 } 81 82 tst_sig(FORK, DEF_HANDLER, cleanup); 83 84 TEST_PAUSE; 85 86 if (sigemptyset(&signalset) == -1) 87 tst_brkm(TFAIL | TERRNO, NULL, "sigemptyset() failed"); 88 89 if (sigaddset(&signalset, SIGUSR1) == -1) 90 tst_brkm(TFAIL | TERRNO, NULL, "sigaddset() failed"); 91 92 sa.sa_flags = 0; 93 sa.sa_handler = sighandler; 94 if (sigemptyset(&sa.sa_mask) == -1) 95 tst_brkm(TFAIL | TERRNO, NULL, "sigemptyset() failed"); 96 97 if (sigaction(SIGUSR1, &sa, NULL) == -1) 98 tst_brkm(TFAIL | TERRNO, NULL, "sigaction() failed"); 99 100 SAFE_PIPE(NULL, fds); 101 102 epfd = epoll_create(1); 103 if (epfd == -1) { 104 tst_brkm(TBROK | TERRNO, cleanup, 105 "failed to create epoll instance"); 106 } 107 108 epevs.events = EPOLLIN; 109 epevs.data.fd = fds[0]; 110 111 if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[0], &epevs) == -1) { 112 tst_brkm(TBROK | TERRNO, cleanup, 113 "failed to register epoll target"); 114 } 115 } 116 117 static void verify_sigmask(void) 118 { 119 if (TEST_RETURN == -1) { 120 tst_resm(TFAIL | TTERRNO, "epoll_pwait() failed"); 121 return; 122 } 123 124 if (TEST_RETURN != 0) { 125 tst_resm(TFAIL, "epoll_pwait() returned %li, expected 0", 126 TEST_RETURN); 127 return; 128 } 129 130 tst_resm(TPASS, "epoll_pwait(sigmask) blocked signal"); 131 } 132 133 static void verify_nonsigmask(void) 134 { 135 if (TEST_RETURN != -1) { 136 tst_resm(TFAIL, "epoll_wait() succeeded unexpectedly"); 137 return; 138 } 139 140 if (TEST_ERRNO == EINTR) { 141 tst_resm(TPASS | TTERRNO, "epoll_wait() failed as expected"); 142 } else { 143 tst_resm(TFAIL | TTERRNO, "epoll_wait() failed unexpectedly, " 144 "expected EINTR"); 145 } 146 } 147 148 static void sighandler(int sig LTP_ATTRIBUTE_UNUSED) 149 { 150 151 } 152 153 static void do_test(sigset_t *sigmask) 154 { 155 pid_t cpid; 156 157 cpid = tst_fork(); 158 if (cpid < 0) 159 tst_brkm(TBROK | TERRNO, cleanup, "fork() failed"); 160 161 if (cpid == 0) 162 do_child(); 163 164 TEST(epoll_pwait(epfd, &epevs, 1, 100, sigmask)); 165 166 if (sigmask != NULL) 167 verify_sigmask(); 168 else 169 verify_nonsigmask(); 170 171 tst_record_childstatus(cleanup, cpid); 172 } 173 174 static void do_child(void) 175 { 176 if (tst_process_state_wait2(getppid(), 'S') != 0) { 177 tst_brkm(TBROK | TERRNO, cleanup, 178 "failed to wait for parent process's state"); 179 } 180 181 SAFE_KILL(cleanup, getppid(), SIGUSR1); 182 183 cleanup(); 184 tst_exit(); 185 } 186 187 static void cleanup(void) 188 { 189 if (epfd > 0 && close(epfd)) 190 tst_resm(TWARN | TERRNO, "failed to close epfd"); 191 192 if (close(fds[0])) 193 tst_resm(TWARN | TERRNO, "close(fds[0]) failed"); 194 195 if (close(fds[1])) 196 tst_resm(TWARN | TERRNO, "close(fds[1]) failed"); 197 } 198