1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker * Select abstraction functions for the CUPS scheduler.
3*5e7646d2SAndroid Build Coastguard Worker *
4*5e7646d2SAndroid Build Coastguard Worker * Copyright 2007-2016 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker * Copyright 2006-2007 by Easy Software Products.
6*5e7646d2SAndroid Build Coastguard Worker *
7*5e7646d2SAndroid Build Coastguard Worker * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
8*5e7646d2SAndroid Build Coastguard Worker */
9*5e7646d2SAndroid Build Coastguard Worker
10*5e7646d2SAndroid Build Coastguard Worker /*
11*5e7646d2SAndroid Build Coastguard Worker * Include necessary headers...
12*5e7646d2SAndroid Build Coastguard Worker */
13*5e7646d2SAndroid Build Coastguard Worker
14*5e7646d2SAndroid Build Coastguard Worker #include "cupsd.h"
15*5e7646d2SAndroid Build Coastguard Worker
16*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_EPOLL
17*5e7646d2SAndroid Build Coastguard Worker # include <sys/epoll.h>
18*5e7646d2SAndroid Build Coastguard Worker # include <poll.h>
19*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_KQUEUE)
20*5e7646d2SAndroid Build Coastguard Worker # include <sys/event.h>
21*5e7646d2SAndroid Build Coastguard Worker # include <sys/time.h>
22*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_POLL)
23*5e7646d2SAndroid Build Coastguard Worker # include <poll.h>
24*5e7646d2SAndroid Build Coastguard Worker #else
25*5e7646d2SAndroid Build Coastguard Worker # include <sys/select.h>
26*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_EPOLL */
27*5e7646d2SAndroid Build Coastguard Worker
28*5e7646d2SAndroid Build Coastguard Worker
29*5e7646d2SAndroid Build Coastguard Worker /*
30*5e7646d2SAndroid Build Coastguard Worker * Design Notes for Poll/Select API in CUPSD
31*5e7646d2SAndroid Build Coastguard Worker * -----------------------------------------
32*5e7646d2SAndroid Build Coastguard Worker *
33*5e7646d2SAndroid Build Coastguard Worker * SUPPORTED APIS
34*5e7646d2SAndroid Build Coastguard Worker *
35*5e7646d2SAndroid Build Coastguard Worker * OS select poll epoll kqueue /dev/poll
36*5e7646d2SAndroid Build Coastguard Worker * -------------- ------ ------ ------ ------ ---------
37*5e7646d2SAndroid Build Coastguard Worker * AIX YES YES NO NO NO
38*5e7646d2SAndroid Build Coastguard Worker * FreeBSD YES YES NO YES NO
39*5e7646d2SAndroid Build Coastguard Worker * HP-UX YES YES NO NO NO
40*5e7646d2SAndroid Build Coastguard Worker * Linux YES YES YES NO NO
41*5e7646d2SAndroid Build Coastguard Worker * macOS YES YES NO YES NO
42*5e7646d2SAndroid Build Coastguard Worker * NetBSD YES YES NO YES NO
43*5e7646d2SAndroid Build Coastguard Worker * OpenBSD YES YES NO YES NO
44*5e7646d2SAndroid Build Coastguard Worker * Solaris YES YES NO NO YES
45*5e7646d2SAndroid Build Coastguard Worker * Tru64 YES YES NO NO NO
46*5e7646d2SAndroid Build Coastguard Worker * Windows YES NO NO NO NO
47*5e7646d2SAndroid Build Coastguard Worker *
48*5e7646d2SAndroid Build Coastguard Worker *
49*5e7646d2SAndroid Build Coastguard Worker * HIGH-LEVEL API
50*5e7646d2SAndroid Build Coastguard Worker *
51*5e7646d2SAndroid Build Coastguard Worker * typedef void (*cupsd_selfunc_t)(void *data);
52*5e7646d2SAndroid Build Coastguard Worker *
53*5e7646d2SAndroid Build Coastguard Worker * void cupsdStartSelect(void);
54*5e7646d2SAndroid Build Coastguard Worker * void cupsdStopSelect(void);
55*5e7646d2SAndroid Build Coastguard Worker * void cupsdAddSelect(int fd, cupsd_selfunc_t read_cb,
56*5e7646d2SAndroid Build Coastguard Worker * cupsd_selfunc_t write_cb, void *data);
57*5e7646d2SAndroid Build Coastguard Worker * void cupsdRemoveSelect(int fd);
58*5e7646d2SAndroid Build Coastguard Worker * int cupsdDoSelect(int timeout);
59*5e7646d2SAndroid Build Coastguard Worker *
60*5e7646d2SAndroid Build Coastguard Worker *
61*5e7646d2SAndroid Build Coastguard Worker * IMPLEMENTATION STRATEGY
62*5e7646d2SAndroid Build Coastguard Worker *
63*5e7646d2SAndroid Build Coastguard Worker * 0. Common Stuff
64*5e7646d2SAndroid Build Coastguard Worker * a. CUPS array of file descriptor to callback functions
65*5e7646d2SAndroid Build Coastguard Worker * and data + temporary array of removed fd's.
66*5e7646d2SAndroid Build Coastguard Worker * b. cupsdStartSelect() creates the arrays
67*5e7646d2SAndroid Build Coastguard Worker * c. cupsdStopSelect() destroys the arrays and all elements.
68*5e7646d2SAndroid Build Coastguard Worker * d. cupsdAddSelect() adds to the array and allocates a
69*5e7646d2SAndroid Build Coastguard Worker * new callback element.
70*5e7646d2SAndroid Build Coastguard Worker * e. cupsdRemoveSelect() removes from the active array and
71*5e7646d2SAndroid Build Coastguard Worker * adds to the inactive array.
72*5e7646d2SAndroid Build Coastguard Worker * f. _cupsd_fd_t provides a reference-counted structure for
73*5e7646d2SAndroid Build Coastguard Worker * tracking file descriptors that are monitored.
74*5e7646d2SAndroid Build Coastguard Worker * g. cupsdDoSelect() frees all inactive FDs.
75*5e7646d2SAndroid Build Coastguard Worker *
76*5e7646d2SAndroid Build Coastguard Worker * 1. select() O(n)
77*5e7646d2SAndroid Build Coastguard Worker * a. Input/Output fd_set variables, copied to working
78*5e7646d2SAndroid Build Coastguard Worker * copies and then used with select().
79*5e7646d2SAndroid Build Coastguard Worker * b. Loop through CUPS array, using FD_ISSET and calling
80*5e7646d2SAndroid Build Coastguard Worker * the read/write callbacks as needed.
81*5e7646d2SAndroid Build Coastguard Worker * c. cupsdRemoveSelect() clears fd_set bit from main and
82*5e7646d2SAndroid Build Coastguard Worker * working sets.
83*5e7646d2SAndroid Build Coastguard Worker * d. cupsdStopSelect() frees all of the memory used by the
84*5e7646d2SAndroid Build Coastguard Worker * CUPS array and fd_set's.
85*5e7646d2SAndroid Build Coastguard Worker *
86*5e7646d2SAndroid Build Coastguard Worker * 2. poll() - O(n log n)
87*5e7646d2SAndroid Build Coastguard Worker * a. Regular array of pollfd, sorted the same as the CUPS
88*5e7646d2SAndroid Build Coastguard Worker * array.
89*5e7646d2SAndroid Build Coastguard Worker * b. Loop through pollfd array, call the corresponding
90*5e7646d2SAndroid Build Coastguard Worker * read/write callbacks as needed.
91*5e7646d2SAndroid Build Coastguard Worker * c. cupsdAddSelect() adds first to CUPS array and flags the
92*5e7646d2SAndroid Build Coastguard Worker * pollfd array as invalid.
93*5e7646d2SAndroid Build Coastguard Worker * d. cupsdDoSelect() rebuilds pollfd array as needed, calls
94*5e7646d2SAndroid Build Coastguard Worker * poll(), then loops through the pollfd array looking up
95*5e7646d2SAndroid Build Coastguard Worker * as needed.
96*5e7646d2SAndroid Build Coastguard Worker * e. cupsdRemoveSelect() flags the pollfd array as invalid.
97*5e7646d2SAndroid Build Coastguard Worker * f. cupsdStopSelect() frees all of the memory used by the
98*5e7646d2SAndroid Build Coastguard Worker * CUPS array and pollfd array.
99*5e7646d2SAndroid Build Coastguard Worker *
100*5e7646d2SAndroid Build Coastguard Worker * 3. epoll() - O(n)
101*5e7646d2SAndroid Build Coastguard Worker * a. cupsdStartSelect() creates epoll file descriptor using
102*5e7646d2SAndroid Build Coastguard Worker * epoll_create() with the maximum fd count, and
103*5e7646d2SAndroid Build Coastguard Worker * allocates an events buffer for the maximum fd count.
104*5e7646d2SAndroid Build Coastguard Worker * b. cupsdAdd/RemoveSelect() uses epoll_ctl() to add
105*5e7646d2SAndroid Build Coastguard Worker * (EPOLL_CTL_ADD) or remove (EPOLL_CTL_DEL) a single
106*5e7646d2SAndroid Build Coastguard Worker * event using the level-triggered semantics. The event
107*5e7646d2SAndroid Build Coastguard Worker * user data field is a pointer to the new callback array
108*5e7646d2SAndroid Build Coastguard Worker * element.
109*5e7646d2SAndroid Build Coastguard Worker * c. cupsdDoSelect() uses epoll_wait() with the global event
110*5e7646d2SAndroid Build Coastguard Worker * buffer allocated in cupsdStartSelect() and then loops
111*5e7646d2SAndroid Build Coastguard Worker * through the events, using the user data field to find
112*5e7646d2SAndroid Build Coastguard Worker * the callback record.
113*5e7646d2SAndroid Build Coastguard Worker * d. cupsdStopSelect() closes the epoll file descriptor and
114*5e7646d2SAndroid Build Coastguard Worker * frees all of the memory used by the event buffer.
115*5e7646d2SAndroid Build Coastguard Worker *
116*5e7646d2SAndroid Build Coastguard Worker * 4. kqueue() - O(n)
117*5e7646d2SAndroid Build Coastguard Worker * b. cupsdStartSelect() creates kqueue file descriptor
118*5e7646d2SAndroid Build Coastguard Worker * using kqueue() function and allocates a global event
119*5e7646d2SAndroid Build Coastguard Worker * buffer.
120*5e7646d2SAndroid Build Coastguard Worker * c. cupsdAdd/RemoveSelect() uses EV_SET and kevent() to
121*5e7646d2SAndroid Build Coastguard Worker * register the changes. The event user data field is a
122*5e7646d2SAndroid Build Coastguard Worker * pointer to the new callback array element.
123*5e7646d2SAndroid Build Coastguard Worker * d. cupsdDoSelect() uses kevent() to poll for events and
124*5e7646d2SAndroid Build Coastguard Worker * loops through the events, using the user data field to
125*5e7646d2SAndroid Build Coastguard Worker * find the callback record.
126*5e7646d2SAndroid Build Coastguard Worker * e. cupsdStopSelect() closes the kqueue() file descriptor
127*5e7646d2SAndroid Build Coastguard Worker * and frees all of the memory used by the event buffer.
128*5e7646d2SAndroid Build Coastguard Worker *
129*5e7646d2SAndroid Build Coastguard Worker * 5. /dev/poll - O(n log n) - NOT YET IMPLEMENTED
130*5e7646d2SAndroid Build Coastguard Worker * a. cupsdStartSelect() opens /dev/poll and allocates an
131*5e7646d2SAndroid Build Coastguard Worker * array of pollfd structs; on failure to open /dev/poll,
132*5e7646d2SAndroid Build Coastguard Worker * revert to poll() system call.
133*5e7646d2SAndroid Build Coastguard Worker * b. cupsdAddSelect() writes a single pollfd struct to
134*5e7646d2SAndroid Build Coastguard Worker * /dev/poll with the new file descriptor and the
135*5e7646d2SAndroid Build Coastguard Worker * POLLIN/POLLOUT flags.
136*5e7646d2SAndroid Build Coastguard Worker * c. cupsdRemoveSelect() writes a single pollfd struct to
137*5e7646d2SAndroid Build Coastguard Worker * /dev/poll with the file descriptor and the POLLREMOVE
138*5e7646d2SAndroid Build Coastguard Worker * flag.
139*5e7646d2SAndroid Build Coastguard Worker * d. cupsdDoSelect() uses the DP_POLL ioctl to retrieve
140*5e7646d2SAndroid Build Coastguard Worker * events from /dev/poll and then loops through the
141*5e7646d2SAndroid Build Coastguard Worker * returned pollfd array, looking up the file descriptors
142*5e7646d2SAndroid Build Coastguard Worker * as needed.
143*5e7646d2SAndroid Build Coastguard Worker * e. cupsdStopSelect() closes /dev/poll and frees the
144*5e7646d2SAndroid Build Coastguard Worker * pollfd array.
145*5e7646d2SAndroid Build Coastguard Worker *
146*5e7646d2SAndroid Build Coastguard Worker * PERFORMANCE
147*5e7646d2SAndroid Build Coastguard Worker *
148*5e7646d2SAndroid Build Coastguard Worker * In tests using the "make test" target with option 0 (keep cupsd
149*5e7646d2SAndroid Build Coastguard Worker * running) and the "testspeed" program with "-c 50 -r 1000", epoll()
150*5e7646d2SAndroid Build Coastguard Worker * performed 5.5% slower than select(), followed by kqueue() at 16%
151*5e7646d2SAndroid Build Coastguard Worker * slower than select() and poll() at 18% slower than select(). Similar
152*5e7646d2SAndroid Build Coastguard Worker * results were seen with twice the number of client connections.
153*5e7646d2SAndroid Build Coastguard Worker *
154*5e7646d2SAndroid Build Coastguard Worker * The epoll() and kqueue() performance is likely limited by the
155*5e7646d2SAndroid Build Coastguard Worker * number of system calls used to add/modify/remove file
156*5e7646d2SAndroid Build Coastguard Worker * descriptors dynamically. Further optimizations may be possible
157*5e7646d2SAndroid Build Coastguard Worker * in the area of limiting use of cupsdAddSelect() and
158*5e7646d2SAndroid Build Coastguard Worker * cupsdRemoveSelect(), however extreme care will be needed to avoid
159*5e7646d2SAndroid Build Coastguard Worker * excess CPU usage and deadlock conditions.
160*5e7646d2SAndroid Build Coastguard Worker *
161*5e7646d2SAndroid Build Coastguard Worker * We may be able to improve the poll() implementation simply by
162*5e7646d2SAndroid Build Coastguard Worker * keeping the pollfd array sync'd with the _cupsd_fd_t array, as that
163*5e7646d2SAndroid Build Coastguard Worker * will eliminate the rebuilding of the array whenever there is a
164*5e7646d2SAndroid Build Coastguard Worker * change and eliminate the fd array lookups in the inner loop of
165*5e7646d2SAndroid Build Coastguard Worker * cupsdDoSelect().
166*5e7646d2SAndroid Build Coastguard Worker *
167*5e7646d2SAndroid Build Coastguard Worker * Since /dev/poll will never be able to use a shadow array, it may
168*5e7646d2SAndroid Build Coastguard Worker * not make sense to implement support for it. ioctl() overhead will
169*5e7646d2SAndroid Build Coastguard Worker * impact performance as well, so my guess would be that, for CUPS,
170*5e7646d2SAndroid Build Coastguard Worker * /dev/poll will yield a net performance loss.
171*5e7646d2SAndroid Build Coastguard Worker */
172*5e7646d2SAndroid Build Coastguard Worker
173*5e7646d2SAndroid Build Coastguard Worker /*
174*5e7646d2SAndroid Build Coastguard Worker * Local structures...
175*5e7646d2SAndroid Build Coastguard Worker */
176*5e7646d2SAndroid Build Coastguard Worker
177*5e7646d2SAndroid Build Coastguard Worker typedef struct _cupsd_fd_s
178*5e7646d2SAndroid Build Coastguard Worker {
179*5e7646d2SAndroid Build Coastguard Worker int fd, /* File descriptor */
180*5e7646d2SAndroid Build Coastguard Worker use; /* Use count */
181*5e7646d2SAndroid Build Coastguard Worker cupsd_selfunc_t read_cb, /* Read callback */
182*5e7646d2SAndroid Build Coastguard Worker write_cb; /* Write callback */
183*5e7646d2SAndroid Build Coastguard Worker void *data; /* Data pointer for callbacks */
184*5e7646d2SAndroid Build Coastguard Worker } _cupsd_fd_t;
185*5e7646d2SAndroid Build Coastguard Worker
186*5e7646d2SAndroid Build Coastguard Worker
187*5e7646d2SAndroid Build Coastguard Worker /*
188*5e7646d2SAndroid Build Coastguard Worker * Local globals...
189*5e7646d2SAndroid Build Coastguard Worker */
190*5e7646d2SAndroid Build Coastguard Worker
191*5e7646d2SAndroid Build Coastguard Worker static cups_array_t *cupsd_fds = NULL;
192*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_EPOLL) || defined(HAVE_KQUEUE)
193*5e7646d2SAndroid Build Coastguard Worker static cups_array_t *cupsd_inactive_fds = NULL;
194*5e7646d2SAndroid Build Coastguard Worker static int cupsd_in_select = 0;
195*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_EPOLL || HAVE_KQUEUE */
196*5e7646d2SAndroid Build Coastguard Worker
197*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_KQUEUE
198*5e7646d2SAndroid Build Coastguard Worker static int cupsd_kqueue_fd = -1,
199*5e7646d2SAndroid Build Coastguard Worker cupsd_kqueue_changes = 0;
200*5e7646d2SAndroid Build Coastguard Worker static struct kevent *cupsd_kqueue_events = NULL;
201*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_POLL)
202*5e7646d2SAndroid Build Coastguard Worker static int cupsd_alloc_pollfds = 0,
203*5e7646d2SAndroid Build Coastguard Worker cupsd_update_pollfds = 0;
204*5e7646d2SAndroid Build Coastguard Worker static struct pollfd *cupsd_pollfds = NULL;
205*5e7646d2SAndroid Build Coastguard Worker # ifdef HAVE_EPOLL
206*5e7646d2SAndroid Build Coastguard Worker static int cupsd_epoll_fd = -1;
207*5e7646d2SAndroid Build Coastguard Worker static struct epoll_event *cupsd_epoll_events = NULL;
208*5e7646d2SAndroid Build Coastguard Worker # endif /* HAVE_EPOLL */
209*5e7646d2SAndroid Build Coastguard Worker #else /* select() */
210*5e7646d2SAndroid Build Coastguard Worker static fd_set cupsd_global_input,
211*5e7646d2SAndroid Build Coastguard Worker cupsd_global_output,
212*5e7646d2SAndroid Build Coastguard Worker cupsd_current_input,
213*5e7646d2SAndroid Build Coastguard Worker cupsd_current_output;
214*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_KQUEUE */
215*5e7646d2SAndroid Build Coastguard Worker
216*5e7646d2SAndroid Build Coastguard Worker
217*5e7646d2SAndroid Build Coastguard Worker /*
218*5e7646d2SAndroid Build Coastguard Worker * Local functions...
219*5e7646d2SAndroid Build Coastguard Worker */
220*5e7646d2SAndroid Build Coastguard Worker
221*5e7646d2SAndroid Build Coastguard Worker static int compare_fds(_cupsd_fd_t *a, _cupsd_fd_t *b);
222*5e7646d2SAndroid Build Coastguard Worker static _cupsd_fd_t *find_fd(int fd);
223*5e7646d2SAndroid Build Coastguard Worker #define release_fd(f) { \
224*5e7646d2SAndroid Build Coastguard Worker (f)->use --; \
225*5e7646d2SAndroid Build Coastguard Worker if (!(f)->use) free((f));\
226*5e7646d2SAndroid Build Coastguard Worker }
227*5e7646d2SAndroid Build Coastguard Worker #define retain_fd(f) (f)->use++
228*5e7646d2SAndroid Build Coastguard Worker
229*5e7646d2SAndroid Build Coastguard Worker
230*5e7646d2SAndroid Build Coastguard Worker /*
231*5e7646d2SAndroid Build Coastguard Worker * 'cupsdAddSelect()' - Add a file descriptor to the list.
232*5e7646d2SAndroid Build Coastguard Worker */
233*5e7646d2SAndroid Build Coastguard Worker
234*5e7646d2SAndroid Build Coastguard Worker int /* O - 1 on success, 0 on error */
cupsdAddSelect(int fd,cupsd_selfunc_t read_cb,cupsd_selfunc_t write_cb,void * data)235*5e7646d2SAndroid Build Coastguard Worker cupsdAddSelect(int fd, /* I - File descriptor */
236*5e7646d2SAndroid Build Coastguard Worker cupsd_selfunc_t read_cb, /* I - Read callback */
237*5e7646d2SAndroid Build Coastguard Worker cupsd_selfunc_t write_cb,/* I - Write callback */
238*5e7646d2SAndroid Build Coastguard Worker void *data) /* I - Data to pass to callback */
239*5e7646d2SAndroid Build Coastguard Worker {
240*5e7646d2SAndroid Build Coastguard Worker _cupsd_fd_t *fdptr; /* File descriptor record */
241*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_EPOLL
242*5e7646d2SAndroid Build Coastguard Worker int added; /* 1 if added, 0 if modified */
243*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_EPOLL */
244*5e7646d2SAndroid Build Coastguard Worker
245*5e7646d2SAndroid Build Coastguard Worker
246*5e7646d2SAndroid Build Coastguard Worker /*
247*5e7646d2SAndroid Build Coastguard Worker * Range check input...
248*5e7646d2SAndroid Build Coastguard Worker */
249*5e7646d2SAndroid Build Coastguard Worker
250*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2,
251*5e7646d2SAndroid Build Coastguard Worker "cupsdAddSelect(fd=%d, read_cb=%p, write_cb=%p, data=%p)",
252*5e7646d2SAndroid Build Coastguard Worker fd, read_cb, write_cb, data);
253*5e7646d2SAndroid Build Coastguard Worker
254*5e7646d2SAndroid Build Coastguard Worker if (fd < 0)
255*5e7646d2SAndroid Build Coastguard Worker return (0);
256*5e7646d2SAndroid Build Coastguard Worker
257*5e7646d2SAndroid Build Coastguard Worker /*
258*5e7646d2SAndroid Build Coastguard Worker * See if this FD has already been added...
259*5e7646d2SAndroid Build Coastguard Worker */
260*5e7646d2SAndroid Build Coastguard Worker
261*5e7646d2SAndroid Build Coastguard Worker if ((fdptr = find_fd(fd)) == NULL)
262*5e7646d2SAndroid Build Coastguard Worker {
263*5e7646d2SAndroid Build Coastguard Worker /*
264*5e7646d2SAndroid Build Coastguard Worker * No, add a new entry...
265*5e7646d2SAndroid Build Coastguard Worker */
266*5e7646d2SAndroid Build Coastguard Worker
267*5e7646d2SAndroid Build Coastguard Worker if ((fdptr = calloc(1, sizeof(_cupsd_fd_t))) == NULL)
268*5e7646d2SAndroid Build Coastguard Worker return (0);
269*5e7646d2SAndroid Build Coastguard Worker
270*5e7646d2SAndroid Build Coastguard Worker fdptr->fd = fd;
271*5e7646d2SAndroid Build Coastguard Worker fdptr->use = 1;
272*5e7646d2SAndroid Build Coastguard Worker
273*5e7646d2SAndroid Build Coastguard Worker if (!cupsArrayAdd(cupsd_fds, fdptr))
274*5e7646d2SAndroid Build Coastguard Worker {
275*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_EMERG, "Unable to add fd %d to array!", fd);
276*5e7646d2SAndroid Build Coastguard Worker free(fdptr);
277*5e7646d2SAndroid Build Coastguard Worker return (0);
278*5e7646d2SAndroid Build Coastguard Worker }
279*5e7646d2SAndroid Build Coastguard Worker
280*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_EPOLL
281*5e7646d2SAndroid Build Coastguard Worker added = 1;
282*5e7646d2SAndroid Build Coastguard Worker }
283*5e7646d2SAndroid Build Coastguard Worker else
284*5e7646d2SAndroid Build Coastguard Worker added = 0;
285*5e7646d2SAndroid Build Coastguard Worker #else
286*5e7646d2SAndroid Build Coastguard Worker }
287*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_EPOLL */
288*5e7646d2SAndroid Build Coastguard Worker
289*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_KQUEUE
290*5e7646d2SAndroid Build Coastguard Worker {
291*5e7646d2SAndroid Build Coastguard Worker struct kevent event; /* Event data */
292*5e7646d2SAndroid Build Coastguard Worker struct timespec timeout; /* Timeout value */
293*5e7646d2SAndroid Build Coastguard Worker
294*5e7646d2SAndroid Build Coastguard Worker
295*5e7646d2SAndroid Build Coastguard Worker timeout.tv_sec = 0;
296*5e7646d2SAndroid Build Coastguard Worker timeout.tv_nsec = 0;
297*5e7646d2SAndroid Build Coastguard Worker
298*5e7646d2SAndroid Build Coastguard Worker if (fdptr->read_cb != read_cb)
299*5e7646d2SAndroid Build Coastguard Worker {
300*5e7646d2SAndroid Build Coastguard Worker if (read_cb)
301*5e7646d2SAndroid Build Coastguard Worker EV_SET(&event, fd, EVFILT_READ, EV_ADD, 0, 0, fdptr);
302*5e7646d2SAndroid Build Coastguard Worker else
303*5e7646d2SAndroid Build Coastguard Worker EV_SET(&event, fd, EVFILT_READ, EV_DELETE, 0, 0, fdptr);
304*5e7646d2SAndroid Build Coastguard Worker
305*5e7646d2SAndroid Build Coastguard Worker if (kevent(cupsd_kqueue_fd, &event, 1, NULL, 0, &timeout))
306*5e7646d2SAndroid Build Coastguard Worker {
307*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_EMERG, "kevent() returned %s",
308*5e7646d2SAndroid Build Coastguard Worker strerror(errno));
309*5e7646d2SAndroid Build Coastguard Worker return (0);
310*5e7646d2SAndroid Build Coastguard Worker }
311*5e7646d2SAndroid Build Coastguard Worker }
312*5e7646d2SAndroid Build Coastguard Worker
313*5e7646d2SAndroid Build Coastguard Worker if (fdptr->write_cb != write_cb)
314*5e7646d2SAndroid Build Coastguard Worker {
315*5e7646d2SAndroid Build Coastguard Worker if (write_cb)
316*5e7646d2SAndroid Build Coastguard Worker EV_SET(&event, fd, EVFILT_WRITE, EV_ADD, 0, 0, fdptr);
317*5e7646d2SAndroid Build Coastguard Worker else
318*5e7646d2SAndroid Build Coastguard Worker EV_SET(&event, fd, EVFILT_WRITE, EV_DELETE, 0, 0, fdptr);
319*5e7646d2SAndroid Build Coastguard Worker
320*5e7646d2SAndroid Build Coastguard Worker if (kevent(cupsd_kqueue_fd, &event, 1, NULL, 0, &timeout))
321*5e7646d2SAndroid Build Coastguard Worker {
322*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_EMERG, "kevent() returned %s",
323*5e7646d2SAndroid Build Coastguard Worker strerror(errno));
324*5e7646d2SAndroid Build Coastguard Worker return (0);
325*5e7646d2SAndroid Build Coastguard Worker }
326*5e7646d2SAndroid Build Coastguard Worker }
327*5e7646d2SAndroid Build Coastguard Worker }
328*5e7646d2SAndroid Build Coastguard Worker
329*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_POLL)
330*5e7646d2SAndroid Build Coastguard Worker # ifdef HAVE_EPOLL
331*5e7646d2SAndroid Build Coastguard Worker if (cupsd_epoll_fd >= 0)
332*5e7646d2SAndroid Build Coastguard Worker {
333*5e7646d2SAndroid Build Coastguard Worker struct epoll_event event; /* Event data */
334*5e7646d2SAndroid Build Coastguard Worker
335*5e7646d2SAndroid Build Coastguard Worker
336*5e7646d2SAndroid Build Coastguard Worker event.events = 0;
337*5e7646d2SAndroid Build Coastguard Worker
338*5e7646d2SAndroid Build Coastguard Worker if (read_cb)
339*5e7646d2SAndroid Build Coastguard Worker event.events |= EPOLLIN;
340*5e7646d2SAndroid Build Coastguard Worker
341*5e7646d2SAndroid Build Coastguard Worker if (write_cb)
342*5e7646d2SAndroid Build Coastguard Worker event.events |= EPOLLOUT;
343*5e7646d2SAndroid Build Coastguard Worker
344*5e7646d2SAndroid Build Coastguard Worker event.data.ptr = fdptr;
345*5e7646d2SAndroid Build Coastguard Worker
346*5e7646d2SAndroid Build Coastguard Worker if (epoll_ctl(cupsd_epoll_fd, added ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd,
347*5e7646d2SAndroid Build Coastguard Worker &event))
348*5e7646d2SAndroid Build Coastguard Worker {
349*5e7646d2SAndroid Build Coastguard Worker close(cupsd_epoll_fd);
350*5e7646d2SAndroid Build Coastguard Worker cupsd_epoll_fd = -1;
351*5e7646d2SAndroid Build Coastguard Worker cupsd_update_pollfds = 1;
352*5e7646d2SAndroid Build Coastguard Worker }
353*5e7646d2SAndroid Build Coastguard Worker }
354*5e7646d2SAndroid Build Coastguard Worker else
355*5e7646d2SAndroid Build Coastguard Worker # endif /* HAVE_EPOLL */
356*5e7646d2SAndroid Build Coastguard Worker
357*5e7646d2SAndroid Build Coastguard Worker cupsd_update_pollfds = 1;
358*5e7646d2SAndroid Build Coastguard Worker
359*5e7646d2SAndroid Build Coastguard Worker #else /* select() */
360*5e7646d2SAndroid Build Coastguard Worker /*
361*5e7646d2SAndroid Build Coastguard Worker * Add or remove the file descriptor in the input and output sets
362*5e7646d2SAndroid Build Coastguard Worker * for select()...
363*5e7646d2SAndroid Build Coastguard Worker */
364*5e7646d2SAndroid Build Coastguard Worker
365*5e7646d2SAndroid Build Coastguard Worker if (read_cb)
366*5e7646d2SAndroid Build Coastguard Worker FD_SET(fd, &cupsd_global_input);
367*5e7646d2SAndroid Build Coastguard Worker else
368*5e7646d2SAndroid Build Coastguard Worker {
369*5e7646d2SAndroid Build Coastguard Worker FD_CLR(fd, &cupsd_global_input);
370*5e7646d2SAndroid Build Coastguard Worker FD_CLR(fd, &cupsd_current_input);
371*5e7646d2SAndroid Build Coastguard Worker }
372*5e7646d2SAndroid Build Coastguard Worker
373*5e7646d2SAndroid Build Coastguard Worker if (write_cb)
374*5e7646d2SAndroid Build Coastguard Worker FD_SET(fd, &cupsd_global_output);
375*5e7646d2SAndroid Build Coastguard Worker else
376*5e7646d2SAndroid Build Coastguard Worker {
377*5e7646d2SAndroid Build Coastguard Worker FD_CLR(fd, &cupsd_global_output);
378*5e7646d2SAndroid Build Coastguard Worker FD_CLR(fd, &cupsd_current_output);
379*5e7646d2SAndroid Build Coastguard Worker }
380*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_KQUEUE */
381*5e7646d2SAndroid Build Coastguard Worker
382*5e7646d2SAndroid Build Coastguard Worker /*
383*5e7646d2SAndroid Build Coastguard Worker * Save the (new) read and write callbacks...
384*5e7646d2SAndroid Build Coastguard Worker */
385*5e7646d2SAndroid Build Coastguard Worker
386*5e7646d2SAndroid Build Coastguard Worker fdptr->read_cb = read_cb;
387*5e7646d2SAndroid Build Coastguard Worker fdptr->write_cb = write_cb;
388*5e7646d2SAndroid Build Coastguard Worker fdptr->data = data;
389*5e7646d2SAndroid Build Coastguard Worker
390*5e7646d2SAndroid Build Coastguard Worker return (1);
391*5e7646d2SAndroid Build Coastguard Worker }
392*5e7646d2SAndroid Build Coastguard Worker
393*5e7646d2SAndroid Build Coastguard Worker
394*5e7646d2SAndroid Build Coastguard Worker /*
395*5e7646d2SAndroid Build Coastguard Worker * 'cupsdDoSelect()' - Do a select-like operation.
396*5e7646d2SAndroid Build Coastguard Worker */
397*5e7646d2SAndroid Build Coastguard Worker
398*5e7646d2SAndroid Build Coastguard Worker int /* O - Number of files or -1 on error */
cupsdDoSelect(long timeout)399*5e7646d2SAndroid Build Coastguard Worker cupsdDoSelect(long timeout) /* I - Timeout in seconds */
400*5e7646d2SAndroid Build Coastguard Worker {
401*5e7646d2SAndroid Build Coastguard Worker int nfds; /* Number of file descriptors */
402*5e7646d2SAndroid Build Coastguard Worker _cupsd_fd_t *fdptr; /* Current file descriptor */
403*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_KQUEUE
404*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
405*5e7646d2SAndroid Build Coastguard Worker struct kevent *event; /* Current event */
406*5e7646d2SAndroid Build Coastguard Worker struct timespec ktimeout; /* kevent() timeout */
407*5e7646d2SAndroid Build Coastguard Worker
408*5e7646d2SAndroid Build Coastguard Worker
409*5e7646d2SAndroid Build Coastguard Worker cupsd_in_select = 1;
410*5e7646d2SAndroid Build Coastguard Worker
411*5e7646d2SAndroid Build Coastguard Worker if (timeout >= 0 && timeout < 86400)
412*5e7646d2SAndroid Build Coastguard Worker {
413*5e7646d2SAndroid Build Coastguard Worker ktimeout.tv_sec = timeout;
414*5e7646d2SAndroid Build Coastguard Worker ktimeout.tv_nsec = 0;
415*5e7646d2SAndroid Build Coastguard Worker
416*5e7646d2SAndroid Build Coastguard Worker nfds = kevent(cupsd_kqueue_fd, NULL, 0, cupsd_kqueue_events, MaxFDs,
417*5e7646d2SAndroid Build Coastguard Worker &ktimeout);
418*5e7646d2SAndroid Build Coastguard Worker }
419*5e7646d2SAndroid Build Coastguard Worker else
420*5e7646d2SAndroid Build Coastguard Worker nfds = kevent(cupsd_kqueue_fd, NULL, 0, cupsd_kqueue_events, MaxFDs, NULL);
421*5e7646d2SAndroid Build Coastguard Worker
422*5e7646d2SAndroid Build Coastguard Worker cupsd_kqueue_changes = 0;
423*5e7646d2SAndroid Build Coastguard Worker
424*5e7646d2SAndroid Build Coastguard Worker for (i = nfds, event = cupsd_kqueue_events; i > 0; i --, event ++)
425*5e7646d2SAndroid Build Coastguard Worker {
426*5e7646d2SAndroid Build Coastguard Worker fdptr = (_cupsd_fd_t *)event->udata;
427*5e7646d2SAndroid Build Coastguard Worker
428*5e7646d2SAndroid Build Coastguard Worker if (cupsArrayFind(cupsd_inactive_fds, fdptr))
429*5e7646d2SAndroid Build Coastguard Worker continue;
430*5e7646d2SAndroid Build Coastguard Worker
431*5e7646d2SAndroid Build Coastguard Worker retain_fd(fdptr);
432*5e7646d2SAndroid Build Coastguard Worker
433*5e7646d2SAndroid Build Coastguard Worker if (fdptr->read_cb && event->filter == EVFILT_READ)
434*5e7646d2SAndroid Build Coastguard Worker (*(fdptr->read_cb))(fdptr->data);
435*5e7646d2SAndroid Build Coastguard Worker
436*5e7646d2SAndroid Build Coastguard Worker if (fdptr->use > 1 && fdptr->write_cb && event->filter == EVFILT_WRITE &&
437*5e7646d2SAndroid Build Coastguard Worker !cupsArrayFind(cupsd_inactive_fds, fdptr))
438*5e7646d2SAndroid Build Coastguard Worker (*(fdptr->write_cb))(fdptr->data);
439*5e7646d2SAndroid Build Coastguard Worker
440*5e7646d2SAndroid Build Coastguard Worker release_fd(fdptr);
441*5e7646d2SAndroid Build Coastguard Worker }
442*5e7646d2SAndroid Build Coastguard Worker
443*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_POLL)
444*5e7646d2SAndroid Build Coastguard Worker struct pollfd *pfd; /* Current pollfd structure */
445*5e7646d2SAndroid Build Coastguard Worker int count; /* Number of file descriptors */
446*5e7646d2SAndroid Build Coastguard Worker
447*5e7646d2SAndroid Build Coastguard Worker
448*5e7646d2SAndroid Build Coastguard Worker # ifdef HAVE_EPOLL
449*5e7646d2SAndroid Build Coastguard Worker cupsd_in_select = 1;
450*5e7646d2SAndroid Build Coastguard Worker
451*5e7646d2SAndroid Build Coastguard Worker if (cupsd_epoll_fd >= 0)
452*5e7646d2SAndroid Build Coastguard Worker {
453*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
454*5e7646d2SAndroid Build Coastguard Worker struct epoll_event *event; /* Current event */
455*5e7646d2SAndroid Build Coastguard Worker
456*5e7646d2SAndroid Build Coastguard Worker
457*5e7646d2SAndroid Build Coastguard Worker if (timeout >= 0 && timeout < 86400)
458*5e7646d2SAndroid Build Coastguard Worker nfds = epoll_wait(cupsd_epoll_fd, cupsd_epoll_events, MaxFDs,
459*5e7646d2SAndroid Build Coastguard Worker timeout * 1000);
460*5e7646d2SAndroid Build Coastguard Worker else
461*5e7646d2SAndroid Build Coastguard Worker nfds = epoll_wait(cupsd_epoll_fd, cupsd_epoll_events, MaxFDs, -1);
462*5e7646d2SAndroid Build Coastguard Worker
463*5e7646d2SAndroid Build Coastguard Worker if (nfds < 0 && errno != EINTR)
464*5e7646d2SAndroid Build Coastguard Worker {
465*5e7646d2SAndroid Build Coastguard Worker close(cupsd_epoll_fd);
466*5e7646d2SAndroid Build Coastguard Worker cupsd_epoll_fd = -1;
467*5e7646d2SAndroid Build Coastguard Worker }
468*5e7646d2SAndroid Build Coastguard Worker else
469*5e7646d2SAndroid Build Coastguard Worker {
470*5e7646d2SAndroid Build Coastguard Worker for (i = nfds, event = cupsd_epoll_events; i > 0; i --, event ++)
471*5e7646d2SAndroid Build Coastguard Worker {
472*5e7646d2SAndroid Build Coastguard Worker fdptr = (_cupsd_fd_t *)event->data.ptr;
473*5e7646d2SAndroid Build Coastguard Worker
474*5e7646d2SAndroid Build Coastguard Worker if (cupsArrayFind(cupsd_inactive_fds, fdptr))
475*5e7646d2SAndroid Build Coastguard Worker continue;
476*5e7646d2SAndroid Build Coastguard Worker
477*5e7646d2SAndroid Build Coastguard Worker retain_fd(fdptr);
478*5e7646d2SAndroid Build Coastguard Worker
479*5e7646d2SAndroid Build Coastguard Worker if (fdptr->read_cb && (event->events & (EPOLLIN | EPOLLERR | EPOLLHUP)))
480*5e7646d2SAndroid Build Coastguard Worker (*(fdptr->read_cb))(fdptr->data);
481*5e7646d2SAndroid Build Coastguard Worker
482*5e7646d2SAndroid Build Coastguard Worker if (fdptr->use > 1 && fdptr->write_cb &&
483*5e7646d2SAndroid Build Coastguard Worker (event->events & (EPOLLOUT | EPOLLERR | EPOLLHUP)) &&
484*5e7646d2SAndroid Build Coastguard Worker !cupsArrayFind(cupsd_inactive_fds, fdptr))
485*5e7646d2SAndroid Build Coastguard Worker (*(fdptr->write_cb))(fdptr->data);
486*5e7646d2SAndroid Build Coastguard Worker
487*5e7646d2SAndroid Build Coastguard Worker release_fd(fdptr);
488*5e7646d2SAndroid Build Coastguard Worker }
489*5e7646d2SAndroid Build Coastguard Worker
490*5e7646d2SAndroid Build Coastguard Worker goto release_inactive;
491*5e7646d2SAndroid Build Coastguard Worker }
492*5e7646d2SAndroid Build Coastguard Worker }
493*5e7646d2SAndroid Build Coastguard Worker # endif /* HAVE_EPOLL */
494*5e7646d2SAndroid Build Coastguard Worker
495*5e7646d2SAndroid Build Coastguard Worker count = cupsArrayCount(cupsd_fds);
496*5e7646d2SAndroid Build Coastguard Worker
497*5e7646d2SAndroid Build Coastguard Worker if (cupsd_update_pollfds)
498*5e7646d2SAndroid Build Coastguard Worker {
499*5e7646d2SAndroid Build Coastguard Worker /*
500*5e7646d2SAndroid Build Coastguard Worker * Update the cupsd_pollfds array to match the current FD array...
501*5e7646d2SAndroid Build Coastguard Worker */
502*5e7646d2SAndroid Build Coastguard Worker
503*5e7646d2SAndroid Build Coastguard Worker cupsd_update_pollfds = 0;
504*5e7646d2SAndroid Build Coastguard Worker
505*5e7646d2SAndroid Build Coastguard Worker /*
506*5e7646d2SAndroid Build Coastguard Worker * (Re)allocate memory as needed...
507*5e7646d2SAndroid Build Coastguard Worker */
508*5e7646d2SAndroid Build Coastguard Worker
509*5e7646d2SAndroid Build Coastguard Worker if (count > cupsd_alloc_pollfds)
510*5e7646d2SAndroid Build Coastguard Worker {
511*5e7646d2SAndroid Build Coastguard Worker int allocfds = count + 16;
512*5e7646d2SAndroid Build Coastguard Worker
513*5e7646d2SAndroid Build Coastguard Worker
514*5e7646d2SAndroid Build Coastguard Worker if (cupsd_pollfds)
515*5e7646d2SAndroid Build Coastguard Worker pfd = realloc(cupsd_pollfds, (size_t)allocfds * sizeof(struct pollfd));
516*5e7646d2SAndroid Build Coastguard Worker else
517*5e7646d2SAndroid Build Coastguard Worker pfd = malloc((size_t)allocfds * sizeof(struct pollfd));
518*5e7646d2SAndroid Build Coastguard Worker
519*5e7646d2SAndroid Build Coastguard Worker if (!pfd)
520*5e7646d2SAndroid Build Coastguard Worker {
521*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_EMERG, "Unable to allocate %d bytes for polling.", (int)((size_t)allocfds * sizeof(struct pollfd)));
522*5e7646d2SAndroid Build Coastguard Worker
523*5e7646d2SAndroid Build Coastguard Worker return (-1);
524*5e7646d2SAndroid Build Coastguard Worker }
525*5e7646d2SAndroid Build Coastguard Worker
526*5e7646d2SAndroid Build Coastguard Worker cupsd_pollfds = pfd;
527*5e7646d2SAndroid Build Coastguard Worker cupsd_alloc_pollfds = allocfds;
528*5e7646d2SAndroid Build Coastguard Worker }
529*5e7646d2SAndroid Build Coastguard Worker
530*5e7646d2SAndroid Build Coastguard Worker /*
531*5e7646d2SAndroid Build Coastguard Worker * Rebuild the array...
532*5e7646d2SAndroid Build Coastguard Worker */
533*5e7646d2SAndroid Build Coastguard Worker
534*5e7646d2SAndroid Build Coastguard Worker for (fdptr = (_cupsd_fd_t *)cupsArrayFirst(cupsd_fds), pfd = cupsd_pollfds;
535*5e7646d2SAndroid Build Coastguard Worker fdptr;
536*5e7646d2SAndroid Build Coastguard Worker fdptr = (_cupsd_fd_t *)cupsArrayNext(cupsd_fds), pfd ++)
537*5e7646d2SAndroid Build Coastguard Worker {
538*5e7646d2SAndroid Build Coastguard Worker pfd->fd = fdptr->fd;
539*5e7646d2SAndroid Build Coastguard Worker pfd->events = 0;
540*5e7646d2SAndroid Build Coastguard Worker
541*5e7646d2SAndroid Build Coastguard Worker if (fdptr->read_cb)
542*5e7646d2SAndroid Build Coastguard Worker pfd->events |= POLLIN;
543*5e7646d2SAndroid Build Coastguard Worker
544*5e7646d2SAndroid Build Coastguard Worker if (fdptr->write_cb)
545*5e7646d2SAndroid Build Coastguard Worker pfd->events |= POLLOUT;
546*5e7646d2SAndroid Build Coastguard Worker }
547*5e7646d2SAndroid Build Coastguard Worker }
548*5e7646d2SAndroid Build Coastguard Worker
549*5e7646d2SAndroid Build Coastguard Worker if (timeout >= 0 && timeout < 86400)
550*5e7646d2SAndroid Build Coastguard Worker nfds = poll(cupsd_pollfds, (nfds_t)count, timeout * 1000);
551*5e7646d2SAndroid Build Coastguard Worker else
552*5e7646d2SAndroid Build Coastguard Worker nfds = poll(cupsd_pollfds, (nfds_t)count, -1);
553*5e7646d2SAndroid Build Coastguard Worker
554*5e7646d2SAndroid Build Coastguard Worker if (nfds > 0)
555*5e7646d2SAndroid Build Coastguard Worker {
556*5e7646d2SAndroid Build Coastguard Worker /*
557*5e7646d2SAndroid Build Coastguard Worker * Do callbacks for each file descriptor...
558*5e7646d2SAndroid Build Coastguard Worker */
559*5e7646d2SAndroid Build Coastguard Worker
560*5e7646d2SAndroid Build Coastguard Worker for (pfd = cupsd_pollfds; count > 0; pfd ++, count --)
561*5e7646d2SAndroid Build Coastguard Worker {
562*5e7646d2SAndroid Build Coastguard Worker if (!pfd->revents)
563*5e7646d2SAndroid Build Coastguard Worker continue;
564*5e7646d2SAndroid Build Coastguard Worker
565*5e7646d2SAndroid Build Coastguard Worker if ((fdptr = find_fd(pfd->fd)) == NULL)
566*5e7646d2SAndroid Build Coastguard Worker continue;
567*5e7646d2SAndroid Build Coastguard Worker
568*5e7646d2SAndroid Build Coastguard Worker retain_fd(fdptr);
569*5e7646d2SAndroid Build Coastguard Worker
570*5e7646d2SAndroid Build Coastguard Worker if (fdptr->read_cb && (pfd->revents & (POLLIN | POLLERR | POLLHUP)))
571*5e7646d2SAndroid Build Coastguard Worker (*(fdptr->read_cb))(fdptr->data);
572*5e7646d2SAndroid Build Coastguard Worker
573*5e7646d2SAndroid Build Coastguard Worker if (fdptr->use > 1 && fdptr->write_cb &&
574*5e7646d2SAndroid Build Coastguard Worker (pfd->revents & (POLLOUT | POLLERR | POLLHUP)))
575*5e7646d2SAndroid Build Coastguard Worker (*(fdptr->write_cb))(fdptr->data);
576*5e7646d2SAndroid Build Coastguard Worker
577*5e7646d2SAndroid Build Coastguard Worker release_fd(fdptr);
578*5e7646d2SAndroid Build Coastguard Worker }
579*5e7646d2SAndroid Build Coastguard Worker }
580*5e7646d2SAndroid Build Coastguard Worker
581*5e7646d2SAndroid Build Coastguard Worker #else /* select() */
582*5e7646d2SAndroid Build Coastguard Worker struct timeval stimeout; /* Timeout for select() */
583*5e7646d2SAndroid Build Coastguard Worker int maxfd; /* Maximum file descriptor */
584*5e7646d2SAndroid Build Coastguard Worker
585*5e7646d2SAndroid Build Coastguard Worker
586*5e7646d2SAndroid Build Coastguard Worker /*
587*5e7646d2SAndroid Build Coastguard Worker * Figure out the highest file descriptor number...
588*5e7646d2SAndroid Build Coastguard Worker */
589*5e7646d2SAndroid Build Coastguard Worker
590*5e7646d2SAndroid Build Coastguard Worker if ((fdptr = (_cupsd_fd_t *)cupsArrayLast(cupsd_fds)) == NULL)
591*5e7646d2SAndroid Build Coastguard Worker maxfd = 1;
592*5e7646d2SAndroid Build Coastguard Worker else
593*5e7646d2SAndroid Build Coastguard Worker maxfd = fdptr->fd + 1;
594*5e7646d2SAndroid Build Coastguard Worker
595*5e7646d2SAndroid Build Coastguard Worker /*
596*5e7646d2SAndroid Build Coastguard Worker * Do the select()...
597*5e7646d2SAndroid Build Coastguard Worker */
598*5e7646d2SAndroid Build Coastguard Worker
599*5e7646d2SAndroid Build Coastguard Worker cupsd_current_input = cupsd_global_input;
600*5e7646d2SAndroid Build Coastguard Worker cupsd_current_output = cupsd_global_output;
601*5e7646d2SAndroid Build Coastguard Worker
602*5e7646d2SAndroid Build Coastguard Worker if (timeout >= 0 && timeout < 86400)
603*5e7646d2SAndroid Build Coastguard Worker {
604*5e7646d2SAndroid Build Coastguard Worker stimeout.tv_sec = timeout;
605*5e7646d2SAndroid Build Coastguard Worker stimeout.tv_usec = 0;
606*5e7646d2SAndroid Build Coastguard Worker
607*5e7646d2SAndroid Build Coastguard Worker nfds = select(maxfd, &cupsd_current_input, &cupsd_current_output, NULL,
608*5e7646d2SAndroid Build Coastguard Worker &stimeout);
609*5e7646d2SAndroid Build Coastguard Worker }
610*5e7646d2SAndroid Build Coastguard Worker else
611*5e7646d2SAndroid Build Coastguard Worker nfds = select(maxfd, &cupsd_current_input, &cupsd_current_output, NULL,
612*5e7646d2SAndroid Build Coastguard Worker NULL);
613*5e7646d2SAndroid Build Coastguard Worker
614*5e7646d2SAndroid Build Coastguard Worker if (nfds > 0)
615*5e7646d2SAndroid Build Coastguard Worker {
616*5e7646d2SAndroid Build Coastguard Worker /*
617*5e7646d2SAndroid Build Coastguard Worker * Do callbacks for each file descriptor...
618*5e7646d2SAndroid Build Coastguard Worker */
619*5e7646d2SAndroid Build Coastguard Worker
620*5e7646d2SAndroid Build Coastguard Worker for (fdptr = (_cupsd_fd_t *)cupsArrayFirst(cupsd_fds);
621*5e7646d2SAndroid Build Coastguard Worker fdptr;
622*5e7646d2SAndroid Build Coastguard Worker fdptr = (_cupsd_fd_t *)cupsArrayNext(cupsd_fds))
623*5e7646d2SAndroid Build Coastguard Worker {
624*5e7646d2SAndroid Build Coastguard Worker retain_fd(fdptr);
625*5e7646d2SAndroid Build Coastguard Worker
626*5e7646d2SAndroid Build Coastguard Worker if (fdptr->read_cb && FD_ISSET(fdptr->fd, &cupsd_current_input))
627*5e7646d2SAndroid Build Coastguard Worker (*(fdptr->read_cb))(fdptr->data);
628*5e7646d2SAndroid Build Coastguard Worker
629*5e7646d2SAndroid Build Coastguard Worker if (fdptr->use > 1 && fdptr->write_cb &&
630*5e7646d2SAndroid Build Coastguard Worker FD_ISSET(fdptr->fd, &cupsd_current_output))
631*5e7646d2SAndroid Build Coastguard Worker (*(fdptr->write_cb))(fdptr->data);
632*5e7646d2SAndroid Build Coastguard Worker
633*5e7646d2SAndroid Build Coastguard Worker release_fd(fdptr);
634*5e7646d2SAndroid Build Coastguard Worker }
635*5e7646d2SAndroid Build Coastguard Worker }
636*5e7646d2SAndroid Build Coastguard Worker
637*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_KQUEUE */
638*5e7646d2SAndroid Build Coastguard Worker
639*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_EPOLL) || defined(HAVE_KQUEUE)
640*5e7646d2SAndroid Build Coastguard Worker /*
641*5e7646d2SAndroid Build Coastguard Worker * Release all inactive file descriptors...
642*5e7646d2SAndroid Build Coastguard Worker */
643*5e7646d2SAndroid Build Coastguard Worker
644*5e7646d2SAndroid Build Coastguard Worker # ifndef HAVE_KQUEUE
645*5e7646d2SAndroid Build Coastguard Worker release_inactive:
646*5e7646d2SAndroid Build Coastguard Worker # endif /* !HAVE_KQUEUE */
647*5e7646d2SAndroid Build Coastguard Worker
648*5e7646d2SAndroid Build Coastguard Worker cupsd_in_select = 0;
649*5e7646d2SAndroid Build Coastguard Worker
650*5e7646d2SAndroid Build Coastguard Worker for (fdptr = (_cupsd_fd_t *)cupsArrayFirst(cupsd_inactive_fds);
651*5e7646d2SAndroid Build Coastguard Worker fdptr;
652*5e7646d2SAndroid Build Coastguard Worker fdptr = (_cupsd_fd_t *)cupsArrayNext(cupsd_inactive_fds))
653*5e7646d2SAndroid Build Coastguard Worker {
654*5e7646d2SAndroid Build Coastguard Worker cupsArrayRemove(cupsd_inactive_fds, fdptr);
655*5e7646d2SAndroid Build Coastguard Worker release_fd(fdptr);
656*5e7646d2SAndroid Build Coastguard Worker }
657*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_EPOLL || HAVE_KQUEUE */
658*5e7646d2SAndroid Build Coastguard Worker
659*5e7646d2SAndroid Build Coastguard Worker /*
660*5e7646d2SAndroid Build Coastguard Worker * Return the number of file descriptors handled...
661*5e7646d2SAndroid Build Coastguard Worker */
662*5e7646d2SAndroid Build Coastguard Worker
663*5e7646d2SAndroid Build Coastguard Worker return (nfds);
664*5e7646d2SAndroid Build Coastguard Worker }
665*5e7646d2SAndroid Build Coastguard Worker
666*5e7646d2SAndroid Build Coastguard Worker
667*5e7646d2SAndroid Build Coastguard Worker #ifdef CUPSD_IS_SELECTING
668*5e7646d2SAndroid Build Coastguard Worker /*
669*5e7646d2SAndroid Build Coastguard Worker * 'cupsdIsSelecting()' - Determine whether we are monitoring a file
670*5e7646d2SAndroid Build Coastguard Worker * descriptor.
671*5e7646d2SAndroid Build Coastguard Worker */
672*5e7646d2SAndroid Build Coastguard Worker
673*5e7646d2SAndroid Build Coastguard Worker int /* O - 1 if selecting, 0 otherwise */
cupsdIsSelecting(int fd)674*5e7646d2SAndroid Build Coastguard Worker cupsdIsSelecting(int fd) /* I - File descriptor */
675*5e7646d2SAndroid Build Coastguard Worker {
676*5e7646d2SAndroid Build Coastguard Worker return (find_fd(fd) != NULL);
677*5e7646d2SAndroid Build Coastguard Worker }
678*5e7646d2SAndroid Build Coastguard Worker #endif /* CUPSD_IS_SELECTING */
679*5e7646d2SAndroid Build Coastguard Worker
680*5e7646d2SAndroid Build Coastguard Worker
681*5e7646d2SAndroid Build Coastguard Worker /*
682*5e7646d2SAndroid Build Coastguard Worker * 'cupsdRemoveSelect()' - Remove a file descriptor from the list.
683*5e7646d2SAndroid Build Coastguard Worker */
684*5e7646d2SAndroid Build Coastguard Worker
685*5e7646d2SAndroid Build Coastguard Worker void
cupsdRemoveSelect(int fd)686*5e7646d2SAndroid Build Coastguard Worker cupsdRemoveSelect(int fd) /* I - File descriptor */
687*5e7646d2SAndroid Build Coastguard Worker {
688*5e7646d2SAndroid Build Coastguard Worker _cupsd_fd_t *fdptr; /* File descriptor record */
689*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_EPOLL
690*5e7646d2SAndroid Build Coastguard Worker struct epoll_event event; /* Event data */
691*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_KQUEUE)
692*5e7646d2SAndroid Build Coastguard Worker struct kevent event; /* Event data */
693*5e7646d2SAndroid Build Coastguard Worker struct timespec timeout; /* Timeout value */
694*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_POLL)
695*5e7646d2SAndroid Build Coastguard Worker /* No variables for poll() */
696*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_EPOLL */
697*5e7646d2SAndroid Build Coastguard Worker
698*5e7646d2SAndroid Build Coastguard Worker
699*5e7646d2SAndroid Build Coastguard Worker /*
700*5e7646d2SAndroid Build Coastguard Worker * Range check input...
701*5e7646d2SAndroid Build Coastguard Worker */
702*5e7646d2SAndroid Build Coastguard Worker
703*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdRemoveSelect(fd=%d)", fd);
704*5e7646d2SAndroid Build Coastguard Worker
705*5e7646d2SAndroid Build Coastguard Worker if (fd < 0)
706*5e7646d2SAndroid Build Coastguard Worker return;
707*5e7646d2SAndroid Build Coastguard Worker
708*5e7646d2SAndroid Build Coastguard Worker /*
709*5e7646d2SAndroid Build Coastguard Worker * Find the file descriptor...
710*5e7646d2SAndroid Build Coastguard Worker */
711*5e7646d2SAndroid Build Coastguard Worker
712*5e7646d2SAndroid Build Coastguard Worker if ((fdptr = find_fd(fd)) == NULL)
713*5e7646d2SAndroid Build Coastguard Worker return;
714*5e7646d2SAndroid Build Coastguard Worker
715*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_EPOLL
716*5e7646d2SAndroid Build Coastguard Worker if (epoll_ctl(cupsd_epoll_fd, EPOLL_CTL_DEL, fd, &event))
717*5e7646d2SAndroid Build Coastguard Worker {
718*5e7646d2SAndroid Build Coastguard Worker close(cupsd_epoll_fd);
719*5e7646d2SAndroid Build Coastguard Worker cupsd_epoll_fd = -1;
720*5e7646d2SAndroid Build Coastguard Worker cupsd_update_pollfds = 1;
721*5e7646d2SAndroid Build Coastguard Worker }
722*5e7646d2SAndroid Build Coastguard Worker
723*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_KQUEUE)
724*5e7646d2SAndroid Build Coastguard Worker timeout.tv_sec = 0;
725*5e7646d2SAndroid Build Coastguard Worker timeout.tv_nsec = 0;
726*5e7646d2SAndroid Build Coastguard Worker
727*5e7646d2SAndroid Build Coastguard Worker if (fdptr->read_cb)
728*5e7646d2SAndroid Build Coastguard Worker {
729*5e7646d2SAndroid Build Coastguard Worker EV_SET(&event, fd, EVFILT_READ, EV_DELETE, 0, 0, fdptr);
730*5e7646d2SAndroid Build Coastguard Worker
731*5e7646d2SAndroid Build Coastguard Worker if (kevent(cupsd_kqueue_fd, &event, 1, NULL, 0, &timeout))
732*5e7646d2SAndroid Build Coastguard Worker {
733*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_EMERG, "kevent() returned %s",
734*5e7646d2SAndroid Build Coastguard Worker strerror(errno));
735*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
736*5e7646d2SAndroid Build Coastguard Worker }
737*5e7646d2SAndroid Build Coastguard Worker }
738*5e7646d2SAndroid Build Coastguard Worker
739*5e7646d2SAndroid Build Coastguard Worker if (fdptr->write_cb)
740*5e7646d2SAndroid Build Coastguard Worker {
741*5e7646d2SAndroid Build Coastguard Worker EV_SET(&event, fd, EVFILT_WRITE, EV_DELETE, 0, 0, fdptr);
742*5e7646d2SAndroid Build Coastguard Worker
743*5e7646d2SAndroid Build Coastguard Worker if (kevent(cupsd_kqueue_fd, &event, 1, NULL, 0, &timeout))
744*5e7646d2SAndroid Build Coastguard Worker {
745*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_EMERG, "kevent() returned %s",
746*5e7646d2SAndroid Build Coastguard Worker strerror(errno));
747*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
748*5e7646d2SAndroid Build Coastguard Worker }
749*5e7646d2SAndroid Build Coastguard Worker }
750*5e7646d2SAndroid Build Coastguard Worker
751*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_POLL)
752*5e7646d2SAndroid Build Coastguard Worker /*
753*5e7646d2SAndroid Build Coastguard Worker * Update the pollfds array...
754*5e7646d2SAndroid Build Coastguard Worker */
755*5e7646d2SAndroid Build Coastguard Worker
756*5e7646d2SAndroid Build Coastguard Worker cupsd_update_pollfds = 1;
757*5e7646d2SAndroid Build Coastguard Worker
758*5e7646d2SAndroid Build Coastguard Worker #else /* select() */
759*5e7646d2SAndroid Build Coastguard Worker FD_CLR(fd, &cupsd_global_input);
760*5e7646d2SAndroid Build Coastguard Worker FD_CLR(fd, &cupsd_global_output);
761*5e7646d2SAndroid Build Coastguard Worker FD_CLR(fd, &cupsd_current_input);
762*5e7646d2SAndroid Build Coastguard Worker FD_CLR(fd, &cupsd_current_output);
763*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_EPOLL */
764*5e7646d2SAndroid Build Coastguard Worker
765*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_KQUEUE
766*5e7646d2SAndroid Build Coastguard Worker cleanup:
767*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_KQUEUE */
768*5e7646d2SAndroid Build Coastguard Worker
769*5e7646d2SAndroid Build Coastguard Worker /*
770*5e7646d2SAndroid Build Coastguard Worker * Remove the file descriptor from the active array and add to the
771*5e7646d2SAndroid Build Coastguard Worker * inactive array (or release, if we don't need the inactive array...)
772*5e7646d2SAndroid Build Coastguard Worker */
773*5e7646d2SAndroid Build Coastguard Worker
774*5e7646d2SAndroid Build Coastguard Worker cupsArrayRemove(cupsd_fds, fdptr);
775*5e7646d2SAndroid Build Coastguard Worker
776*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_EPOLL) || defined(HAVE_KQUEUE)
777*5e7646d2SAndroid Build Coastguard Worker if (cupsd_in_select)
778*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(cupsd_inactive_fds, fdptr);
779*5e7646d2SAndroid Build Coastguard Worker else
780*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_EPOLL || HAVE_KQUEUE */
781*5e7646d2SAndroid Build Coastguard Worker
782*5e7646d2SAndroid Build Coastguard Worker release_fd(fdptr);
783*5e7646d2SAndroid Build Coastguard Worker }
784*5e7646d2SAndroid Build Coastguard Worker
785*5e7646d2SAndroid Build Coastguard Worker
786*5e7646d2SAndroid Build Coastguard Worker /*
787*5e7646d2SAndroid Build Coastguard Worker * 'cupsdStartSelect()' - Initialize the file polling engine.
788*5e7646d2SAndroid Build Coastguard Worker */
789*5e7646d2SAndroid Build Coastguard Worker
790*5e7646d2SAndroid Build Coastguard Worker void
cupsdStartSelect(void)791*5e7646d2SAndroid Build Coastguard Worker cupsdStartSelect(void)
792*5e7646d2SAndroid Build Coastguard Worker {
793*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdStartSelect()");
794*5e7646d2SAndroid Build Coastguard Worker
795*5e7646d2SAndroid Build Coastguard Worker cupsd_fds = cupsArrayNew((cups_array_func_t)compare_fds, NULL);
796*5e7646d2SAndroid Build Coastguard Worker
797*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_EPOLL) || defined(HAVE_KQUEUE)
798*5e7646d2SAndroid Build Coastguard Worker cupsd_inactive_fds = cupsArrayNew((cups_array_func_t)compare_fds, NULL);
799*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_EPOLL || HAVE_KQUEUE */
800*5e7646d2SAndroid Build Coastguard Worker
801*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_EPOLL
802*5e7646d2SAndroid Build Coastguard Worker cupsd_epoll_fd = epoll_create(MaxFDs);
803*5e7646d2SAndroid Build Coastguard Worker cupsd_epoll_events = calloc((size_t)MaxFDs, sizeof(struct epoll_event));
804*5e7646d2SAndroid Build Coastguard Worker cupsd_update_pollfds = 0;
805*5e7646d2SAndroid Build Coastguard Worker
806*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_KQUEUE)
807*5e7646d2SAndroid Build Coastguard Worker cupsd_kqueue_fd = kqueue();
808*5e7646d2SAndroid Build Coastguard Worker cupsd_kqueue_changes = 0;
809*5e7646d2SAndroid Build Coastguard Worker cupsd_kqueue_events = calloc((size_t)MaxFDs, sizeof(struct kevent));
810*5e7646d2SAndroid Build Coastguard Worker
811*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_POLL)
812*5e7646d2SAndroid Build Coastguard Worker cupsd_update_pollfds = 0;
813*5e7646d2SAndroid Build Coastguard Worker
814*5e7646d2SAndroid Build Coastguard Worker #else /* select() */
815*5e7646d2SAndroid Build Coastguard Worker FD_ZERO(&cupsd_global_input);
816*5e7646d2SAndroid Build Coastguard Worker FD_ZERO(&cupsd_global_output);
817*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_EPOLL */
818*5e7646d2SAndroid Build Coastguard Worker }
819*5e7646d2SAndroid Build Coastguard Worker
820*5e7646d2SAndroid Build Coastguard Worker
821*5e7646d2SAndroid Build Coastguard Worker /*
822*5e7646d2SAndroid Build Coastguard Worker * 'cupsdStopSelect()' - Shutdown the file polling engine.
823*5e7646d2SAndroid Build Coastguard Worker */
824*5e7646d2SAndroid Build Coastguard Worker
825*5e7646d2SAndroid Build Coastguard Worker void
cupsdStopSelect(void)826*5e7646d2SAndroid Build Coastguard Worker cupsdStopSelect(void)
827*5e7646d2SAndroid Build Coastguard Worker {
828*5e7646d2SAndroid Build Coastguard Worker _cupsd_fd_t *fdptr; /* Current file descriptor */
829*5e7646d2SAndroid Build Coastguard Worker
830*5e7646d2SAndroid Build Coastguard Worker
831*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdStopSelect()");
832*5e7646d2SAndroid Build Coastguard Worker
833*5e7646d2SAndroid Build Coastguard Worker for (fdptr = (_cupsd_fd_t *)cupsArrayFirst(cupsd_fds);
834*5e7646d2SAndroid Build Coastguard Worker fdptr;
835*5e7646d2SAndroid Build Coastguard Worker fdptr = (_cupsd_fd_t *)cupsArrayNext(cupsd_fds))
836*5e7646d2SAndroid Build Coastguard Worker free(fdptr);
837*5e7646d2SAndroid Build Coastguard Worker
838*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(cupsd_fds);
839*5e7646d2SAndroid Build Coastguard Worker cupsd_fds = NULL;
840*5e7646d2SAndroid Build Coastguard Worker
841*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_EPOLL) || defined(HAVE_KQUEUE)
842*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(cupsd_inactive_fds);
843*5e7646d2SAndroid Build Coastguard Worker cupsd_inactive_fds = NULL;
844*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_EPOLL || HAVE_KQUEUE */
845*5e7646d2SAndroid Build Coastguard Worker
846*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_KQUEUE
847*5e7646d2SAndroid Build Coastguard Worker if (cupsd_kqueue_events)
848*5e7646d2SAndroid Build Coastguard Worker {
849*5e7646d2SAndroid Build Coastguard Worker free(cupsd_kqueue_events);
850*5e7646d2SAndroid Build Coastguard Worker cupsd_kqueue_events = NULL;
851*5e7646d2SAndroid Build Coastguard Worker }
852*5e7646d2SAndroid Build Coastguard Worker
853*5e7646d2SAndroid Build Coastguard Worker if (cupsd_kqueue_fd >= 0)
854*5e7646d2SAndroid Build Coastguard Worker {
855*5e7646d2SAndroid Build Coastguard Worker close(cupsd_kqueue_fd);
856*5e7646d2SAndroid Build Coastguard Worker cupsd_kqueue_fd = -1;
857*5e7646d2SAndroid Build Coastguard Worker }
858*5e7646d2SAndroid Build Coastguard Worker
859*5e7646d2SAndroid Build Coastguard Worker cupsd_kqueue_changes = 0;
860*5e7646d2SAndroid Build Coastguard Worker
861*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_POLL)
862*5e7646d2SAndroid Build Coastguard Worker # ifdef HAVE_EPOLL
863*5e7646d2SAndroid Build Coastguard Worker if (cupsd_epoll_events)
864*5e7646d2SAndroid Build Coastguard Worker {
865*5e7646d2SAndroid Build Coastguard Worker free(cupsd_epoll_events);
866*5e7646d2SAndroid Build Coastguard Worker cupsd_epoll_events = NULL;
867*5e7646d2SAndroid Build Coastguard Worker }
868*5e7646d2SAndroid Build Coastguard Worker
869*5e7646d2SAndroid Build Coastguard Worker if (cupsd_epoll_fd >= 0)
870*5e7646d2SAndroid Build Coastguard Worker {
871*5e7646d2SAndroid Build Coastguard Worker close(cupsd_epoll_fd);
872*5e7646d2SAndroid Build Coastguard Worker cupsd_epoll_fd = -1;
873*5e7646d2SAndroid Build Coastguard Worker }
874*5e7646d2SAndroid Build Coastguard Worker # endif /* HAVE_EPOLL */
875*5e7646d2SAndroid Build Coastguard Worker
876*5e7646d2SAndroid Build Coastguard Worker if (cupsd_pollfds)
877*5e7646d2SAndroid Build Coastguard Worker {
878*5e7646d2SAndroid Build Coastguard Worker free(cupsd_pollfds);
879*5e7646d2SAndroid Build Coastguard Worker cupsd_pollfds = NULL;
880*5e7646d2SAndroid Build Coastguard Worker cupsd_alloc_pollfds = 0;
881*5e7646d2SAndroid Build Coastguard Worker }
882*5e7646d2SAndroid Build Coastguard Worker
883*5e7646d2SAndroid Build Coastguard Worker cupsd_update_pollfds = 0;
884*5e7646d2SAndroid Build Coastguard Worker
885*5e7646d2SAndroid Build Coastguard Worker #else /* select() */
886*5e7646d2SAndroid Build Coastguard Worker FD_ZERO(&cupsd_global_input);
887*5e7646d2SAndroid Build Coastguard Worker FD_ZERO(&cupsd_global_output);
888*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_EPOLL */
889*5e7646d2SAndroid Build Coastguard Worker }
890*5e7646d2SAndroid Build Coastguard Worker
891*5e7646d2SAndroid Build Coastguard Worker
892*5e7646d2SAndroid Build Coastguard Worker /*
893*5e7646d2SAndroid Build Coastguard Worker * 'compare_fds()' - Compare file descriptors.
894*5e7646d2SAndroid Build Coastguard Worker */
895*5e7646d2SAndroid Build Coastguard Worker
896*5e7646d2SAndroid Build Coastguard Worker static int /* O - Result of comparison */
compare_fds(_cupsd_fd_t * a,_cupsd_fd_t * b)897*5e7646d2SAndroid Build Coastguard Worker compare_fds(_cupsd_fd_t *a, /* I - First file descriptor */
898*5e7646d2SAndroid Build Coastguard Worker _cupsd_fd_t *b) /* I - Second file descriptor */
899*5e7646d2SAndroid Build Coastguard Worker {
900*5e7646d2SAndroid Build Coastguard Worker return (a->fd - b->fd);
901*5e7646d2SAndroid Build Coastguard Worker }
902*5e7646d2SAndroid Build Coastguard Worker
903*5e7646d2SAndroid Build Coastguard Worker
904*5e7646d2SAndroid Build Coastguard Worker /*
905*5e7646d2SAndroid Build Coastguard Worker * 'find_fd()' - Find an existing file descriptor record.
906*5e7646d2SAndroid Build Coastguard Worker */
907*5e7646d2SAndroid Build Coastguard Worker
908*5e7646d2SAndroid Build Coastguard Worker static _cupsd_fd_t * /* O - FD record pointer or NULL */
find_fd(int fd)909*5e7646d2SAndroid Build Coastguard Worker find_fd(int fd) /* I - File descriptor */
910*5e7646d2SAndroid Build Coastguard Worker {
911*5e7646d2SAndroid Build Coastguard Worker _cupsd_fd_t *fdptr, /* Matching record (if any) */
912*5e7646d2SAndroid Build Coastguard Worker key; /* Search key */
913*5e7646d2SAndroid Build Coastguard Worker
914*5e7646d2SAndroid Build Coastguard Worker
915*5e7646d2SAndroid Build Coastguard Worker cupsArraySave(cupsd_fds);
916*5e7646d2SAndroid Build Coastguard Worker
917*5e7646d2SAndroid Build Coastguard Worker key.fd = fd;
918*5e7646d2SAndroid Build Coastguard Worker fdptr = (_cupsd_fd_t *)cupsArrayFind(cupsd_fds, &key);
919*5e7646d2SAndroid Build Coastguard Worker
920*5e7646d2SAndroid Build Coastguard Worker cupsArrayRestore(cupsd_fds);
921*5e7646d2SAndroid Build Coastguard Worker
922*5e7646d2SAndroid Build Coastguard Worker return (fdptr);
923*5e7646d2SAndroid Build Coastguard Worker }
924