1*663afb9bSAndroid Build Coastguard Worker /* $OpenBSD: poll.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
2*663afb9bSAndroid Build Coastguard Worker
3*663afb9bSAndroid Build Coastguard Worker /*
4*663afb9bSAndroid Build Coastguard Worker * Copyright 2000-2007 Niels Provos <[email protected]>
5*663afb9bSAndroid Build Coastguard Worker * Copyright 2007-2012 Niels Provos and Nick Mathewson
6*663afb9bSAndroid Build Coastguard Worker *
7*663afb9bSAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
8*663afb9bSAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions
9*663afb9bSAndroid Build Coastguard Worker * are met:
10*663afb9bSAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright
11*663afb9bSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
12*663afb9bSAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright
13*663afb9bSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the
14*663afb9bSAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution.
15*663afb9bSAndroid Build Coastguard Worker * 3. The name of the author may not be used to endorse or promote products
16*663afb9bSAndroid Build Coastguard Worker * derived from this software without specific prior written permission.
17*663afb9bSAndroid Build Coastguard Worker *
18*663afb9bSAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19*663afb9bSAndroid Build Coastguard Worker * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20*663afb9bSAndroid Build Coastguard Worker * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21*663afb9bSAndroid Build Coastguard Worker * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22*663afb9bSAndroid Build Coastguard Worker * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23*663afb9bSAndroid Build Coastguard Worker * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*663afb9bSAndroid Build Coastguard Worker * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*663afb9bSAndroid Build Coastguard Worker * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*663afb9bSAndroid Build Coastguard Worker * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27*663afb9bSAndroid Build Coastguard Worker * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*663afb9bSAndroid Build Coastguard Worker */
29*663afb9bSAndroid Build Coastguard Worker #include "event2/event-config.h"
30*663afb9bSAndroid Build Coastguard Worker #include "evconfig-private.h"
31*663afb9bSAndroid Build Coastguard Worker
32*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_POLL
33*663afb9bSAndroid Build Coastguard Worker
34*663afb9bSAndroid Build Coastguard Worker #include <sys/types.h>
35*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_SYS_TIME_H
36*663afb9bSAndroid Build Coastguard Worker #include <sys/time.h>
37*663afb9bSAndroid Build Coastguard Worker #endif
38*663afb9bSAndroid Build Coastguard Worker #include <sys/queue.h>
39*663afb9bSAndroid Build Coastguard Worker #include <poll.h>
40*663afb9bSAndroid Build Coastguard Worker #include <signal.h>
41*663afb9bSAndroid Build Coastguard Worker #include <limits.h>
42*663afb9bSAndroid Build Coastguard Worker #include <stdio.h>
43*663afb9bSAndroid Build Coastguard Worker #include <stdlib.h>
44*663afb9bSAndroid Build Coastguard Worker #include <string.h>
45*663afb9bSAndroid Build Coastguard Worker #include <unistd.h>
46*663afb9bSAndroid Build Coastguard Worker #include <errno.h>
47*663afb9bSAndroid Build Coastguard Worker
48*663afb9bSAndroid Build Coastguard Worker #include "event-internal.h"
49*663afb9bSAndroid Build Coastguard Worker #include "evsignal-internal.h"
50*663afb9bSAndroid Build Coastguard Worker #include "log-internal.h"
51*663afb9bSAndroid Build Coastguard Worker #include "evmap-internal.h"
52*663afb9bSAndroid Build Coastguard Worker #include "event2/thread.h"
53*663afb9bSAndroid Build Coastguard Worker #include "evthread-internal.h"
54*663afb9bSAndroid Build Coastguard Worker #include "time-internal.h"
55*663afb9bSAndroid Build Coastguard Worker
56*663afb9bSAndroid Build Coastguard Worker /* Since Linux 2.6.17, poll is able to report about peer half-closed connection
57*663afb9bSAndroid Build Coastguard Worker using special POLLRDHUP flag on a read event.
58*663afb9bSAndroid Build Coastguard Worker */
59*663afb9bSAndroid Build Coastguard Worker #if !defined(POLLRDHUP)
60*663afb9bSAndroid Build Coastguard Worker #define POLLRDHUP 0
61*663afb9bSAndroid Build Coastguard Worker #define EARLY_CLOSE_IF_HAVE_RDHUP 0
62*663afb9bSAndroid Build Coastguard Worker #else
63*663afb9bSAndroid Build Coastguard Worker #define EARLY_CLOSE_IF_HAVE_RDHUP EV_FEATURE_EARLY_CLOSE
64*663afb9bSAndroid Build Coastguard Worker #endif
65*663afb9bSAndroid Build Coastguard Worker
66*663afb9bSAndroid Build Coastguard Worker
67*663afb9bSAndroid Build Coastguard Worker struct pollidx {
68*663afb9bSAndroid Build Coastguard Worker int idxplus1;
69*663afb9bSAndroid Build Coastguard Worker };
70*663afb9bSAndroid Build Coastguard Worker
71*663afb9bSAndroid Build Coastguard Worker struct pollop {
72*663afb9bSAndroid Build Coastguard Worker int event_count; /* Highest number alloc */
73*663afb9bSAndroid Build Coastguard Worker int nfds; /* Highest number used */
74*663afb9bSAndroid Build Coastguard Worker int realloc_copy; /* True iff we must realloc
75*663afb9bSAndroid Build Coastguard Worker * event_set_copy */
76*663afb9bSAndroid Build Coastguard Worker struct pollfd *event_set;
77*663afb9bSAndroid Build Coastguard Worker struct pollfd *event_set_copy;
78*663afb9bSAndroid Build Coastguard Worker };
79*663afb9bSAndroid Build Coastguard Worker
80*663afb9bSAndroid Build Coastguard Worker static void *poll_init(struct event_base *);
81*663afb9bSAndroid Build Coastguard Worker static int poll_add(struct event_base *, int, short old, short events, void *idx);
82*663afb9bSAndroid Build Coastguard Worker static int poll_del(struct event_base *, int, short old, short events, void *idx);
83*663afb9bSAndroid Build Coastguard Worker static int poll_dispatch(struct event_base *, struct timeval *);
84*663afb9bSAndroid Build Coastguard Worker static void poll_dealloc(struct event_base *);
85*663afb9bSAndroid Build Coastguard Worker
86*663afb9bSAndroid Build Coastguard Worker const struct eventop pollops = {
87*663afb9bSAndroid Build Coastguard Worker "poll",
88*663afb9bSAndroid Build Coastguard Worker poll_init,
89*663afb9bSAndroid Build Coastguard Worker poll_add,
90*663afb9bSAndroid Build Coastguard Worker poll_del,
91*663afb9bSAndroid Build Coastguard Worker poll_dispatch,
92*663afb9bSAndroid Build Coastguard Worker poll_dealloc,
93*663afb9bSAndroid Build Coastguard Worker 1, /* need_reinit */
94*663afb9bSAndroid Build Coastguard Worker EV_FEATURE_FDS|EARLY_CLOSE_IF_HAVE_RDHUP,
95*663afb9bSAndroid Build Coastguard Worker sizeof(struct pollidx),
96*663afb9bSAndroid Build Coastguard Worker };
97*663afb9bSAndroid Build Coastguard Worker
98*663afb9bSAndroid Build Coastguard Worker static void *
poll_init(struct event_base * base)99*663afb9bSAndroid Build Coastguard Worker poll_init(struct event_base *base)
100*663afb9bSAndroid Build Coastguard Worker {
101*663afb9bSAndroid Build Coastguard Worker struct pollop *pollop;
102*663afb9bSAndroid Build Coastguard Worker
103*663afb9bSAndroid Build Coastguard Worker if (!(pollop = mm_calloc(1, sizeof(struct pollop))))
104*663afb9bSAndroid Build Coastguard Worker return (NULL);
105*663afb9bSAndroid Build Coastguard Worker
106*663afb9bSAndroid Build Coastguard Worker evsig_init_(base);
107*663afb9bSAndroid Build Coastguard Worker
108*663afb9bSAndroid Build Coastguard Worker evutil_weakrand_seed_(&base->weakrand_seed, 0);
109*663afb9bSAndroid Build Coastguard Worker
110*663afb9bSAndroid Build Coastguard Worker return (pollop);
111*663afb9bSAndroid Build Coastguard Worker }
112*663afb9bSAndroid Build Coastguard Worker
113*663afb9bSAndroid Build Coastguard Worker #ifdef CHECK_INVARIANTS
114*663afb9bSAndroid Build Coastguard Worker static void
poll_check_ok(struct pollop * pop)115*663afb9bSAndroid Build Coastguard Worker poll_check_ok(struct pollop *pop)
116*663afb9bSAndroid Build Coastguard Worker {
117*663afb9bSAndroid Build Coastguard Worker int i, idx;
118*663afb9bSAndroid Build Coastguard Worker struct event *ev;
119*663afb9bSAndroid Build Coastguard Worker
120*663afb9bSAndroid Build Coastguard Worker for (i = 0; i < pop->fd_count; ++i) {
121*663afb9bSAndroid Build Coastguard Worker idx = pop->idxplus1_by_fd[i]-1;
122*663afb9bSAndroid Build Coastguard Worker if (idx < 0)
123*663afb9bSAndroid Build Coastguard Worker continue;
124*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(pop->event_set[idx].fd == i);
125*663afb9bSAndroid Build Coastguard Worker }
126*663afb9bSAndroid Build Coastguard Worker for (i = 0; i < pop->nfds; ++i) {
127*663afb9bSAndroid Build Coastguard Worker struct pollfd *pfd = &pop->event_set[i];
128*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(pop->idxplus1_by_fd[pfd->fd] == i+1);
129*663afb9bSAndroid Build Coastguard Worker }
130*663afb9bSAndroid Build Coastguard Worker }
131*663afb9bSAndroid Build Coastguard Worker #else
132*663afb9bSAndroid Build Coastguard Worker #define poll_check_ok(pop)
133*663afb9bSAndroid Build Coastguard Worker #endif
134*663afb9bSAndroid Build Coastguard Worker
135*663afb9bSAndroid Build Coastguard Worker static int
poll_dispatch(struct event_base * base,struct timeval * tv)136*663afb9bSAndroid Build Coastguard Worker poll_dispatch(struct event_base *base, struct timeval *tv)
137*663afb9bSAndroid Build Coastguard Worker {
138*663afb9bSAndroid Build Coastguard Worker int res, i, j, nfds;
139*663afb9bSAndroid Build Coastguard Worker long msec = -1;
140*663afb9bSAndroid Build Coastguard Worker struct pollop *pop = base->evbase;
141*663afb9bSAndroid Build Coastguard Worker struct pollfd *event_set;
142*663afb9bSAndroid Build Coastguard Worker
143*663afb9bSAndroid Build Coastguard Worker poll_check_ok(pop);
144*663afb9bSAndroid Build Coastguard Worker
145*663afb9bSAndroid Build Coastguard Worker nfds = pop->nfds;
146*663afb9bSAndroid Build Coastguard Worker
147*663afb9bSAndroid Build Coastguard Worker #ifndef EVENT__DISABLE_THREAD_SUPPORT
148*663afb9bSAndroid Build Coastguard Worker if (base->th_base_lock) {
149*663afb9bSAndroid Build Coastguard Worker /* If we're using this backend in a multithreaded setting,
150*663afb9bSAndroid Build Coastguard Worker * then we need to work on a copy of event_set, so that we can
151*663afb9bSAndroid Build Coastguard Worker * let other threads modify the main event_set while we're
152*663afb9bSAndroid Build Coastguard Worker * polling. If we're not multithreaded, then we'll skip the
153*663afb9bSAndroid Build Coastguard Worker * copy step here to save memory and time. */
154*663afb9bSAndroid Build Coastguard Worker if (pop->realloc_copy) {
155*663afb9bSAndroid Build Coastguard Worker struct pollfd *tmp = mm_realloc(pop->event_set_copy,
156*663afb9bSAndroid Build Coastguard Worker pop->event_count * sizeof(struct pollfd));
157*663afb9bSAndroid Build Coastguard Worker if (tmp == NULL) {
158*663afb9bSAndroid Build Coastguard Worker event_warn("realloc");
159*663afb9bSAndroid Build Coastguard Worker return -1;
160*663afb9bSAndroid Build Coastguard Worker }
161*663afb9bSAndroid Build Coastguard Worker pop->event_set_copy = tmp;
162*663afb9bSAndroid Build Coastguard Worker pop->realloc_copy = 0;
163*663afb9bSAndroid Build Coastguard Worker }
164*663afb9bSAndroid Build Coastguard Worker memcpy(pop->event_set_copy, pop->event_set,
165*663afb9bSAndroid Build Coastguard Worker sizeof(struct pollfd)*nfds);
166*663afb9bSAndroid Build Coastguard Worker event_set = pop->event_set_copy;
167*663afb9bSAndroid Build Coastguard Worker } else {
168*663afb9bSAndroid Build Coastguard Worker event_set = pop->event_set;
169*663afb9bSAndroid Build Coastguard Worker }
170*663afb9bSAndroid Build Coastguard Worker #else
171*663afb9bSAndroid Build Coastguard Worker event_set = pop->event_set;
172*663afb9bSAndroid Build Coastguard Worker #endif
173*663afb9bSAndroid Build Coastguard Worker
174*663afb9bSAndroid Build Coastguard Worker if (tv != NULL) {
175*663afb9bSAndroid Build Coastguard Worker msec = evutil_tv_to_msec_(tv);
176*663afb9bSAndroid Build Coastguard Worker if (msec < 0 || msec > INT_MAX)
177*663afb9bSAndroid Build Coastguard Worker msec = INT_MAX;
178*663afb9bSAndroid Build Coastguard Worker }
179*663afb9bSAndroid Build Coastguard Worker
180*663afb9bSAndroid Build Coastguard Worker EVBASE_RELEASE_LOCK(base, th_base_lock);
181*663afb9bSAndroid Build Coastguard Worker
182*663afb9bSAndroid Build Coastguard Worker res = poll(event_set, nfds, msec);
183*663afb9bSAndroid Build Coastguard Worker
184*663afb9bSAndroid Build Coastguard Worker EVBASE_ACQUIRE_LOCK(base, th_base_lock);
185*663afb9bSAndroid Build Coastguard Worker
186*663afb9bSAndroid Build Coastguard Worker if (res == -1) {
187*663afb9bSAndroid Build Coastguard Worker if (errno != EINTR) {
188*663afb9bSAndroid Build Coastguard Worker event_warn("poll");
189*663afb9bSAndroid Build Coastguard Worker return (-1);
190*663afb9bSAndroid Build Coastguard Worker }
191*663afb9bSAndroid Build Coastguard Worker
192*663afb9bSAndroid Build Coastguard Worker return (0);
193*663afb9bSAndroid Build Coastguard Worker }
194*663afb9bSAndroid Build Coastguard Worker
195*663afb9bSAndroid Build Coastguard Worker event_debug(("%s: poll reports %d", __func__, res));
196*663afb9bSAndroid Build Coastguard Worker
197*663afb9bSAndroid Build Coastguard Worker if (res == 0 || nfds == 0)
198*663afb9bSAndroid Build Coastguard Worker return (0);
199*663afb9bSAndroid Build Coastguard Worker
200*663afb9bSAndroid Build Coastguard Worker i = evutil_weakrand_range_(&base->weakrand_seed, nfds);
201*663afb9bSAndroid Build Coastguard Worker for (j = 0; j < nfds; j++) {
202*663afb9bSAndroid Build Coastguard Worker int what;
203*663afb9bSAndroid Build Coastguard Worker if (++i == nfds)
204*663afb9bSAndroid Build Coastguard Worker i = 0;
205*663afb9bSAndroid Build Coastguard Worker what = event_set[i].revents;
206*663afb9bSAndroid Build Coastguard Worker if (!what)
207*663afb9bSAndroid Build Coastguard Worker continue;
208*663afb9bSAndroid Build Coastguard Worker
209*663afb9bSAndroid Build Coastguard Worker res = 0;
210*663afb9bSAndroid Build Coastguard Worker
211*663afb9bSAndroid Build Coastguard Worker /* If the file gets closed notify */
212*663afb9bSAndroid Build Coastguard Worker if (what & (POLLHUP|POLLERR|POLLNVAL))
213*663afb9bSAndroid Build Coastguard Worker what |= POLLIN|POLLOUT;
214*663afb9bSAndroid Build Coastguard Worker if (what & POLLIN)
215*663afb9bSAndroid Build Coastguard Worker res |= EV_READ;
216*663afb9bSAndroid Build Coastguard Worker if (what & POLLOUT)
217*663afb9bSAndroid Build Coastguard Worker res |= EV_WRITE;
218*663afb9bSAndroid Build Coastguard Worker if (what & POLLRDHUP)
219*663afb9bSAndroid Build Coastguard Worker res |= EV_CLOSED;
220*663afb9bSAndroid Build Coastguard Worker if (res == 0)
221*663afb9bSAndroid Build Coastguard Worker continue;
222*663afb9bSAndroid Build Coastguard Worker
223*663afb9bSAndroid Build Coastguard Worker evmap_io_active_(base, event_set[i].fd, res);
224*663afb9bSAndroid Build Coastguard Worker }
225*663afb9bSAndroid Build Coastguard Worker
226*663afb9bSAndroid Build Coastguard Worker return (0);
227*663afb9bSAndroid Build Coastguard Worker }
228*663afb9bSAndroid Build Coastguard Worker
229*663afb9bSAndroid Build Coastguard Worker static int
poll_add(struct event_base * base,int fd,short old,short events,void * idx_)230*663afb9bSAndroid Build Coastguard Worker poll_add(struct event_base *base, int fd, short old, short events, void *idx_)
231*663afb9bSAndroid Build Coastguard Worker {
232*663afb9bSAndroid Build Coastguard Worker struct pollop *pop = base->evbase;
233*663afb9bSAndroid Build Coastguard Worker struct pollfd *pfd = NULL;
234*663afb9bSAndroid Build Coastguard Worker struct pollidx *idx = idx_;
235*663afb9bSAndroid Build Coastguard Worker int i;
236*663afb9bSAndroid Build Coastguard Worker
237*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT((events & EV_SIGNAL) == 0);
238*663afb9bSAndroid Build Coastguard Worker if (!(events & (EV_READ|EV_WRITE|EV_CLOSED)))
239*663afb9bSAndroid Build Coastguard Worker return (0);
240*663afb9bSAndroid Build Coastguard Worker
241*663afb9bSAndroid Build Coastguard Worker poll_check_ok(pop);
242*663afb9bSAndroid Build Coastguard Worker if (pop->nfds + 1 >= pop->event_count) {
243*663afb9bSAndroid Build Coastguard Worker struct pollfd *tmp_event_set;
244*663afb9bSAndroid Build Coastguard Worker int tmp_event_count;
245*663afb9bSAndroid Build Coastguard Worker
246*663afb9bSAndroid Build Coastguard Worker if (pop->event_count < 32)
247*663afb9bSAndroid Build Coastguard Worker tmp_event_count = 32;
248*663afb9bSAndroid Build Coastguard Worker else
249*663afb9bSAndroid Build Coastguard Worker tmp_event_count = pop->event_count * 2;
250*663afb9bSAndroid Build Coastguard Worker
251*663afb9bSAndroid Build Coastguard Worker /* We need more file descriptors */
252*663afb9bSAndroid Build Coastguard Worker tmp_event_set = mm_realloc(pop->event_set,
253*663afb9bSAndroid Build Coastguard Worker tmp_event_count * sizeof(struct pollfd));
254*663afb9bSAndroid Build Coastguard Worker if (tmp_event_set == NULL) {
255*663afb9bSAndroid Build Coastguard Worker event_warn("realloc");
256*663afb9bSAndroid Build Coastguard Worker return (-1);
257*663afb9bSAndroid Build Coastguard Worker }
258*663afb9bSAndroid Build Coastguard Worker pop->event_set = tmp_event_set;
259*663afb9bSAndroid Build Coastguard Worker
260*663afb9bSAndroid Build Coastguard Worker pop->event_count = tmp_event_count;
261*663afb9bSAndroid Build Coastguard Worker pop->realloc_copy = 1;
262*663afb9bSAndroid Build Coastguard Worker }
263*663afb9bSAndroid Build Coastguard Worker
264*663afb9bSAndroid Build Coastguard Worker i = idx->idxplus1 - 1;
265*663afb9bSAndroid Build Coastguard Worker
266*663afb9bSAndroid Build Coastguard Worker if (i >= 0) {
267*663afb9bSAndroid Build Coastguard Worker pfd = &pop->event_set[i];
268*663afb9bSAndroid Build Coastguard Worker } else {
269*663afb9bSAndroid Build Coastguard Worker i = pop->nfds++;
270*663afb9bSAndroid Build Coastguard Worker pfd = &pop->event_set[i];
271*663afb9bSAndroid Build Coastguard Worker pfd->events = 0;
272*663afb9bSAndroid Build Coastguard Worker pfd->fd = fd;
273*663afb9bSAndroid Build Coastguard Worker idx->idxplus1 = i + 1;
274*663afb9bSAndroid Build Coastguard Worker }
275*663afb9bSAndroid Build Coastguard Worker
276*663afb9bSAndroid Build Coastguard Worker pfd->revents = 0;
277*663afb9bSAndroid Build Coastguard Worker if (events & EV_WRITE)
278*663afb9bSAndroid Build Coastguard Worker pfd->events |= POLLOUT;
279*663afb9bSAndroid Build Coastguard Worker if (events & EV_READ)
280*663afb9bSAndroid Build Coastguard Worker pfd->events |= POLLIN;
281*663afb9bSAndroid Build Coastguard Worker if (events & EV_CLOSED)
282*663afb9bSAndroid Build Coastguard Worker pfd->events |= POLLRDHUP;
283*663afb9bSAndroid Build Coastguard Worker poll_check_ok(pop);
284*663afb9bSAndroid Build Coastguard Worker
285*663afb9bSAndroid Build Coastguard Worker return (0);
286*663afb9bSAndroid Build Coastguard Worker }
287*663afb9bSAndroid Build Coastguard Worker
288*663afb9bSAndroid Build Coastguard Worker /*
289*663afb9bSAndroid Build Coastguard Worker * Nothing to be done here.
290*663afb9bSAndroid Build Coastguard Worker */
291*663afb9bSAndroid Build Coastguard Worker
292*663afb9bSAndroid Build Coastguard Worker static int
poll_del(struct event_base * base,int fd,short old,short events,void * idx_)293*663afb9bSAndroid Build Coastguard Worker poll_del(struct event_base *base, int fd, short old, short events, void *idx_)
294*663afb9bSAndroid Build Coastguard Worker {
295*663afb9bSAndroid Build Coastguard Worker struct pollop *pop = base->evbase;
296*663afb9bSAndroid Build Coastguard Worker struct pollfd *pfd = NULL;
297*663afb9bSAndroid Build Coastguard Worker struct pollidx *idx = idx_;
298*663afb9bSAndroid Build Coastguard Worker int i;
299*663afb9bSAndroid Build Coastguard Worker
300*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT((events & EV_SIGNAL) == 0);
301*663afb9bSAndroid Build Coastguard Worker if (!(events & (EV_READ|EV_WRITE|EV_CLOSED)))
302*663afb9bSAndroid Build Coastguard Worker return (0);
303*663afb9bSAndroid Build Coastguard Worker
304*663afb9bSAndroid Build Coastguard Worker poll_check_ok(pop);
305*663afb9bSAndroid Build Coastguard Worker i = idx->idxplus1 - 1;
306*663afb9bSAndroid Build Coastguard Worker if (i < 0)
307*663afb9bSAndroid Build Coastguard Worker return (-1);
308*663afb9bSAndroid Build Coastguard Worker
309*663afb9bSAndroid Build Coastguard Worker /* Do we still want to read or write? */
310*663afb9bSAndroid Build Coastguard Worker pfd = &pop->event_set[i];
311*663afb9bSAndroid Build Coastguard Worker if (events & EV_READ)
312*663afb9bSAndroid Build Coastguard Worker pfd->events &= ~POLLIN;
313*663afb9bSAndroid Build Coastguard Worker if (events & EV_WRITE)
314*663afb9bSAndroid Build Coastguard Worker pfd->events &= ~POLLOUT;
315*663afb9bSAndroid Build Coastguard Worker if (events & EV_CLOSED)
316*663afb9bSAndroid Build Coastguard Worker pfd->events &= ~POLLRDHUP;
317*663afb9bSAndroid Build Coastguard Worker poll_check_ok(pop);
318*663afb9bSAndroid Build Coastguard Worker if (pfd->events)
319*663afb9bSAndroid Build Coastguard Worker /* Another event cares about that fd. */
320*663afb9bSAndroid Build Coastguard Worker return (0);
321*663afb9bSAndroid Build Coastguard Worker
322*663afb9bSAndroid Build Coastguard Worker /* Okay, so we aren't interested in that fd anymore. */
323*663afb9bSAndroid Build Coastguard Worker idx->idxplus1 = 0;
324*663afb9bSAndroid Build Coastguard Worker
325*663afb9bSAndroid Build Coastguard Worker --pop->nfds;
326*663afb9bSAndroid Build Coastguard Worker if (i != pop->nfds) {
327*663afb9bSAndroid Build Coastguard Worker /*
328*663afb9bSAndroid Build Coastguard Worker * Shift the last pollfd down into the now-unoccupied
329*663afb9bSAndroid Build Coastguard Worker * position.
330*663afb9bSAndroid Build Coastguard Worker */
331*663afb9bSAndroid Build Coastguard Worker memcpy(&pop->event_set[i], &pop->event_set[pop->nfds],
332*663afb9bSAndroid Build Coastguard Worker sizeof(struct pollfd));
333*663afb9bSAndroid Build Coastguard Worker idx = evmap_io_get_fdinfo_(&base->io, pop->event_set[i].fd);
334*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(idx);
335*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(idx->idxplus1 == pop->nfds + 1);
336*663afb9bSAndroid Build Coastguard Worker idx->idxplus1 = i + 1;
337*663afb9bSAndroid Build Coastguard Worker }
338*663afb9bSAndroid Build Coastguard Worker
339*663afb9bSAndroid Build Coastguard Worker poll_check_ok(pop);
340*663afb9bSAndroid Build Coastguard Worker return (0);
341*663afb9bSAndroid Build Coastguard Worker }
342*663afb9bSAndroid Build Coastguard Worker
343*663afb9bSAndroid Build Coastguard Worker static void
poll_dealloc(struct event_base * base)344*663afb9bSAndroid Build Coastguard Worker poll_dealloc(struct event_base *base)
345*663afb9bSAndroid Build Coastguard Worker {
346*663afb9bSAndroid Build Coastguard Worker struct pollop *pop = base->evbase;
347*663afb9bSAndroid Build Coastguard Worker
348*663afb9bSAndroid Build Coastguard Worker evsig_dealloc_(base);
349*663afb9bSAndroid Build Coastguard Worker if (pop->event_set)
350*663afb9bSAndroid Build Coastguard Worker mm_free(pop->event_set);
351*663afb9bSAndroid Build Coastguard Worker if (pop->event_set_copy)
352*663afb9bSAndroid Build Coastguard Worker mm_free(pop->event_set_copy);
353*663afb9bSAndroid Build Coastguard Worker
354*663afb9bSAndroid Build Coastguard Worker memset(pop, 0, sizeof(struct pollop));
355*663afb9bSAndroid Build Coastguard Worker mm_free(pop);
356*663afb9bSAndroid Build Coastguard Worker }
357*663afb9bSAndroid Build Coastguard Worker
358*663afb9bSAndroid Build Coastguard Worker #endif /* EVENT__HAVE_POLL */
359