xref: /aosp_15_r20/external/libcups/scheduler/select.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
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