1 /* Basic tests for Linux epoll_* wrappers.
2    Copyright (C) 2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library 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 the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <errno.h>
20 #include <intprops.h>
21 #include <support/check.h>
22 #include <support/support.h>
23 #include <support/xsignal.h>
24 #include <support/xunistd.h>
25 #include <support/xtime.h>
26 #include <stdlib.h>
27 #include <sys/epoll.h>
28 
29 /* The test focus on checking if the timeout argument is correctly handled
30    by glibc wrappers.  */
31 
32 static void
handler(int sig)33 handler (int sig)
34 {
35 }
36 
37 typedef int (*epoll_wait_check_t) (int, struct epoll_event *, int,
38 				   int, const sigset_t *);
39 
40 static void
test_epoll_basic(epoll_wait_check_t epoll_wait_check)41 test_epoll_basic (epoll_wait_check_t epoll_wait_check)
42 {
43   {
44     sigset_t ss_usr1;
45     sigemptyset (&ss_usr1);
46     sigaddset (&ss_usr1, SIGUSR1);
47     TEST_COMPARE (sigprocmask (SIG_BLOCK, &ss_usr1, NULL), 0);
48   }
49 
50   int fds[2][2];
51   xpipe (fds[0]);
52   xpipe (fds[1]);
53 
54   sigset_t ss;
55   TEST_COMPARE (sigprocmask (SIG_SETMASK, NULL, &ss), 0);
56   sigdelset (&ss, SIGUSR1);
57 
58   int efd = epoll_create1 (0);
59   TEST_VERIFY_EXIT (efd != -1);
60 
61   struct epoll_event event;
62 
63   event.data.fd = fds[1][0];
64   event.events = EPOLLIN | EPOLLET;
65   TEST_COMPARE (epoll_ctl (efd, EPOLL_CTL_ADD, fds[1][0], &event), 0);
66 
67   pid_t parent = getpid ();
68   pid_t p = xfork ();
69   if (p == 0)
70     {
71       xclose (fds[0][1]);
72       xclose (fds[1][0]);
73 
74       event.data.fd = fds[0][0];
75       event.events = EPOLLIN | EPOLLET;
76       TEST_COMPARE (epoll_ctl (efd, EPOLL_CTL_ADD, fds[0][0], &event), 0);
77 
78       int e;
79       do
80 	{
81 	  if (getppid () != parent)
82 	    FAIL_EXIT1 ("getppid()=%d != parent=%d", getppid(), parent);
83 
84 	  errno = 0;
85 	  e = epoll_wait_check (efd, &event, 1, 500, &ss);
86 	}
87       while (e == 0);
88 
89       TEST_COMPARE (e, -1);
90       TEST_COMPARE (errno, EINTR);
91 
92       TEMP_FAILURE_RETRY (write (fds[1][1], "foo", 3));
93 
94       exit (0);
95     }
96 
97   xclose (fds[0][0]);
98   xclose (fds[1][1]);
99 
100   /* Wait some time so child is blocked on the syscall.  */
101   nanosleep (&(struct timespec) {0, 10000000}, NULL);
102   TEST_COMPARE (kill (p, SIGUSR1), 0);
103 
104   int e = epoll_wait_check (efd, &event, 1, 500000000, &ss);
105   TEST_COMPARE (e, 1);
106   TEST_VERIFY (event.events & EPOLLIN);
107 
108   xclose (fds[0][1]);
109   xclose (fds[1][0]);
110   xclose (efd);
111 }
112 
113 
114 static void
test_epoll_large_timeout(epoll_wait_check_t epoll_wait_check)115 test_epoll_large_timeout (epoll_wait_check_t epoll_wait_check)
116 {
117   timer_t t = support_create_timer (0, 100000000, true, NULL);
118 
119   int fds[2];
120   xpipe (fds);
121 
122   fd_set rfds;
123   FD_ZERO (&rfds);
124   FD_SET (fds[0], &rfds);
125 
126   sigset_t ss;
127   TEST_COMPARE (sigprocmask (SIG_SETMASK, NULL, &ss), 0);
128   sigdelset (&ss, SIGALRM);
129 
130   int efd = epoll_create1 (0);
131   TEST_VERIFY_EXIT (efd != -1);
132 
133   struct epoll_event event;
134   event.data.fd = fds[0];
135   event.events = EPOLLIN | EPOLLET;
136   TEST_COMPARE (epoll_ctl (efd, EPOLL_CTL_ADD, fds[0], &event), 0);
137 
138   int tmo = TYPE_MAXIMUM (int);
139   TEST_COMPARE (epoll_wait_check (efd, &event, 1, tmo, &ss), -1);
140   TEST_VERIFY (errno == EINTR || errno == EOVERFLOW);
141 
142   TEST_COMPARE (epoll_wait_check (efd, &event, 1, -1, &ss), -1);
143   TEST_VERIFY (errno == EINTR || errno == EOVERFLOW);
144 
145   support_delete_timer (t);
146 
147   xclose (fds[0]);
148   xclose (fds[1]);
149   xclose (efd);
150 }
151 
152 
153 static int
epoll_wait_check(int epfd,struct epoll_event * ev,int maxev,int tmo,const sigset_t * ss)154 epoll_wait_check (int epfd, struct epoll_event *ev, int maxev, int tmo,
155 		  const sigset_t *ss)
156 {
157   sigset_t orig;
158   TEST_COMPARE (sigprocmask (SIG_SETMASK, ss, &orig), 0);
159   int r = epoll_wait (epfd, ev, maxev, tmo);
160   TEST_COMPARE (sigprocmask (SIG_SETMASK, &orig, NULL), 0);
161   return r;
162 }
163 
164 static int
epoll_pwait_check(int epfd,struct epoll_event * ev,int maxev,int tmo,const sigset_t * ss)165 epoll_pwait_check (int epfd, struct epoll_event *ev, int maxev, int tmo,
166 		   const sigset_t *ss)
167 {
168   return epoll_pwait (epfd, ev, maxev, tmo, ss);
169 }
170 
171 static int
epoll_pwait2_check(int epfd,struct epoll_event * ev,int maxev,int tmo,const sigset_t * ss)172 epoll_pwait2_check (int epfd, struct epoll_event *ev, int maxev, int tmo,
173 		    const sigset_t *ss)
174 {
175   time_t s = tmo == -1 ? TYPE_MAXIMUM (time_t) : tmo / 1000;
176   long int ns = tmo == -1 ? 0 : (tmo % 1000) * 1000000;
177   return epoll_pwait2 (epfd, ev, maxev, &(struct timespec) { s, ns }, ss);
178 }
179 
180 static int
do_test(void)181 do_test (void)
182 {
183   {
184     struct sigaction sa;
185     sa.sa_handler = handler;
186     sa.sa_flags = 0;
187     sigemptyset (&sa.sa_mask);
188     xsigaction (SIGUSR1, &sa, NULL);
189 
190     sa.sa_handler = SIG_IGN;
191     xsigaction (SIGCHLD, &sa, NULL);
192   }
193 
194   int r = epoll_pwait2 (-1, NULL, 0, NULL, NULL);
195   TEST_COMPARE (r, -1);
196   bool pwait2_supported = errno != ENOSYS;
197 
198   test_epoll_basic (epoll_wait_check);
199   test_epoll_basic (epoll_pwait_check);
200   if (pwait2_supported)
201     test_epoll_basic (epoll_pwait2_check);
202 
203   test_epoll_large_timeout (epoll_wait_check);
204   test_epoll_large_timeout (epoll_pwait_check);
205   if (pwait2_supported)
206     test_epoll_large_timeout (epoll_pwait2_check);
207 
208   return 0;
209 }
210 
211 #include <support/test-driver.c>
212